HEVC中与dpb(decoder picture buffer)相关的语法元素的理解

来源:互联网 发布:淘宝站外推广人 编辑:程序博客网 时间:2024/06/01 22:06

    hevc标准中有很多语法元素理解起来比较麻烦,所以在此记录下来,供以后查阅。

sps中的sps_max_num_reorder_pics

    标准中的解释:"sps_max_num_reorder_pics[ i ] indicates the maximum allowed number of pictures that can precede any picture in the CVS in decoding order and follow that picture in output order when HighestTid is equal to i". 翻译过来就是:显示次序在某帧图像之后,解码次序在某帧图像之前的图像数量的最大值。理解起来有点拗口,之所以有这个变量,是因为编码器中的B帧不仅有前向参考,还有后向参考。后向参考要求当前图像编码前,参考的后向图像已经编码完成,所以会导致图像的编码顺序和显示顺序不一样。
    下图为编码一个GOP的示意图。在这个GOP内部,可以看到显示次序为1的帧 有4帧图像解码次序在他之前,显示次序在他之后的帧,分别为POC=16, 8, 4, 2的帧,是整个GOP内部拥有最多解码次序在前,显示次序在后的帧,所以sps_max_num_reorder_pics=4。 
    sps_max_num_reorder_pics会影响帧的输出时间(picture timing中的pic_dpb_output_delay)。下图中的GOP中,第一个I帧解码完之后并不能立刻输出。这是因为对解码器而言,一旦开始输出帧,则要求接下来解一帧输出一帧。下面分析一下这个GOP的解码和帧输出过程:
  • I帧(POC=0)解完,不能立刻输出(假设I帧输出,接下来应该输出POC=1的帧),因为接下来解码P帧(POC=16)。
  • P帧(POC=16)解完,也不能输出I帧(假设I帧输出,接下来应该输出POC=1的帧)因为接下来解码B帧(POC=8)。
  • B帧(POC=8)解完,也不能输出I帧(假设I帧输出,接下来应该输出POC=1的帧)因为接下来解码B帧(POC=4)。
  • B帧(POC=4)解完,也不能输出I帧(假设I帧输出,接下来应该输出POC=1的帧)因为接下来解码B帧(POC=2)。
  • B帧(POC=2)解完,可以输出I帧,因为接下来解码b帧(POC=1),而且可以保证后面解一帧就输出一帧。
    为什么解码POC=1的帧之后就可以持续输出了呢?因为POC=1的帧拥有最多的解码次序在他之前,显示次序在他之后的帧,POC=1的帧是导致输出延迟的根源。

    综上,I帧需要延迟四个帧间隔才能输出,POC=1的帧解完就立马输出,POC=2的帧延迟2个帧间隔输出,......,这种延迟称为pic_dpb_output_delay。

sps中的sps_max_dec_pic_buffering

    标准中的解释:"sps_max_dec_pic_buffering_minus1[ i ] plus 1 specifies the maximum required size of the decoded picture buffer for the CVS in units of picture storage buffers when HighestTid is equal to i." 指定了dpb的大小。

    在x265中,max_num_reorder_pics和sps_max_num_reorder_pics的赋值如下代码所示。
    因为x265只支持一级的hierarchical B,所以当开启B帧做参考(bBPyramid)且B帧数量大于等于2时,numReorderPics = 2;否则如果没有bBpyramid但是有B帧,则numReorderPics = 1;如果没有B帧,则没有任何reorder,numReorderPics = 0。
    有了max_num_reorder_pics,max_num_dec_pic_buffering就好计算了。不过max_dec_pic_buffering还与最大参考帧数有关,参考帧越多,要求的dpb size也越大,很好理解。
bool enforceLevel(x265_param& param, VPS& vps){    vps.numReorderPics = (param.bBPyramid && param.bframes > 1) ? 2 : !!param.bframes;    vps.maxDecPicBuffering = X265_MIN(MAX_NUM_REF, X265_MAX(vps.numReorderPics + 2, (uint32_t)param.maxNumReferences) + 1);    ......}

