您的位置:首页 > 其它

H264相关

2015-10-10 10:24 381 查看

一 H.264句法

1.1元素分层结构

H.264编码器输出的Bit流中,每个Bit都隶属于某个句法元素。句法元素被组织成有层次的结构,分别描述各个层次的信息。

 
 



图1
H.264分层结构由五层组成,分别是序列参数集、图像参数集、片(Slice)、和宏块和子块。参数集是一个独立的数据单位,不依赖于参数集外的其它句法元素。图2描述了参数集与参数集外的句法元素之间的关系。

 



图2
一个参数集不对应某一个特定的图像或序列,同一序列参数集可以被多个图像参数集引用,同理,同一个图像参数集也可以被多个图像引用。只在编码器认为需要更新参数集的内容时,才会发出新的参数集。

 

在H.264中,图像以序列为单位进行组织。一个序列的第一个图像叫做IDR图像,IDR图像都是I帧,H.264引入IDR图像为了解码的同步,当解码器解码到IDR图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。

 

IDR是I帧,但I帧不一定是IDR。I帧之后的图像有可能会使用I帧之前的图像做运动参考。

 

1.2描述子

描述子描述从Bit流中取出句法元素的方法。

编号
语法
说明
1
ae(e)

CABAC

2
b(8)

读进连续的8个Bit

3
ce(v)

CAVLC

4
f(n)

读进连续的n个Bit

5
i(n)/i(v)

读进连续的若干Bit,并把它们解释为有符号整数

6
me(v)

映射指数Golomb熵编码

7
se(v)

有符号指数Golomb熵编码

8
te(v)

截断指数Golomb熵编码

9
u(n)/u(v)

读进连续的若干Bit,并把它们解释为无符号整数

10
ue(v)

无符号指数Golomb熵编码

表1

1.3句法的表示方法

句法元素的名称由小写字母和一系列下划线组成,变量名称是大小写字母组成,中间没有下划线。

二 句法表

定义了H.264的句法,指明在码流中依次出现的句法元素及它们出现的条件、提取描述子等。句法表是分层嵌套的。

句法表中的C字段表示该句法元素的分类,这是为片区服务,分类的具体含义如下表描述。

nal_unit_type
NAL类型
C
0
未使用

 
1
不分区、非IDR的片

2,3,4
2
片分区A

2
3
片分区B

3
4
版分区C

4
5
IDR图像中的片

2,3
6
补充增强信息单元(SEI)

5
7
序列参数集

0
8
图像参数集

1
9
分界符

6
10
序列结束

7
11
码流结束

8
12
填充

9
13..23
保留

 
24..31
不保留

 
表2

2.1 NAL语法

 

句法
C
Desc

