overlay
过滤器和多个输入源。基本上,我想在静态图像上叠加多个视频源。我查看了 ffmpeg 提供的示例,并根据它实现了我的代码,但是似乎不如预期地工作。
在 ffmpeg 过滤示例中,似乎只有一个视频输入。我必须处理多个视频输入,但我不确定我的解决方案是否正确。我已经尝试找到其他示例,但似乎这是唯一的一个。
这是我的代码:
AVFilterContext **inputContexts;
AVFilterContext *outputContext;
AVFilterGraph *graph;
int initFilters(AVFrame *bgFrame, int inputCount, AVCodecContext **codecContexts, char *filters)
{
int i;
int returnCode;
char args[512];
char name[9];
AVFilterInOut **graphInputs = NULL;
AVFilterInOut *graphOutput = NULL;
AVFilter *bufferSrc = avfilter_get_by_name("buffer");
AVFilter *bufferSink = avfilter_get_by_name("buffersink");
graph = avfilter_graph_alloc();
if(graph == NULL)
return -1;
//allocate inputs
graphInputs = av_calloc(inputCount + 1, sizeof(AVFilterInOut *));
for(i = 0; i <= inputCount; i++)
{
graphInputs[i] = avfilter_inout_alloc();
if(graphInputs[i] == NULL)
return -1;
}
//allocate input contexts
inputContexts = av_calloc(inputCount + 1, sizeof(AVFilterContext *));
//first is the background
snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=1/1:pixel_aspect=0", bgFrame->width, bgFrame->height, bgFrame->format);
returnCode = avfilter_graph_create_filter(&inputContexts[0], bufferSrc, "background", args, NULL, graph);
if(returnCode < 0)
return returnCode;
graphInputs[0]->filter_ctx = inputContexts[0];
graphInputs[0]->name = av_strdup("background");
graphInputs[0]->next = graphInputs[1];
//allocate the rest
for(i = 1; i <= inputCount; i++)
{
AVCodecContext *codecCtx = codecContexts[i - 1];
snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
codecCtx->width, codecCtx->height, codecCtx->pix_fmt,
codecCtx->time_base.num, codecCtx->time_base.den,
codecCtx->sample_aspect_ratio.num, codecCtx->sample_aspect_ratio.den);
snprintf(name, sizeof(name), "video_%d", i);
returnCode = avfilter_graph_create_filter(&inputContexts[i], bufferSrc, name, args, NULL, graph);
if(returnCode < 0)
return returnCode;
graphInputs[i]->filter_ctx = inputContexts[i];
graphInputs[i]->name = av_strdup(name);
graphInputs[i]->pad_idx = 0;
if(i < inputCount)
{
graphInputs[i]->next = graphInputs[i + 1];
}
else
{
graphInputs[i]->next = NULL;
}
}
//allocate outputs
graphOutput = avfilter_inout_alloc();
returnCode = avfilter_graph_create_filter(&outputContext, bufferSink, "out", NULL, NULL, graph);
if(returnCode < 0)
return returnCode;
graphOutput->filter_ctx = outputContext;
graphOutput->name = av_strdup("out");
graphOutput->next = NULL;
graphOutput->pad_idx = 0;
returnCode = avfilter_graph_parse_ptr(graph, filters, graphInputs, &graphOutput, NULL);
if(returnCode < 0)
return returnCode;
returnCode = avfilter_graph_config(graph, NULL);
return returnCode;
return 0;
}
该函数的
filters
参数被传递给avfilter_graph_parse_ptr
,它看起来像这样:[background] scale=512x512 [base]; [video_1] scale=256x256 [tmp_1]; [base][tmp_1] overlay=0:0 [out]
。在调用avfilter_graph_config
后,会出现警告:Output pad "default" with type video of the filter instance "background" of buffer not connected to any destination
和错误Invalid argument
。请问我做错了什么?编辑:我发现了两个问题:
似乎
avfilter_graph_parse_ptr
的描述有点模糊。参数ouputs
表示图形的当前输出列表,在我的情况下,这是graphInputs
变量,因为这些是buffer
过滤器的输出。参数inputs
表示图形的当前输入列表,在这种情况下,这是graphOutput
变量,因为它代表buffersink
过滤器的输入。我尝试使用
scale
过滤器和单个输入进行了一些测试。似乎avfilter_graph_parse_ptr
所需的AVFilterInOut
结构的名称需要为in
。我尝试了不同的版本:in_1
,in_link_1
。它们都不起作用,我也没有找到任何相关的文档。
avfilter_graph_parse2(...); avfilter_graph_config(graph, NULL)
时,您将看到过滤器形成了一个链接列表。可以通过avfilter_graph_get_filter(graph, "Parsed_buffer_0");
和avfilter_graph_get_filter(graph, "Parsed_buffer_1")
获取in_1
和in_2
过滤器上下文。您最好调试程序并检查图形的filters
字段,它是从解析字符串构建的链接列表。 - pingsoli