hevc角度预测_【HEVC】4、HM-16.7编码一个CU(帧内部分) 3.帧内预测各种模式实现

HEVC中一共定义了35中帧内编码预测模式,编号分别以0-34定义。其中模式0定义为平面模式(INTRA_PLANAR),模式1定义为均值模式(INTRA_DC),模式2~34定义为角度预测模式(INTRA_ANGULAR2~INTRA_ANGULAR34),分别代表了不同的角度。

最简单的Intra_DC模式,DC模式适用于大面积平摊区域,当前预测值可由其左侧和上方(不包含左上角,左下方和右上方)参考像素的平均值得到。该模式同角度预测模式实现在同一个函数Void TComPrediction::xPredIntraAng(...)中:

1 Void TComPrediction::xPredIntraAng( Int bitDepth,2 const Pel*pSrc, Int srcStride,3 Pel*pTrueDst, Int dstStrideTrue,4 UInt uiWidth, UInt uiHeight, ChannelType channelType,5 UInt dirMode, constBool bEnableEdgeFilters6 )7 {8 Int width=Int(uiWidth);9 Int height=Int(uiHeight);10

11 //Map the mode index to main prediction direction and angle

12 assert( dirMode != PLANAR_IDX ); //no planar

13 const Bool modeDC = dirMode==DC_IDX;14

15 //Do the DC prediction

16 if(modeDC)17 {18 const Pel dcval =predIntraGetPredValDC(pSrc, srcStride, width, height);19

20 for (Int y=height;y>0;y--, pTrueDst+=dstStrideTrue)21 {22 for (Int x=0; x

23 {24 pTrueDst[x++] =dcval;25 }26 }27 }28 else //Do angular predictions

29 {30 //........31 }32 }

在这个函数中可以看到,Intra_DC模式中所有预测块的像素值都是同一个值dcval,这个值是由一个函数predIntraGetPredValDC计算得到:

1 Pel TComPrediction::predIntraGetPredValDC( const Pel*pSrc, Int iSrcStride, UInt iWidth, UInt iHeight)2 {3 assert(iWidth > 0 && iHeight > 0);4 Int iInd, iSum = 0;5 Pel pDcVal;6

7 for (iInd = 0;iInd < iWidth;iInd++)8 {9 iSum += pSrc[iInd-iSrcStride];//左列参考像素总和10 }11 for (iInd = 0;iInd < iHeight;iInd++)12 {13 iSum += pSrc[iInd*iSrcStride-1];//上方行参考像素总和14 }15

16 pDcVal = (iSum + iWidth) / (iWidth +iHeight);//取平均值17

18 returnpDcVal;19 }

其次是Planar模式,该模式定义在xPredIntraPlanar函数中。适用于像素值缓慢变化的区域,Planar使用水平和垂直方向的两个线性滤波器,并将二者的平均值作为当前像素的预测值。Planar能够使像素平缓变化,与其他模式相比能够提升视频的主管质量。

1 Void TComPrediction::xPredIntraPlanar( const Pel* pSrc, Int srcStride, Pel*rpDst, Int dstStride, UInt width, UInt height )2 {3 assert(width <=height);4

5 Int leftColumn[MAX_CU_SIZE+1], topRow[MAX_CU_SIZE+1], bottomRow[MAX_CU_SIZE], rightColumn[MAX_CU_SIZE];6 UInt shift1Dhor = g_aucConvertToBit[ width ] + 2;7 UInt shift1Dver = g_aucConvertToBit[ height ] + 2;8

9 //Get left and above reference column and row

10 for(Int k=0;k

15 for (Int k=0; k < height+1; k++)//记录左列数据16 {17 leftColumn[k] = pSrc[k*srcStride-1];18 }19

20 //Prepare intermediate variables used in interpolation

21 Int bottomLeft =leftColumn[height];//左下角像素值22 Int topRight =topRow[width];//右上角像素值23 /*计算底行的数据,方法是用左下角的像素减去顶行相应位置的像素得到底行。*/

24 for(Int k=0;k

30 for(Int k=0;k

36 const UInt topRowShift = 0;37

38 //Generate prediction signal

39 for (Int y=0;y

47 Int vertPred = ((topRow[x] + topRowShift)>>topRowShift);//水平方向(x,y)预测值48 rpDst[y*dstStride+x] = ( horPred + vertPred ) >> (shift1Dhor+1);//预测像素是水平和垂直两个方向预测值得平均值49 }50 }51 }

最后是角度预测,mode=2~34时采用角度预测模式。实现的方式在xPredIntraAng中:

1 Void TComPrediction::xPredIntraAng( Int bitDepth,2 const Pel*pSrc, Int srcStride,3 Pel*pTrueDst, Int dstStrideTrue,4 UInt uiWidth, UInt uiHeight, ChannelType channelType,5 UInt dirMode, constBool bEnableEdgeFilters6 )7 {8 Int width=Int(uiWidth);9 Int height=Int(uiHeight);10

11 //Map the mode index to main prediction direction and angle

12 assert( dirMode != PLANAR_IDX ); //no planar

13 const Bool modeDC = dirMode==DC_IDX;14

15 //Do the DC prediction

16 if(modeDC)17 {18 const Pel dcval =predIntraGetPredValDC(pSrc, srcStride, width, height);19

20 for (Int y=height;y>0;y--, pTrueDst+=dstStrideTrue)21 {22 for (Int x=0; x

23 {24 pTrueDst[x++] =dcval;25 }26 }27 }28 else //Do angular predictions

29 {30 const Bool bIsModeVer = (dirMode >= 18);31 const Int intraPredAngleMode = (bIsModeVer) ? (Int)dirMode - VER_IDX : -((Int)dirMode -HOR_IDX);32 const Int absAngMode =abs(intraPredAngleMode);33 const Int signAng = intraPredAngleMode < 0 ? -1 : 1;34 const Bool edgeFilter = bEnableEdgeFilters && isLuma(channelType) && (width <= MAXIMUM_INTRA_FILTERED_WIDTH) && (height <=MAXIMUM_INTRA_FILTERED_HEIGHT);35

36 //Set bitshifts and scale the angle parameter to block size

37 static const Int angTable[9] = {0, 2, 5, 9, 13, 17, 21, 26, 32};38 static const Int invAngTable[9] = {0, 4096, 1638, 910, 630, 482, 390, 315, 256}; //(256 * 32) / Angle

39 Int invAngle =invAngTable[absAngMode];40 Int absAng =angTable[absAngMode];41 Int intraPredAngle = signAng *absAng;42

43 Pel*refMain;44 Pel*refSide;45

46 Pel refAbove[2*MAX_CU_SIZE+1];47 Pel refLeft[2*MAX_CU_SIZE+1];48

49 //Initialize the Main and Left reference array.

50 if (intraPredAngle < 0)51 {52 const Int refMainOffsetPreScale = (bIsModeVer ? height : width ) - 1;53 const Int refMainOffset = height - 1;54 for (Int x=0;x

65 //Extend the Main reference to the left.

66 Int invAngleSum = 128; //rounding for (shift by 8)

67 for (Int k=-1; k>(refMainOffsetPreScale+1)*intraPredAngle>>5; k--)68 {69 invAngleSum +=invAngle;70 refMain[k] = refSide[invAngleSum>>8];71 }72 }73 else

74 {75 for (Int x=0;x<2*width+1;x++)76 {77 refAbove[x] = pSrc[x-srcStride-1];78 }79 for (Int y=0;y<2*height+1;y++)80 {81 refLeft[y] = pSrc[(y-1)*srcStride-1];82 }83 refMain = bIsModeVer ?refAbove : refLeft ;84 refSide = bIsModeVer ?refLeft : refAbove;85 }86

87 //swap width/height if we are doing a horizontal mode:

88 Pel tempArray[MAX_CU_SIZE*MAX_CU_SIZE];89 const Int dstStride = bIsModeVer ?dstStrideTrue : MAX_CU_SIZE;90 Pel *pDst = bIsModeVer ?pTrueDst : tempArray;91 if (!bIsModeVer)92 {93 std::swap(width, height);94 }95

96 if (intraPredAngle == 0) //pure vertical or pure horizontal

97 {98 for (Int y=0;y

106 if(edgeFilter)107 {108 for (Int y=0;y> 1) );111 }112 }113 }114 else

115 {116 Pel *pDsty=pDst;117

118 for (Int y=0, deltaPos=intraPredAngle; y> 5;121 const Int deltaFract = deltaPos & (32 - 1);122

123 if(deltaFract)124 {125 //Do linear filtering

126 const Pel *pRM=refMain+deltaInt+1;127 Int lastRefMainPel=*pRM++;128 for (Int x=0;x> 5);132 lastRefMainPel=thisRefMainPel;133 }134 }135 else

136 {137 //Just copy the integer samples

138 for (Int x=0;x

146 //Flip the block if this is the horizontal mode

147 if (!bIsModeVer)148 {149 for (Int y=0; y

帧内预测是在TComPrediction::predIntraAng(...)实现:

1 Void TComPrediction::predIntraAng( const ComponentID compID, UInt uiDirMode, Pel* piOrg /*Will be null for decoding*/, UInt uiOrgStride, Pel* piPred, UInt uiStride, TComTU &rTu, const Bool bUseFilteredPredSamples, constBool bUseLosslessDPCM )2 {3 const ChannelType channelType =toChannelType(compID);4 const TComRectangle &rect = rTu.getRect(isLuma(compID) ?COMPONENT_Y : COMPONENT_Cb);5 const Int iWidth =rect.width;6 const Int iHeight =rect.height;7

8 assert( g_aucConvertToBit[ iWidth ] >= 0 ); //4x 4

9 assert( g_aucConvertToBit[ iWidth ] <= 5 ); //128x12810 //assert( iWidth == iHeight );

11

12 Pel *pDst =piPred;13

14 //get starting pixel in block

15 const Int sw = (2 * iWidth + 1);16

17 if( bUseLosslessDPCM )//如果预测方式为垂直或水平,则bUseLosslessDPCM =118 {19 const Pel *ptrSrc = getPredictorPtr( compID, false);20 //Sample Adaptive intra-Prediction (SAP)

21 if (uiDirMode==HOR_IDX)//竖直方向预测22 {23 //left column filled with reference samples24 //remaining columns filled with piOrg data (if available).

25 for(Int y=0; y

32 for(Int y=0; y

39 {40 //top row filled with reference samples41 //remaining rows filled with piOrd data (if available)

42 for(Int x=0; x

49 for(Int y=1; y

57 {58 const Pel *ptrSrc =getPredictorPtr( compID, bUseFilteredPredSamples );59

60 if ( uiDirMode ==PLANAR_IDX )61 {62 xPredIntraPlanar( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight );63 }64 else

65 {66 //Create the prediction

67 TComDataCU *const pcCU =rTu.getCU();68 const UInt uiAbsPartIdx =rTu.GetAbsPartIdxTU();69 const Bool enableEdgeFilters = !(pcCU->isRDPCMEnabled(uiAbsPartIdx) && pcCU->getCUTransquantBypass(uiAbsPartIdx));70 #if O0043_BEST_EFFORT_DECODING

71 const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getStreamBitDepth(channelType);72 #else

73 const Int channelsBitDepthForPrediction = rTu.getCU()->getSlice()->getSPS()->getBitDepth(channelType);74 #endif

75 xPredIntraAng( channelsBitDepthForPrediction, ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType, uiDirMode, enableEdgeFilters );76

77 if( uiDirMode ==DC_IDX )78 {79 xDCPredFiltering( ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType );80 }81 }82 }83

84 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值