gpt4 book ai didi

android - 在 Android NDK 中使用 Libavfilter 库实现多输入过滤器图

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:40:29 25 4
gpt4 key购买 nike

我正在尝试为 Android 应用程序使用具有多个输入源的 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]; [视频_1] 比例=256x256 [tmp_1]; [base][tmp_1] overlay=0:0 [out]

在调用 avfilter_graph_config 后调用中断并出现警告:输出垫“默认”,缓冲区的过滤器实例“背景”类型视频未连接到任何目的地和错误无效参数

我做错了什么?

编辑:我发现了两个问题:

  1. 看起来 avfilter_graph_parse_ptr 的描述有点模糊。 ouputs 参数表示图的当前输出列表,在我的例子中是 graphInputs 变量,因为这些是 buffer 过滤器。 inputs 参数表示图的当前输入列表,在本例中为 graphOutput 变量,因为它表示 buffersink 过滤器。

  2. 我使用 scale 过滤器和单个输入进行了一些测试。看来avfilter_graph_parse_ptr需要的AVFilterInOut结构的名称需要在in。我尝试过不同的版本:in_1in_link_1。它们都不起作用,我也找不到与此相关的任何文档。

所以问题依然存在。如何实现具有多个输入的过滤器图?

最佳答案

我找到了解决问题的简单方法。这涉及更换 avfilter_graph_parse_ptravfilter_graph_parse2并添加 bufferbuffersink过滤到 filters avfilter_graph_parse2 的参数.

因此,在您有一张背景图片和一个输入视频的简单情况下,filters 的值参数应如下所示:

buffer=video_size=1024x768:pix_fmt=2:time_base=1/25:pixel_aspect=3937/3937 [in_1]; buffer=video_size=1920x1080:pix_fmt=0:time_base=1/180000:pixel_aspect=0/1 [in_2]; [in_1] [in_2] overlay=0:0 [result]; [result] buffersink

avfilter_graph_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;
}

关于android - 在 Android NDK 中使用 Libavfilter 库实现多输入过滤器图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22414753/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com