FFmpeg 已经内置了一百多种滤镜,可以对音视频实现很多特效处理。但是当我们想实现类似各短视频平台上的特殊效果时,FFmpeg 内置滤镜就无能为力了,这时我们需要为 FFmpeg 添加自定义的滤镜。
关于 FFmpeg 内置滤镜:ffmpeg-filters
FFmpeg添加自定义滤镜的模板
既然是自定义 FFmpeg 滤镜,那么我们就必须要按照 FFmpeg 规定的套路来实现。
先看一下示例模板:
typedef struct GLWaveContext{const AVClass *class;GLuint program; // 着色器程序GLuint frame_tex; // 纹理 IDGLuint pos_buf; // 顶点缓存GLint time;GLFWwindow *window;
} GLWaveContext;AVFILTER_DEFINE_CLASS(glwave);static av_cold int init(AVFilterContext *ctx)
{return glfwInit() ? 0 : -1;
}static av_cold void uninit(AVFilterContext *ctx)
{GLWaveContext *gs = ctx->priv;glDeleteTextures(1, &gs->frame_tex);glDeleteBuffers(1, &gs->pos_buf);glDeleteProgram(gs->program);glfwDestroyWindow(gs->window);
}static int query_formats(AVFilterContext *ctx)
{static const enum AVPixelFormat formats[] = {AV_PIX_FMT_RGB24,AV_PIX_FMT_NONE};return ff_set_common_formats(ctx, ff_make_format_list(formats));
}static const AVFilterPad glwave_inputs[] = {{.name = "default",.type = AVMEDIA_TYPE_VIDEO,.config_props = config_input,.filter_frame = glwave_filter_frame,.needs_writable = 1,},{ NULL }
};static const AVFilterPad glwave_outputs[] = {{.name = "default",.type = AVMEDIA_TYPE_VIDEO,},{ NULL }
};AVFilter ff_vf_glwave = {.name = "glwave",.description = NULL_IF_CONFIG_SMALL("Generic OpenGL shader filter"),.priv_size = sizeof(GLWaveContext),.init = init,.uninit = uninit,.query_formats = query_formats,.inputs = glwave_inputs,.outputs = glwave_outputs,.priv_class = &glwave_class,.flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
};
首先我们要 coding 一个 C 文件,因为 FFmpeg 源码为 C 。
AVFilter 结构:
.name 对外宣称的滤镜名称,和命令行要使用的 "-vf wave" 是一样的。
.priv_size 初始化 GLWaveContext,这个是 filter 的私有上下文,可以存放本地全局变量。
.init 如果 GLWaveContext 有什么内容需要初始化,就放在init,如果没有,可以删掉。
.uninit 同上 init 。
.query_formats 支持的 AVFrame 格式,按需添加,可以添加多个。
.inputs 交互桥梁,最重要的是 glwave_inputs 结构内的函数指针 filter_frame,我们可以在filter_frame 内获得需要处理的 AVFrame 。至于 config_input 则可以在其中构建好 shader 特效处理代码。
.outputs 用于配置输出的 frame 的大小。
总结
上面所述就是按照 FFmpeg 规则添加滤镜,最重要的还是为 filter_frame,但仅仅是提到我们可以在此函数指针内获得所需处理的 AVFrame。细心的朋友会发现 AVFilterLink,这部分内容需要理清 AVFilterGraph, AVFilterContext, AVFilterLink, AVFilterPad 之间错综复杂的关系,这里不做分析,旨在如何最快实现自定义滤镜。