您的位置:首页 > 其它

H264—帧,片,参数集,NALU等概念

2016-08-30 14:02 169 查看
h264是一个编码压缩的格式,可以使用x264库进行编码,源码开放,可下载编译使用。

-------------------------------------------------------------------------------------------------------------

H.264 Codec

h264概念上区分视频编码层(VCL)和网络抽象层(NAL).

VCL包含Codec的信令处理功能;以及如转换,量化,运动补偿预测机制;以及循环过滤器。他遵从今天大多数视频codec的一般概念,基于宏快的编码器,使用基于运动补偿的图像间预测和残余信号的转换编码。

(NAL)编码器封装VCL编码器输出的片断到网络抽象层单元(NAL units),它适合于通过包网路传输或用于面向包的多路复用环境。

-------------------------------------------------------------------------------------------------------------

网络抽象层单元(NALU)类型

NAL单元类型字节格式如下:

    

      +---------------+

      |0|1|2|3|4|5|6|7|

      +-+-+-+-+-+-+-+-+

      |F|NRI|  Type   |

      +---------------+

 

   NAL单元类型字节部件的语义在H.264规范中制定, 简要描述如下.

 

   F: 1 bit

      forbidden_zero_bit.  H.264规范声明设置为1指示语法违例。

 

   NRI: 2 bits

      nal_ref_idc.  00值指示NAL单元的不用于帧间图像预测的重构参考图像。这样的NAL单元可以被丢弃而不用冒参考

      图像完整性的风险。大于0的值指示NAL单元的解码要求维护参考图像的完整性。

 

   Type: 5 bits

      nal_unit_type.  本部件指定NAL单元荷载类型定义在[1]的表 7-1中和本文后面。为了参考所有当前定义的NAL单元类型

      和他们的语义

0:未规定

1:非IDR图像中不采用数据划分的片段

2:非IDR图像中A类数据划分片段

3:非IDR图像中B类数据划分片段

4:非IDR图像中C类数据划分片段

5:IDR图像的片段

6:补充增强信息(SEI)

7:序列参数集(SPS)

8:图像参数集(PPS)

9:分割符

10:序列结束符

11:流结束符

12:填充数据

13:序列参数集扩展

14:带前缀的NAL单元

15:子序列参数集

16 – 18:保留

19:不采用数据划分的辅助编码图像片段

20:编码片段扩展

21 – 23:保留

24 – 31:未规定

