H.264原始码流(裸流)是由⼀个接⼀个NALU组成,它的功能分为两层,VCL(视频编码层)和 NAL(⽹络提取层):
VCL:包括核⼼压缩引擎和块,宏块和⽚的语法级别定义,设计⽬标是尽可能地独⽴于⽹ 络进⾏⾼效的编码;
NAL:负责将VCL产⽣的⽐特字符串适配到各种各样的⽹络和多元环境中,覆盖了所有⽚级 以上的语法级别
⼀个NALU = ⼀组对应于视频编码的NALU头部信息 + ⼀个原始字节序列负荷(RBSP,Raw Byte Sequence Payload).
NALU结构单元的主体结构如下所示;⼀个原始的H.264 NALU单元通常由[StartCode] [NALU Header] [NALU Payload]三部分组成,其中 Start Code ⽤于标示这是⼀个NALU 单元的开 始,必须是"00 00 00 01" 或"00 00 01",除此之外基本相当于⼀个NAL header + RBSP;
(对于FFmpeg解复⽤后,MP4⽂件读取出来的packet是不带startcode,但TS⽂件读取出来的packet带了startcode)
每个NAL单元是⼀个⼀定语法元素的可变⻓字节字符串,包括包含⼀个字节的头信息(⽤来表 示数据类型),以及若⼲整数字节的负荷数据。
NALU头信息(⼀个字节):
T为负荷数据类型,占5bit
nal_unit_type:这个NALU单元的类型,1~12由H.264使⽤,24~31由H.264以外的应⽤使⽤
5 IDR帧 、6 辅助增强信息 (SEI) 、 7 序列参数集sps 、8 图像参数集pps
R为重要性指示位,占2个bit nal_ref_idc.:取00~11,似乎指示这个NALU的重要性,如00的NALU解码器可以丢弃它⽽不 影响图像的回放,0~3,取值越⼤,表示当前NAL越重要,需要优先受到保护。如果当前 NAL是属于参考帧的⽚,或是序列参数集,或是图像参数集这些重要的单位时,本句法元 素必需⼤于0。
最后的F为禁⽌位,占1bit forbidden_zero_bit: 在 H.264 规范中规定了这⼀位必须为 0.
H.264标准指出,当数据流是储存在介质上时,在每个NALU 前添加起始码:0x000001 或 0x00000001,⽤来指示⼀个NALU 的起始和终⽌位置: 在这样的机制下,在码流中检测起始码,作为⼀个NALU得起始标识,当检测到下⼀个起始 码时,当前NALU结束。 3字节的0x000001只有⼀种场合下使⽤,就是⼀个完整的帧被编为多个slice(⽚)的时 候,包含这些slice的NALU 使⽤3字节起始码。其余场合都是4字节0x00000001的。
H264 annexb模式
H264有两种封装 ⼀种是annexb模式,传统模式,有startcode,SPS和PPS是在ES中 ⼀种是mp4模式,⼀般mp4 mkv都是mp4模式,没有startcode,SPS和PPS以及其它信息被封装在container中,每⼀个frame前⾯4个字节是这个frame的⻓度很多解码器只⽀持annexb这种模式,因此需要将mp4做转换:在ffmpeg中⽤ h264_mp4toannexb_filter可以做转换
文章评论