HM中參考圖像列表的設置

對於幀間預測而言,一定會涉及到參考圖像的問題,但是搞清楚HM中參考圖像是如何配置,對理解其編碼結構尤爲關鍵。顧名思義,參考圖像應該是屬於picture級別的,因此可以在compressGOP函數中找到相應的函數。主要包括以下三個函數:

1、arrangeLongtermPicturesInRPS(pcSlice, rcListPic);

2、pcSlice->setRefPicList ( rcListPic );

3、pcSlice->setRefPOCList();

首先說第一個函數,主要是在RPS(Reference Picture Set)句法中設置LongTermPicture,那麼什麼是LT呢?參考圖像主要有以下三種:long-term,short-term before curr和short-term after curr。第一個函數就是用來提供long-term 參考圖像的,具體實現可以查看函數,這裏不做重點敘述。



重點是第二個函數setRefPicList,上面我們瞭解到參考圖像主要有三種,但是最後參考圖像列表中的參考圖像是通過下面的方式確定的。那些在參考列表中用到的參考圖像,其標誌爲1,相反,則爲0;故setRefPicList函數的實現過程是先通過標誌位判斷(if(m_pcRPS->getUsed(i)))確定三種參考圖像的實際參考幀(如下面第一部分),然後再通過ref_pic_list_init過程,再組成list0和list1列表,實現過程詳見程序。



