文章目录
FFmpeg学习(一)开篇
为什么要学习FFmpeg
本人希望打算深入研究音视频领域,音视频领域的内容很多,我自己打算从几方面循序渐进:FFmpeg常用功能实践, FFmpeg源码研究, OpenGL
, OpenGLES
, Metal
, AR
, WebRTC
, 直播架构等方向去研究。
音视频目前主要有哪些应用场景呢?
- 直播类:音视频会议,教育直播,娱乐/游戏直播等 (例如花椒,映客,腾讯课堂,腾讯会议, 斗鱼)
- 短视频:抖音,快手,小咖秀等, 这类应用主要是对声音和视频做特殊处理,如声音变声,变调,男声变女声,女声变童声;如视频处理有:美颜,滤镜处理。
- 网络视频: 优酷,腾讯视频,爱奇艺等。
- 音视频通话:微信,QQ, Skype等。
- 视频监控: 网络摄像机IPC等
- 人工智能:人脸识别,智能音箱等,这类应用更关注于算法。
从上面这么多应用场景,我们可以看出音视频技术是多么重要,特别是5G时代,网络传输问题大大提升,更多的音视频需求会爆发出来。
我们可以看一下一个简单播放器的架构,如下图:
音频解码,视频解码一般都用FFmpeg解码,在IOS8 之后提供了VideoToolBox框架支持硬解码。
而视频渲染一般使用OpenGL直接用GPU渲染,视频渲染第三方框架有GPUImage, SDL, VLC
音频视频播放涉及到音视频同步是一个 复杂的技术。
学习一个技术,需要一个高效的方法,只有不断的实践才能理解深刻。学习FFmpeg我们也需要好的文档来学习,下面列举一些必备的学习文档地址:
- FFmpeg官方文档:http://ffmpeg.org/documentation.html
- FFmpeg官方wiki: https://trac.ffmpeg.org
上述都是英文的文档,如果英文学习困难,可以参考下面的中文资料:
- 雷霄骅博士总结的资料: http://blog.csdn.net/leixiaohua1020
- 罗索实验室:http://www.rosoo.net
- ChinaFFmpeg: http://bbs/chinaffmpeg.com
此外推荐两本非常好的书籍:
- FFmpeg从入门到精通
- 音视频开发进阶指南:基于Android与iOS平台的实践
1. FFmpeg简介
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL
或GPL
许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec
,为了保证高可移植性和编解码质量,libavcodec
里很多code
都是从头开发的。
FFmpeg在Linux
平台下开发,但它同样也可以在其它操作系统环境中编译运行,包括Windows
、Mac OS X
等。这个项目最早由Fabrice Bellard发起,2004年至2015年间由Michael Niedermayer主要负责维护。许多FFmpeg的开发人员都来自MPlayer
项目,而且当前FFmpeg也是放在MPlayer
项目组的服务器上。项目的名称来自MPEG视频编码标准,前面的"FF"代表"Fast Forward"
- 一个伟大的软件产生必定有它的一段传奇历史,FFmpeg的创建者是法国天才程序员Fabrice Bellard (法布里斯*贝拉)在 2000年是开发出初版;
法布里斯*贝拉:
- 高中就读期间开发了著名的可执行压缩程序LZEXE
- 2000年创建了FFmpeg项目
- 2011年,他用JavaScript写了一个Linux虚拟机(JSLinux)
- 他还是QEMU,TinyCC 的作者
-
2004年,迈克尔(Michael Niedermayer)接管FFmpeg, 迈克尔将滤镜子系统
libavfilter
加入FFmepg项目中,使得FFmpeg的多媒体处理更加多样,更加方便。在FFmpeg发布了0.5版本后,很长一段时间没有进行新版本的发布,直到后来FFmpeg采用Git作为版本控制服务器以后才开始继续更新发布版本。 -
2011年3月, 由于FFmpeg项目中有一些提交者对FFmpeg的项目管理方式和发展方向不一致,FFmpeg团队分成了两派,其中一派认为FFmpeg应该更加专注于音视频开发,研究更新先进的音视频技术,这些人重新创建了一个新的项目叫
Libav
。 另外一派认为他们要兼顾老的FFmpeg技术,然后逐步发展。 -
2015年8月迈克尔主动辞去FFmpeg项目负责人的职务。迈克尔从Libav中移植了大量的代码和功能到FFmpegZhong , 从此Libav又和FFmpeg合并一起发展。
2. FFmpeg能做什么
- 多媒体视频处理工具FFmpeg有非常强大的功能包括视频采集功能、视频格式转换、视频抓图、给视频加水印等
- 视频采集功能:
ffmpeg视频采集功能非常强大,不仅可以采集视频采集卡或USB
摄像头的图像,还可以进行屏幕录制,同时还支持以RTP
方式将视频流传送给支持RTSP
的流媒体服务器,支持直播应用。
- 在Linux平台上,
ffmpeg
对V4L2
的视频设备提供了很好的支持,如:./ffmpeg -t 10 -f video4linux2 -s 176*144 -r 8 -i /dev/video0 -vcodec h263 -f rtp rtp://192.168.1.105:5060 > /tmp/ffmpeg.sdp
以上命令表示:采集10秒钟视频,对video4linux2视频设备进行采集,采集QCIF(176*144)的视频,每秒8帧,视频设备为/dev/video0,视频编码为H263,输出格式为RTP,后面定义了IP地址及端口,将该码流所对应的SDP文件重定向到/tmp/ffmpeg.sdp中,将此SDP文件上传到流媒体服务器就可以实现直播了。- 在windows下关于ffmpeg视频采集的资料非常少,但是ffmpeg还是支持windows下视频采集的。ffmpeg支持windows下video for windows(VFW)设备的视频采集,不过
VFW
设备已经过时,正在被WDM
的视频设备所取代,但是ffmpeg还没有支持WDM的计划,不过好像有将WDM转为VFW的工具,因此ffmpeg还是可以在windows下进行视频采集的。
- 视频格式转换功能:
- ffmpeg视频转换功能。视频格式转换,比如可以将多种视频格式转换为flv格式,可不是视频信号转换 。
- ffmpeg可以轻易地实现多种视频格式之间的相互转换(
wma
,rm
,avi
,mod
等),例如可以将摄录下的视频avi
等转成视频网站所采用的flv
格式。
- 视频截图功能:
- 对于选定的视频,截取指定时间的缩略图。视频抓图,获取静态图和动态图,不提倡抓
gif
文件;因为抓出的gif
文件大而播放不流畅。- 给视频加水印功能
- 使用ffmpeg 视频添加水印(
logo
)。
3. FFmpeg架构模块组成
我们先看一下一张FFmpeg的架构图:
下载好的源码,我们也可以看到大概的源码结构:
3. 1 libavutil
- libavutil : 包含一些公共的工具函数;
AVUtil是FFmepg的核心工具库,该模块是最基础的模块之一,下面的许多其他模块都会依赖该库做一些基本的音视频处理操作。
3. 2 libavformat
- libavformat:用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能;
- AVFormat 是文件格式和协议库,封装了Protocol层和Demuxer,Muxer层,使得协议和格式对于开发者来说是透明的。
AVFormat
中实现了目前多媒体领域中的绝大多数媒体封装格式,包括封装和解封装,如MP4
,FLV
,KV
,TS
等文件封装格式,RTMP
,RTSP
,MMS
,HLS
等网络协议封装格式。
FFmpeg是否支持某种媒体封装格式,取决于编译时是否包含了该格式的封装库。根据实际需求,可进行媒体封装格式的扩展,增加自己定制的封装格式,即在AVFormat中增加自己的封装处理模块。
3. 3 libavcodec
- libavcodec:用于各种类型声音/图像编解码;
AVCodec是编解码库,该模块封装了Codec层,但是有一些Codec是具备自己的License的,FFmpeg是不会默认添加像libx264,FDK-AAC,lame等库的,但是FFmpeg就像一个平台一样,可以将其他的第三方的Codec以插件的方式添加进来,然后为开发者提供统一的接口。
AVCodec中实现了目前多媒体绝大多数的编解码格式,既支持编码,也支持解码。
AVCodec除了支持MPEG4,AAC, MJPEG等自带的媒体编解码格式之外,还支持第三方的编解码器,如H.264(AVC)编码,需要使用x264编码器; H.265(HEVC)编码,需要使用x265编码器; MP3(mp3lame)编码,需要使用libmp3lame编码器。如果希望增加自己的编码格式,或者硬件编解码,则需要在AVCodec中增加相应的编解码模块。
3. 4 libavfilter
- AVFilter : 是音视频滤镜库,该模块提供了包括音频特性和视频特效的处理,在使用FFmpeg的API进行编解码的过程中,直接使用该模块为音视频数据做特效处理时非常方便同时也非常高效的一种方式。
3. 5 libavdevice
- AVDevice : 输入输出设备,比如,需要编译出播放声音或者视频的工具ffplay,就需要确保该模块是打开的,同时也需要libSDL的预先编译