1 综述
FFMPEG 除了具有强大的封装/解封装,编/解码功能之外,还包含了一个非常强大的组件,滤镜avfilter。 avfilter 组件常用于多媒体处理与编辑,ffmpeg 包含多种滤镜,比如旋转,加水印,多宫格等等。 这里我们主要介绍关于filter 相关的API。
2 滤镜使用
filter 开出的API 很多,但是常用的就那么几个, 下面我们着重介绍下常用的几个API。分为三个部分:1 初始化部分,2 数据转换部分,3 退出部分。
2.1 滤镜初始化:
AVFilterGraph * avfilter_graph_alloc (void) : alloc 后,得到AVFilterGraph 结构体,它是filter 部分范围最广结构体,AVFilterContext 都是它的成员。 使用filter 第一个被调用的函数
int avfilter_graph_create_filter(AVFilterContext **filt_ctx, const AVFilter *filt,const char *name, const char *args, void *opaque, AVFilterGraph *graph_ctx): 创建过滤器实例并将其添加到现有graph 中
AVFilterInOut *avfilter_inout_alloc(void):alloc 一个AVFilterInout 结构体, 后面avfilter_graph_parse()需要用到。
int avfilter_graph_parse_ptr(AVFilterGraph *graph, const char *filters, AVFilterInOut **open_inputs_ptr, AVFilterInOut **open_outputs_ptr, void *log_ctx):敲黑板,重点!视频特效需要许多滤镜组合而成的,比如视频缩放旋转。现通过scale 滤镜将视频缩放,然后通过transpose 滤镜去做旋转。那么如何将用户的行为传递给代码呢? 就需要此API 的const char * filters 去指定。 比如视频缩放成78:24,然后逆时针旋转90度.const char * filters = "scale=78:24,transpose=cclock";
除此方法之外,还可以通过avfilter_link()将滤镜相连,这种可能会麻烦一点。
int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx): 在滤镜初始化完成时去调用,检查滤镜是否初始化成,各个模块是否连接正确。 >=0 说明成功, 小于0 则不可用。4
2.2 数据转换
滤镜初始化成功之后,就可以对音视频数据做特效处理了。 总共2支API。一个负责将转换前的frame 推到滤镜, 一个接收做完特效的frame.
int av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags)
int av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame)
2.3 退出
void avfilter_inout_free(AVFilterInOut **inout):// 释放AVFilterInOut
void avfilter_graph_free(AVFilterGraph **graph):// 释放AVFilterGraph, 连AVFilterContext 也一起释放了。
关于滤镜使用的具体方法 ,请参考ffmpeg 提供的demo:在doc/examples 目录下的filter_video.c 。
3 filter 相关API
函数名 | 作用 |
unsigned avfilter_version (void) | 返回libavfilter_version_int常量 |
const char * avfilter_configuration (void) | 返回libavfilter构建时配置 |
const char * avfilter_license (void) | 返回libavfilter许可证。 |
int avfilter_pad_count (const AVFilterPad *pads) | 获取空终止的avfilterpads数组中的元素数 |
const char * avfilter_pad_get_name (const AVFilterPad *pads, int pad_idx) | 获取avfilterpad的名称。 |
enum AVMediaType avfilter_pad_get_type (const AVFilterPad *pads, int pad_idx) | 获取avfilterpad的类型。 |
int avfilter_link (AVFilterContext *src, unsigned srcpad, AVFilterContext *dst, unsigned dstpad) | 将两个过滤器连接在一起 |
void avfilter_link_free (AVFilterLink **link) | 释放*link中的链接,并将其指针设置为null |
int avfilter_config_links (AVFilterContext *filter) | 协商所有输入到过滤器的媒体格式、尺寸等。 |
int avfilter_process_command (AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags) | 让过滤器实例处理一个命令。 |
const AVFilter * av_filter_iterate (void **opaque) | 遍历所有注册的过滤器 |
const AVFilter * avfilter_get_by_name (const char *name) | 获取与给定名称匹配的筛选器定义 |
int avfilter_init_str (AVFilterContext *ctx, const char *args) | 用提供的参数初始化过滤器 |
int avfilter_init_dict (AVFilterContext *ctx, AVDictionary **options) | 用提供的选项字典初始化过滤器 |
void avfilter_free (AVFilterContext *filter) | 释放筛选器上下文 |
int avfilter_insert_filter (AVFilterLink *link, AVFilterContext *filt, unsigned filt_srcpad_idx, unsigned filt_dstpad_idx) | 在现有链接的中间插入过滤器 |
const AVClass * avfilter_get_class (void) | |
AVFilterGraph * avfilter_graph_alloc (void) | 分配过滤图 |
AVFilterContext * avfilter_graph_alloc_filter (AVFilterGraph *graph, const AVFilter *filter, const char *name) | 在过滤器图中创建新的过滤器实例 |
AVFilterContext * avfilter_graph_get_filter (AVFilterGraph *graph, 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) | 创建过滤器实例并将其添加到现有图形中 |
void avfilter_graph_set_auto_convert (AVFilterGraph *graph, unsigned flags) | 启用或禁用图形内部的自动格式转换 |
int avfilter_graph_config (AVFilterGraph *graphctx, void *log_ctx) | 检查有效性并配置图表中的所有链接和格式 |
void avfilter_graph_free (AVFilterGraph **graph) | 释放一个图,销毁它的链接,并将*graph设置为null |
AVFilterInOut * avfilter_inout_alloc (void) | 分配一个avfilterinout条目 |
void avfilter_inout_free (AVFilterInOut **inout) | 释放提供的avfilterinout列表,并将*inout设置为null |
int avfilter_graph_parse (AVFilterGraph *graph, const char *filters, AVFilterInOut *inputs, AVFilterInOut *outputs, void *log_ctx) | 将字符串描述的图形添加到图形中 |
int avfilter_graph_parse_ptr (AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs, void *log_ctx) | 同上 |
int avfilter_graph_parse2 (AVFilterGraph *graph, const char *filters, AVFilterInOut **inputs, AVFilterInOut **outputs) | 同上 |
int avfilter_graph_send_command (AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, char *res, int res_len, int flags) | 向一个或多个过滤器实例发送命令 |
int avfilter_graph_queue_command (AVFilterGraph *graph, const char *target, const char *cmd, const char *arg, int flags, double ts) | 为一个或多个过滤器实例排队命令 |
char * avfilter_graph_dump (AVFilterGraph *graph, const char *options) | 将图形转储为人类可读的字符串表示形式 |
int avfilter_graph_request_oldest (AVFilterGraph *graph) | 在最早的接收链路上请求帧 |