Void TComSlice::setRefPicList( TComList<TComPic*>& rcListPic )
{
  if (m_eSliceType == I_SLICE)
  {//==對於I幀而言,直接返回==//
    ::memset( m_apcRefPicList, 0, sizeof (m_apcRefPicList));
    ::memset( m_aiNumRefIdx,   0, sizeof ( m_aiNumRefIdx ));
    
    return;
  }
  
  m_aiNumRefIdx[0] = getNumRefIdx(REF_PIC_LIST_0); //==list0參考圖像數目==//
  m_aiNumRefIdx[1] = getNumRefIdx(REF_PIC_LIST_1); //==list0參考圖像數目==//

  TComPic*  pcRefPic= NULL;
  TComPic*  RefPicSetStCurr0[16];
  TComPic*  RefPicSetStCurr1[16];
  TComPic*  RefPicSetLtCurr[16];
  UInt NumPocStCurr0 = 0;
  UInt NumPocStCurr1 = 0;
  UInt NumPocLtCurr = 0;
  Int i;

  for(i=0; i < m_pcRPS->getNumberOfNegativePictures(); i++)
  {// 設置short term negative(即前向參考圖像)
    if(m_pcRPS->getUsed(i))
    {
      pcRefPic = xGetRefPic(rcListPic, getPOC()+m_pcRPS->getDeltaPOC(i));
      pcRefPic->setIsLongTerm(0);
      pcRefPic->setIsUsedAsLongTerm(0);
      pcRefPic->getPicYuvRec()->extendPicBorder();
      RefPicSetStCurr0[NumPocStCurr0 ] = pcRefPic;
      NumPocStCurr0++;
      pcRefPic->setCheckLTMSBPresent(false);  
    }
  }
  for(; i < m_pcRPS->getNumberOfNegativePictures()+m_pcRPS->getNumberOfPositivePictures(); i++)
  {// 設置short term positive(即後向參考圖像)
    if(m_pcRPS->getUsed(i))
    {
      pcRefPic = xGetRefPic(rcListPic, getPOC()+m_pcRPS->getDeltaPOC(i));
      pcRefPic->setIsLongTerm(0);
      pcRefPic->setIsUsedAsLongTerm(0);
      pcRefPic->getPicYuvRec()->extendPicBorder();
      RefPicSetStCurr1[NumPocStCurr1] = pcRefPic;
      NumPocStCurr1++;
      pcRefPic->setCheckLTMSBPresent(false);  
    }
  }
  for(i = m_pcRPS->getNumberOfNegativePictures()+m_pcRPS->getNumberOfPositivePictures()+m_pcRPS->getNumberOfLongtermPictures()-1; i > m_pcRPS->getNumberOfNegativePictures()+m_pcRPS->getNumberOfPositivePictures()-1 ; i--)
  {//==設置long term參考圖像==//
    if(m_pcRPS->getUsed(i))
    {
      pcRefPic = xGetLongTermRefPic(rcListPic, m_pcRPS->getPOC(i));
      pcRefPic->setIsLongTerm(1);
      pcRefPic->setIsUsedAsLongTerm(1);
      pcRefPic->getPicYuvRec()->extendPicBorder();
      RefPicSetLtCurr[NumPocLtCurr] = pcRefPic;
      NumPocLtCurr++;
    }
    if(pcRefPic==NULL) 
    {
      pcRefPic = xGetLongTermRefPic(rcListPic, m_pcRPS->getPOC(i));
    }
    pcRefPic->setCheckLTMSBPresent(m_pcRPS->getCheckLTMSBPresent(i));  
  }
  // ref_pic_list_init
#if RPL_INIT_FIX
  TComPic*  rpsCurrList0[MAX_NUM_REF+1];
  TComPic*  rpsCurrList1[MAX_NUM_REF+1];
  Int numPocTotalCurr = NumPocStCurr0 + NumPocStCurr1 + NumPocLtCurr;

  {
    Int cIdx = 0;
    for ( i=0; i<NumPocStCurr0; i++, cIdx++)
    {//==(0<=cIdx<NumPocStCurr0)==//
      rpsCurrList0[cIdx] = RefPicSetStCurr0[i];
    }
    for ( i=0; i<NumPocStCurr1; i++, cIdx++)
    {//==(NumPocStCurr0<=cIdx<NumPocStCurr1+NumPocStCurr0)==//
      rpsCurrList0[cIdx] = RefPicSetStCurr1[i];
    }
    for ( i=0; i<NumPocLtCurr;  i++, cIdx++)
    {//==(NumPocStCurr1<=cIdx<numPocTotalCurr)==//
      rpsCurrList0[cIdx] = RefPicSetLtCurr[i];
    }
  }

  if (m_eSliceType==B_SLICE)
  {
    Int cIdx = 0;
    for ( i=0; i<NumPocStCurr1; i++, cIdx++)
    {//==(0<=cIdx<NumPocStCurr0)==//
      rpsCurrList1[cIdx] = RefPicSetStCurr1[i];
    }
    for ( i=0; i<NumPocStCurr0; i++, cIdx++)
    {//==(NumPocStCurr0<=cIdx<NumPocStCurr1+NumPocStCurr0)==//
      rpsCurrList1[cIdx] = RefPicSetStCurr0[i];
    }
    for ( i=0; i<NumPocLtCurr;  i++, cIdx++)
    {//==(NumPocStCurr1+NumPocStCurr0<=cIdx<numPocTotalCurr)==//
      rpsCurrList1[cIdx] = RefPicSetLtCurr[i];
    }
  }
   
  ///=====Unification of reference picture list modification processes(參考JCTVC-H0138)=====///
  for (Int rIdx = 0; rIdx <= (m_aiNumRefIdx[0]-1); rIdx ++)
  {//===修正list0列表===//
    m_apcRefPicList[0][rIdx] = m_RefPicListModification.getRefPicListModificationFlagL0() ? rpsCurrList0[ m_RefPicListModification.getRefPicSetIdxL0(rIdx) ] : rpsCurrList0[rIdx % numPocTotalCurr];
  }
  if ( m_eSliceType == P_SLICE )
  {//////////////////==若爲P幀,則list1爲零==/////////////////////////////
    m_aiNumRefIdx[1] = 0;
    ::memset( m_apcRefPicList[1], 0, sizeof(m_apcRefPicList[1]));
  }
  else
  {//===修正list1列表===//
    for (Int rIdx = 0; rIdx <= (m_aiNumRefIdx[1]-1); rIdx ++)
    {
      m_apcRefPicList[1][rIdx] = m_RefPicListModification.getRefPicListModificationFlagL1() ? rpsCurrList1[ m_RefPicListModification.getRefPicSetIdxL1(rIdx) ] : rpsCurrList1[rIdx % numPocTotalCurr];
    }
  }

而最後一個函數setRefPOCList就是實現將參考圖像轉化成其相應的POC列表。

Void TComSlice::setRefPOCList       ()
{//===將參考圖像列表轉化成相應的POC===//
  for (Int iDir = 0; iDir < 2; iDir++)
  {
    for (Int iNumRefIdx = 0; iNumRefIdx < m_aiNumRefIdx[iDir]; iNumRefIdx++)
    {
      m_aiRefPOCList[iDir][iNumRefIdx] = m_apcRefPicList[iDir][iNumRefIdx]->getPOC();
    }
  }
}


另外在第二個函數中有涉及到ListModification(列表修正)的問題,由於篇幅有限,將和 List Combination(參考列表聯合)一起留到後續再討論!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章