ffmpeg filter编写

2024-01-08 21:57:46 浏览数 (2)

简介

ffmpeg中的libavfilter提供了一整套基于filter的机制,filter类似于插件, 可以快速组装所需效果。

Filter一般有以下几种分类:

source filter(只有输出)、audio filter、video filter、Multimedia filter、sink filter(只有输入)

除了source filter和sink filter之外,其余filter至少都有一个输入一个输出。

filter定义(ffmpeg4.0以上)

代码语言:C复制
AVFilter ff_vf_mag = {
    .name        = "mag",
    .description = NULL_IF_CONFIG_SMALL("mag Force constant framerate."),
    .init        = init,
    .uninit      = uninit,
    .priv_size   = sizeof(MagContext),
    .priv_class  = &mag_class,
    .activate    = activate,
    .inputs      = avfilter_vf_mag_inputs,
    .outputs     = avfilter_vf_mag_outputs,
}
代码语言:C复制
typedef struct MagContext{
	const AVClass * class; 
	... 
}

如上图所示,第一部分定义了一个新的filter,filter的名字为mag,可以通过-vf mag=参数来使用这个filter

description: filter描述

init: filter初始化调用函数

uninit:filter处理完毕退出时调用函数

priv_class: 保存这个filter的私有数据, 声明AVOptions.

priv_size: 私有数据size

activate: 激活函数,替代filter_frame和request_frame,可检查inlinks和outlinks, 处理图像

inputs outputs:filter输入输出的处理函数,可以为空

把这些函数和类定义都实现,就可以使用这个filter

2、inputs 和 outputs

代码语言:C复制
static const AVFilterPad avfilter_vf_mag_inputs[] = {
    {
        .name         = "default",
        .type         = AVMEDIA_TYPE_VIDEO,
        .config_props = config_input,
    },
    { NULL }
};


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

AVMEDIA_TYPE_VIDEO 表示输入或输出为视频流

config_input,根据视频输入进行一些起始操作

config_props, 在输出前,对于处理结果和输出格式做一个协调,输出正确格式的数据

3、类定义

代码语言:C复制
#define AVFILTER_DEFINE_CLASS(fname)            
    static const AVClass fname##_class = {      
        .class_name = #fname,                   
        .item_name  = av_default_item_name,     
        .option     = fname##_options,          
        .version    = LIBAVUTIL_VERSION_INT,    
        .category   = AV_CLASS_CATEGORY_FILTER, 
    }
	AVFILTER_DEFINE_CLASS(mag);

这部分会定义一个唯一的class,可以在AVFilter中引用

这个宏扩展开是这样的:

代码语言:C复制
 static const AVClass mag_class = {      
        .class_name = mag,                   
        .item_name  = av_default_item_name,     
        .option     = mag_options,          
        .version    = LIBAVUTIL_VERSION_INT,    
        .category   = AV_CLASS_CATEGORY_FILTER, 
    }

下面就是对应的OPTION, 可以对入参进行定义, 比如mag这个filter定义了入参source和start_time,可以-vf mag=source=xx:start_time=xx的方式来调用, 它们的值也会存储到MagContext类的对应位置

代码语言:C复制
#define OFFSET(x) offsetof(MagContext, x)
#define V AV_OPT_FLAG_VIDEO_PARAM
#define F AV_OPT_FLAG_FILTERING_PARAM
static const AVOption mag_options[] = {
    { "source", "set model source, such as source=mag(ours)|ml(lab)|nv ", OFFSET(source), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, V|F},
    { "start_time", "Assume the first PTS should be this value.", OFFSET(start_time), AV_OPT_TYPE_DOUBLE, { .dbl = DBL_MAX}, -DBL_MAX, DBL_MAX, V|F },

};

0 人点赞