网站建设方案实施,3合1网站建设价格,三维建模,西安网站建设价格本来不是什么难搞的问题#xff0c;代码写完了#xff0c;音频流信息中的详细信息#xff0c;具体代码表现为
format_ctx-streams[audio_stream_index]-codecpar是空指针。
这个查了一圈也没人给出正确答案#xff0c;实际上是由于我自己编译的ffmpeg时候#x…本来不是什么难搞的问题代码写完了音频流信息中的详细信息具体代码表现为
format_ctx-streams[audio_stream_index]-codecpar是空指针。
这个查了一圈也没人给出正确答案实际上是由于我自己编译的ffmpeg时候开启的选项的导致的。把音频解码器相关的给禁掉了。重新开启相关编译选项编译ffmpeg后一切正常。
具体的选项为
ffmpeg 交叉编译./configure --prefix../arm-ffmpegbuild \
--enable-shared \
--enable-libmp3lame \--enable-libx264 \--enable-gpl \--disable-asm \--enable-version3 \--enable-libmp3lame \--enable-libx264 \--enable-libvpx \--enable-nonfree \--cross-prefixaarch64-linux- \--target-oslinux \--extra-cflags-I /opt/ffmpeg_test_make/lame-3.100/lamebuild/include \--extra-ldflags-L /opt/ffmpeg_test_make/lame-3.100/lamebuild/lib \--enable-cross-compile \--enable-small \--archarm64 \--enable-decoderh264 \--enable-parserh264 \--enable-demuxerrtsp \--extra-ldflags-L ../x264build/lib \--extra-cflags-I ../x264build/includelame交叉编译./configure \--hostaarch64-linux \--prefix/opt/ffmpeg_test_make/lame-3.100/lamebuild \ccaarch64-linux-gcc
话不多说上代码 bool FfpDecoderWav::dump_wav(std::string rtsp_url, std::string file_path) {AVDictionary *format_options NULL;av_dict_set(format_options, rtsp_transport, tcp, 0); // 以tcp的方式打开,av_register_all();avformat_network_init();// 打开 RTSP 流int reconnect_times 3;AVFormatContext *format_ctx NULL;bool online false;while (reconnect_times-- 0) {if (format_ctx ! NULL) {avformat_close_input(format_ctx);format_ctx NULL;}format_ctx avformat_alloc_context();if (avformat_open_input(format_ctx, rtsp_url.c_str(), NULL, format_options) ! 0) {Logger::error(open rtsp url:{} faile, rtsp_url);// std::this_thread::sleep_for(std::chrono::milliseconds(500));usleep(100000);} else {online true;break;}}av_dict_free(format_options); // 释放 format_optionsif (!online) {return false;}Logger::info(open rtsp url:{} for wav success, rtsp_url);// 查找音频流int audio_stream_index -1;if (avformat_find_stream_info(format_ctx, NULL) 0) {Logger::info(can not avformat_find_stream_info url:{}, rtsp_url);return false;}AVCodec *codec NULL;audio_stream_index av_find_best_stream(format_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, codec, 0);std::cout codec name : codec-name std::endl;std::cout codec long_name : codec-long_name std::endl;std::cout codec AVMediaType : (int)codec-type std::endl;std::cout codec AVCodecID : (int)codec-id std::endl;if (audio_stream_index 0 || codec NULL) {Logger::info(can not find sound stream rtsp url:{}, rtsp_url);return false;}Logger::info(find sound stream success index:{}, audio_stream_index);av_dump_format(format_ctx, 0, rtsp_url.c_str(), 0);bool had_audio_code true;SwrContext *swr_ctx NULL;AVCodecContext *codec_ctx avcodec_alloc_context3(codec);if (format_ctx-streams[audio_stream_index]-codecpar) {Logger::info(avcodec_alloc_context3 success channels{}, codec_ctx-channels);Logger::info(avcodec_alloc_context3 success sample_rate{}, codec_ctx-sample_rate);// std::cout had codecpar inf std::endl;// printf(had codecpar inf\n);avcodec_parameters_to_context(codec_ctx, format_ctx-streams[audio_stream_index]-codecpar);if (avcodec_open2(codec_ctx, codec, NULL) 0) {Logger::info(avcodec_open2 error rtsp url:{}, rtsp_url);return false;}Logger::info(avcodec_open2 success channels{}, codec_ctx-channels);Logger::info(avcodec_open2 success sample_rate{}, codec_ctx-sample_rate);// 创建重采样上下文swr_ctx swr_alloc_set_opts(NULL, NUM_CHANNELS, AV_SAMPLE_FMT_S16, SAMPLE_RATE, codec_ctx-channels,codec_ctx-sample_fmt, codec_ctx-sample_rate, 0, NULL);Logger::info(swr_alloc_set_opts success);if (!swr_ctx || swr_init(swr_ctx) 0) {// Logger::info(swr_init error rtsp url:{}, rtsp_url);return false;}} else {printf(cdecpar is nullodecpar is nullodecpar is nullodecpar is null\n);std::cout codecpar is null std::endl;had_audio_code false;}// 创建输出 WAV 文件std::ofstream wav_file(file_path.c_str(), std::ios::binary);if (!wav_file) {// Logger::info(fopen local_path save wav failed path:{}, file_path);return false;}// Logger::info(open wav_file success);// 写入 WAV 文件头WAVHeader wav_header;unsigned int file_size sizeof(wav_header);// Logger::info(wav_header size:{}, file_size);wav_file.write((const char *)wav_header, file_size);time_t start_time time(NULL);AVPacket packet;int ret 0;int count 1000;while (true) {if (ret av_read_frame(format_ctx, packet) 0) {// Logger::info(av_read_frame failed: {}, ret);break;}time_t current_time time(NULL);time_t duration current_time - start_time;if (duration 60) {// Logger::info(save sound end by 20 s time);break;}if (packet.stream_index audio_stream_index) {if (!had_audio_code) {wav_file.write((char *)packet.data, packet.size);std::cout write sws data codecpar inf insfsjfjaslkjfas std::endl;printf( wav_file.write((char *)packet.data, packet.size);\n);continue;}AVFrame *frame av_frame_alloc();if (avcodec_send_packet(codec_ctx, packet) 0 avcodec_receive_frame(codec_ctx, frame) 0) {uint8_t *out_buffer[NUM_CHANNELS];int out_samples 0;int out_size 0;for (int i 0; i NUM_CHANNELS; i) {out_buffer[i] (uint8_t *)malloc(frame-nb_samples * 2 * sizeof(uint8_t));}out_samples swr_convert(swr_ctx, out_buffer, frame-nb_samples, (const uint8_t **)frame-data,frame-nb_samples);out_size out_samples * NUM_CHANNELS * 2;wav_file.write(reinterpret_castchar *(out_buffer[0]), out_size);// std::cout write sws data codecpar inf std::endl;// printf( wav_file.write(reinterpret_castchar *(out_buffer[0]), out_siz22;\n);for (int i 0; i NUM_CHANNELS; i) {free(out_buffer[i]);}}av_frame_free(frame);}av_packet_unref(packet);}// 更新 WAV 文件头中的数据大小uint32_t subchunk2Size static_castunsigned int(wav_file.tellp()) - 44;uint32_t chunkSize subchunk2Size 36;wav_file.seekp(4, std::ios::beg);wav_file.write(reinterpret_castchar *(chunkSize), 4);wav_file.seekp(40, std::ios::beg);wav_file.write(reinterpret_castchar *(subchunk2Size), 4);// 关闭文件wav_file.close();// 释放资源avcodec_close(codec_ctx);avcodec_free_context(codec_ctx);avformat_close_input(format_ctx);swr_free(swr_ctx);// Logger::info(save local_path wav success path:{}, file_path);return true;
}
wav格式的数据头文件
struct WAVHeader {char chunkID[4] {R, I, F, F};uint32_t chunkSize 0;char format[4] {W, A, V, E};char subchunk1ID[4] {f, m, t, };uint32_t subchunk1Size 16;uint16_t audioFormat 1;uint16_t numChannels NUM_CHANNELS;uint32_t sampleRate SAMPLE_RATE;uint32_t byteRate SAMPLE_RATE * NUM_CHANNELS * 16 / 8;uint16_t blockAlign 4;uint16_t bitsPerSample 16;char subchunk2ID[4] {d, a, t, a};uint32_t subchunk2Size 4;
};
最后就是wav注意的地方一共是两个值
chunkSize 和subchunk2Size
// 更新 WAV 文件头中的数据大小
也就是说subchunk2Size是出去wav文件头部数据意外的数据长度。
即文件总长度减去头部长度44个字节。
chunkSizesubchunk2Size36
具体为什么可以查看wav格式的说明。