前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >刘歧:FFmpeg Filter深度应用

刘歧:FFmpeg Filter深度应用

作者头像
LiveVideoStack
发布2021-09-01 11:10:58
5380
发布2021-09-01 11:10:58
举报
文章被收录于专栏:音视频技术音视频技术

本文来自OnVideo视频创作云平台联合创始人刘歧在LiveVideoStackCon的讲师热身分享,刘歧分享了FFmpeg的基本原理、使用方法及开发方法。在10月19-20日的LiveVideoStackCon 2018上,刘歧还将分享如何通过FFmpeg实现视频版权保护的方法。

文 / 刘歧

整理 / LiveVideoStack

直播回放:

https://www.baijiayun.com/web/playback/index?classid=18081550127330&session_id=201808160&token=UpmOXagOUwZt681rrJ0J_fi3uef2YslR9xPZowdmKaIVnKE7ZcXWwkkNnUrZm8So4_FWYYdehfAKp0fXMnVKLQ

大家好我是刘歧,目前和几个朋友一起创办了视频云创作平台OnVideo,主要负责做一些新功能预研和整体方向把控。

今天主要从四个方面来介绍一下FFmpeg的滤镜深度应用:

1. Filter基本原理

2. Filter使用方法

3. Filter开发基础

4. Filter开发

一. Filter基本原理

基本原理的理解可以从以下六点出发:

  1. 线性属性:滤镜是一个线性的属性,是一步接着一步的往下走的,当然也可以有多线程的,但是多线程的实现不是特别好,一般的实现都是通过单线程来线性处理的。
  2. 输入输出标签:滤镜都有输入和输出的标签。
  3. 滤镜名
  4. 滤镜参数:当我们在使用某一类滤镜时,需要知道对应的参数大小,如位置,宽高等。
  5. 内置变量:在使用滤镜时,可以用到它的很多内置变量,如帧率,PTS等,这些变量可以在命令行中使用,在调用API时也会用到。
  6. 压缩前、解压后的YUV/RGB/PCM数据:对数据进行滤镜处理时使用的都是原始数据,也就是未压缩的数据。

线性处理图解

如上图所示,从滤镜线性处理图中可以看出,对每一个的滤镜处理过程必须要有输入和输出,比如在最后滤镜8的位置没有输出1来承接它的结果,则会报错。另外,如从滤镜1到滤镜2的过程,滤镜1的输出Out可以作为滤镜2的输入In,从滤镜2再往后,滤镜2的输出Out可以分为两部分,分别作为其它滤镜处理的输入。

原始数据处理

滤镜的处理都是基于原始数据来进行的,比如视频图像的每一帧,当然也包括音频。如上图所示,每一帧可以有前后的多个层,一般情况下是两层,当有多层时,如Frame1是三层,则可以先处理前两层,处理之后合并成一层,再跟另一层一起去做处理。当处理完Frame1后送到编码器进行编码,再依次处理Frame2、Frame3、Frame4,处理完后均送到编码器进行压缩编码为另一个格式,比如H.264。

二. Filter使用方法

1. 常用滤镜

常用的滤镜中重点的是:scale、trim、overlay、yadif、rotate、movie

比如常用的scale 可以用来做缩放,trim可以做比较精确的帧级的剪切,overlay可以来实现视频混流,画中画或多画面等叠加处理,rotate来做旋转,movie可以加载第三方的视频等等,yadif可以在摄像机上做隔行扫描,在PC端的播放器可以做去交错。另外,还有delogo、crop、colorkey、chromakey、zoompan; delogo可以用来模糊化某一区域,crop用于图像区域剪切,colorkey和chromakey是用于抠图的,chromakey以YUV输入为主,colorkey以RGB输入为主,zoompan可以将图像放大。

2. 命令行

ffmpeg -filters

通过这一命令,可以列出所有的滤镜,但需要弄清楚每一个滤镜的作用,比如上图的adelay,它的作用是音频转音频,延缓一个或更多的音频通道。在滤镜参数里面还包括timeline support、slice threading、command support,等在后面也会有介绍。

ffmpeg -h filters=rotate

当某个滤镜不知道它里面都有什么参数或者参数怎么用时,那么可以通过上面这条help命令去查看滤镜的内容。比如在上图,查看旋转(rotate)滤镜,可以看出它支持slice threading,而在最下面可以看到还支持timeline操作,并且输入和输出都是Video格式,再下面就是rotate的一些参数,值得注意的是,在FFmpeg里面,尤其滤镜这部分,为了让大家在输入参数时候更简单,它会把很长的参数提供一个简化的名称。

命令行的使用开头都是:filter_complex,然后再在后面接一些字符串,如下:

下面列出几个例子的命令行使用:

1. 跑马灯

代码语言:javascript
复制
[0:v][1:v]overlay=x='if(gte(t,0), -w+(mod(n, W+w))+5, NAN)':y=0[out]

应用场景如新闻播放时画面下方的小栏预告,从右跑到左。

2. 图像旋转

代码语言:javascript
复制
[1:v]rotate=a=60*PI/180:ow=180:oh=180[v1];[0:v][v1]overlay=x=-20:y=-20[o]

