FFMpeg音频混合,背景音(七):fileter音频混合存入缓存队列

//FFMpeg版本:3.3.1
#include<iostream> #include<windows.h> using namespace std; //用到的C的头文件 extern "C" { #include<libavcodec/avcodec.h> #include<libavfilter/avfilter.h> #include<libavfilter/buffersink.h> #include<libavfilter/buffersrc.h> #include<libavfilter/avfiltergraph.h> #include<libavformat/avformat.h> #include<libavutil/avutil.h> #include<libavutil/fifo.h> #include<libavutil/audio_fifo.h> #include<libavdevice/avdevice.h> } //对用到的预编译 #pragma comment(lib, "avcodec.lib") #pragma comment(lib, "avfilter.lib") #pragma comment(lib, "avutil.lib") #pragma comment(lib, "avformat.lib") #pragma comment(lib, "swscale.lib") //第一个音频文件 AVFormatContext* ctx3 = NULL; int ctx3index = -1; AVCodecContext* codec_ctx_three = NULL; AVAudioFifo* ctx3buff = NULL; //第二个音频文件 AVFormatContext* ctx4 = NULL; int ctx4index = -1; AVCodecContext* codec_ctx_four = NULL; AVAudioFifo* ctx4buff = NULL; AVFilterGraph* filter_graph = NULL; AVFilterContext* filter_three_ctx = NULL; AVFilterContext* filter_four_ctx = NULL; AVFilterContext* filter_out_ctx = NULL; //打开输出的文件流IO //输出文件初始化 AVCodecContext* acode = NULL; AVFormatContext* out = NULL; bool status = false; //打开第一个音频文件 int openMp3Codec3(char* filename) { int ret = 0; ret = avformat_open_input(&ctx3, filename, NULL, NULL); if (ret < 0) { cout << "avformat_open_input ctx3 faaild" << endl; return -1; } ret = avformat_find_stream_info(ctx3, NULL); if (ret < 0) { cout << "avformat_find_stream_info ctx3 faaild" << endl; return -1; } for (int i = 0; i < ctx3->nb_streams; i++) { if (ctx3->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { ctx3index = i; break; } } if (ctx3index < 0) { cout << "stream not find ctx3 failed" << endl; return -1; } AVCodec* codec = avcodec_find_decoder(ctx3->streams[ctx3index]->codecpar ->codec_id); if (!codec) { cout << "avcodec_find_decoder ctx3 failed" << endl; return -1; } //根据找到的解码器创造上下文 codec_ctx_three = avcodec_alloc_context3(codec); avcodec_parameters_to_context(codec_ctx_three, ctx3->streams[ctx3index]->codecpar); avcodec_open2(codec_ctx_three, codec, NULL); if (ret < 0) { cout << "avcodec_open2 ctx3 failed" << endl; return -1; } //第四个参数设置为0,表示输入的音频数据,如果为1的话,就是输出的音频数据 av_dump_format(ctx3, ctx3index, filename,0); return ret; } //打开第二个音频文件 int openMp3Codec4(char* filename) { int ret = 0; ret = avformat_open_input(&ctx4, filename, NULL, NULL); ret = avformat_find_stream_info(ctx4, NULL); for (int i = 0; i < ctx4->nb_streams; i++) { if (ctx4->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { ctx4index = i; break; } } AVCodec* codec = avcodec_find_decoder(ctx4->streams[ctx4index]->codecpar->codec_id); //根据找到的解码器创造上下文 codec_ctx_four = avcodec_alloc_context3(codec); avcodec_parameters_to_context(codec_ctx_four, ctx4->streams[ctx4index]->codecpar); avcodec_open2(codec_ctx_four, codec, NULL); //第四个参数设置为0,表示输入的音频数据,如果为1的话,就是输出的音频数据 av_dump_format(ctx4, ctx4index, filename, 0); return ret; } int openFileIO(char* filename) { int ret = 0; AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_MP3); if (!codec) { cout << "avcodec_find_encoder faild" << endl; return -1; } acode = avcodec_alloc_context3(codec); if (!acode) { cout << "avcodec_alloc_context3 out faild" << endl; return -1; } acode->sample_rate = 44100; acode->bit_rate = 320000; acode->time_base.num = 1; acode->time_base.den = 44100; acode->channels = 2; acode->channel_layout = AV_CH_LAYOUT_STEREO; acode->sample_fmt = AV_SAMPLE_FMT_S32P; acode->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; ret = avcodec_open2(acode, codec, NULL); if (ret < 0) { cout << "avcodec_open2 out faild" << endl; return -1; } ret = avformat_alloc_output_context2(&out, NULL, NULL, filename); if (ret < 0) { cout << "avformat_alloc_output_context2 out faild" << endl; return -1; } AVStream* audio_stream = avformat_new_stream(out, NULL); audio_stream->codecpar->codec_tag = 0; avcodec_parameters_from_context(audio_stream->codecpar, acode); ret = avio_open(&out->pb, filename, AVIO_FLAG_WRITE); if (ret < 0) { cout << "avio_open out faild" << endl; return -1; } avformat_write_header(out, NULL); ctx3buff = av_audio_fifo_alloc(codec_ctx_three->sample_fmt, ctx3->streams[ctx3index]->codecpar->channels, 30 * codec_ctx_three->frame_size ); ctx4buff = av_audio_fifo_alloc(codec_ctx_four->sample_fmt, ctx4->streams[ctx4index]->codecpar->channels, 30 * codec_ctx_four->frame_size ); return ret; } int InitFilter(const char* filter_desc) { int ret = 0; const char* mp3_three = "in0"; const char* mp3_four = "in1"; //用于装载音频参数 char args_three[512]; char args_four[512]; //寻找输入输出的过滤器 AVFilter * filter_three = avfilter_get_by_name("abuffer"); AVFilter* filter_four = avfilter_get_by_name("abuffer"); AVFilter* filter_out = avfilter_get_by_name("abuffersink"); if (!filter_three || !filter_four || !filter_out) { cout << " avfilter_get_by_name faild" << endl; return -1; } //AVFilterGraph,分配输入输出流 AVFilterInOut* filter_three_inout = avfilter_inout_alloc(); AVFilterInOut* filter_four_inout = avfilter_inout_alloc(); AVFilterInOut* filter_out_inout = avfilter_inout_alloc(); //分配一个过滤图 filter_graph = avfilter_graph_alloc(); if (!filter_graph) { cout << " avfilter_inout_alloc faild" << endl; return -1; } sprintf_s(args_three, sizeof(args_three), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%I64x", codec_ctx_three->time_base.num, codec_ctx_three->time_base.den, ctx3->streams[ctx3index]->codecpar->sample_rate, av_get_sample_fmt_name(codec_ctx_three->sample_fmt), ctx3->streams[ctx3index]->codecpar->channel_layout ); sprintf_s(args_four, sizeof(args_four), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%I64x", codec_ctx_four->time_base.num, codec_ctx_four->time_base.den, ctx4->streams[ctx4index]->codecpar->sample_rate, av_get_sample_fmt_name(codec_ctx_four->sample_fmt), ctx4->streams[ctx4index]->codecpar->channel_layout ); //AVFilterContext* filter_three_ctx = NULL; //AVFilterContext* filter_four_ctx = NULL; //AVFilterContext* filter_out_ctx = NULL; ret = avfilter_graph_create_filter(&filter_three_ctx, filter_three, mp3_three, args_three, NULL, filter_graph); if (ret < 0) { cout << "avfilter_graph_create_filter faild" << endl; return -1; } ret = avfilter_graph_create_filter(&filter_four_ctx, filter_four, mp3_four, args_four, NULL, filter_graph); if (ret < 0) { cout << "avfilter_graph_create_filter faild" << endl; return -1; } //初始化AVFilterContext,并将其添加到过滤图,输出的过滤图初始化 ret = avfilter_graph_create_filter(&filter_out_ctx, filter_out, "out", NULL, NULL, filter_graph); if (ret < 0) { cout << "avfilter_graph_create_filter faild" << endl; return -1; } //输出的采样率,样本格式,通道样本布局 ret = av_opt_set_bin(filter_out_ctx, "sample_rates", (uint8_t *)&acode->sample_rate, sizeof(acode->sample_rate), AV_OPT_SEARCH_CHILDREN); if (ret < 0) { cout << "av_opt_set_bin faild" << endl; return -1; } ret = av_opt_set_bin(filter_out_ctx, "channel_layouts", (uint8_t*)&acode->channel_layout, sizeof(acode->channel_layout), AV_OPT_SEARCH_CHILDREN); if (ret < 0) { cout << "av_opt_set_bin faild" << endl; return -1; } ret = av_opt_set_bin(filter_out_ctx, "sample_fmts", (uint8_t*)&acode->sample_fmt, sizeof(acode->sample_fmt), AV_OPT_SEARCH_CHILDREN); if (ret < 0) { cout << "av_opt_set_bin faild" << endl; return -1; } //AVFilterGraph分配输入输出流 filter_three_inout->name = av_strdup(mp3_three); filter_three_inout->filter_ctx = filter_three_ctx; filter_three_inout->pad_idx = 0; filter_three_inout->next = filter_four_inout; filter_four_inout->name = av_strdup(mp3_four); filter_four_inout->filter_ctx = filter_four_ctx; filter_four_inout->pad_idx = 0; filter_four_inout->next = NULL; filter_out_inout->name = av_strdup("out"); filter_out_inout->filter_ctx = filter_out_ctx; filter_out_inout->pad_idx = 0; filter_out_inout->next = NULL; AVFilterInOut* filter_outputs[2]; filter_outputs[0] = filter_three_inout; filter_outputs[1] = filter_four_inout; //将描述的过滤图添加到对象中 ret = avfilter_graph_parse_ptr(filter_graph, filter_desc, &filter_out_inout, filter_outputs, NULL); if (ret < 0) { cout << "avfilter_graph_parse_ptr faild" << endl; return -1; } //检查过滤图所有链接格式 ret = avfilter_graph_config(filter_graph, NULL); if (ret < 0) { cout << " avfilter_graph_config faild" << endl; return -1; } char *infos = avfilter_graph_dump(filter_graph, NULL); printf("%s ", infos); return ret; } DWORD WINAPI three_demux(LPVOID IpParam) { int ret = 0; AVPacket packet; av_init_packet(&packet); AVFrame* pFrame = av_frame_alloc(); while (status) { packet.data = NULL; packet.size = 0; //读取数据 ret = av_read_frame(ctx3, &packet); if (ret < 0) { av_packet_unref(&packet); break; } cout << packet.size << endl; //将数据发送到解码线程 ret = avcodec_send_packet(codec_ctx_three, &packet); if (ret < 0) { cout << "avcodec_send_packet faild" << endl; break; } //接受解码后的数据 ret = avcodec_receive_frame(codec_ctx_three, pFrame); int three_size = av_audio_fifo_space(ctx3buff); while (three_size < pFrame->nb_samples && !status) { Sleep(10); three_size = av_audio_fifo_space(ctx3buff); cout<< "ctx3buff full wait" << endl; } //判断缓存队列中可供写入大小 if (three_size >= pFrame->nb_samples) { av_audio_fifo_write(ctx3buff, (void**)pFrame->data, pFrame->nb_samples); } av_packet_unref(&packet); } av_frame_free(&pFrame); return ret; } DWORD WINAPI four_demux(LPVOID IpParam) { int ret = 0; AVPacket packet; AVFrame* pFrame = av_frame_alloc(); av_init_packet(&packet); while (status) { packet.data = NULL; packet.size = 0; ret = av_read_frame(ctx4, &packet); if (ret < 0) { av_packet_unref(&packet); break; } cout << packet.size << endl; ret = avcodec_send_packet(codec_ctx_four, &packet); if (ret < 0) { cout << "avcodec_send_packet faild" << endl; break; } ret = avcodec_receive_frame(codec_ctx_four, pFrame); int four_size = av_audio_fifo_space(ctx4buff); while (four_size < pFrame->nb_samples && !status) { Sleep(10); four_size = av_audio_fifo_space(ctx4buff); cout << "ctx3buff full wait" << endl; } if (four_size >= pFrame->nb_samples) { av_audio_fifo_write(ctx4buff, (void**)pFrame->data, pFrame->nb_samples); } av_packet_unref(&packet); } av_frame_free(&pFrame); return ret; } int main() { //注册 av_register_all(); avcodec_register_all(); avfilter_register_all(); int ret = 0; char input3[] = "3.mp3"; char input4[] = "4.mp3"; ret = openMp3Codec3(input3); if (ret < 0) { cout << "openMp3Codec3 faild" << endl; return -1; } ret = openMp3Codec4(input4); if (ret < 0) { cout << "openMp3Codec4 faild" << endl; return -1; } char outfile[] = "out.mp3"; ret = openFileIO(outfile); if (ret < 0) { cout << "openFileIO faild" << endl; return -1; } //过滤器配置 const char* filter_desc = "[in0][in1]amix=inputs=2[out]"; ret = InitFilter(filter_desc); if (ret < 0) { cout << "InitFilter faild" << endl; return -1; } status = true; CreateThread(NULL, 0, three_demux, 0, 0, NULL); CreateThread(NULL, 0, four_demux, 0, 0, NULL); while (status) { } return 0; }
原文地址:https://www.cnblogs.com/zhangxianrong/p/13879051.html