基于vs2017 vc++ ffmpeg4.0.2下测试
ffmpeg 环境配置请百度(vs2017 ffmpeg )
主要是先将音频avframe采集到队列或链表里,再通过
av_buffersrc_add_frame添加多帧取出就是混音的贴出filter初始化的
字符串[in0][in1]amix=inputs=2[out]
其他的像写入空声音啥的请进群交流(讨论群261074724)或查看前面的教程
int InitFilter(const char* filter_desc, VideoState1 *pVideo)
{
char args[512], pad_name[20];
int ret = 0, anum = 2;
/*static const enum AVSampleFormat out_sample_fmts[] = { AV_SAMPLE_FMT_S16 ,AV_SAMPLE_FMT_NONE };
static const uint8_t out_channel_layouts[] = { AV_CH_LAYOUT_STEREO, -1 };
static const uint8_t out_sample_rates[] = { 44100 };*/
const AVFilter** buffersrc = (const AVFilter**)av_malloc(anum * sizeof(AVFilter**));
const AVFilter* buffersink = avfilter_get_by_name("abuffersink");
AVFilterInOut **outputs = (AVFilterInOut**)av_malloc(anum * sizeof(AVFilterInOut*));
AVFilterInOut* filter_input = avfilter_inout_alloc();
AVFilterGraph *_filter_graph = avfilter_graph_alloc();
for (int i = 0; i < anum; i++)
{
buffersrc[i] = avfilter_get_by_name("abuffer");
outputs[i] = avfilter_inout_alloc();
pVideo[i].filter_ctx_sink = NULL;
}
/* buffer video source: the decoded frames from the decoder will be inserted here. */
if (!buffersrc || !buffersink) {
av_log(NULL, AV_LOG_ERROR, "filtering source or sink element not found\n");
ret = AVERROR_UNKNOWN;
goto end;
}
for (int i = 0; i < anum; i++) {
snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%I64x",
pVideo[i].pInputFormatCtx->streams[pVideo[i].audioIndex]->time_base.num,
pVideo[i].pInputFormatCtx->streams[pVideo[i].audioIndex]->time_base.den,
pVideo[i].pInputFormatCtx->streams[pVideo[i].audioIndex]->codecpar->sample_rate,
av_get_sample_fmt_name((AVSampleFormat)pVideo[i].pInputFormatCtx->streams[pVideo[i].audioIndex]->codecpar->format),
pVideo[i].pInputFormatCtx->streams[pVideo[i].audioIndex]->codecpar->channel_layout);
snprintf(pad_name, sizeof(pad_name), "in%d", i + 1);
ret = avfilter_graph_create_filter(&pVideo[i].buffersrc_ctx, buffersrc[i], pad_name, args, NULL, _filter_graph);
if (ret < 0)
{
printf("Filter: failed to call avfilter_graph_create_filter -- src mic\n");
return -1;
}
}
ret = avfilter_graph_create_filter(&pVideo[0].filter_ctx_sink, buffersink, "out", NULL, NULL, _filter_graph);
if (ret < 0)
{
printf("Filter: failed to call avfilter_graph_create_filter -- sink\n");
return -1;
}
ret = av_opt_set_bin(pVideo[0].filter_ctx_sink, "sample_fmts", (uint8_t*)&pVideo[0].des_sampleFormat, sizeof(pVideo[0].des_sampleFormat), AV_OPT_SEARCH_CHILDREN);
if (ret < 0)
{
printf("Filter: failed to call av_opt_set_bin -- sample_fmts\n");
return -1;
}
ret = av_opt_set_bin(pVideo[0].filter_ctx_sink, "channel_layouts", (uint8_t*)&pVideo[0].des_channel_layout, sizeof(pVideo[0].des_channel_layout), AV_OPT_SEARCH_CHILDREN);
if (ret < 0)
{
printf("Filter: failed to call av_opt_set_bin -- channel_layouts\n");
return -1;
}
ret = av_opt_set_bin(pVideo[0].filter_ctx_sink, "sample_rates", (uint8_t*)&pVideo[0].des_samplerate, sizeof(pVideo[0].des_samplerate), AV_OPT_SEARCH_CHILDREN);
if (ret < 0)
{
printf("Filter: failed to call av_opt_set_bin -- sample_rates\n");
return -1;
}
for (int i = 0; i < anum; i++)
{
snprintf(pad_name, sizeof(pad_name), "in%d", i);
outputs[i]->name = av_strdup(pad_name);
outputs[i]->filter_ctx = pVideo[i ].buffersrc_ctx;
outputs[i]->pad_idx = 0;
if (i == anum - 1)
outputs[i]->next = NULL;
else
outputs[i]->next = outputs[i + 1];
}
filter_input->name = av_strdup("out");
filter_input->filter_ctx = pVideo[0].filter_ctx_sink;
filter_input->pad_idx = 0;
filter_input->next = NULL;
ret = avfilter_graph_parse_ptr(_filter_graph, filter_desc, &filter_input, outputs, NULL);
if (ret < 0)
{
printf("Filter: failed to call avfilter_graph_parse_ptr\n");
return -1;
}
ret = avfilter_graph_config(_filter_graph, NULL);
if (ret < 0)
{
printf("Filter: failed to call avfilter_graph_config\n");
return -1;
}
end:
avfilter_inout_free(&filter_input);
for (int i = 0; i < anum; i++) {
av_free(pVideo[i].buffersrc_ctx);
}
avfilter_inout_free(outputs);
//av_free(filter_outputs);
char* temp = avfilter_graph_dump(_filter_graph, NULL);
printf("%s\n", temp);
//Output: srate:44100Hz fmt:s16 chlayout:stereo
return 0;
}
采集的视频可以保存pcm 、aac、rmtp、或者用PortAudio播放都是可以的
(讨论群261074724)