視頻編碼中由於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