Chinaunix首页 | 论坛 | 博客
  • 博客访问: 680378
  • 博文数量: 404
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 1237
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-03 10:45
文章分类

全部博文(404)

文章存档

2017年(1)

2016年(27)

2015年(39)

2014年(55)

2013年(66)

2012年(216)

分类: LINUX

2016-08-22 09:25:09


1 FFmpeg 的基本组成
FFmpeg 的基本组成包含Format、Codec、Filter、Devices、Utils等,结构如图:

AvFormats: 主要为媒体文件的封装格式,也可以称之为多媒体编码数据的容器,包含了音频数据,视频数据,字幕数据之类的容器;
AvCodecs:主要为媒体文件容器内的具体的数据对应的压缩方式,例如音频的aac压缩数据,音频的speex压缩数据,视频h264压缩数据等,或ASS字幕数据等;
AvFilters:主要为媒体的音频数据,视频数据进行渲染,例如多个视频文件视频数据前景与背景进行叠加、透明处理、音频重采样、音频合并等处理;
AvDevices:主要为媒体的播放输出设备,媒体的采集设备,例如音频采集设备,音频输出设备,视频的采集设备,视频的输出设备等;
Utils:主要为FFmpeg中的AVFormats,AVCodecs,AVFilters等所用到的公用的接口;
Swscale: 主要为FFmpeg中做缩放,rgb转yuv,混色计算等用的接口。


1.1 FFmpeg 的封装模块avformat
libavformat中实现了目前多媒体领域中的几乎所有封装格式,可以封装,可以解封装,根据需求不同,所支持的也有所不同,ffmpeg能否支持一种封装格式的视频的封装与解封装,完全取决于这个库,例如mp4、flv、mkv等容器的封装与解封装;又或者RTMP、RTSP、TCP、UDP等协议的封装与解封装;关于封装与解封装的操作,对CPU的消耗不会特别严重,因为封装与解封装不涉及到复杂的计算,更多的是I/O,如果希望增加自己定制的封装格式的话,需要在libavformat中增加自己的对应的format模块。通过代码的文件结构可以看得出来

1.2 FFmpeg 的编解码模块libavcodec
libavcodec中实现了目前多媒体领域几乎所有的编解码格式,可以编码,可以解码,不过有些编码需要使用第三方的编码器,例如H.264(AVC)编码需要使用x264编码器,H.265(HEVC)编码需要使用x265编码器,mp3(mp3lame)编码需要使用libmp3lame编码器等编码器,ffmpeg本身同时也支持多种编码格式,例如mpeg4、aac、mjpeg等编码,如果希望增加自己的编码格式,或者硬件编解码,需要在libavcodec中增加自己的codec模块,关于更多libavcode相关的信息以及使用信息将会在后面章节进行详细的介绍。

1.3 FFmpeg 的万金油libavfilter
Libavfilter 库提供了一个通用的 音频 / 视频滤镜框架,处理一些滤镜相关的操作。在 libavfilter中,滤镜框架可以有多个输入和多个输出。为了说明的各种存在的场景,我们参考一下下面这个filtergraph例子:

图中这个例子中的filtergraph讲输入的视频切割成了两部分流,一部分流抛给crop与vclip进行操作,另一部分保持原样,当crop与vflip操作完成后,将流合并到原有的overlay中,并显示在最上面一层,输出新的视频,对应的命令行如下:

点击(此处)折叠或打开

  1. ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT
下面看一下具体的执行情况,用来验证该命令的可行性:

运行后生成的视频结果将是视频的上半部分镜像到底部一半的输出视频;下面详细说明一下规则:
1. 相同的Filter线性链由逗号分隔
2. 不同的Filter线性链之间用分号分隔
在图示例中,crop与vflip使用的是同一个Filter线性链,split和overlay使用的是另外一个线性链,线性链接入到另一个线性链汇合处时是通过方括号’[]’括起来的标签进行标示的。在这个例子中,两个流处理后是通过[main]与[tmp]进行关联汇合的。
split filter将分割后的视频流的第二部分分配给滤镜,打上标签[tmp],将该部分流通过crop filter进行处理,然后进行纵坐标调换操作,打上标签[flip],然后将main与flip进行合并,flip标签的视频流显示的时候从视频的左边最中间的位置开始显示,就出现了镜像效果。
可以对比一下运行的前后效果:
首先代表花果山致以忠诚的问候:bbs.chinaffmpeg.com 孙悟空


