[HEVC] HEVC學習(五) —— 幀內預測系列之三

[HEVC] HEVC學習(五) —— 幀內預測系列之三

今天主要介紹幀內預測一個很重要的函數initAdiPattern,它的主要功能有三個,(1)檢測當前PU的相鄰樣點包括左上、上、右上、左、左下鄰域樣點值的可用性,或者說檢查這些點是否存在;(2)參考樣點的替換過程,主要實現的是JCTVC-J1003即draft 8.4.4.2.2的內容,主要由函數fillReferenceSamples來完成,這個在之前的文章已經討論過了;(3)相鄰樣點即參考樣點的平滑濾波,主要實現draft 8.4.4.2.3的內容。話不多說,下面給出initAdiPattern的實現和我個人的一些註釋,供大家參考。
  1. Void TComPattern::initAdiPattern( TComDataCU* pcCU, UInt uiZorderIdxInPart, UInt uiPartDepth, Int* piAdiBuf, Int iOrgBufStride, Int iOrgBufHeight, Bool& bAbove, Bool& bLeft, Bool bLMmode )
  2. {//! bLMmode is usually false 
  3.   Pel*  piRoiOrigin;
  4.   Int*  piAdiTemp;
  5.   UInt  uiCuWidth   = pcCU->getWidth(0) >> uiPartDepth; //!< CU的寬度
  6.   UInt  uiCuHeight  = pcCU->getHeight(0)>> uiPartDepth; //!< CU的高度
  7.   UInt  uiCuWidth2  = uiCuWidth<<1;
  8.   UInt  uiCuHeight2 = uiCuHeight<<1;
  9.   UInt  uiWidth;
  10.   UInt  uiHeight;
  11.   Int   iPicStride = pcCU->getPic()->getStride();
  12.   Int   iUnitSize = 0;
  13.   Int   iNumUnitsInCu = 0;
  14.   Int   iTotalUnits = 0;
  15.   Bool  bNeighborFlags[4 * MAX_NUM_SPU_W + 1];  //!< 用於存放4個方向上的相鄰樣點值的可用性, 4 x 32 + 1
  16.   Int   iNumIntraNeighbor = 0; //!< 給可用鄰塊進行計數
  17.   
  18.   UInt uiPartIdxLT, uiPartIdxRT, uiPartIdxLB;

  19.   //! 獲取當前PU左上角LT,右上角RT以及左下角LB 以4x4塊爲單位的Zorder
  20.   pcCU->deriveLeftRightTopIdxAdi( uiPartIdxLT, uiPartIdxRT, uiZorderIdxInPart, uiPartDepth );
  21.   pcCU->deriveLeftBottomIdxAdi  ( uiPartIdxLB,              uiZorderIdxInPart, uiPartDepth );
  22.   
  23.   iUnitSize      = g_uiMaxCUWidth >> g_uiMaxCUDepth;
  24.   iNumUnitsInCu  = uiCuWidth / iUnitSize;
  25.   iTotalUnits    = (iNumUnitsInCu << 2) + 1; // Top + RightTop + Left + LeftBottom + LeftTop = iNumUnitsInCu + iNumUnitsInCu + iNumUnitsInCu + iNumUnitsInCu + 1
  26.   //! 掃描順序是從左下到左上,再從左上到右上
  27.   bNeighborFlags[iNumUnitsInCu*2] = isAboveLeftAvailable( pcCU, uiPartIdxLT );
  28.   iNumIntraNeighbor  += (Int)(bNeighborFlags[iNumUnitsInCu*2]);
  29.   iNumIntraNeighbor  += isAboveAvailable     ( pcCU, uiPartIdxLT, uiPartIdxRT, bNeighborFlags+(iNumUnitsInCu*2)+1 );
  30.   iNumIntraNeighbor  += isAboveRightAvailable( pcCU, uiPartIdxLT, uiPartIdxRT, bNeighborFlags+(iNumUnitsInCu*3)+1 );
  31.   iNumIntraNeighbor  += isLeftAvailable      ( pcCU, uiPartIdxLT, uiPartIdxLB, bNeighborFlags+(iNumUnitsInCu*2)-1 );
  32.   iNumIntraNeighbor  += isBelowLeftAvailable ( pcCU, uiPartIdxLT, uiPartIdxLB, bNeighborFlags+ iNumUnitsInCu   -1 );
  33.   
  34.   bAbove = true;
  35.   bLeft  = true;

  36.   uiWidth=uiCuWidth2+1;
  37.   uiHeight=uiCuHeight2+1;
  38.   
  39.   if (((uiWidth<<2)>iOrgBufStride)||((uiHeight<<2)>iOrgBufHeight))
  40.   {
  41.     return;
  42.   }
  43.   //! piRoiOrigin指向當前PU左上角
  44.   piRoiOrigin = pcCU->getPic()->getPicYuvRec()->getLumaAddr(pcCU->getAddr(), pcCU->getZorderIdxInCU()+uiZorderIdxInPart);
  45.   piAdiTemp   = piAdiBuf;

  46.   fillReferenceSamples ( pcCU, piRoiOrigin, piAdiTemp, bNeighborFlags, iNumIntraNeighbor, iUnitSize, iNumUnitsInCu, iTotalUnits, uiCuWidth, uiCuHeight, uiWidth, uiHeight, iPicStride, bLMmode);
  47.   
  48.   Int   i;
  49.   // generate filtered intra prediction samples
  50.   Int iBufSize = uiCuHeight2 + uiCuWidth2 + 1;  // left and left above border + above and above right border + top left corner = length of 3. filter buffer

  51.   UInt uiWH = uiWidth * uiHeight;               // number of elements in one buffer

  52.   //! 下面所進行的工作主要是對參考樣點進行3抽頭的濾波。piAdiBuf指向濾波前的參考樣點的首地址,在濾波前,先將所有參考樣點
  53.   //! 拷貝到piFilterBuf指向的區域,經濾波後的樣點值保存在piFilterBufN指向的區域,最終將濾波後的樣點值拷貝到piFilterBuf1
  54.   //! 值得一提的是,最終的結果是,piAdiBuf指向的區域是未經濾波的樣點值,而piFilterBuf1指向的區域是經過濾波的樣點值,
  55.   //! 兩者的地址相差uiWH = uiWidth * uiHeight = (uiCuWidth2 + 1) * (uiCuHeight2 + 1),這就解釋了在進行真正的幀內預測時,
  56.   //! 在需要濾波時,指向piAdiBuf的指針需要加上uiWH的偏移量
  57.   Int* piFilteredBuf1 = piAdiBuf + uiWH;        // 1. filter buffer
  58.   Int* piFilteredBuf2 = piFilteredBuf1 + uiWH;  // 2. filter buffer
  59.   Int* piFilterBuf = piFilteredBuf2 + uiWH;     // buffer for 2. filtering (sequential)
  60.   Int* piFilterBufN = piFilterBuf + iBufSize;   // buffer for 1. filtering (sequential) //!<存放的是參考樣點經3抽頭濾波後的值

  61.   // draft 8.4.4.2.3 Filtering process of neighbouring samples
  62.   Int l = 0;
  63.   // left border from bottom to top
  64.   for (i = 0; i < uiCuHeight2; i++)
  65.   {
  66.     piFilterBuf[l++] = piAdiTemp[uiWidth * (uiCuHeight2 - i)]; //!< 左邊界,存儲順序爲從下往上
  67.   }
  68.   // top left corner
  69.   piFilterBuf[l++] = piAdiTemp[0];  //!< 左上邊界
  70.   // above border from left to right
  71.   for (i=0; i < uiCuWidth2; i++)
  72.   {
  73.     piFilterBuf[l++] = piAdiTemp[1 + i];  //!<上邊界,存儲順序爲從左往右
  74.   }

  75.   // 1. filtering with [1 2 1]
  76.   piFilterBufN[0] = piFilterBuf[0]; //!< 第1個點直接保存,不濾波
  77.   piFilterBufN[iBufSize - 1] = piFilterBuf[iBufSize - 1]; //!< 最後一個點也直接保存,不濾波
  78.   for (i = 1; i < iBufSize - 1; i++) //!< 對中間樣點值進行3抽頭[1 2 1] / 4 的平滑濾波
  79.   {
  80.     piFilterBufN[i] = (piFilterBuf[i - 1] + 2 * piFilterBuf[i]+piFilterBuf[i + 1] + 2) >> 2;
  81.   }

  82.   // fill 1. filter buffer with filtered values
  83.   l=0;
  84.   for (i = 0; i < uiCuHeight2; i++)
  85.   {
  86.     piFilteredBuf1[uiWidth * (uiCuHeight2 - i)] = piFilterBufN[l++];  // left border from bottom to top //!< 左邊界
  87.   }
  88.   piFilteredBuf1[0] = piFilterBufN[l++]; //!< 左上邊界
  89.   for (i = 0; i < uiCuWidth2; i++)
  90.   {
  91.     piFilteredBuf1[1 + i] = piFilterBufN[l++]; // above border from left to right //!< 上邊界
  92.   }
  93. }
複製代碼
最後附上圖,以幫助大家更好地理解代碼,我就不對圖多作解釋了,相信大家對着代碼能比較容易看明白的。
[img][/img]




(轉載請註明出處。原文地址:http://blog.csdn.net/hevc_cjl/article/details/8184276

圖片1.jpg (12.99 KB)

圖1

圖片1.jpg

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