nal_nuit(NumBytesInNALunit){/* NumBytesInNALunit为统计出来的数据长度 */

 
 

    forbidden_zero_bit /* 等于0 */

All
f(1)

    nal_ref_idc/* 当前NAL的优先级,取值范围0-3 */

All
u(2)

    nal_unit_type /* NAL类型,见表2描述 */

All
u(5)

    NumBytesInRBSP=0

 
 

    for(i=1;i<NumBytesInNALunit;i++){

 
 

        if(i+2<NumBytesInNALunit && next_bits(24)==0x000003{

 
 

        /* 0x000003伪起始码,需要删除0x03这个字节 */

 
 

        rbsp_byte[NumBytesInRBSP++]

All
b(8)

        rbsp_byte[NumBytesInRBSP++]

All
b(8)

        i+=2/* 取出前两个0x00后,跳过0x03 */

 
 

        emulation_prevention_three_byte/* equal to 0x03 */

All
f(8)

    }else{

 
 

        rbsp_byte[NumBytesInRBSP++] /* 继续读取后面的字节 */

All
b(8)

    }

 
 

}

 
 

表3

2.2序列参数集(SPS)

句法
C
Desc

seq_parameter_set_rbsp(){

 
 

    profile_idc/*
指明所用的Profile */

0
u(8)

    constraint_set0_flag

0
u(1)

    constraint_set1_flag

0
u(1)

    constraint_set1_flag

0
u(1)

    reserved_zero_5bits /* equal to 0 */

0
u(5)

    level_idc /* 指明所用的Level */

0
u(8)

    seq_parameter_set_id /* 指明本序列参数集的id号,0-31,被图像集引用,编码需要产生新的序列集时,使用新的id,而不是改变原来参数集的内容
*/

0
ue(v)

    log2_max_frame_num_minus4/* 为读取元素frame_num服务,frame_num标识图像的解码顺序,frame_num的解码函数是ue(v),其中v=log2_max_frame_num_minus4+4,该元素同时指明frame_num的最大值MaxFrameNum=2(
log2_max_frame_num_minus4+4)*/

0
ue(v)

    pic_order_cnt_type /* 指明poc的编码方法,poc标识图像的播放顺序,poc可以由frame_num计算,也可以显示传送。poc共三种计算方式
*/

0
ue(v)

    if(pic_order_cnt_type==0)

 
 

        log2_max_pic_order_cnt_lsb_minus4 /*
指明变量MaxPicOrderCntLsb的值, MaxPicOrderCntLsb=2(log2_max_pic_order_cnt_lsb_minus4+4)
*/

0
ue(v)

    else if(pic_order_cnt_type==1){

 
 

        delta_pic_order_always_zero_flag /* 等于1时,元素delta_pic_order_cnt[0]和delta_pic_order_cnt[1]不在片头中出现,并且它们的默认值是0,等于0时,上述两元素出现的片头中
*/

0
u(1)

        offset_for_non_ref_pic /* 用来计算非参考帧或场的poc,[-231,231-1]
*/

0
se(v)

        offset_for_top_to_bottom_field/* 计算帧的底场的poc */

0
se(v)

        num_ref_frames_inpic_order_cnt_cycle /*
用来解码poc,[0.255] */

0
ue(v)

        for(i=0;i<num_ref_frames_inpic_order_cnt_cycle;i++)

 
 

            offset_for_ref_frame[i]/* 用来解码poc,对于循环中的每个元素指定一个偏移 */

0
se(v)

    }

 
 

    num_ref_frames /* 参考帧队列可达到的最大长度,[0,16] */

0
ue(v)

    gaps_in_frame_num_value_allowed_flag /* 为1,允许slice header中的frame_num不连续 */

0
u(1)

    pic_width_inmbs_minus1 /* 本元素加1,指明以宏块为单位的图像宽度 PicWidthInMbs=pic_width_in_mbs_minus1+1 */

0
ue(v)

    pic_height_in_map_units_minus1 /* 本元素加1,指明以宏块为单位的图像高宽度 PicHeightInMapUnitsMbs=pic_height_in_map_units_minus1+1
*/

0
ue(v)

    frame_mbs_only_flag /* 等于0表示本序列中所有图像均为帧编码;等于1,表示可能是帧,也可能场或帧场自适应,具体编码方式由其它元素决定。结合前一元素:FrameHeightInMbs=(2-frame_mbs_only_flag)*PicHeightInMapUnits
*/

0
ue(v)

    if(frame_mbs_only_flag)

 
 

      mb_adaptiv_frame_field_flag /* 指明本序列是否是帧场自适应模式:

frame_mbs_only_flag=1,全部是帧

frame_mbs_only_flag=0, mb_adaptiv_frame_field_flag=0,帧场共存

frame_mbs_only_flag=0, mb_adaptiv_frame_field_flag=1,帧场自适应和场共存*/

0
u(1)

    direct_8x8_inference_flag /* 用于指明B片的直接和skip模式下的运动矢量的计算方式
*/

0
u(1)

    frame_cropping_flag /* 解码器是否要将图像裁剪后输出,如果是,后面为裁剪的左右上下的宽度 */

0
u(1)

    if(frame_cropping_flag){

 
 

        frame_crop_left_offset

0
ue(1)

        frame_crop_right_offset

0
ue(1)

        frame_crop_top_offset

0
ue(1)

        frame_crop_bottom_offset

0
ue(1)

    }

 
 

    vui_parameters_present_flag /* 指明vui子结构是否出现在码流中,vui子结构在附录中指明,用于表征视频格式的信息
*/

0
u(1)

    if(vui_parameters_present_flag)

 
 

        vui_parameters()

0
 

    rbsp_trailing_bits()

0
 

}

 
 

表4
//////////////////////////////////////////////////////////////////////////代码//////////////////////////////////////////////////////////////////////////////////

以下是解析宽高的代码:

view sourceprint?

001
bool
UDPReceiver::getResolution(
int
channel,
int
&Width,
int
& Height)
002
{
003
    
BYTE
*buf =
new
BYTE
[1024];
004
    
int
nLen;
005
    
AVPacket packet;
006
    
BOOL
bSpsComplete = FALSE;
007
    
// Find SPS
008
    
while
(!bSpsComplete)
009
    
{

010
        
int
ret = av_read_frame(m_pFormatContext[channel], &packet);
011
        
if
(packet.flags & AV_PKT_FLAG_KEY)
012
        
{
013
            
BYTE
* p = packet.data;
014
            
BYTE
last_nal_type = 0;
015
            
int
last_nal_pos = 0;
016
            
for
(
int
i=0; i<packet.size-5; i++)
017
            
{
018
                
p = packet.data + i;
019
                
if
(p[0]==0x00&&p[1]==0x00&&p[2]==0x00&&p[3]==0x01)
020
                
{
021
                    
if
(last_nal_type == 0x67)
022
                    
{
023
                        
nLen = i-last_nal_pos;
024
                        
memcpy
(buf, packet.data+last_nal_pos, nLen);
025
                        
bSpsComplete = TRUE;
026
                    
}
027
                    
last_nal_type = p[4];
028
                    
last_nal_pos = i;
029
                    
if
(bSpsComplete)
030
                    
{
031
                        
break
;
032
                    
}
033
                
}
034
            
}
035
            
if
(last_nal_type == 0x67 && bSpsComplete == FALSE)
036
            
{
037
                
nLen = packet.size - last_nal_pos;
038
                
memcpy
(buf, packet.data+last_nal_pos, nLen);
039
                
bSpsComplete = TRUE;
040
            
}
041
        
}
042
    
}

043
    
// Analyze SPS to find width and height
044
    
UINT
StartBit=0; 
045
        
buf = buf + 4;
046
    
int
forbidden_zero_bit=u(1,buf,StartBit);
047
    
int
nal_ref_idc=u(2,buf,StartBit);
048
    
int
nal_unit_type=u(5,buf,StartBit);
049
    
if
(nal_unit_type==7)
050
    
{

051
        
int
profile_idc=u(8,buf,StartBit);
052
        
int
constraint_set0_flag=u(1,buf,StartBit);
//(buf[1] & 0x80)>>7;
053
        
int
constraint_set1_flag=u(1,buf,StartBit);
//(buf[1] & 0x40)>>6;
054
        
int
constraint_set2_flag=u(1,buf,StartBit);
//(buf[1] & 0x20)>>5;
055
        
int
constraint_set3_flag=u(1,buf,StartBit);
//(buf[1] & 0x10)>>4;
056
        
int
reserved_zero_4bits=u(4,buf,StartBit);
057
        
int
level_idc=u(8,buf,StartBit);
058
 
 
059
        
int
seq_parameter_set_id=Ue(buf,nLen,StartBit);
060
 
 
061
        
if
( profile_idc == 100 || profile_idc == 110 ||
062
            
profile_idc == 122 || profile_idc == 144 )
063
        
{
064
            
int
chroma_format_idc=Ue(buf,nLen,StartBit);
065
            
if
( chroma_format_idc == 3 )
066
                
int
residual_colour_transform_flag=u(1,buf,StartBit);
067
            
int
bit_depth_luma_minus8=Ue(buf,nLen,StartBit);
068
            
int
bit_depth_chroma_minus8=Ue(buf,nLen,StartBit);
069
            
int
qpprime_y_zero_transform_bypass_flag=u(1,buf,StartBit);
070
            
int
seq_scaling_matrix_present_flag=u(1,buf,StartBit);
071
 
 
072
            
int
seq_scaling_list_present_flag[8];
073
            
if
( seq_scaling_matrix_present_flag )
074
            
{
075
                
for
(
int

i = 0; i < 8; i++ ) {
076
                    
seq_scaling_list_present_flag[i]=u(1,buf,StartBit);
077
                
}
078
            
}
079
        
}
080
        
int
log2_max_frame_num_minus4=Ue(buf,nLen,StartBit);
081
        
int
pic_order_cnt_type=Ue(buf,nLen,StartBit);
082
        
if
( pic_order_cnt_type == 0 )
083
            
int
log2_max_pic_order_cnt_lsb_minus4=Ue(buf,nLen,StartBit);
084
        
else
if
( pic_order_cnt_type == 1 )
085
        
{
086
            
int
delta_pic_order_always_zero_flag=u(1,buf,StartBit);
087
            
int
offset_for_non_ref_pic=Se(buf,nLen,StartBit);
088
            
int
offset_for_top_to_bottom_field=Se(buf,nLen,StartBit);
089
            
int
num_ref_frames_in_pic_order_cnt_cycle=Ue(buf,nLen,StartBit);
090
 
 
091
            
int
*offset_for_ref_frame=
new
int
[num_ref_frames_in_pic_order_cnt_cycle];
092
            
for
(
int

i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ )
093
                
offset_for_ref_frame[i]=Se(buf,nLen,StartBit);
094
            
delete
[] offset_for_ref_frame;
095
        
}
096
        
int
num_ref_frames=Ue(buf,nLen,StartBit);
097
        
int
gaps_in_frame_num_value_allowed_flag=u(1,buf,StartBit);
098
        
int
pic_width_in_mbs_minus1=Ue(buf,nLen,StartBit);
099
        
int
pic_height_in_map_units_minus1=Ue(buf,nLen,StartBit);
100
 
 
101
        
Width=(pic_width_in_mbs_minus1+1)*16;
102
        
Height=(pic_height_in_map_units_minus1+1)*16;
103
 
 
104
        
return
true
;
105
    
}

106
    
else
107
    
{

108
        
return
false
;
109
    
}

110
}
111
 
 
112
// Ue find the num of zeros and get (num+1) bits from the first 1, and 
113
// change it to decimal
114
// e.g. 00110 -> return 6(110)

115
UINT
UDPReceiver::Ue(
BYTE
*pBuff,
UINT
nLen,
UINT
&nStartBit)
116
{
117
    
//计算0bit的个数
118
    
UINT
nZeroNum = 0;
119
    
while
(nStartBit < nLen * 8)
120
    
{

121
        
if
(pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8)))
//&:按位与,%取余
122
        
{
123
            
break
;
124
        
}
125
        
nZeroNum++;
126
        
nStartBit++;
127
    
}

128
    
nStartBit ++;
129
 
 
130
 
 
131
    
//计算结果
132
    
DWORD
dwRet = 0;
133
    
for
(
UINT

i=0; i<nZeroNum; i++)
134
    
{

135
        
dwRet <<= 1;
136
        
if
(pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8)))
137
        