在实际的H264数据帧中,往往帧前面带有00 00 00 01 或 00 00 01分隔符,一般来说编码器编出的首帧数据为PPS与SPS,接着为IDR帧(关于IDR与I的区别http://blog.csdn.net/jammg/article/details/52357245

比如,将rgb转换转换成yuv后(x264只支持将yuv编码压缩),使用x264编码器编码出的264文件前面一般是这样:

00 00 00 01 67 ....(sps)....... 00 00 00 01 68 .........(pps)....... 00 00 00 01 65 ......(IDR)...........

[由于NAL的语法中没有给出长度信息,实际的传输、存储系统需要增加额外的头实现各个NAL单元的定界。]

-------------------------------------------------------------------------------------------------------------

参数集概念(SPS/PPS)

 

   H.264一个非常基本的设计概念是产生自包含包, 使得如RFC2429的头重复或MPEG-4的头扩展编码(HEC)[11]机制变得不必要。

   这是通过从媒体流解耦合不止一个片断的相对信息来实现的。高层meta信息应该可靠/异步的发送,事先不和包含片断包的RTP

   包流发送。(对于没有通过带外传输信道发送本信息的应用,通过带内发送本信息也提供了手段)。高层参数的组合被称为参数集。

   H.264规范包括两类参数集:顺序参数集和图像参数集。一个活动顺序参数集在一个编码视频序列中保持不变,一个活动图像参数集

   在一个编码图像里保持不变。顺序和图像参数集结构包含如图像大小,采用的可选的编码模式,宏块到片断组映射等信息。

 

   为了改变图像参数(如图像大小)而不用同步传送参数集修改给片断包流,编码器和解码器可以维护不止一个顺序和图像参数集的

   列表。每个片断头包含一个码字指示使用的顺序和图像参数集。

 

   本机制允许从包流中解耦合参数集的传输,通过外部手段传输他们(即,作为能力交换的副作用),或通过一个(可靠或不可靠)控制协议

   他们从没有被传送但是被应用设计规范修复甚至是可能的。

帧(frame)与 片(slice)

-------------------------------------------------------------------------------------------------------------

大小关系

对于 H.264中出现的一些概念从大到小排序依次是:序列、图像(大多时候称为帧,包括I,P,B帧)、片组、片(包括I,P,B片,SP片,SI片)、NALU、宏块、亚宏块、块、像素

注:图像以序列为单位进行组织

-------------------------------------------------------------------------------------------------------------

帧、NALU、片

(1)、在 H.264协议中图像是个集合概念,顶场、底场、帧都可以称为图像(本文图像概念时都是集合概念)。因此我们可以知道,对于H.264 协议来说,我们平常所熟悉的那些称呼,例如:I 帧、P 帧、B帧等等,实际上都是我们把图像这个概念具体化和细小化了。我们在 H.264里提到的“帧”通常就是指不分场的图像;
(2)、如果不采用FMO(灵活宏块排序) 机制,则一幅图像只有一个片组

(3)、如果不使用多个片,则一个片组只有一个片

(4)、如果不采用DP(数据分割)机制,则一个片就是一个NALU一个 NALU 也就是一个片

      否则,一个片由 三个 NALU 组成(即标准“表7-1”中 nal_unit_type 值为2、3、4 的三个 NALU 属于 一个片);  
   2编码条带数据分割块A  slice_data_partition_a_layer_rbsp()

   3 编码条带数据分割块Bslice_data_partition_b_layer_rbsp( )

   4 编码条带数据分割块Cslice_data_partition_c_layer_rbsp( )

也即对应上面的:       

        H264NT_SLICE_DPA,

        H264NT_SLICE_DPB,

        H264NT_SLICE_DPC,

帧可以包含一个或多个片,片由宏块组成,宏块是编码处理的基本单元。

[b]一幅图像由 1~N个片组组成,而每一个片组又由一个或若干个片组成一个片由一个NALU或三个NALU(假如有数据分割)组成。图像解码过程中总是按照片进行解码,然后按照片组将解码宏块重组成图像。从这种意义上讲,片实际是最大的解码单元。

-------------------------------------------------------------------------------------------------------------
[/b]

I,P,B帧的依赖关系

I frame 是自己独立编码,不依赖于其他frame 数据。

P frame 依赖 I frame 数据。
B frame 依赖 I frame, P frame 或其他 B frame 数据。

对应地,NAL nal_unit_type中的1(非IDR图像的编码条带)、2(编码条带数据分割块A)、3(编码条带数据分割块B)、4(编码条带数据分割块C)、5(IDR图像的编码条带)种类型 与 Slice种的三种编码模式:I_slice、P_slice、B_slice NAL nal_unit_type 里的五种类型,代表接下来数据是表示啥信息的和具体如何分块。

I_slice、P_slice、B_slice 表示I类型的片、P类型的片,B类型的片.其中I_slice为帧内预测模式编码;P_slice为单向预测编码或帧内模式;B_slice 中为双向预测或帧内模式。

// H.264 NAL type

   enum H264NALTYPE

    {

        H264NT_NAL = 0,

        H264NT_SLICE, //P 帧

        H264NT_SLICE_DPA,

        H264NT_SLICE_DPB,

        H264NT_SLICE_DPC,

        H264NT_SLICE_IDR, // I 帧

        H264NT_SEI,

        H264NT_SPS,

        H264NT_PPS,

   };

//  0x00 0x00  0x00 0x01  0x65(0x45)   前四个字节为帧头,0x65  是关键帧

//0x00  0x00 0x01  0x65(0x45)  也为关键帧

H264GetNALType(unsigned char * pBSBuf, const int nBSLen)

{
if ( nBSLen < 5 )  // 不完整的NAL单元
   return H264NT_NAL;

unsigned char * pBS = (unsigned char *)pBSBuf;

int nType = pBS[4] & 0x1F;  // NAL类型在固定的位置上 
if ( nType <= H264NT_PPS )
    return nType;// nTYPE  为5  表示关键帧

return 0;

}
-------------------------------------------------------------------------------------------------------------

NAL语法语义

NAL层句法:
在编码器输出的码流中,数据的基本单元是句法元素。
句法表征句法元素的组织结构。
语义阐述句法元素的具体含义。
分组都有头部,解码器可以很方便的检测出NAL的分界,依次取出NAL进行解码。
但为了节省码流,H.264没有另外在NAL的头部设立表示起始位置的句法元素。
如果编码数据是存储在介质上的,由于NAL是依次紧密相连的,解码器就无法在数据流中分辨出每个NAL的起始位置和终止位置。
解决方案:在每个NAL前添加起始码:0X000001
在某些类型的介质上,为了寻址的方便,要求数据流在长度上对齐,或某个常数的整数倍。所以在起始码前添加若干字节的0来填充。
检测NAL的开始:
0X000001和0X000000
我们必须考虑当NAL内部出现了0X000001和0X000000
解决方案:
H.264提出了“防止竞争”机制:
0X000000——0X00000300
0X000001——0X00000301
0X000002——0X00000302
0X000003——0X00000303
为此,我们可以知道:
在NAL单元中,下面的三字节序列不应在任何字节对齐的位置出现
0X000000
0X000001
0X000002
Forbidden_zero_bit =0;
Nal_ref_idc:表示NAL的优先级。0~3,取值越大,表示当前NAL越重要,需要优先受到保护。如果当前NAL是属于参考帧的片,或是序列参数集,或是图像参数集这些重要的单位时,本句法元素必需大于0。
Nal_unit_type:当前NAL 单元的类型
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编码 h264 NALU 概念
相关文章推荐