创建FILTER的一般流程:
1、初始化一个Filter对象:
(1)调用avfilter_graph_alloc()函数创建一个Filter对象
(2)调用函数avfilter_graph_parse_ptr()把描述信息加到Filter对象上。
(3)调用avfilter_graph_config()函数检查配置有效性、配置滤镜的连接和格式。
2、使用Filter对象:
(1)使用av_buffersrc_add_frame_flags()把解码的帧数据传给Filter。
(2)使用av_buffersink_get_frame()从Filter中把处理好的数据取出。
3、实例代码:
int InitFilter(AVCodecContext * codecContext)
{
char args[512];
int ret = 0;
AVFilter *buffersrc = avfilter_get_by_name("buffer");
AVFilter *buffersink = avfilter_get_by_name("buffersink");
g_outputs = avfilter_inout_alloc();
g_inputs = avfilter_inout_alloc();
string filters_descr;// = "scale=iw*2:ih*2";
// 注意字体文件存放位置
// fontcolor=red : 红色
// x,y:输出的位置
// text:输出的内容
// fontsize:字符大小
filters_descr = "drawtext=fontfile=msyh.ttf:fontsize=100:fontcolor=red:text='filter sample':x=100:y=100";
enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P };
// 创建滤镜对象
g_filter_graph = avfilter_graph_alloc();
if (!g_outputs || !g_inputs || !g_filter_graph) {
ret = AVERROR(ENOMEM);
goto InitFilter_error;
}
sprintf_s(args, sizeof(args),
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
codecContext->width, codecContext->height, // 视频宽高
codecContext->pix_fmt, // 视频格式
codecContext->time_base.num, codecContext->time_base.den,// 视频频率
codecContext->sample_aspect_ratio.num, codecContext->sample_aspect_ratio.den// 视频宽高比
);
// 创建滤镜的输入端
ret = avfilter_graph_create_filter(&g_buffersrcContext, buffersrc, "in",
args, NULL, g_filter_graph);
if (ret < 0) {
goto InitFilter_error;
}
// 创建滤镜的输出端
ret = avfilter_graph_create_filter(&g_buffersinkContext, buffersink, "out",
NULL, NULL, g_filter_graph);
if (ret < 0) {
goto InitFilter_error;
}
ret = av_opt_set_int_list(g_buffersinkContext, "pix_fmts", pix_fmts,
AV_PIX_FMT_YUV420P, AV_OPT_SEARCH_CHILDREN);
if (ret < 0) {
goto InitFilter_error;
}
g_outputs->name = av_strdup("in");
g_outputs->filter_ctx = g_buffersrcContext;// 把输出端与输入连接
g_outputs->pad_idx = 0;
g_outputs->next = NULL;
g_inputs->name = av_strdup("out");
g_inputs->filter_ctx = g_buffersinkContext;// 把输入端与输出连接
g_inputs->pad_idx = 0;
g_inputs->next = NULL;
if ((ret = avfilter_graph_parse_ptr(g_filter_graph,
filters_descr.c_str(),
&g_inputs,
&g_outputs,
NULL))
< 0
)
goto InitFilter_error;
// 检查有效性,配置滤镜的连接和格式
if ((ret = avfilter_graph_config(g_filter_graph, NULL)) < 0)
goto InitFilter_error;
return ret;
InitFilter_error:
avfilter_inout_free(&g_inputs);
avfilter_inout_free(&g_outputs);
g_inputs = nullptr;
g_outputs = nullptr;
return ret;
}
// 加一帧数据到buffer源,
if (av_buffersrc_add_frame_flags(g_buffersrcContext, pSrcFrame, AV_BUFFERSRC_FLAG_KEEP_REF) >= 0)
{
// 从sink中取出带滤镜数据的帧。
if (av_buffersink_get_frame(g_buffersinkContext, filterFrame) >= 0)
{
....
}
}
4、工程项目源程序下载:
在Debug – x86
工程中包含了开发环境。