背景
在学习投屏专题开发相关课程时候,不可以避免的就是需要了解音视频相关的知识点,虽然可以使用标准的mediacodec接口等,只是实现功能的话可以不知道音视频的具体原理等。但一旦出现问题,或者深入问题分析,及相关原理等,就不得不认真学习相关音视频基础知识。比如视频最大的代表h264,还有音频最大代表aac等。
H.264的功能分两层
VCL (VideoCoding Layer,视频编码层):负责高效的视频内容表示。
NAL(NetworkAbstraction Layer,网络提取层):负责以网络所要求的恰当的方式对数据进行打包和传送。
简单直观理解如下:
VCL关心如何进行视频压缩
NAL关心压缩后的视频流如何被网络传输和解码播放
H.264码流格式情况
使用start code分隔NAL(start code为三字节或四字节,0x000001或0x00000001,为了节省码流, H.264 没有另外在 NAL 的头部设立表示起始的句法元素 。 但是如果编码数据时,由于 NAL 是依次紧密排列,解码器将无法在数据流中分辨每个 NAL的起始和终止,所以必须要有另外的机制来解决这个问题 。所以,H.264 提出方案,在存储或传输时,在每个NALU前加上0x00000001或0x000001。
NALU
VCL层是对核心算法引擎、块、宏块及片的语法级别的定义,最终输出压缩编码后的数据 SODB。VCL数据在传输或存储之前,先被映射或封装进NAL单元中。NAL层将SODB打包成RBSP然后加上NAL头,组成一个NALU(NAL单元)。
NAL层定义片级以上的语法级别(如序列参数集和图像参数集,针对网络传输),同时支持以下功能:独立片解码,起始码唯一保证,SEI以及流格式编码数据传送。
每个NAL单元是一个一定字语法元素的可变长字节字符串,包括一个字节的头信息(用来表示数据类型),以及若干个整数字节的原始字节序列负荷(RBSP)。
H264编码中数据形式相关解释
SODB(String of Data Bits)数据比特串:最原始的编码数据,即VCL数据,没有任何附加数据。
RBSP(Raw ByteSequence Payload)原始字节序列载荷:在SODB的后面填加了结尾比特(RBSP trailing bits),一个bit“1”,若干bit “0”,以便字节对齐;
EBSP(EncapsulationByte Sequence Packets)扩展字节序列载荷:在RBSP基础上加了仿校验字节(0X03)。它的原因是:需要添加每组NALU之前的起始码StartCode。解码器检测每个起始码,作为一个NAL的起始标识,当检测到下一个起始码时,当前NAL结束。
起始码引入的问题:如果在NAL内部出现0x00 00 00 或者0x 00 00 01怎么办?而且这种可能性是很大的!
解决引入问题的方案:“防止竞争”机制
具体操作如下:
当编码器编码完一个NAL后,检查该NAL单元内部是否出现以下左侧的四个字节序列,如果存在,编码器将在最后一个字节前插入一个新的字节:0x03
从而使其变成右侧的样子,这样在NAL内部就不会出现0x00 00 00或者0x00 00 01了;然后解码器在NAL内部检测到0x00 00 03的序列时,将0x03丢弃,
恢复原始数据。
0x00 00 00 -----> 0x00 00 03 00
0x00 00 01 -----> 0x00 00 03 01
0x00 00 02 -----> 0x00 00 03 02
0x00 00 03 -----> 0x00 00 03 03
0x00 00 02是做保留用,0x00 00 03是为了避免原始数据中0x00 00 03序列
NALU HEADER
forbidden_zero_bit (F,占1bit)
在 H.264 规范中规定了这⼀位必须为 0 。
nal_ref_idc (NRI,占2bit)
NAL重要性,值越大,越重要,解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU,而不影响图像的回放 。 如果当前NALU是属于参考帧的片,或是序列参数集,或是图像参数集这些重要的单位时,本句法元素必需大于0。
nal_unit_type(Type,占5bit):
这个NALU单元的类型,1~12由H.264使用,24~31由H.264以外的应用使用。
NALU类型的对照表 :
常见的一些类型列表:
SPS和PPS简单介绍
SPS(Sequence Paramater Set)又称作序列参数集。对应的是针对一段连续编码视频序列的参数。包含 帧数、POC的约束、参考帧数目、解码图像尺寸和帧场编码模式选择标识等信息。
PPS(Picture Parameter Set)又称作图像参数集。对应的是一个序列中某一副图像或者某几幅图像的参数。包含 熵编码模式选择标识、片组数目、初始量化参数和去方块滤波系数调整标识等信息。
SPS、PPS的内容都是编码器写入的。解码时,解码器一开始要收到SPS、PPS来做初始化,如果H.264码流中没有SPS或PPS的话,解码器是无法解析码流数据,自然是无法播放。如果编码参数改变,则还需要一组新的SPS、PPS。
VCL和NAL的关系
(1)VCL只关心编码部分,重点在于编码算法以及在特定硬件平台的实现,VCL输出的是编码后的纯视频流信息,没有任何头信息
(2)NAL关心的是VCL的输出纯视频流如何被表达和封包以利于网络传输
(3)SODB:String Of Data Bits(VCL输出的纯视频流)
(4)RBSP:Raw Byte Sequence Payload
(5)NALU:Network Abstraction Layer Units NALU是H264文件的基本组成单元
(6)关系:
SODB + RBSP trailing bits = RBSP
NALU header(1 byte) + RBSP = NALU
实战观察h264文件相关NALU单元情况:
传递依次是:
SPS
PPS
SEI
IDR
参考书:
《新一代视频压缩编码标准H.264/AVC》——毕厚杰主编
更多framework技术干货,请关注下面“千里马学框架”