视频编码中由于B帧的存在使得视频的播放顺序和编码顺序不一样。解码后的视频需要按播放顺序排列播放,POC(picture order count)就是视频帧按播放顺序的标识号。

POC的作用主要有:帧的唯一标识符、用于merge模式下生成运动信息、解码端一致性检查。

每一个编码的帧都有一个POC,可以用变量PicOrderCntVal表示,取值范围为-2^31~2^31-1,所以POC值需要31比特表示,为了节省比特,码流中只传输POC的低有效位(LSB),而高有效位(MSB)可以由前面帧计算得到。

POC计算过程如下:

当当前帧不是NoRaslOutputFlag=1的IRAP图像时,变量prevPicOrderCntLsbprevPicOrderCntMsb 可由下面步骤求得:

  1. prevTid0Pic是时域层为0(TemporalId=0)且按解码顺序离当前图像最近的非RASL、RADL或SLNR(sub-layer non-reference picture)图像。

  2. prevPicOrderCntLsb等于prevTid0Pic的 slice_pic_order_cnt_lsb。

  3. prevPicOrderCntMsb等于prevTid0Pic的PicOrderCntMsb。

当前图像的PicOrderCntMsb的计算过程如下:

  1. 如果当前图像是IRAP图像,且NoRaslOutputFlag=1,则PicOrderCntMsb=0。

  2. 否则,PicOrderCntMsb按下面步骤生成:

if( ( slice_pic_order_cnt_lsb < prevPicOrderCntLsb ) &&
( ( prevPicOrderCntLsb − slice_pic_order_cnt_lsb ) >= ( MaxPicOrderCntLsb / 2 ) ) )
PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb
else if( (slice_pic_order_cnt_lsb > prevPicOrderCntLsb ) &&
( ( slice_pic_order_cnt_lsb − prevPicOrderCntLsb ) > ( MaxPicOrderCntLsb / 2 ) ) )
PicOrderCntMsb = prevPicOrderCntMsb − MaxPicOrderCntLsb
else
PicOrderCntMsb = prevPicOrderCntMsb

最终POC的计算如下:

PicOrderCntVal = PicOrderCntMsb + slice_pic_order_cnt_lsb

注意:对所有IDR图像PicOrderCntVal=0。

HM中相关代码如下:

  if( pcSlice->getIdrPicFlag() )
    {//!<IDR图像POC=0
      pcSlice->setPOC(0);
      TComReferencePictureSet* rps = pcSlice->getLocalRPS();
      (*rps)=TComReferencePictureSet();
      pcSlice->setRPS(rps);
    }
    else
    {
      READ_CODE(sps->getBitsForPOC(), uiCode, "slice_pic_order_cnt_lsb");
      Int iPOClsb = uiCode;
      Int iPrevPOC = prevTid0POC;
      Int iMaxPOClsb = 1<< sps->getBitsForPOC();
      Int iPrevPOClsb = iPrevPOC & (iMaxPOClsb - 1);
      Int iPrevPOCmsb = iPrevPOC-iPrevPOClsb;
      Int iPOCmsb;
      if( ( iPOClsb  <  iPrevPOClsb ) && ( ( iPrevPOClsb - iPOClsb )  >=  ( iMaxPOClsb / 2 ) ) )
      {
        iPOCmsb = iPrevPOCmsb + iMaxPOClsb;
      }
      else if( (iPOClsb  >  iPrevPOClsb )  && ( (iPOClsb - iPrevPOClsb )  >  ( iMaxPOClsb / 2 ) ) )
      {
        iPOCmsb = iPrevPOCmsb - iMaxPOClsb;
      }
      else
      {
        iPOCmsb = iPrevPOCmsb;
      }
      if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL
        || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP )
      {
        // For BLA picture types, POCmsb is set to 0.
        iPOCmsb = 0;
      }
      pcSlice->setPOC              (iPOCmsb+iPOClsb);

感兴趣的请关注微信公众号Video Coding

POC计算_h.265/hevc