FFmpeg编程开发笔记 —— 基本概念

视频格式

视频格式本地影像视频和网络流媒体影像视频两大类。常见的格式有:
MPEG/MPG/DAT:
MPEG-1 广泛用于VCD,MPEG-2 用于DVD制作;
MPEG-1和MPEG-2是采用相同原理为基础的预测编码、变换编码、熵编码及运动补偿等第一代数据压缩编码技术
MPEG-4 是基于第二代压缩编码技术制定的国际标准,它以视听媒体对象为基本单元,采用基于内容的压缩编码,以实现数字视音频、图形合成应用及交互式多媒体的集成
AVI 音频视频交错(Audio Video Interleaved)的英文缩写
MOV Mac上QuickTime使用的视频格式
ASF 高级流格式
WMV 一种独立于编码方式的在Internet上实时传播多媒体的技术标准,Microsoft公司希望用其取代QuickTime之类的技术标准以及WAV、AVI之类的文件扩展名
NAVI 是New AVI 的缩写,是一个名为Shadow Realm 的地下组织发展起来的一种新视频格式
3GP 是一种3G流媒体的视频编码格式,主要是为了配合3G网络的高传输速度而开发的
MKV 是一种全称为Matroska的新型多媒体封装格式,这种先进的、开放的封装格式已经给我们展示出非常好的应用前景
FLV 是FLASH VIDEO的简称,FLV流媒体格式是一种新的视频格式
F4V 作为一种更小更清晰,更利于在网络传播的格式,F4V已经逐渐取代了传统FLV,也已经被大多数主流播放器兼容播放,而不需要通过转换等复杂的方式。F4V是Adobe公司为了迎接高清时代而推出继FLV格式后的支持H.264的F4V流媒体格式。FLV格式采用的是H263编码,而F4V则支持H.264编码的高清晰视频,码率最高可达50Mbps
RMVB的前身为RM格式,它们是Real Networks公司所制定的音频视频压缩规范,根据不同的网络传输速率,而制定出不同的压缩比率,从而实现在低速率的网络上进行影像数据实时传送和播放,具有体积小,画质也还不错的优点。
WebM 影片格式其实是以 Matroska(即 MKV)容器格式为基础开发的新容器格式,里面包括了 VP8 影片轨和 Ogg Vorbis 音轨,其中Google将其拥有的VP8视频编码技术以类似BSD授权开源,Ogg Vorbis 本来就是开放格式

音频格式

CD 格式、 格式、 WAVE(*.WAV)、 AIFF、AU 、MP3 、MIDI 、WMA、RealAudio、VQF、OggVorbis、 AAC、APE

字幕格式

外挂字幕:是视频文件和字幕文件分离,播放时导入字幕文件
内嵌字幕:视频文件和字幕文件已经集成到了一起,没有办法改变和去掉

外挂字幕视频与内嵌字幕视频的画面比较
外挂字幕相对于内嵌字幕来说,视频质量的损害小很多。

外挂字幕的格式

srt格式:这是最好的,体积小,用记事本可以打开编辑
sub+idx:这是图形字幕,只能用字幕转换软件,体积比较大
ass 字幕:网上比较少,比srt多一些特效

采集录制和播放渲染

视频采集(Video Capture)吧模拟视频转换成数字视频,并按数字视频文件的格式保存下来。所谓视频采集就是将模拟摄像机、录像机、LD视盘机、电视机输出的视频信号,通过专用的模拟、数字转换设备,转换为二进制数字信息的过程。

编解码器

编解码器指一个能够对信号或者数据流进行变换的设备或程序。这里指的变换既包括将信号或者数据流进行编码(通常是为了传输、存储或者加密) 或者提取得到一个编码流的操作。
多媒体数据通常包含音频/视频数据,这是常常会加入一些用于音频和视频数据同步的元数据。这三种数据流可能会被不同的程序,进程或硬件处理,但当他们传输或者存储的时候,这三种数据通常是被封装在一起的。

容器格式和编码格式

文件既包括视频又包括音频,甚至还带有脚本的集合,也可以叫容器
文件当中的视频和音频的压缩算法才是具体的编码

多媒体容器文件格式

