【HEVC】2、HM-16.7编码一个CU(帧内部分) 1.帧内预测相邻参考像素获取

     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<uiWidth; i++) //!< AboveLeft + Above + AboveRight 
 26     {
 27       piIntraTemp[i] = iDCValue;
 28     }
 29     for (i=1; i<uiHeight; i++)//!< Left + BelowLeft
 30     {
 31       piIntraTemp[i*uiWidth] = iDCValue;
 32     }
 33   }
 34   else if (iNumIntraNeighbor == iTotalUnits)// all samples are available  
 35   {
 36     // Fill top-left border and top and top right with rec. samples
 37     piRoiTemp = piRoiOrigin - iPicStride - 1; //!< AboveLeft
 38 
 39     for (i=0; i<uiWidth; i++)
 40     {
 41 #if O0043_BEST_EFFORT_DECODING
 42       piIntraTemp[i] = piRoiTemp[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<uiHeight; i++)
 52     {
 53 #if O0043_BEST_EFFORT_DECODING
 54       piIntraTemp[i*uiWidth] = (*(piRoiTemp)) << 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<iTotalSamples; i++)
 72     {
 73       piIntraLine[i] = iDCValue;
 74     }
 75 
 76     // Fill top-left sample
 77     piRoiTemp = piRoiOrigin - iPicStride - 1;//!< 指向重建Yuv左上角  
 78     piIntraLineTemp = piIntraLine + (iLeftUnits * unitHeight);//!< piAdiLine的扫描顺序为左下到左上,再从左到右上  
 79     pbNeighborFlags = bNeighborFlags + iLeftUnits;//!< 标记neighbor可用性的数组同样移动至左上角 
 80     if (*pbNeighborFlags)//!< 如果左上角可用,则左上角4个像素点均赋值为重建Yuv左上角的样点值
 81     {
 82 #if O0043_BEST_EFFORT_DECODING
 83       Pel topLeftVal=piRoiTemp[0] << bitDepthDelta;
 84 #else
 85       Pel topLeftVal=piRoiTemp[0];
 86 #endif
 87       for (i=0; i<unitWidth; i++)
 88       {
 89         piIntraLineTemp[i] = topLeftVal;
 90       }
 91     }
 92 
 93     // Fill left & below-left samples (downwards)
 94     piRoiTemp += iPicStride;//!< piRoiTemp指向重建Yuv的左边界
 95     piIntraLineTemp--;//移动指针至左边界
 96     pbNeighborFlags--;//移动指针至左边界
 97 
 98     for (j=0; j<iLeftUnits; j++)//从左向左下扫描
 99     {
100       if (*pbNeighborFlags)//如果可用
101       {
102         for (i=0; i<unitHeight; i++)//!< 每个4x4块里的4个样点分别被赋值为对应位置的重建Yuv的样点值 
103         {
104 #if O0043_BEST_EFFORT_DECODING
105           piIntraLineTemp[-i] = piRoiTemp[i*iPicStride] << bitDepthDelta;
106 #else
107           piIntraLineTemp[-i] = piRoiTemp[i*iPicStride];
108 #endif
109         }
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<iAboveUnits; j++) //!< 从左扫描至右上  
122     {
123       if (*pbNeighborFlags)//如果可用
124       {
125         for (i=0; i<unitWidth; i++)//!< 每个4x4块里的4个样点分别被赋值为对应位置的重建Yuv的样点值  
126         {
127 #if O0043_BEST_EFFORT_DECODING
128           piIntraLineTemp[i] = piRoiTemp[i] << bitDepthDelta;
129 #else
130           piIntraLineTemp[i] = piRoiTemp[i];
131 #endif
132         }
133       }
134       piRoiTemp += unitWidth;//!< 指针右移,实际是右移了4
135       piIntraLineTemp += unitWidth;//!< 指针右移,实际是右移了4
136       pbNeighborFlags++;//!< 指针右移,以4个像素点为单位标记可用性
137     }
138 
139     // Pad reference samples when necessary
140     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 value
156         Int iNextOrTop = std::min<Int>(iNext, iLeftUnits);
157         // fill left column
158         while (iCurrJnit < iNextOrTop) //!< 遍历所有neighboring samples 
159         {
160           for (i=0; i<unitHeight; i++)
161           {
162             piIntraLineCur[i] = refSample;
163           }
164           piIntraLineCur += unitHeight;
165           iCurrJnit++;
166         }
167         // fill top row
168         while (iCurrJnit < iNext)
169         {
170           for (i=0; i<unitWidth; i++)
171           {
172             piIntraLineCur[i] = refSample;
173           }
174           piIntraLineCur += unitWidth;
175           iCurrJnit++;
176         }
177       }
178     }
179 
180     // pad all other reference samples.
181     while (iCurrJnit < iTotalUnits)
182     {
183       if (!bNeighborFlags[iCurrJnit]) // samples not available
184       {
185         {
186           const Int numSamplesInCurrUnit = (iCurrJnit >= iLeftUnits) ? unitWidth : unitHeight;
187           const Pel refSample = *(piIntraLineCur-1);
188           for (i=0; i<numSamplesInCurrUnit; i++)
189           {
190             piIntraLineCur[i] = refSample;
191           }
192           piIntraLineCur += numSamplesInCurrUnit;
193           iCurrJnit++;
194         }
195       }
196       else
197       {
198         piIntraLineCur += (iCurrJnit >= iLeftUnits) ? unitWidth : unitHeight;
199         iCurrJnit++;
200       }
201     }
202 
203     // Copy processed samples
204 
205     piIntraLineTemp = piIntraLine + uiHeight + unitWidth - 2;
206     // top left, top and top right samples
207     for (i=0; i<uiWidth; i++)
208     {
209       piIntraTemp[i] = piIntraLineTemp[i];
210     }
211 
212     piIntraLineTemp = piIntraLine + uiHeight - 1;
213     for (i=1; i<uiHeight; i++)
214     {
215       piIntraTemp[i*uiWidth] = piIntraLineTemp[-i];
216     }
217   }
218 }

 

转载于:https://www.cnblogs.com/545235abc/p/5190689.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值