HEVC帧内预测的35中预测模式是在PU基础上定义的,实际帧内预测的过程则以TU为单位。PU以四叉树划分TU,一个PU内所有TU共享同一种预测模式。帧内预测分3个步骤:
(1) 判断当前TU相邻像素点是否可用并做相应的处理
(2) 对参考像素进行滤波
(3) 根据滤波后的参考像素计算当前TU的预测像素值。
HM-16.7中fillReferenceSamples()主要实现第一个步骤,真正进行帧内预测之前,使用重建后的Yuv图像对当前PU的相邻样点进行赋值,为接下来进行的角度预测提供参考样点值,对应于draft 8.4.4.2.2的内容。主要过程是:
(1)如果所有相邻点均不可用,则参考样点值均被赋值为DC值;
iDCValue = 1 << (bitDepth - 1),对于8bit像素,该值为128。
(2)如果所有相邻点均可用,则参考样点值都会被赋值为重建Yuv图像中与其位置相同的样点值;
(3)如果不满足上述两个条件,则按照从左下往左上,从左上往右上的扫描顺序进行遍历,如果第一个点不可用,则使用下一个可用点对应的重建Yuv样点值对其进行赋值;对于除第一个点外的其它邻点,如果该点不可用,则使用它的前一个样点值进行赋值(前一个步骤保证了前一个样点值一定是存在的),直到遍历完毕。
1 Void fillReferenceSamples( const Int bitDepth, 2 #if O0043_BEST_EFFORT_DECODING 3 const Int bitDepthDelta, 4 #endif 5 const Pel* piRoiOrigin, 6 Pel* piIntraTemp, 7 const Bool* bNeighborFlags, 8 const Int iNumIntraNeighbor, 9 const Int unitWidth, 10 const Int unitHeight, 11 const Int iAboveUnits, 12 const Int iLeftUnits, 13 const UInt uiWidth, 14 const UInt uiHeight, 15 const Int iPicStride ) 16 { 17 const Pel* piRoiTemp;//piRoiOrgin指向重建Yuv图像对应于当前PU所在位置的首地址,piRoiTemp用于指向所感兴趣的重建Yuv的位置 18 Int i, j; 19 Int iDCValue = 1 << (bitDepth - 1);//参考像素不可用时的填充值,8bit时候为128. 20 const Int iTotalUnits = iAboveUnits + iLeftUnits + 1; //+1 for top-left //以4个像素点为单位标记,其中左上角单独标记 21 22 if (iNumIntraNeighbor == 0) // all samples are not available 23 { 24 // Fill border with DC value 25 for (i=0; i<< bitDepthDelta; 43 #else 44 piIntraTemp[i] = piRoiTemp[i]; 45 #endif 46 } 47 48 // Fill left and below left border with rec. samples 49 piRoiTemp = piRoiOrigin - 1; 50 51 for (i=1; i << bitDepthDelta; 55 #else 56 piIntraTemp[i*uiWidth] = *(piRoiTemp);//!< 每个参考样点赋值为对应位置重建Yuv样点值 57 #endif 58 piRoiTemp += iPicStride;//!< 指向重建Yuv下一行 59 } 60 } 61 else // reference samples are partially available 62 { 63 // all above units have "unitWidth" samples each, all left/below-left units have "unitHeight" samples each 64 //!< neighboring samples的总数 65 const Int iTotalSamples = (iLeftUnits * unitHeight) + ((iAboveUnits + 1) * unitWidth); 66 Pel piIntraLine[5 * MAX_CU_SIZE]; 67 Pel *piIntraLineTemp;//! <临时存储用于填充neighboring samples的样点值 68 const bool *pbneighborflags; 保存以四个像素点为单位的可用性 69 70 initialize 71 for (i="0;" i << bitDepthDelta; 84 #else 85 Pel topLeftVal=piRoiTemp[0]; 86 #endif 87 for (i=0; i << bitDepthDelta;106 #else107 piIntraLineTemp[-i] = piRoiTemp[i*iPicStride];108 #endif109 }110 }111 piRoiTemp += unitHeight*iPicStride;//!< 指针挪到下一个行(以4x4块为单位,即实际上下移了4行) 112 piIntraLineTemp -= unitHeight;//!< 指针下移 113 pbNeighborFlags--;//!< 指针下移 114 }115 116 // Fill above & above-right samples (left-to-right) (each unit has "unitWidth" samples)117 piRoiTemp = piRoiOrigin - iPicStride;//!< piRoiTemp 指向重建Yuv的上边界118 // offset line buffer by iNumUints2*unitHeight (for left/below-left) + unitWidth (for above-left)119 piIntraLineTemp = piIntraLine + (iLeftUnits * unitHeight) + unitWidth;120 pbNeighborFlags = bNeighborFlags + iLeftUnits + 1;121 for (j=0; j 临时存储用于填充neighboring><< bitDepthDelta;129 #else130 piIntraLineTemp[i] = piRoiTemp[i];131 #endif132 }133 }134 piRoiTemp += unitWidth;//!< 指针右移,实际是右移了4135 piIntraLineTemp += unitWidth;//!< 指针右移,实际是右移了4136 pbNeighborFlags++;//!< 指针右移,以4个像素点为单位标记可用性137 }138 139 // Pad reference samples when necessary140 Int iCurrJnit = 0;141 Pel *piIntraLineCur = piIntraLine;//!< 指向左下角(纵坐标最大的那个位置,即扫描起点) 142 const UInt piIntraLineTopRowOffset = iLeftUnits * (unitHeight - unitWidth);143 144 if (!bNeighborFlags[0])145 {146 // very bottom unit of bottom-left; at least one unit will be valid.147 {148 Int iNext = 1;149 while (iNext < iTotalUnits && !bNeighborFlags[iNext])150 {151 iNext++;152 }153 Pel *piIntraLineNext = piIntraLine + ((iNext < iLeftUnits) ? (iNext * unitHeight) : (piIntraLineTopRowOffset + (iNext * unitWidth)));154 const Pel refSample = *piIntraLineNext;155 // Pad unavailable samples with new value156 Int iNextOrTop = std::min (iNext, iLeftUnits);157 // fill left column158 while (iCurrJnit < iNextOrTop) //!< 遍历所有neighboring samples 159 {160 for (i=0; i = iLeftUnits) ? unitWidth : unitHeight;187 const Pel refSample = *(piIntraLineCur-1);188 for (i=0; i = iLeftUnits) ? unitWidth : unitHeight;199 iCurrJnit++;200 }201 }202 203 // Copy processed samples204 205 piIntraLineTemp = piIntraLine + uiHeight + unitWidth - 2;206 // top left, top and top right samples207 for (i=0; i