文件格式一般包括文件头部分、索引部分和多媒体数据部分
文件头部分:说明多媒体数据符合的压缩标准和规范信息,多媒体数据符合的规范信息可以包括视频的分辨率、帧率,音频的采样率等
索引部分:多媒体数据通常会被分成若干块,各块数据之间也可能不连续存储,因此需要在索引部分建立多媒体数据的存储位置索引
多媒体数据部分:就是经过压缩的多媒体数据,包括视频数据、音频数据、文本数据以及其他多媒体数据

协议

音视频压缩标准方面,mpeg系列的协议是 iso指定的标准,而h系列的协议是itu制定的标准。

视频协议

主要的视频压缩协议: h.261、h263、h264、mpeg-1、mpeg-2、mpeg-4等
从技术角度来说,h系列的协议对网络的支持更好些,mpeg系列则算法上更先进一些,主要用来做存储协议。

音频协议

音频协议也氛围两大类,itu组织主要是用于视频会议的g系列协议,包括g711、g722、g723、g726、g728、g729等。这些协议比较关注语音压缩,毕竟开会主要是要听人讲话,对音乐的压缩效果不太好,压缩率比较大,码率比较低。iso的协议包括mp3、aac(mp4),mp3全称 mpeg-1 audio layer 3,aac 定义在mpeg-2 或 mpeg-4的音频部分。iso协议的特点是音质好,支持多声道,高采样精度和采样频率,尤其对音乐的压缩效果比g系列协议要好太多了。

上层通讯协议

视频会议系统中,目前最流行的有h323 和 sip 协议,在流媒体应用中,isma,rtsp,rtmp应用得比较多。h323主要用于视频会议,h系列视频压缩协议和g系列音频压缩协议都属于它的子协议。sip协议是由ietf提出的应用控制协议。h323 和 sip分别是通信领域与因特网两大阵营推出的。rtsp主要用于流媒体传输,英文名为 real time streaming protocol。

硬解

视频解码分为软解和硬解
软解就是通过软件使用CPU对视频进行解码处理,硬解则不依赖于CPU,通过专用的设备单独完成视频解码。目前主流的GPU都将硬解码模块整合进去了。
硬解的优势:
CPU占用低,功耗低等
劣势:
硬解码兼容性不够软解强。并且,软解拥有大量画面输出补偿以及画质增强技术,而硬解这方面做得远远不够

IBP帧

基本概念:
I Frame: 帧内编码帧,又称为 intra picture, I帧通常是每个GOP(MPEG
所使用的一种视频压缩技术)的第一个帧,I帧是一个图像经过压缩后的产物。
P Frame:前向预测编码帧,又称 predictive-frame。通过充分将低于图像序列中前面已编码帧的时间冗余信息来压缩传输数据量的编码图像,也叫预测帧。
B Frame: 双向预测内插编码帧,又叫 bi-directional interpolated frame,既考虑与源图像序列前面已编码帧,也顾及源图像序列后面已编码帧之间的时间冗余信息来压缩传输数据量的编码图像,也叫做双向预测帧
PTS:Presentation Time Stamp PTS主要用于度量解码后的视频帧什么时候被显示出来
DTS:Decode Time stamp DTS主要标识读入内存中的bit 流在什么时候开始送入解码器中进行解码
在没有B帧存在的情况下,DTS 和 PTS 的顺序应该是一样的。

IBP的特点

