上一篇博客介绍了如何添加一个自定义的处理滤镜。
src滤镜和处理滤镜的区别就是src滤镜没有输入,通过接口直接获取AVFrame 然后输出ff_filter_frame
具体看一个实现
AVFilter ff_avsrc_lottie = {
.name = "lottie",// 滤镜名
.description = NULL_IF_CONFIG_SMALL("Read from a lottie source."),
.priv_size = sizeof(LottieContext),// 滤镜上下文,保存参数
.priv_class = &lottie_class,
.init = lottie_common_init, //初始化
.uninit = lottie_uninit,
.query_formats = lottie_query_formats,//支持的格式
.inputs = NULL,
.outputs = NULL,
.flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS,
.process_command = process_command //命令处理
};
初始化的时候,先注册这个新的src滤镜
LottieContext *lottie = ctx->priv;
if (!lottie->file_name) {
av_log(ctx, AV_LOG_ERROR, "No filename provided!\n");
return AVERROR(EINVAL);
}
av_register_all();
lottie->lt = alloc_lottie_handle(lottie->file_name);
if(lottie->lt == NULL)
{
av_log(ctx, AV_LOG_ERROR,
"alloc_lottie_handle failed.\n");
return AVERROR_PATCHWELCOME;
}
// Try to find the lottie format (container)
lottie->frame_buf = (uint8_t*)av_malloc(MAX_FRAME_SIZE);
if(lottie->frame_buf == NULL)
{
av_log(ctx, AV_LOG_ERROR, "av_malloc failed!\n");
return AVERROR(EINVAL);
}
lottie->fill_buf = (uint8_t*)av_malloc(MAX_FRAME_SIZE);
if(lottie->fill_buf == NULL)
{
av_log(ctx, AV_LOG_ERROR, "av_malloc failed!\n");
return AVERROR(EINVAL);
}
lottie->total_frames = lottie_get_totalframes(lottie->lt);
AVFilterPad pad = { 0 };
pad.type = AVMEDIA_TYPE_VIDEO;
pad.name = av_strdup("out0");
if (!pad.name)
return AVERROR(ENOMEM);
pad.config_props = lottie_config_output_props;
pad.request_frame = lottie_request_frame;
ff_insert_outpad(ctx, 0, &pad);// 插入滤镜相关信息,包括入口函数lottie_request_frame
static int lottie_request_frame(AVFilterLink *outlink)
{ AVFrame *frm = av_frame_alloc();
ff_filter_frame(outlink,frm);
}
具体实现还有不懂得可以加qq交流