1.4 FFmpeg 的视频图像转换计算模块libswscale
FFmpeg 的libswscale 模块提供了高级别的图像转换API接口。特别是,它允许一个进行图像缩放和像素格式转换。常见于将图像从1080p转换成720p或者480p等缩放,或者将图像数据从yuv420p转换成yuyv,或者yuv转rgb等图像格式转换。

1.5 FFmpeg 的音频转换计算模块libresample
FFmpeg 的libresample 模块提供了高级别的音频重采样API接口。特别是,它允许一个执行音频采样、 音频通道布局 rematrixing 和转换的音频格式和包装布局

1.6 FFmpeg 的编解码工具ffmpeg
关于ffmpeg的介绍,可以在网上搜索到很多,本节主要介绍实战,通过实战对ffmpeg进行了解会更加深刻,下面看一个例子:
ffmpeg -i input.mp4 output.avi
执行过程输出:

这是一条最简单的ffmpeg命令,可以看到,ffmpeg通过-i参数将input.mp4作为输入源输入,然后进行了转码与转封装操作,输出到output.avi中。这条命令最主要做了如下工作:
1. 获得输入源input.mp4
2. 输出文件output.avi
看似简单的两步主要的工作,其实远远不止是从后缀名为mp4的文件输出后缀名为avi的文件,因为在ffmpeg中,mp4与avi是两种流媒体格式,并不是后缀名所可以决定的,例如上面上的命令行同样可以这样写:
ffmpeg -i input.mp4 -f avi output.dat
执行过程输出:

这条ffmpeg命令相对前面的那条命令做了一些改变,加了一个“-f”进行约束,“-f”参数的工作非常重要,它制定了输出的文件的容器格式,所以可以看到输出的文件为output.dat,文件后缀为.dat,但是其主要工作依然与之前的指令相同。
分析两个图中的Output #0部分,可以看到都是avi,只是输出的文件名不同,其他内容均相同。
ffmpeg的工作主要流程也相对比较简单:
1. 解复用(Demuxing)
2. 解码(Decoding)
3. 编码(Encoding)
4. 复用(Muxing)

其中需要经过5个步骤:
1. 读取输入源
2. 读取编码的数据包
3. 解码每一帧数据
4. 输出每一帧编码
5. 输出到目标
整体工作流程与步骤可以通过流程图绘制出来:

根据图中的转码工作流程可以看出,首先ffmpeg读取输入源,然后通过Demuxer将音视频包分解开,这个动作通过调用libavformat中的接口即可实现,接下来通过Decoder进行解码,将音视频通过Decoder解包成为YVU或者PCM这样的数据,这个Decoer通过libavcodec中的接口即可实现,然后将对应的数据通过Encoder进行编码,编码可以通过libavcodec中的接口进行实现,接下来将编码后的音视频数据包通过Muxer进行封装,Muxer封装通过libavformat中的接口即可实现,输出成为输出流。


1.7 FFmpeg的播放器ffplay
FFmpeg不但可以提供转码转封装等功能,同时还提供了播放器相关的功能,使用FFmpeg的avformat与avcodec,可以播放各种媒体文件或者流。如果想要使用ffplay,系统首先需要有一个SDL库来进行ffplay的基础支撑。
ffplay与ffmpeg在FFmpeg项目中充当的角色基本相同,主要为Demo与测试使用的工具,使用ffplay可以看到一些音视频相关的图像信息,音频的波形信息等。


1.8 FFmpeg的多媒体分析器ffprobe
FFmpeg项目中的ffprobe是一个非常强大的多媒体分析工具,可以从媒体文件或者媒体流中获得到你想要了解到的媒体信息,比如音频的参数,视频的参数,媒体容器的参数信息等。
例如分析某个媒体容器中的音频是什么编码格式,视频是什么编码格式,同时还可以得到媒体文件中媒体的总时长,复合码率等信息。
使用ffprobe还可以分析媒体文件中的每个包的长度,包的类型,帧的信息等。下面举一个例子来看一下,对ffprobe会有一个基本的概念:

根据图中可以看到,使用ffprobe能够查看到mp4文件容器中的流的信息,包含了一个视频流,由于该文件中只有视频流,流相关的信息通过[STREAM][/STREAM]的方式展现出来,在[STREAM]与[/STREAM]之间的信息为该mp4文件的视频流信息。当视频文件容器中包含音频流与视频流或者更多路流时,会通过[STREAM]与[/STREAM]进行多个流的分隔,分割后区分流的索引信息采用的是index来进行区分。


阅读(518) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~