picture timing sei message

    picture timing sei提供了关于当前access unit的CPB removal delay和DPB output delay信息。一些分析软件分析码流的VBV Buffer模型时可以根据这些语法元素计算每个access unit从CPB中的移出时间,验证码流是否有上下溢。

au_cpb_removal_delay_minus1

    标准中解释为"au_cpb_removal_delay_minus1 plus 1 specifies the number clock ticks between the nominal CPB removal time of the access unit associated with the picture timing SEI message and the preceding access unit in decoding order that contained a buffering period SEI message."
    au_cpb_removal_delay_minus1 等于 该picture timing sei所对应的AU的Clock Tick 减去 距离当前AU最近的携带Buffering period sei的AU的Clock Tick。一般关键帧携带Buffering period sei。
    所以对编码器来说,码流按照编码次序(解码次序)从cpb中输出,所以在GOP内部,au_cpb_removal_delay_minus1随着编码次序依次递增。对于GOP起始I帧,au_cpb_removal_delay_minus1等于当前I帧POC 减去 上一个GOP的起始I帧的POC。

pic_dpb_output_delay

    标准中的解释为"pic_dpb_output_delay is used to compute the DPB output time of the picture when SubPicHrdFlag is equal to 0. It specifies how many clock ticks to wait after removal of the last decoding unit in an access unit from the CPB before the decoded picture is output from the DPB."
    这也是由于编码中B帧存在后向参考,导致编码次序(解码次序)和显示次序是不完全一致的,因此解码之后可能不能立刻从dpb中输出帧进行显示。pic_dpb_output_delay就是用于计算帧从dpb中移出的时间。
    pic_dpb_output_delay = sps_max_num_reorder_pics[0] + frame_count - encode_order;
    示例:对于IbBbP 序列,各个语法元素的值是如下计算的:
                               I   b   B   b   P
frame_count                    0   1   2   3   4
encode_order                   0   3   2   4   1
au_cpb_removal_delay           ?   2   1   3   0
pic_dpb_output_delay           2   0   2   1   5

Buffering period SEI message

    标准中的解释为"A buffering period SEI message provides initial CPB removal delay and initial CPB removal delay offset information for initialization of the HRD at the position of the associated access unit in decoding order"。
    我的理解:根据VBV Buffer模型,当前帧从cpb中移出给解码端,为了使解码可以流畅不卡顿,需要保证VBV Buffer中有足够的数据才行。因为码率是波动的,如果中间出现一段时间码率超过平均码率,那么VBV Buffer中的数据消耗很快,所以VBV Buffer如果没有足够的起始数据,中间就可能出现卡顿。

nal_initial_cpb_removal_delay

    nal_initial_cpb_removal_delay[ i ] and nal_initial_alt_cpb_removal_delay[ i ] specify the default and the alternative initial CPB removal delays, respectively, for the i-th CPB when the NAL HRD parameters are in use. The syntax elements have a length in bits given by initial_cpb_removal_delay_length_minus1 + 1, and are in units of a 90 kHz clock. The values of the syntax elements shall not be equal to 0 and shall be less than or equal to 90000 * ( CpbSize[ i ] ÷ BitRate[ i ] ), the time-equivalent of the CPB size in 90 kHz clock units.
    理解:Buffering Period SEI应该是Key Frame才会携带。当播放器有seek操作时,会找到目标时间点的Key Frame的Access Unit,但是此时并不能立马进行解码,而是要缓冲一定量数据,等待VBV Buffer有了初始缓冲了,才开始解码,以保证后续播放不会卡顿。这里具体要缓冲多少,就是buffering period sei中的initial_cpb_removal_delay所指定的。在编码器内部,会根据I帧编完之后VBV Buffer的填充状态来更新key frame的nal_initial_cpb_removal_delay。

    待续......

版权声明:本文为博主原创文章,未经博主允许请勿转载。