FFmpeg中的滤镜(一):滤镜概念及命令规则

  1. 概述
    本文介绍libavfiter库提供的filter、sources、sink组件

  2. Filter介绍
    在ffmpeg框架中,滤镜(filter)功能通过libavfilter库实现。
    一个filter可以同时有多个输入和输出。以图为例:
    这里写图片描述
    图中的一系列操作共使用了四个filter,分别是
    splite:将输入的流进行分裂复制,分两路输出。
    crop:根据给定的参数,对视频进行裁剪
    vflip:根据给定参数,对视频进行翻转等操作
    overlay:将一路输入覆盖到另一路之上,合并输出为一路视频
    整个过程的命令为下图:
    这里写图片描述
    最终实现的效果是,视频的上半部分水平翻转,下半部分被覆盖,输出一个水平对称的视频。

    命令行分析:splite有两路输出,分别被标签标记为[main]和[tmp],在命令中,可以用这种形式来标记输入输出,在后面命令中,对被标记的输出进行引用。其中一路输出[tmp]作为输入传递给crop。crop的参数格式为w:h:x:y,其中w、h为输出视频的宽和高,x、y标记输入视频中的某点,将该点作为基准点,向右下进行裁剪得到输出视频。示例中crop的参数为iw:ih/2:0:0,iw、ih分别为输入流视频的宽和高,因此该参数表明,以原视频左上角为基准点,宽度不变,裁剪原视频的上半部分。从crop得到的输出被传递给vflip,vflip对输入做水平翻转处理,得到输出[flip]。然后将splite的另一路输出[main]和[flip]一起传递给overlay,其中第一个输入[main]为主流,第二个输入[flip]是副流,overlay根据参数指定的规则将副流覆盖于主流之上。该命令中overlay的参数为0:H/2,即[flip]左上角对齐[mian]的坐标为(0,H/2)的点进行覆盖,H为[main]的高。

    以上为ffmpeg滤镜的基本使用方式。其中有一些命令的格式需要注意:
    1、命令中同一个滤镜链中的滤镜之间通过逗号分隔开,如上例中[crop]和[vflip]处于同一个滤镜链,而知以逗号分隔开。

    2、不同的滤镜链之间以分号隔开,如上例中[crop]和[vflip]组成的滤镜链与[split]、[overlay]之间。

    3、滤镜链的输入输出通过方括号标记命名,若示例中[split]滤镜产生了两路输出,分别被标记为[main]和[tmp]

    4、有的滤镜可以指定参数列表,通过在滤镜名后面接一个等号,然后等号后指定需要的参数即可,不同的参数之间需要使用冒号隔开。如示例中[crop]的参数iw:ih/2:0:0

  3. 滤镜图(filtergraph )介绍
    多个滤镜按照一定的方向连接起来成为滤镜图。滤镜图中可以包含循环,两个滤镜之间也可以同时存在多条连接。每个连接(link)通过一个输入端(input pad)和输出端(output pad),其中输入端从上一个滤镜接受数据,输出端向下一个滤镜输出数据。
    滤镜图中的每个滤镜都是注册到应用中的某个类型的滤镜的实例,每种类型的滤镜都定义了它的特点,以及每个实例拥有输入端和输出端的数量。
    没有输入端的滤镜称为“源(source)”,没有输出端的滤镜称为“槽(sink)”。

    1. 滤镜图格式
      滤镜图使用一段文本进行描述,可以通过-filter/-vf/-af/-filter_complex选项在ffmpeg命令中指定,或者 通过-vf/-af选项在ffplay命令中制定,或者通过libavfilter/avfilter.h头文件中的avfilter_graph_parse_ptr()函数定义。
      一个滤镜链中包含一系列顺序连接的滤镜。滤镜之间通过逗号分隔开。
      一个滤镜图中包含一系列滤镜链。滤镜链之间通过分号隔开。
      滤镜描述格式:[in_link_1]...[in_link_N]filter_name=arguments[out_link_1]...[out_link_M]
      filter_name是应用中已注册的某个滤镜类型的名称。filter_name后面可以使用“=arguments”指定参数。
      arguments是一个包含参数的字符串,这些参数用于初始化滤镜实例。参数可以有两种
      格式:
      • 冒号分隔的key=value列表,其中key为每个类型滤镜声明的选项名。
      • 冒号分隔的value列表。这种情况下,value按照滤镜的默认参数选项顺序一一对应。例如[fade]滤镜声明了三个参数的顺序为type、start_frame和nb_frames,如果现在有参数字符串为in:0:30,即代表type=in,start_frame=0,nb_frame=30。
      • 冒号分隔的value形式与key=value形式混用的列表。这种情况下value形式的参数必须在key=value参数之前,其解析方法与纯value形式相同。Key=value形式则可以任意形式排列。

      如果参数的选项的值是一个列表,那么列表的元素之间通常用“|”分隔开。例如format滤镜的argument为pix_fmts,用于指定输出的格式,因此滤镜命令如下:format=pix_fmts=yuv420p|yuv444p|yuv410p。命令表示尝试将输入的视频转换为yuv420p、yuv444p、yuv410p三种格式的输出并选择最适合的一种传输给下一个滤镜。

      滤镜的arguments可以通过单引号进行引用,将要引用的内容至于单引号对内即可。引用内容中若有特殊字符,如单引号本身,需要使用’\‘进行转义,否则命令可能异常结束。

      过滤器的名字和参数可以写在前面,后面跟着一个link label列表。每个link label代表一个关联到filter输出端或者输入端的连接(link)。前面的[in_link_1]...[in_link_N]关联到滤镜的输入端,后面的[out_link_1]...[out_link_M]关联到滤镜的输出端。

      当滤镜图中有两个一样名字的link label时,二者对应的输人端和输出端之间即创建一个link。

      如果一个滤镜的输出端没有关联任何link label,那么它将在滤镜图中往后查找第一个有未关联link label的输入端的滤镜,并与之连接。例:nullsrc, split[L1], [L2]overlay, nullsink
      滤镜[split]有两个输出端,[overlay]有两个输入端。split的第一个输出端标记为L1,overlay的第一个输入端标记为L2,split的第二个输出端默认连接到overlay的第二个输入端,因为他们都没有与之关联的link label。

      在写滤镜的命令时,如果没有指定第一个滤镜的输入端,那么将会假设一个“in”作为输入端;如果没有指定最后一个滤镜的输出端,那么将会假设一个“out”作为输出端。

      一个完成的滤镜链中,所有未关联link lable的输出输入端都必须正常连接。一个有效的滤镜图中所有滤镜链里面的输入端和输出端都必须连接的。

      libavfilter会在需要转换格式的地方自动插入scale滤镜。通过附加sws_flags=flags给滤镜图,可以为自动插入的scale滤镜指定缩放参数。

  4. 基于时间的控制
    一些滤镜支持普通的开关选项。如果滤镜支持时间剪辑,那么选项可以被设置成为表达式,在将数据帧传送给滤镜处理前对表达式求值,如果求值结果不等于0,那么允许滤镜对数据进行处理,否则数据将不被处理直接传送给下一个滤镜。
    表达式接受一下值:
    ‘t’:时间戳(单位为s),如果时间戳未知,则值为NAN
    ‘n’:输出数据帧的序号,从0开始
    ‘pos’:输入数据帧在整个文件中的未知,若未知则值为NAN
    ‘w’、’h’:输入视频帧的宽和高。
    此外,这些滤镜还支持’enable’命令,用于使能这些表达式。
    和其他任何滤镜选项一样,’enable’选项遵守同样的规则。
    例:为允许blur滤镜在10s到3分钟的时间段内处理数据;

    smartblur = enable='between(t,10,3*60)',
     例:从3s开始允许curves滤镜开始处理数据;
    curves = enable='gte(t,3)' : preset=cross_process

你可能感兴趣的:(FFmpeg中的滤镜)