I帧特点:
全帧压缩编码帧。
解码时,仅用I帧数据就可重构完整图像
I帧描述了图像北京和运动主体的详情
I帧不需要参考其他画面而生成
I帧是帧组(GOP)的基础帧,其质量直接影响到同组中后面各帧的质量
I帧不需要考虑运动矢量
I帧所占数据的信息量比较大
P帧特点:
P帧预测与重构:P帧是以I帧为参考帧,I帧中某点的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧某点的预测值并与差值相加得到P帧某点的实际值,从而可得到完整的P帧。
P帧是I帧后面像个1~2帧的编码帧
P帧采用运动补偿的方法传送它与前面的I或P帧的差值以及运动矢量
解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像
P帧属于前向预测的帧间编码,只参考前面最靠近它的I帧或者P帧
P帧可以是其后面P帧的参考帧,也可以时其前后的B帧的参考帧
由于P帧是参考帧,它可能造成解码错误的扩散
由于是差值传送,P帧的压缩比较高
B帧特点:
B帧以前面的I或者P帧和后面的P帧为参考帧,找出P帧某点的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中找出预测值并与差值求和,得到B帧某点的值,从而得到完整的B帧
B帧是由前面的I或P帧和后面的P帧之间的预测误差及运动矢量
B帧是双向预测编码帧
B帧压缩比最高,因为它只反映两个参考帧间运动主体的变化情况,预测比较准确。
B帧不是参考帧,不会造成解码错误的扩散。
IBP各帧是根据压缩算法的需要,是人为定义的。它们都是实实在在的物理帧,至于图像中哪一帧是I帧,是随机的,一旦确定了I帧,以后的各帧就严格按照规定顺序排列。
如果视频流只有I帧和P帧,解码器可以不管后面的数据,边读边解码,线性前进。但网络上的电影很多都采用了B帧,因为B帧记录的是前后帧的差别,比P帧能节约更多的空间,但这样一来,文件笑了,解码器就麻烦了。在解码时,不仅要缓存前面的画面,还要知道下一个I帧或P帧的画面,而且B帧不能简单地丢掉,因为B帧也包含了画面信息,如果简单丢掉,并用之前的画面简单重复,就会造成画面卡(丢帧)。
I的压缩率是7,根JPG差不多,P是20,B可以达到50,使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质

GOP Group of Pictures 画面组

GOP策略影响编码质量:一个GOP就是一组连续的画面。MPEG编码将画面(即帧)分为 IBP三种。没有I帧,P帧和B帧就无法解码。这是MPEG格式难以精确剪辑的原因。

MPEG-2 压缩的帧率结构有两个参数,一个是GOP 图像组的长度,一般可按编码方式从1~15;另一个是I帧和P帧之间B帧的数量, 一般是1~2个。

MPEG-4视频中的IBP的判定

每一帧开头固定为: 00 00 01 b6, 接下来的 2 bit 标志了帧的类型:
00:I Frame
01:P Frame
10:B Frame
也就是说,我们看到的MPEG-4 视频帧的16进制格式如下:
00 00 01 b6 10 34 26 59 07 33 ... I帧
00 00 01 b6 50 34 26 59 07 33 ... P帧
00 00 01 b6 96 34 26 59 07 33 ... B帧
I帧、P帧、B帧对应的数值:
0x10 = 0001 0000
0x50 = 0101 0000
0x96 = 1001 0000

帧率(FPS)
画面刷新的速度。国内电视机一般是25FPS,电影标准是24FPS

FFmpeg中的时间单位

  • AV_TIME_BASE
    声明:
#define         AV_TIME_BASE   1000000

定义:
FFmpeg的内部计时单位(时钟基准),ffmpeg中的所有时间都基于它。

  • AV_TIME_BASE_Q
    声明:
#define         AV_TIME_BASE_Q   (AVRational){1, AV_TIME_BASE}

定义:
FFmpeg时钟基准的分数表示。

  • AVRational
    声明:
typedef struct AVRational {
int num;
int den;
} AVRational;

定义:
AVRational结构体是用来存放时钟值的,FFmpeg提供了把AVRational结构转换成double的函数:

static inline double av_q2d(AVRational a){
    return a.num / (double) a.den;
}

因此,实际的pts时间值计算一般是如下:

PresentationTimeStamp = pts * av_q2d(pStream->time_base);

经过前面的转换后,我们得到的显示时间戳就是实际的是时钟值了。
因此,视频长度计算如下:

durationTime = pStream->duration * av_q2d(pStream->time_base);

这里的durationTime 就是实际的时长秒数。

从这里可以看出,ffmpeg中的时间基准其实是以微妙(10 的 -6 次方)为单位的,因此我们需要利用时间time(秒)求出FFmpeg的内部时间戳,相互转换如下:

ts = AV_TIME_BASE * time(秒)
time(秒) = AV_TIME_BASE_Q * ts

因此,我们在开发一个定位到某个毫秒级的关键帧上,如何如下:

// 将需要定位的毫秒ms转换成FFmpeg的内部时间戳
uint64_t timestamp = ms * AV_TIME_BASE / 1000.0f;
// 定位到某个关键帧:
av_seek_frame(pFormatCtx, streamIndex, timestamp, AVSEEK_FLAG_BACKWARD);

推荐阅读更多精彩内容