在Android NDK中使用Libavfilter库实现多输入过滤器图
我正在尝试为Android应用程序使用带有多个输入源的在Android NDK中使用Libavfilter库实现多输入过滤器图,android,android-ndk,ffmpeg,Android,Android Ndk,Ffmpeg,我正在尝试为Android应用程序使用带有多个输入源的overlay过滤器。基本上,我想在静态图像上叠加多个视频源。 我已经查看了ffmpeg附带的示例,并在此基础上实现了我的代码,但事情似乎没有按预期进行 在ffmpeg过滤示例中,似乎只有一个视频输入。我必须处理多个视频输入,我不确定我的解决方案是否正确。我试图找到其他的例子,但似乎这是唯一的一个 这是我的密码: AVFilterContext**InputContext; AVFilterContext*输出上下文; AVFilterGra
overlay
过滤器。基本上,我想在静态图像上叠加多个视频源。
我已经查看了ffmpeg附带的示例,并在此基础上实现了我的代码,但事情似乎没有按预期进行
在ffmpeg过滤示例中,似乎只有一个视频输入。我必须处理多个视频输入,我不确定我的解决方案是否正确。我试图找到其他的例子,但似乎这是唯一的一个
这是我的密码:
AVFilterContext**InputContext;
AVFilterContext*输出上下文;
AVFilterGraph*图;
int initFilters(AVFrame*bgFrame,int inputCount,AVCodecContext**codeccontext,char*过滤器)
{
int i;
返回码;
char-args[512];
字符名[9];
AVFilterInOut**graphInputs=NULL;
AVFilterInOut*Graphhoutput=NULL;
AVFilter*bufferSrc=AVFilter_get_by_name(“buffer”);
AVFilter*bufferSink=AVFilter_get_by_name(“bufferSink”);
graph=avfilter_graph_alloc();
if(图==NULL)
返回-1;
//分配投入
graphInputs=av_calloc(inputCount+1,sizeof(AVFilterInOut*);
用于(i=0;i宽度,bgFrame->高度,bgFrame->格式);
returnCode=avfilter\u graph\u create\u filter(&inputContexts[0],bufferSrc,“background”,args,NULL,graph);
如果(返回代码<0)
返回代码;
graphInputs[0]->filter_ctx=inputContexts[0];
graphInputs[0]->name=av_strdup(“背景”);
graphInputs[0]->next=graphInputs[1];
//分配其余的
对于(i=1;i宽度,codecCtx->高度,codecCtx->pix_fmt,
codecCtx->time\u base.num,codecCtx->time\u base.den,
codecCtx->sample\u aspect\u ratio.num,codecCtx->sample\u aspect\u ratio.den);
snprintf(名称,sizeof(名称),“视频”,i);
returnCode=avfilter\u graph\u create\u filter(&inputContexts[i],bufferSrc,name,args,NULL,graph);
如果(返回代码<0)
返回代码;
graphInputs[i]>filter_ctx=inputContexts[i];
图形输入[i]->name=av_strdup(name);
图形输入[i]>pad_idx=0;
如果(i<输入计数)
{
graphInputs[i]>next=graphInputs[i+1];
}
其他的
{
graphInputs[i]>next=NULL;
}
}
//分配产出
graphhoutput=avfilter_inout_alloc();
returnCode=avfilter\u graph\u create\u filter(&outputContext,bufferSink,“out”,NULL,NULL,graph);
如果(返回代码<0)
返回代码;
graphhoutput->filter\u ctx=outputContext;
graphhoutput->name=av_strdup(“out”);
graphhoutput->next=NULL;
图形输出->pad_idx=0;
returnCode=avfilter\u graph\u parse\u ptr(graph、filters、graphInputs和graphOutput,NULL);
如果(返回代码<0)
返回代码;
returnCode=avfilter\u graph\u config(图形,NULL);
返回代码;
返回0;
}
函数的filters
参数被传递到avfilter\u graph\u parse\u ptr
,它可以如下所示:[background]scale=512x512[base];[video_1]比例=256x256[tmp_1];[base][tmp_1]overlay=0:0[out]
调用avfilter\u graph\u config
后,调用中断,并显示警告:
输出pad“default”,其中缓冲区的筛选器实例“background”的类型video未连接到任何目标
,并且错误参数无效
我做得不对的是什么
编辑:我发现了两个问题:
avfilter\u graph\u parse\u ptr
的描述有点模糊。outputs
参数表示图形的当前输出列表,在我的例子中,它是graphInputs
变量,因为这些是来自缓冲区的输出。inputs
参数表示图形当前输入的列表,在这种情况下,这是graphhoutput
变量,因为它表示buffersink
过滤器的输入
scale
过滤器和单个输入进行了一些测试。似乎avfilter\u graph\u parse\u ptr
所需的AVFilterInOut
结构的名称需要是in
。我尝试过不同的版本:in_1
,in_link_1
。它们都不起作用,我也没有找到任何与此相关的文档因此,问题仍然存在。如何实现具有多个输入的过滤图?我找到了一个简单的解决方案。 这涉及到用
avfilter\u graph\u parse2
替换avfilter\u graph\u parse2
并将buffer
和buffersink
过滤器添加到avfilter\u parse2
的过滤器
参数中
因此,在一个背景图像和一个输入视频的简单情况下,filters
参数的值应该如下所示:
buffer=video\u size=1024x768:pix\u fmt=2:time\u base=1/25:pixel\u aspect=3937/3937[in\u 1];缓冲区=视频大小=1920x1080:pix\u fmt=0:time\u base=1/180000:pixel\u aspect=0/1[英寸2];[in_1][in_2]叠加=0:0[结果];[结果]缓冲接收器
avfilter\u graph\u parse2将建立所有图形连接并初始化所有过滤器。输入缓冲区和输出缓冲区的过滤器上下文可以在末尾从图形本身检索。这些用于从过滤器图中添加/获取帧
代码的简化版本如下所示:
AVFilterContext **inputContexts;
AVFilterContext *outputContext;
AVFilterGraph *graph;
int initFilters(AVFrame *bgFrame, int inputCount, AVCodecContext **codecContexts)
{
int i;
int returnCode;
char filters[1024];
AVFilterInOut *gis = NULL;
AVFilterInOut *gos = NULL;
graph = avfilter_graph_alloc();
if(graph == NULL)
{
printf("Cannot allocate filter graph.");
return -1;
}
//build the filters string here
// ...
returnCode = avfilter_graph_parse2(graph, filters, &gis, &gos);
if(returnCode < 0)
{
cs_printAVError("Cannot parse graph.", returnCode);
return returnCode;
}
returnCode = avfilter_graph_config(graph, NULL);
if(returnCode < 0)
{
cs_printAVError("Cannot configure graph.", returnCode);
return returnCode;
}
//get the filter contexts from the graph here
return 0;
}
[0:v]pad=1008:734:144:0:black[pad];[pad][1:v]overlay=0:576[out]
AVFilterContext**InputContext;
AVFilterContext*输出上下文;
AVFilterGraph*图;
int initFilters(AVFrame*bgFrame,int inputCount,AVCodecContext**codeccontext)
{
int i;
返回码;
炭纤维
ffmpeg -i first.mp4 -i second.mp4 -filter_complex "[0:v]pad=1008:734:144:0:black[pad];[pad][1:v]overlay=0:576[out]" -map "[out]" -map 0:a output.mp4
filterGraph = avfilter_graph_alloc();
NULLC(filterGraph);
bufferSink = avfilter_get_by_name("buffersink");
NULLC(bufferSink);
filterInput = avfilter_inout_alloc();
AVBufferSinkParams* buffersinkParams = av_buffersink_params_alloc();
buffersinkParams->pixel_fmts = pixelFormats;
FFMPEGHRC(avfilter_graph_create_filter(&bufferSinkContext, bufferSink, "out", NULL, buffersinkParams, filterGraph));
av_free(buffersinkParams);
filterInput->name = av_strdup("out");
filterInput->filter_ctx = bufferSinkContext;
filterInput->pad_idx = 0;
filterInput->next = NULL;
filterOutputs = new AVFilterInOut*[inputFiles.size()];
ZeroMemory(filterOutputs, sizeof(AVFilterInOut*) * inputFiles.size());
bufferSourceContext = new AVFilterContext*[inputFiles.size()];
ZeroMemory(bufferSourceContext, sizeof(AVFilterContext*) * inputFiles.size());
for (i = inputFiles.size() - 1; i >= 0 ; i--)
{
snprintf(args, sizeof(args), "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
videoCodecContext[i]->width, videoCodecContext[i]->height, videoCodecContext[i]->pix_fmt, videoCodecContext[i]->time_base.num, videoCodecContext[i]->time_base.den, videoCodecContext[i]->sample_aspect_ratio.num, videoCodecContext[i]->sample_aspect_ratio.den);
filterOutputs[i] = avfilter_inout_alloc();
NULLC(filterOutputs[i]);
bufferSource = avfilter_get_by_name("buffer");
NULLC(bufferSource);
sprintf(args2, outputTemplate, i);
FFMPEGHRC(avfilter_graph_create_filter(&bufferSourceContext[i], bufferSource, "in", args, NULL, filterGraph));
filterOutputs[i]->name = av_strdup(args2);
filterOutputs[i]->filter_ctx = bufferSourceContext[i];
filterOutputs[i]->pad_idx = 0;
filterOutputs[i]->next = i < inputFiles.size() - 1 ? filterOutputs[i + 1] : NULL;
}
FFMPEGHRC(avfilter_graph_parse_ptr(filterGraph, description, &filterInput, filterOutputs, NULL));
FFMPEGHRC(avfilter_graph_config(filterGraph, NULL));