ffmpeg1.2的filter分析

我想,filter实际上是形成一个AVFilterGraph,就是一个filter的图。里面定义了filter的关系,frame进去后,经过怎样的路线图进行输入和输出。
总之,最后就是形成了filter_graph。

ffmpeg -re -i ~/input.flv -threads 2 -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" -vcodec libx264 -acodec libfdk_aac -f flv -y rtmp://dev:1935/live/livestream
等价于:
ffmpeg -re -i ~/input.flv -threads 2 -vf "[in] split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2 [out]" -vcodec libx264 -acodec libfdk_aac -f
flv -y rtmp://dev:1935/live/livestream
其中,标签[in]和[out]是可以省略的。
应用了如下filter:
1. split:将流分成两路,[main]和[tmp]
2. [tmp]:这路流的处理filter是,corp裁剪取上半部分,vflip为翻转,输出为[flip]
3. [main][flip]:两路流经过overlay合并为一路。
结果就是将图像上半部分镜像翻转。

跟踪这个命令,看创建了哪些filter:
[winlin@dev6 ~]$ gdb --args ffmpeg -re -i ~/input.flv -threads 2 -vf "[in] split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2 [out]" -vcodec libx264 -acodec libfdk_aac -f flv -y rtmp://dev:1935/live/livestream
(gdb) b avfilter_graph_create_filter

(gdb) b avfilter_get_by_name

调用路径如下:
(gdb) bt
#0  avfilter_get_by_name (name=0xf32760 "split") at libavfilter/avfilter.c:404
#1  0x000000000043fc4b in create_filter (filt_ctx=0x7fffffffd770, ctx=0xf37be0, index=0, filt_name=0xf32760 "split", args=0x0, log_ctx=0xf37be0)
    at libavfilter/graphparser.c:105
#2  0x000000000043fec4 in parse_filter (filt_ctx=0x7fffffffd770, buf=0x7fffffffd760, graph=0xf37be0, index=0, log_ctx=0xf37be0) at libavfilter/graphparser.c:169
#3  0x00000000004407df in avfilter_graph_parse2 (graph=0xf37be0, filters=0xf37c6b "[main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2 [out]",
    inputs=0x7fffffffd9c8, outputs=0x7fffffffd9c0) at libavfilter/graphparser.c:404
#4  0x0000000000411d43 in configure_filtergraph (fg=0xf36c20) at ffmpeg_filter.c:762
#5  0x000000000041b369 in transcode_init () at ffmpeg.c:2283
#6  0x000000000041f1c0 in transcode () at ffmpeg.c:3138
可见,会在avfilter_graph_parse2中直接将参数转换,并avfilter_open对应的filter。
#0  avfilter_get_by_name (name=0xf32760 "split") at libavfilter/avfilter.c:404 filt_name=0xf32760 "split", args=0x0
#0  avfilter_get_by_name (name=0xf30f80 "crop") at libavfilter/avfilter.c:404 filt_name=0xf30f80 "crop", args=0xf31020 "iw:ih/2:0:0"
#0  avfilter_get_by_name (name=0xf328e0 "vflip") at libavfilter/avfilter.c:404 filt_name=0xf328e0 "vflip", args=0x0
#0  avfilter_get_by_name (name=0xf39000 "overlay") at libavfilter/avfilter.c:404 filt_name=0xf39000 "overlay", args=0xf39040 "0:H/2"
这个函数也调用avfilter_link来link这些filter:
          src: split           dest: crop
          src: crop           dest: vflip
          src: split           dest: overlay
          src: vflip           dest: overlay
实际上就是建立一个图的概念,就是filter graph了。

然后,是在configure_input_filter中创建video的bufferfilter,用来提供输入源的(即[in])。

args="video_size=400x300:pix_fmt=0:time_base=1/1000:pixel_aspect=1/1:sws_param=flags=2:frame_rate=15/1"

#0  avfilter_get_by_name (name=0xa3c837 "buffer") at libavfilter/avfilter.c:404 at libavfilter/avfiltergraph.c:94

这几个函数中,avfilter_graph_create_filter是从字符串创建的一个函数,实际上等同于三个函数:
args="video_size=400x300:pix_fmt=0:time_base=1/1000:pixel_aspect=1/1:sws_param=flags=2:frame_rate=15/1"
avfilter_graph_create_filter (AVFilterContext **filt_ctx, AVFilter *filt, AVFilterGraph *graph_ctx,  args)

avfilter_open(filt_ctx, filt, name)

avfilter_init_filter(*filt_ctx, args)

avfilter_graph_add_filter(graph_ctx, *filt_ctx)

就是说,从args解析filter参数,创建一个filter_ctx,然后添加到filter_graph。这应该也是filter的基本创建流程,其中init和add没有顺序。

接着,是在configure_output_filter中创建输出的ffbuffersink,用来作为输出的(即[out])。

#0  avfilter_get_by_name (name=0xa3c6d5 "ffbuffersink") at libavfilter/avfilter.c:404 args=0x0, opaque=0x0, graph_ctx=0xf37be0)

还创建了几个其他的filter。譬如:

#0  avfilter_get_by_name (name=0xa3c745 "format") at libavfilter/avfilter.c:404 args=0xf32d70 "yuv420p:yuvj420p:yuv422p:yuv444p"
#0  avfilter_get_by_name (name=0xa44462 "scale") at libavfilter/avfilter.c:404 args=0x7fffffffd5d0 "0:0:flags=0x4"

用来做输出变换的。


视频完了后,就是音频:
#0  avfilter_get_by_name (name=0xf29980 "anull") at libavfilter/avfilter.c:404
#0  avfilter_get_by_name (name=0xa3c8ff "abuffer") at libavfilter/avfilter.c:404 args=0x7fffffffd334 "time_base=1/44100:sample_rate=44100:sample_fmt=fltp:channel_layout=0x3"
#0  avfilter_get_by_name (name=0xa3c74c "ffabuffersink") at libavfilter/avfilter.c:404 args=0x0
#0  avfilter_get_by_name (name=0xa3c805 "aformat") at libavfilter/avfilter.c:404 args=0x7fffffffd1e0 "sample_fmts=s16:sample_rates=96000,88200
#0  avfilter_get_by_name (name=0xa444c6 "aresample") at libavfilter/avfilter.c:404 args=0xfaac80 ""
设置完就开始转码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值