3. delogo(模糊化某一区域)

代码语言:javascript
复制
delogo=x=72:y=32:w=168:h=86:band=1:show=1

下图为以上三条命令行处理后的展示效果:

在FFmpeg的ffplay里可以通过dumpgraph对滤镜的处理过程增加更深的了解,可以看看下面这个例子:

代码语言:javascript
复制
./ffplay -dumpgraph 1 -f lavfi "movie=a.flv[l];movie=logo.png[r];[l][r]overlay=x=0:y=0"

在滤镜处理的过程中是先加载第一个电影,然后再加载一张PNG图片,为了叠加处理比较方便会先将它们转换成YUV,再进行叠加运算,最后输出到一个buffersink中。

3. API

滤镜Filter的API结构包括:

AVFilterContext:滤镜的上下文

AVFilterInOut:滤镜的输入、输出

AVFilterGraph:滤镜的图结构

AVFilter:滤镜的具体处理类

AVFilterPad:包括输入的Pad和输出的Pad

调用API的分为两个大的步骤:

第一步,滤镜的初始化

初始化部分首先要确定In的Buffer和Out的Buffersink,接下来就是创建一个滤镜的Graph,再就是做一个滤镜的解析,最后就是通用配置。

第二步,滤镜处理

滤镜处理过程是先解码,解码之后将帧加入到Buffer,再调用滤镜处理模块,处理之后输出到Buffersink。

滤镜API的使用方法跟之前命令行的使用方法是一样的,只是略微有一点差别。如果我们不会使用多输入多输出的方式,对于API的使用实际上它的输入也可以用字符串处理的方式,就是命令行里边的处理方式,如以下官方demo的代码:

跑马灯

代码语言:javascript
复制
[0:v][1:v]overlay=x='if(gte(t,0), -w+(mod(n, W+w))+5, NAN)':y=0[out]

图像旋转

代码语言:javascript
复制
[1:v]rotate=a=60*PI/180:ow=180:oh=180[v1];[0:v][v1]overlay=x=-20:y=-20[o]

Delogo(模糊化某一区域)

代码语言:javascript
复制
delogo=x=72:y=32:w=168:h=86:band=1:show=1

从上面的介绍可以看出,命令行与API实质上并没有太大的区别。

三. Filter开发基础

1. Module结构

在上面的Module结构里面,可以很清晰的看出步骤流程,先要在滤镜的类里面注册它所对应的所有信息,如滤镜名,上下文等等;下一步就是对Input和Output的处理,对帧的滤镜处理正常都是在一个Input里面处理的;

再就是要看滤镜是否支持Timeline,比如做一些动态的变量,跑马灯之类的,也要有时间线的概念。在这个里面也有一些对应的内置函数,可以把他们理解为一些数字运算的接口。以及下面还有一些变量名的定义。

2. 加入到FFmpeg中

添加滤镜的时候,主要是往下面两个里面添加:

四. Filter开发

在这一部分,为大家做了FFMPEG添加新滤镜的过程的录像,录像地址为http://bbs.chinaffmpeg.com/add_filter.mp4,有兴趣的同学可以看一下

首先建立了一个zoomscale的滤镜文件,建立完这个文件之后,创建对应的context,然后把刚才讲到的那些接口都写进来,定义zoomscale公共的类,下面我们实现了一个filter _frame,它会把里面的input给释放掉,让它变成一个NULL,此时显示的前景图像就会变成一个纯绿色的图像,如果说这里有process commode,那么就可以在做zmq的时候用,如果没有的话,可以留空。关键是filter_frame,可以当作滤镜处理的一个入口,而get_video_buffer可以把它理解为我们看到的很多demo里面写到的get_video_buffer,即创建一个帧的对应Buffer,将其添加至Makefile之后,继续添加一个avfilter。这是FFmpeg4.0之前的版本,在后面新版本里面,采用的是数组的形式,也就没有列表那么麻烦,速度会更快一些,添加完之后,可以通过config进行查看配置,每次config完之后,会有整体的一个输出。添加完成后,进行编译,之后可以在avfilter库里直接查看滤镜是否已经加到FFmpeg的应用程序里,然后调用API部分,直接把字符串传进来就可以使用了。

Q&A:

Q1:直播实时应用滤镜怎么处理?

A:只要性能跟的上就可以,比如说通过滤镜里可以添加OpenCV,或者OpenGL的方式。如果原来是直接调用OpenGL,想更加方便,在FFmpeg里进行处理的话,可以把它添加到FFmpeg的滤镜里面,实现对应的OpenGL方法,再调方法即可。

Q2:在FFmpeg里面滤镜处理都是线性的吗?

A:介绍是这样的,通过代码的演示可以看到滤镜的处理是一步一步进行的,处理完一帧,再处理下一帧。接口的调用也是如此。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 LiveVideoStack 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云直播
云直播(Cloud Streaming Services,CSS)为您提供极速、稳定、专业的云端直播处理服务,根据业务的不同直播场景需求,云直播提供了标准直播、快直播、云导播台三种服务,分别针对大规模实时观看、超低延时直播、便捷云端导播的场景,配合腾讯云视立方·直播 SDK,为您提供一站式的音视频直播解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档