当前位置: 主页 > 图像 >

FFmpeg filter处理流程(cropdetect)

时间:2021-10-15  作者:haden   点击:
【摘要】FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。提供了模板接口,可

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。

提供了模板接口,可以方便调用自己的方法快速实现滤镜,并提供了丰富的现成例子。

详细说明在https://github.com/FFmpeg/FFmpeg/blob/master/doc/writing_filters.txt

调用说明

首先说明一下,FFmpeg对图像滤镜以 vf_ 为前缀,音频特效以 af_ 为前缀。
libavfilter\allfilters.c文件内,声明了所有滤镜/特效的配置。通过avfilter_get_by_name(const char *name)函数可以拿到对应的滤镜配置。

然后通过下面的函数构建、初始化:

int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,
                                 const char *name, const char *args, void *opaque,
                                 AVFilterGraph *graph_ctx)

所有滤镜/特效都要申明在libavfilter/avfilter.h

调用流程

在文档中已经做了详细介绍。这里以 cropdetect 功能为例。

cropdetect 可以检测图像四周黑边,然后返回边框参数,方便后续进行裁剪。滤镜实现文件是libavfilter\vf_cropdetect.c

static const AVFilterPad avfilter_vf_cropdetect_inputs[] = {
    {
        .name         = "default",
        .type         = AVMEDIA_TYPE_VIDEO,
        .config_props = config_input,
        .filter_frame = filter_frame,
    },
};

static const AVFilterPad avfilter_vf_cropdetect_outputs[] = {
    {
        .name = "default",
        .type = AVMEDIA_TYPE_VIDEO
    },
};

const AVFilter ff_vf_cropdetect = {
    .name          = "cropdetect",
    .description   = NULL_IF_CONFIG_SMALL("Auto-detect crop size."),
    .priv_size     = sizeof(CropDetectContext),
    .priv_class    = &cropdetect_class,
    .init          = init,
    FILTER_INPUTS(avfilter_vf_cropdetect_inputs),
    FILTER_OUTPUTS(avfilter_vf_cropdetect_outputs),
    FILTER_PIXFMTS_ARRAY(pix_fmts),
    .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
};

init()

根据文档,首先会调用init()函数。这里会完成最终的初始化, buffer 申请和预计算等工作。注意,这时 local context 已经得到了用户的初始化配置,但是并不知道输入的数据类型,所以这个函数通常用来清洗数据。

uninit()

释放所有的申请的 buffer。
cropdetect并没有实现。

query_formats()

通常这个函数跟在init()函数后面,用于格式协商。通常在这里指定输入输出的像素格式(灰度/rgb32/yuv4:2:0)。所有的像素格式定义在libavutil/pixfmt.h
cropdetect并没有实现。

filter_frame()

这个是等待开始的回调函数,在这里处理收到的图像帧。通过下面函数获取输入链接

static int filter_frame(AVFilterLink *inlink, AVFrame *in) { ... }

可以获取滤镜文本:

AVFilterContext *ctx = inlink->dst;

获取内部状态上下文:

FoobarContext *foobar = ctx->priv;

图像处理后发往的输出链接:

AVFilterLink *outlink = ctx->outputs[0];
顶一下
(0)
0%
踩一下
(0)
0%
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
验证码: 点击我更换图片