媒体流格式说明
本文旨于说明常见的音视频裸流编码格式、媒体封装格式以及原始数据码流格式,以便后续快速了解音视频数据结构。
音视频裸流编码格式主要以H.264(AVC)、MPEG4、AAC、MP3为例进行说明;
媒体(容器)封装格式部分主要以AVI、MP4、以及PS/TS流为例进行说明;
原始数据码流格式部分主要简单说明原始数据格式YUV、RGB及PCM的存储结构;
1 音视频裸流编码格式
1.1 视频裸流H.264编码格式
1.1.1 H.264简介
H.264是一种高度压缩数字视频编解码器标准,由ITU-T视频编码专家组(VCEG)和ISO/IEC动态图像专家组(MPEG)联合组建的联合视频组(JVT,Joint Video Team)共同制定,由此H.264既是ITU-T的H.264标准,又是ISO/IEC的MPEG-4标准的第10部分:高级视频编码(AVC,Advanced Video Coding),因而H.264别名为AVC、MPEG-4 Part 10以及ISO/IEC 14496-10,H.264采用的核心算法是帧内压缩和帧间压缩,帧内压缩是生成I帧的算法,帧间压缩是生成B帧和P帧的算法。
1.1.2 H.264帧结构
在H.264视频编码中,视频被分为多个GOP(Group Of Picture)序列;
帧的类型有I帧(关键帧)、B帧(双向预测帧)、P帧(前向预测帧),一个GOP由一个I帧和多个B、P帧组成;
一帧又被分为多个片(Slice,也有译为“条带”),片的类型也可分为I片、B片、P片;(通常编解码一帧即一片)
一个片又被分为多个宏块(MB,MacroBlock),一个宏块由16*16的YUV数据组成;
宏块又可视复杂度分为子块,此处不做深究,H264编码的基本单位就是宏块
1.1.3 H.264功能结构
H.264的功能分为两层,视频编码层(VCL,Video Coding Layer)和网络提取层(NAL,Network Abstraction Layer),主要有以下两个目的:
其一,可以分别定义VCL视频压缩处理与NAL网络传输机制的接口,这样允许视频编码层VCL的设计可以在不同的处理器平台进行移植,而与NAL层的数据封装格式无关;
其二,VCL和NAL都被设计成工作于不同的传输环境,异构的网络环境并不需要对VCL比特流进行重构和重编码;
视频编码层 (VCL) | 进行视频编解码,包括运动补偿预测,变换编码和熵编码等功能,目的是在尽可能独立于网络的情况下进行高效地编解码 |
网络提取层 (NAL) | 采用适当的格式对VCL视频数据进行封装打包,覆盖了所有的片级以上的语法级别 |
1.1.4 H.264编码框图
H.264编码的基本单元为宏块,对于一个宏块,可能采用帧内预测(Intra)也可能采用帧间预测(Inter)(I帧只有帧内预测模式);
帧内预测编码:Fn表示当前帧,Fn内的宏块根据周围已经编码的宏块单元进行方向性帧内预测,得出当前宏块的预测值P,与真实值Fn相减获得残差块Dn,之后对其进行变换T以及量化Q,获得(精度较粗糙)的数据X经由Reoder扫描(将二维数据重排为一维数据)以及后续的Entorpy Encode(熵编码),完成VCL层的编码功能,即得出NAL数据;
帧间预测编码:Fn内的宏块根据参考帧F'n-1进行运动估计(Motion Estimation,ME)以及运动补偿(Motion Compensation,MC)得到一个运动矢量差(MV difference,MVD),根据已编码的参考图像经过MC后得到当前宏块的预测值P,与真实值Fn相减后得到残差块Dn,后续同为变换T -->量化Q -->Reoder扫描 -->Entorpy Encode(熵编码),并最终得出NAL数据;
(数据送入NAL层的同时,会在X位置(扫描前)进行反量化Q-1和反变换T-1,然后和之前的残差块Dn相加,经过滤波得到当前帧重构的宏块,用于之后相邻宏块的帧内编码参考;)
1.1.5 H.264解码框图
H.264解码基本可以理解为编码的逆流程,由NAL中获得码流数据,经由熵解码和重排后获得数据X,经过反量化Q-1和反变换T-1获得残差块Dn;
帧内预测解码:根据周围宏块信息以及熵解码获取的相关信息获取当前宏块编码的预测方向,并以此得到预测值P,加上残差块Dn,获得当前宏块的预测值uF'n,获得预测值后进行环路滤波进行重构,最终获得解码后数据F'n(同样重构数据对于之后的宏块预测是有用的) ;
帧间预测解码: 根据当前宏块的参考帧信息(熵解码时获得)以及当前块周围的宏块信息进行获取预测值P,根据参考帧对应宏块的MV信息预测当前宏块的MV,从解码流中获得MVD,根据MVD获得当前宏块在参考帧中对应的位置通过亮度插值运算,色度插值运算,获得当前宏块的预测值再加上残差系数,获得当前宏块的预测值uF'n,并进行环路滤波进行重构,最终获得解码后数据F'n;
1.1.6 H.264 帧序列
H.264协议中只规定了bits流格式,没有规定RTP包格式,输出数据都封装为一个个NAL单元(NAL Unit)进行传递,NALU间以起始码前缀 (start_code_prefix_one_3byte[1] “0x000001”或zero_byte[2] “0x00”+ start_code_prefix_one_3bytes “0x000001”)为界,组合形成总的H.264码流。
NALU的类型常见有以下几种:SPS、SEI、PPS、I片、B片、P片以及图像分界符,常见帧序列如下:
SPS | SEI | PPS | I片 | 图像分界符 | P片 | P片 | P片 | … … | P片 |
[2]zero_byte 0x00
如果当前的NALU为sps、pps或者一个访问单元(access unit)的第一个NALU,如一帧的首个Slice NALU,这个字节就会存在。
1.1.7 H.264 NALU结构
单个NALU结构如图NAL Unit ,编码流程如下:
- VCL层视频编码后输出的原始数据字节流(SODB,String of data bits ),然而SODB通常无法字节对齐;
- 因此在添加结尾比特(RBSP trailing bits 1bit“1”)以及若干比特的“0”后,形成字节对齐的原始字节序列载荷(RBSP,Raw Byte Sequence Payload);
- 由于NAL Unit起始码前缀为“0x 00 00 01”或“0x 00 00 00 01”,且无法保证原始数据中不存在“0x 00 00 01”或“0x 00 00 00 01”,因此H.264标准中为防止竞争校验字节,在RBSP内部中添加“特殊的字节0x03(emulation_prevention_three_byte)”组成拓展字节序列载荷EBSP;
- EBSP全称为Extended Byte String Payload,等同于NAL Body的数据本身;
- 最后在EBSP前加上1字节的NAL Header (详见NAL头定义)和Start Code Prefix即为一个完整的NAL单元。
Start Code Prefix (3、4 Bytes ) 0x000001 Or 0x00000001 | NALU ( NAL Unit ) | ||||
NAL Header(1 Bytes) | NAL Body( EBSP,Extended Byte String Payload ) | ||||
forbidden_bit (1 bit) | nal_reference_bit (2 bit) | nal_unit_type (5 bit) | ( RBSP, Raw Byte Sequence Payload ) | ||
VCL ( SODB, String of data bits ) | RBSP trailing bits |
表:NAL头定义
NAL Header (1 Bytes) | |||
forbidden_bit | 禁止位 | 1 bit | 在 H.264 规范中规定了这一位必须为‘0’,值为‘1’表示语法出错。 |
nal_reference_bit | 重要性标志 | 2 bit | 当前NALU的重要性,值为‘00’的NALU,可被解码器丢弃而不影响图像的回放。取值越大,表示当前NAL越重要。 如果当前NALU是属于参考帧(I帧)的片,或是SPS、PPS这些重要的单位时,本句法元素必需大于0。 |
nal_unit_type | NALU类型 | 5 bit | 1~12由H.264使用,24~31由H.264以外的应用使用,如NAL Type所示; |
表:NAL Type
nal_unit_type值 | NALU类型 | |
0 | 0 0000(B) | 未使用 |
1 | 0 0001(B) | 不分区、非IDR的片(P片或B片) |
2 | 0 0010(B) | 片分区A |
3 | 0 0011(B) | 片分区B |
4 | 0 0100(B) | 片分区C |
5 | 0 0101(B) | IDR图像中的片(I片) |
6 | 0 0110(B) | 补充增强信息单元(SEI) |
7 | 0 0111(B) | 序列参数集(SPS) |
8 | 0 1000(B) | 图像参数集(PPS) |
9 | 0 1001(B) | 分界符 |
10 | 0 1010(B) | 序列结束 |
11 | 0 1011(B) | 码流结束 |
12 | 0 1100(B) | 填充 |
13—23 | 0 1101—1 0111(B) | 保留 |
24—31 | 1 1000—1 1111(B) | 不保留 |
1.1.8 H.264 NALU Type解析
上图为一个封装为PS流的H.264编码视频文件的16进制码;
其中绿色框内的为序列参数集(SPS)类型的NALU,由其第五个字节‘0x 67’可知:
0x 67= 0110 0111(B),后5个比特为‘0 0111’,参考表NAL Type,对应的NALU类型为序列参数集SPS;
其中紫色框内的为图像参数集(PPS)类型的NALU,由其第五个字节‘0x 68’可知:
0x 68= 0110 1000(B),后5个比特为‘0 1000’,参考表NAL Type:对应的NALU类型为图像参数集PPS;
其中蓝色框内的为I帧类型的NALU,由其第五个字节‘0x 65’可知:
0x 65= 0110 0101(B),后5个比特为‘0 0101’,参考表NAL Type:对应的NALU类型为I帧;