FFMPEG complex filter的流程

ffmpeg1.2的overlay必须是complex filter,调试这个命令:
ffmpeg -re -i ~/test_22m.flv -i ~/logo.png -filter_complex 'overlay=10:10' -acodec libfdk_aac -ar 8000 -ac 1 -vcodec libx264 -coder 0 -b_strategy 0 -bf 0 -refs 1 -b 300k -threads 2 -f flv -y rtmp://dev:1935/live/livestream
为了简化,也可以去掉音频,调试这个命令:
ffmpeg -re -i ~/test_22m.flv -i ~/logo.png -filter_complex 'overlay=10:10' -an -vcodec libx264 -coder 0 -b_strategy 0 -bf 0 -refs 1 -b 300k -threads 2 -f flv -y rtmp://dev:1935/live/livestream

主要的断点:
opt_filter_complex 解析-filter_complex参数的函数。
configure_complex_filters 配置复杂filter的函数。
init_simple_filtergraph 初始化简单filter的函数。
avfilter_graph_config 结束简单filter和复杂filter配置的函数。
open_output_file 打开输出文件,也会初始化复杂filte。
configure_filtergraph 配置filter图。
avfilter_graph_alloc 创建filter图。
avfilter_graph_parse2 转换filter图。
configure_input_filter 配置输入的filter。
configure_output_filter 配置输出的filter。
avfilter_get_by_name 获取各种filter的函数。

简单filter的主要流程
ffmpeg_parse_options
open_input_file
open_output_file
avformat_new_stream
avcodec_find_encoder
avio_open2
transcode_init
init_simple_filtergraph
configure_filtergraph
avfilter_graph_alloc
avfilter_graph_parse2 "null"
avfilter_get_by_name "null"
configure_input_filter
avfilter_get_by_name "buffer"
configure_output_filter
avfilter_get_by_name "ffbuffersink"
avfilter_get_by_name "format"
avfilter_graph_config
init_simple_filtergraph
configure_filtergraph
avfilter_graph_alloc
avfilter_graph_parse2 "anull"
avfilter_get_by_name "anull"
configure_input_filter
avfilter_get_by_name "abuffer"
configure_output_filter
avfilter_get_by_name "ffabuffersink"
avfilter_get_by_name "aformat"
avfilter_graph_config

复杂filter的主要流程
ffmpeg_parse_options
opt_filter_complex
open_input_file "/home/winlin/test_22m.flv"
open_input_file "/home/winlin/logo.png"
open_output_file "rtmp://dev:1935/live/livestream"
configure_complex_filters
configure_filtergraph
avfilter_graph_alloc
avfilter_graph_parse2 "overlay=10:10"
avfilter_get_by_name "overlay"
init_input_filter
configure_input_filter
avfilter_get_by_name "buffer"
avfilter_get_by_name "buffer"
init_output_filter
avformat_new_stream
avcodec_find_encoder
configure_output_filter
avfilter_get_by_name "ffbuffersink"
avfilter_get_by_name "format"
avio_open2 "rtmp://dev:1935/live/livestream"
transcode_init
avfilter_graph_config
init_simple_filtergraph
configure_filtergraph
avfilter_graph_alloc
avfilter_graph_parse2 "anull"
avfilter_get_by_name "anull"
configure_input_filter
avfilter_get_by_name "abuffer"
configure_output_filter
avfilter_get_by_name "ffabuffersink"
avfilter_get_by_name "aformat"
avfilter_graph_config

解析复杂filter函数 opt_filter_complex
调用堆栈:
#0  opt_filter_complex (optctx=0x0, opt=0x7fffffffe7ad "filter_complex", arg=0x7fffffffe7bc "overlay=10:10") at ffmpeg_opt.c:2196
#1  0x00000000004209d5 in write_option (optctx=0x0, po=0xf98398, opt=0x7fffffffe7ad "filter_complex", arg=0x7fffffffe7bc "overlay=10:10") at cmdutils.c:296
#2  0x0000000000420df2 in parse_optgroup (optctx=0x0, g=0x7fffffffe260) at cmdutils.c:386
#3  0x000000000040f4a7 in ffmpeg_parse_options (argc=32, argv=0x7fffffffe428) at ffmpeg_opt.c:2337
#4  0x000000000041ff7d in main (argc=32, argv=0x7fffffffe428) at ffmpeg.c:3322
主要逻辑:
           // arg is "overlay=10:10"
filtergraphs[nb_filtergraphs - 1]->index       = nb_filtergraphs - 1;
filtergraphs[nb_filtergraphs - 1]->graph_desc = arg;

初始化filter图 avfilter_graph_parse2
// complex: graph_desc is "overlay=10:10"
// output:
// 1. inputs: (AVFilterInOut*)
//      name: 0x0
//      filter_ctx: (AVFilterContext*) 0x1c3e4c0
//          name: "Parsed_overlay_0"
//          filter: (AVFilter*) 0x1463880
//              name: "overlay"
//              description: "Overlay a video source on top of the input."
//          input_count: 2
//          inputs[0]: (AVFilterLink*) 0x0
//          inputs[1]: (AVFilterLink*) 0x0
//          output_count: 1
//          outputs[0]: (AVFilterLink*) 0x0
//      next: (AVFilterInOut*) 0x1af31c0
//          filter_ctx: (AVFilterContext*) 0x1c3e4c0
//          next: (AVFilterInOut*) 0x0
// 2. outputs: (AVFilterInOut*) 0x1af3000
//      name: 0x0
//      filter_ctx: (AVFilterContext*) 0x1c3e4c0
//      next: (AVFilterInOut*) 0x0
// 
// simple: graph_desc is "null"
// output:
// 1. inputs: (AVFilterInOut*) 0x1ae2500
//      name: 0x0
//      filter_ctx: (AVFilterContext*) 0x1c3d1e0
//          name: "Parsed_null_0"
//          filter: (AVFilter*) 0x1463820
//              name: "null"
//              description: "Pass the source unchanged to the output."
//          input_count: 1
//          inputs[0]: (AVFilterLink*) 0x0
//          output_count: 1
//          outputs[0]: (AVFilterLink*) 0x0
//      next: (AVFilterInOut*) 0x0
// 2. outputs: (AVFilterInOut*) 0x1c3cf40
//      name: 0x0
//      filter_ctx: (AVFilterContext*) 0x1c3d1e0
//      next: (AVFilterInOut*) 0x0
// 和simple的区别,是inputs有多个,simple的inputs只有一个。
// 相同点是,filter_ctx都只有一个,simple是anull,而complex是overlay。
// configure_input_filter时,有两个buffer,和overlay对接。

avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)


Winlin


你可能感兴趣的:(FFMPEG complex filter的流程)