H.264参考帧管理

来源:互联网 发布:php fpm 重启 编辑:程序博客网 时间:2024/05/29 17:40

引言

H264相对于以前的标准,采用了多参考帧的技术,提高了编码器的性能,但也增加了实现的复杂度,在理解上也加大了难度。下面是我近来参阅一些资料的总结;

 

frame_num:标志片的解码顺序,当前图像是IDR(立即刷新图像)时,设置为0;相对于前面一个参考帧(解码顺序),增加1

POCpicture order count的缩写,标志片的播放顺序,IDR图像的第一个场的POC0POC由片头信息得出,根据pic_order_cnt_type有三种计算方法;

Type0TopFieldOrderCnt=POCMsb+POCLsb

POCLsb由片头提供,即pic_order_cnt_lsb;当pic_order_cnt_lsb溢出时,POCMsb增加;delta_pic_order_cnt指示顶场和低场POC的变化,默认值为0

例:

播放顺序:IBPBPBPB…

B帧不作参考帧,则POC相对于前面的一个参考帧增加2

 

Access Unit

Type

Used for reference

frame_num

POC_lsb

TopPOC

Display order

1

I

Yes

0

0

0

0

2

P

Yes

1

4

4

2

3

B

No

2

2

2

1

4

P

Yes

2

8

8

4

5

B

No

3

6

6

3

6

P

Yes

3

12

12

6

7

B

No

4

10

10

5

8

P

Yes

4

16

16

8

 

 

 

 

 

 

Type1

在序列参数集中设置一个POC预期值,若POC的值有变化,则只传送相对变化值;序列参数集规定了POC循环的参考帧数目;对于一帧图像,计算POC预期值如下:

1  计算POC循环数(自最近的IDR图像起)

2  计算当前图像在POC循环中的位置

3  计算当前图像POC的预期值

4  如果是非参考帧,加上offset_for_non_ref_pic

 

TopFieldOrderCount=expected POC+delta_pic_order_cnt[0]

BottomFieldOrderCount=expected POC+delta_pic_order_cnt[1](if field_pic = 1)

                               = expected POC+offset to bottom field+delta_pic_order_cnt[0](otherwise)

1

播放顺序:IBPBPBPB…

B帧不作参考帧,一个POC循环中有一个参考帧,offset_for_non_ref_pic=-2offset to next ref frame=4

 

 

Access Unit

Type

Used for

Reference

Frame_num

delta_pic_order_cnt[0]

topFOC

Display order

1

I

Yes

0

0

0

0

2

P

Yes

1

0

4

2

3

B

No

2

0

2

1

4

P

Yes

2

0

8

4

5

B

No

3

0

6

3

6

P

Yes

3

0

12

6

7

B

No

4

0

10

5

8

P

Yes

4

0

16

8

 

 

 

 

 

 

 

2

播放顺序:IBPBPBPB…

B帧不作参考帧,一个POC循环中有一个参考帧,offset_for_non_ref_pic=-4offset to next ref frame=6

 

Access Unit

Type

Used for

Reference

Frame_num

delta_pic_order_cnt[0]

topFOC

Display order

1

I

Yes

0

0

0

0

2

P

Yes

1

0

6

3

3

B

No

2

0

2

1

4

P

Yes

2

2

4

2

5

B

No

3

0

12

6

6

P

Yes

3

0

8

1

7

B

No

4

2

10

2

8

P

Yes

4

0

18

9

 

 

 

 

 

 

 

Type2

播放顺序与解码顺序相同;POCframe_num直接得到

if(used for ref)

  set TopPOC and/or BottomPOC to (2*frame_num)

else

set TopPOC and/or BottomPOC to (2*frame_num-1)

 

参考帧重排序

由于在解码每个MB时,都要用到参考帧的索引ref_idx_l0ref_idx_l1。可能发生这样的情况,有个参考帧(短期参考帧或者长期参考帧)对于解码一个图像特别有用,但是这个参考帧在缺省的队列中并不位于索引值为0的位置,所以编码大的索引值需要花费多的比特。参考帧的重排序可以使这个参考帧位于索引值比较小的位置,以节省编码比特数。

 

 

下面我们以list0的重排序为例来说明

如果ref_pic_list_reordering_flag0,则进入重排序的循环,直到ref_pic_list_reordering_flag3时为止。

 

短期参考帧重排序(short-term):

初始化一个指针refIdxL0使其指向参考帧索引值0abs_diff_pic_num_minus1是相对于预测参考帧的偏移量,对于第一次重排序操作,预测参考帧就是当前图像,对于后续的重排序操作,预测图像就是最近重排序的图像;

if(reordering_of_pic_nums_idc==0)

  remapped_pic=predicted_pic- abs_diff_pic_num_minus1;

else if(reordering_of_pic_nums_idc==1)

  remapped_pic=predicted_pic+ abs_diff_pic_num_minus1;

else if(reordering_of_pic_nums_idc==2)

  remapped_pic= long_tem_pic_run;

else

  return;

得到remapped_pic后,就将remapped_pic移至索引值为refIdxL0的位置,同时更新refIdxL0,并将后面的图像向后移动一个位置;

 

长期参考帧重排序(long-term):

  与短期参考帧重排序类似,参见上面流程;

 

例:

 P片,DPB包含5个参考帧,当前帧的frame_num=158

list0的缺省顺序是:

15715515313

初始化predicted_pic=158refIdxL0=0

1.       reordering_of_pic_nums_idc=0abs_diff_pic_num_minus1=5

remapped_pic=158-5=153

重排序如下:

15315715513

更新remapped_pic=153refIdxL0=1