{
138
            
dwRet += 1;
139
        
}
140
        
nStartBit++;
141
    
}

142
    
return
(1 << nZeroNum) - 1 + dwRet;
143
}
144
 
 
145
int
UDPReceiver::Se(
BYTE
*pBuff,
UINT
nLen,
UINT
&nStartBit)
146
{
147
    
int
UeVal=Ue(pBuff,nLen,nStartBit);
148
    
double
k=UeVal;
149
    
int
nValue=std::
ceil
(k/2);
//ceil函数:ceil函数的作用是求不小于给定实数的最小整数。ceil(2)=ceil(1.2)=cei(1.5)=2.00
150
    
if
(UeVal % 2==0)
151
        
nValue=-nValue;
152
    
return
nValue;
153
}
154
 
 
155
// u Just returns the BitCount bits of buf and change it to decimal.
156
// e.g. BitCount = 4, buf = 01011100, then return 5(0101)
157
DWORD
UDPReceiver::u(
UINT
BitCount,
BYTE
* buf,
UINT
&nStartBit)
158
{
159
    
DWORD
dwRet = 0;
160
    
for
(
UINT

i=0; i<BitCount; i++)
161
    
{

162
        
dwRet <<= 1;
163
        
if
(buf[nStartBit / 8] & (0x80 >> (nStartBit % 8)))
164
        
{
165
            
dwRet += 1;
166
        
}
167
        
nStartBit++;
168
    
}

169
    
return
dwRet;
170
}
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: