视频编码中由于B帧的存在使得视频的播放顺序和编码顺序不一样。解码后的视频需要按播放顺序排列播放,POC(picture order count)就是视频帧按播放顺序的标识号。
POC的作用主要有:帧的唯一标识符、用于merge模式下生成运动信息、解码端一致性检查。
每一个编码的帧都有一个POC,可以用变量PicOrderCntVal表示,取值范围为-2^31~2^31-1,所以POC值需要31比特表示,为了节省比特,码流中只传输POC的低有效位(LSB),而高有效位(MSB)可以由前面帧计算得到。
POC计算过程如下:
当当前帧不是NoRaslOutputFlag=1的IRAP图像时,变量prevPicOrderCntLsb和prevPicOrderCntMsb 可由下面步骤求得:
-
prevTid0Pic是时域层为0(TemporalId=0)且按解码顺序离当前图像最近的非RASL、RADL或SLNR(sub-layer non-reference picture)图像。
-
prevPicOrderCntLsb等于prevTid0Pic的 slice_pic_order_cnt_lsb。
-
prevPicOrderCntMsb等于prevTid0Pic的PicOrderCntMsb。
当前图像的PicOrderCntMsb的计算过程如下:
-
如果当前图像是IRAP图像,且NoRaslOutputFlag=1,则PicOrderCntMsb=0。
-
否则,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