基础
- filter: 数据处理器
- filter_chain: 链表链接链接所有的filter
- filter_graph:数据处理管理器
初始化过滤器
创建graph
//avfilter_register_all(); // 4.0后被删除,同avdevice_regeister_all
AVFilterGraph *filter_graph = avfilter_graph_alloc();
if (!filter_graph) {
printf("failed to create filter graph\n");
return -1;
}
创建chain
编码创建
创建输入buffer
char args[512];
memset(args, 0, 512);
sprintf(args,
"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
in_width,
in_height,
AV_PIX_FMT_YUV420P,
1,
25,
1,
1);
AVFilter *buffser_src =
avfilter_get_by_name("buffer"); // AVFilterGraph的输入源
AVFilterContext *buffer_src_ctx;
ret = avfilter_graph_create_filter(
&buffer_src_ctx, buffser_src, "in", args, NULL, filter_graph);
if (ret < 0) {
printf("failed to create filter buffersrc\n");
return -1;
}
输出buffersink
// sink filter
AVBufferSinkParams *buffer_sink_paras;
AVFilterContext *buffer_sink_ctx;
AVFilter *buffer_sink = avfilter_get_by_name("buffersink");
enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE };
buffer_sink_paras = av_buffersink_params_alloc();
buffer_sink_paras->pixel_fmts = pix_fmts;
ret = avfilter_graph_create_filter(&buffer_sink_ctx,
buffer_sink,
"out",
NULL,
buffer_sink_paras,
filter_graph);
if (ret < 0) {
printf("failed to create split filter\n");
return -1;
}
个人需要使用的filter
// split fitler
AVFilter *split_filter = avfilter_get_by_name("split");
AVFilterContext *split_filter_ctx;
ret = avfilter_graph_create_filter(&split_filter_ctx,
split_filter,
"split",
"outputs=2",
NULL,
filter_graph);
if (ret < 0) {
printf("failed to create split filter\n");
return -1;
}
// crop filter
AVFilter *crop_filter = avfilter_get_by_name("crop");
AVFilterContext *crop_filter_ctx;
ret = avfilter_graph_create_filter(&crop_filter_ctx,
crop_filter,
"crop",
"out_w=iw:out_h=ih/2:x=0:y=0",
NULL,
filter_graph);
if (ret < 0) {
printf("failed to create crop filter\n");
return -1;
}
// vflip filter
AVFilter *vflip_filter = avfilter_get_by_name("vflip");
AVFilterContext *vflip_filter_ctx;
ret = avfilter_graph_create_filter(
&vflip_filter_ctx, vflip_filter, "vflip", NULL, NULL, filter_graph);
if (ret < 0) {
printf("failed to create vflip filter\n");
return -1;
}
// overlap filter
AVFilter *overlay_filter = avfilter_get_by_name("overlay");
AVFilterContext *overlay_filter_ctx;
ret = avfilter_graph_create_filter(&overlay_filter_ctx,
overlay_filter,
"overlay",
"y=0:H/2",
NULL,
filter_graph);
if (ret < 0) {
printf("failed to create overlay filter\n");
return -1;
}
link需要的filters
// src filter to split filter
ret = avfilter_link(buffer_src_ctx, 0, split_filter_ctx, 0);
if (ret != 0) {
printf("failed to link src filter and split filter\n");
return -1;
}
// split filter's first pad to overlay fiilter's main pad
ret = avfilter_link(split_filter_ctx, 0, overlay_filter_ctx, 0);
if (ret != 0) {
printf("failed to link split filter's first pad and overlay filter\n");
return -1;
}
// split fitler's second pad to crop filter
ret = avfilter_link(split_filter_ctx, 1, crop_filter_ctx, 0);
if (ret != 0) {
printf("failed to link split filter's second pad and crop filter\n");
return -1;
}
// crop filter to vflip filter
ret = avfilter_link(crop_filter_ctx, 0, vflip_filter_ctx, 0);
if (ret != 0) {
printf("failed to link crop filter and vflip filter\n");
return -1;
}
// vflip filter to overlay filtes'second pad
ret = avfilter_link(vflip_filter_ctx, 0, overlay_filter_ctx, 1);
if (ret != 0) {
printf("failed to link vflip filter and overlay's second filter\n");
return -1;
}
// overlay filter to sink filter
ret = avfilter_link(overlay_filter_ctx, 0, buffer_sink_ctx, 0);
if (ret != 0) {
printf("failed to link overlay filter and sink filter\n");
return -1;
}
初始化graph
// check filter graph
ret = avfilter_graph_config(filter_graph, NULL);
if (ret < 0) {
printf("failed in filter graph\n");
return -1;
}
命令创建
初始化命令行
char filter_args[1024] = { 0 };
snprintf(
filter_args,
sizeof(filter_args),
"buffer=video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d[v0];" // Parsed_buffer_0
"[v0]split[main][tmp];" // Parsed_split_1
"[tmp]crop=iw:ih/2:0:0,vflip[flip];" // Parsed_crop_2 Parsed_vflip_3
"[main][flip]overlay=0:H/2[result];" // Parsed_overlay_4
"[result]buffersink", // Parsed_buffersink_5
width,
height,
format,
1,
25,
1,
1);
利用命令行初始化graph
AVFilterInOut *inputs = NULL;
AVFilterInOut *outputs = NULL;
int ret = avfilter_graph_parse2(filter_graph, filter_args, &inputs, &outputs);
if (ret < 0) {
printf("cannot parse graph\n");
return ret;
}
ret = avfilter_graph_config(filter_graph, NULL);
if (ret < 0) {
printf("cannot config graph\n");
return ret;
}
获取输入buffer和输出buffersink
mainsrc_ctx = avfilter_graph_get_filter(filter_graph, "Parsed_buffer_0");
if (!mainsrc_ctx) {
printf("avfilter_graph_get_filter Parsed_buffer_0 failed\n");
return -1;
}
resultsink_ctx =
avfilter_graph_get_filter(filter_graph, "Parsed_buffersink_5");
if (!resultsink_ctx) {
printf("avfilter_graph_get_filter Parsed_buffer_5 failed\n");
return -1;
}
处理数据
向buffer中添加数据
if (av_buffersrc_add_frame(mainsrc_ctx, frame_in) < 0) {
printf("error while add frame\n");
break;
}
从buffersink中获取数据
ret = av_buffersink_get_frame(resultsink_ctx, frame_out);
if (ret < 0)
break;
其他业务
// output Y U V
if (frame_out->format == AV_PIX_FMT_YUV420P) {
for (int i = 0; i < frame_out->height; ++i)
fwrite(frame_out->data[0] + frame_out->linesize[0] * i,
1,
frame_out->width,
outFile);
for (int i = 0; i < frame_out->height / 2; ++i)
fwrite(frame_out->data[1] + frame_out->linesize[1] * i,
1,
frame_out->width / 2,
outFile);
for (int i = 0; i < frame_out->height / 2; ++i)
fwrite(frame_out->data[2] + frame_out->linesize[2] * i,
1,
frame_out->width / 2,
outFile);
}
标签:filter,buffer,graph,avfilter,ctx,ret,Filter,FilterGraph,FilterChain
From: https://www.cnblogs.com/faithlocus/p/17226106.html