今天抽空看了看 fillReferenceSamples函数,主要功能是针对帧内预测时所需要的参考像素进行填充功能,如果得不到任何参考像素,则每个值赋值为128,如果每个参考值都能找到,则将其原样复制给重建的参考值,如果是一部分知道的话具体参考draft 8.4.4.2.2,代码里一些重要部分的解释都给了,如果有不对的地方还请指出:
Void fillReferenceSamples( const Int bitDepth, TComDataCU* pcCU, const Pel* piRoiOrigin, Pel* piAdiTemp, const Bool* bNeighborFlags,
const Int iNumIntraNeighbor, const Int unitWidth, const Int unitHeight, const Int iAboveUnits, const Int iLeftUnits,
const UInt uiCuWidth, const UInt uiCuHeight, const UInt uiWidth, const UInt uiHeight, const Int iPicStride,
const ChannelType chType, const ChromaFormat chFmt )
{
// NOTE: RExt - This function has been modified for increased flexibility as part of the Square TU 4:2:2 implementation,piAdiTemp为填充后的值
const Pel* piRoiTemp;
Int i, j;
Int iDCValue = 1 << (bitDepth - 1);//bitDepth为8
const Int iTotalUnits = iAboveUnits + iLeftUnits + 1; //+1 for top-left
if (iNumIntraNeighbor == 0)
{
// Fill border with DC value
for (i=0; i<uiWidth; i++)
{
piAdiTemp[i] = iDCValue;
}
for (i=1; i<uiHeight; i++)
{
piAdiTemp[i*uiWidth] = iDCValue;
}
}
else if (iNumIntraNeighbor == iTotalUnits)
{
// Fill top-left border and top and top right with rec. samples
piRoiTemp = piRoiOrigin - iPicStride - 1;//左上角像素(top_left)
for (i=0; i<uiWidth; i++)
{
#if RExt__O0043_BEST_EFFORT_DECODING
piAdiTemp[i] = piRoiTemp[i] << bitDepthDelta;
#else
piAdiTemp[i] = piRoiTemp[i];
#endif
}
// Fill left and below left border with rec. samples
piRoiTemp = piRoiOrigin - 1;//左边第一个像素
for (i=1; i<uiHeight; i++)
{
#if RExt__O0043_BEST_EFFORT_DECODING
piAdiTemp[i*uiWidth] = (*(piRoiTemp)) << bitDepthDelta;
#else
piAdiTemp[i*uiWidth] = *(piRoiTemp);
#endif
piRoiTemp += iPicStride;
}
}
else // reference samples are partially available
{
// all above units have "unitWidth" samples each, all left/below-left units have "unitHeight" samples each
const Int iTotalSamples = (iLeftUnits * unitHeight) + ((iAboveUnits + 1) * unitWidth);//每行有iAboveUnits个units,每个unit有unitWidth个像素,同理用到高度上,uiWidth-1=iAboveUnits*unitWidth切勿弄错。
Pel piAdiLine[5 * MAX_CU_SIZE];
Pel *piAdiLineTemp;
const Bool *pbNeighborFlags;
// Initialize
for (i=0; i<iTotalSamples; i++)
{
piAdiLine[i] = iDCValue;
}
// Fill top-left sample
piRoiTemp = piRoiOrigin - iPicStride - 1;
piAdiLineTemp = piAdiLine + (iLeftUnits * unitHeight);
pbNeighborFlags = bNeighborFlags + iLeftUnits;
if (*pbNeighborFlags)
{
#if RExt__O0043_BEST_EFFORT_DECODING
Pel topLeftVal=piRoiTemp[0] << bitDepthDelta;
#else
Pel topLeftVal=piRoiTemp[0];
#endif
for (i=0; i<unitWidth; i++)
{
piAdiLineTemp[i] = topLeftVal;
}
}
// Fill left & below-left samples (downwards)
piRoiTemp += iPicStride;
piAdiLineTemp--;
pbNeighborFlags--;
for (j=0; j<iLeftUnits; j++)
{
if (*pbNeighborFlags)
{
for (i=0; i<unitHeight; i++)
{
#if RExt__O0043_BEST_EFFORT_DECODING
piAdiLineTemp[-i] = piRoiTemp[i*iPicStride] << bitDepthDelta;
#else
piAdiLineTemp[-i] = piRoiTemp[i*iPicStride];
#endif
}
}
piRoiTemp += unitHeight*iPicStride;
piAdiLineTemp -= unitHeight;
pbNeighborFlags--;
}
// Fill above & above-right samples (left-to-right) (each unit has "unitWidth" samples)
piRoiTemp = piRoiOrigin - iPicStride;
// offset line buffer by iNumUints2*unitHeight (for left/below-left) + unitWidth (for above-left)
piAdiLineTemp = piAdiLine + (iLeftUnits * unitHeight) + unitWidth;
pbNeighborFlags = bNeighborFlags + iLeftUnits + 1;
for (j=0; j<iAboveUnits; j++)
{
if (*pbNeighborFlags)
{
for (i=0; i<unitWidth; i++)
{
#if RExt__O0043_BEST_EFFORT_DECODING
piAdiLineTemp[i] = piRoiTemp[i] << bitDepthDelta;
#else
piAdiLineTemp[i] = piRoiTemp[i];
#endif
}
}
piRoiTemp += unitWidth;
piAdiLineTemp += unitWidth;
pbNeighborFlags++;
}
// Pad reference samples when necessary
Int iCurrJnit = 0;
Pel *piAdiLineCur = piAdiLine;
const UInt piAdiLineTopRowOffset = iLeftUnits * (unitHeight - unitWidth);
if (!bNeighborFlags[0])
{
// very bottom unit of bottom-left; at least one unit will be valid.
{
Int iNext = 1;
while (iNext < iTotalUnits && !bNeighborFlags[iNext])
{
iNext++;
}
Pel *piAdiLineNext = piAdiLine + ((iNext < iLeftUnits) ? (iNext * unitHeight) : (piAdiLineTopRowOffset + (iNext * unitWidth)));
const Pel refSample = *piAdiLineNext;
// Pad unavailable samples with new value
Int iNextOrTop = std::min<Int>(iNext, iLeftUnits);
// fill left column
while (iCurrJnit < iNextOrTop)
{
for (i=0; i<unitHeight; i++)
{
piAdiLineCur[i] = refSample;
}
piAdiLineCur += unitHeight;
iCurrJnit++;
}
// fill top row
while (iCurrJnit < iNext)
{
for (i=0; i<unitWidth; i++)
{
piAdiLineCur[i] = refSample;
}
piAdiLineCur += unitWidth;
iCurrJnit++;
}
}
}
// pad all other reference samples.
while (iCurrJnit < iTotalUnits)
{
if (!bNeighborFlags[iCurrJnit]) // samples not available
{
{
const Int numSamplesInCurrUnit = (iCurrJnit >= iLeftUnits) ? unitWidth : unitHeight;
const Pel refSample = *(piAdiLineCur-1);
for (i=0; i<numSamplesInCurrUnit; i++)
{
piAdiLineCur[i] = refSample;
}
piAdiLineCur += numSamplesInCurrUnit;
iCurrJnit++;
}
}
else
{
piAdiLineCur += (iCurrJnit >= iLeftUnits) ? unitWidth : unitHeight;
iCurrJnit++;
}
}
// Copy processed samples
piAdiLineTemp = piAdiLine + uiHeight + unitWidth - 2;
// top left, top and top right samples
for (i=0; i<uiWidth; i++)
{
piAdiTemp[i] = piAdiLineTemp[i];
}
piAdiLineTemp = piAdiLine + uiHeight - 1;
for (i=1; i<uiHeight; i++)
{
piAdiTemp[i*uiWidth] = piAdiLineTemp[-i];
}
}
}