Newer
Older

Karsten Suehring
committed
void IntraPrediction::xFillReferenceSamples( const CPelBuf &recoBuf, Pel* refBufUnfiltered, const CompArea &area, const CodingUnit &cu )
{
const ChannelType chType = toChannelType( area.compID );
const CodingStructure &cs = *cu.cs;
const SPS &sps = *cs.sps;
const PreCalcValues &pcv = *cs.pcv;
const int multiRefIdx = (area.compID == COMPONENT_Y) ? cu.firstPU->multiRefIdx : 0;

Karsten Suehring
committed
const int tuWidth = area.width;
const int tuHeight = area.height;
const int predSize = m_topRefLength;
const int predHSize = m_leftRefLength;
const int predStride = predSize + 1 + multiRefIdx;
m_refBufferStride[area.compID] = predStride;

Karsten Suehring
committed
const bool noShift = pcv.noChroma2x2 && area.width == 4; // don't shift on the lowest level (chroma not-split)
const int unitWidth = tuWidth <= 2 && cu.ispMode && isLuma(area.compID) ? tuWidth : pcv.minCUWidth >> (noShift ? 0 : getComponentScaleX(area.compID, sps.getChromaFormatIdc()));
const int unitHeight = tuHeight <= 2 && cu.ispMode && isLuma(area.compID) ? tuHeight : pcv.minCUHeight >> (noShift ? 0 : getComponentScaleY(area.compID, sps.getChromaFormatIdc()));

Karsten Suehring
committed
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
const int totalAboveUnits = (predSize + (unitWidth - 1)) / unitWidth;
const int totalLeftUnits = (predHSize + (unitHeight - 1)) / unitHeight;
const int totalUnits = totalAboveUnits + totalLeftUnits + 1; //+1 for top-left
const int numAboveUnits = std::max<int>( tuWidth / unitWidth, 1 );
const int numLeftUnits = std::max<int>( tuHeight / unitHeight, 1 );
const int numAboveRightUnits = totalAboveUnits - numAboveUnits;
const int numLeftBelowUnits = totalLeftUnits - numLeftUnits;
CHECK( numAboveUnits <= 0 || numLeftUnits <= 0 || numAboveRightUnits <= 0 || numLeftBelowUnits <= 0, "Size not supported" );
// ----- Step 1: analyze neighborhood -----
const Position posLT = area;
const Position posRT = area.topRight();
const Position posLB = area.bottomLeft();
bool neighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1];
int numIntraNeighbor = 0;
memset( neighborFlags, 0, totalUnits );
neighborFlags[totalLeftUnits] = isAboveLeftAvailable( cu, chType, posLT );
numIntraNeighbor += neighborFlags[totalLeftUnits] ? 1 : 0;
numIntraNeighbor += isAboveAvailable ( cu, chType, posLT, numAboveUnits, unitWidth, (neighborFlags + totalLeftUnits + 1) );
numIntraNeighbor += isAboveRightAvailable( cu, chType, posRT, numAboveRightUnits, unitWidth, (neighborFlags + totalLeftUnits + 1 + numAboveUnits) );
numIntraNeighbor += isLeftAvailable ( cu, chType, posLT, numLeftUnits, unitHeight, (neighborFlags + totalLeftUnits - 1) );
numIntraNeighbor += isBelowLeftAvailable ( cu, chType, posLB, numLeftBelowUnits, unitHeight, (neighborFlags + totalLeftUnits - 1 - numLeftUnits) );
// ----- Step 2: fill reference samples (depending on neighborhood) -----
const Pel* srcBuf = recoBuf.buf;
const int srcStride = recoBuf.stride;
Pel* ptrDst = refBufUnfiltered;
const Pel* ptrSrc;
const Pel valueDC = 1 << (sps.getBitDepth( chType ) - 1);
if( numIntraNeighbor == 0 )
{
// Fill border with DC value
for (int j = 0; j <= predSize + multiRefIdx; j++) { ptrDst[j] = valueDC; }
for (int i = 0; i <= predHSize + multiRefIdx; i++)
{
ptrDst[i + predStride] = valueDC;
}

Karsten Suehring
committed
}
else if( numIntraNeighbor == totalUnits )
{
// Fill top-left border and top and top right with rec. samples
ptrSrc = srcBuf - (1 + multiRefIdx) * srcStride - (1 + multiRefIdx);
for (int j = 0; j <= predSize + multiRefIdx; j++) { ptrDst[j] = ptrSrc[j]; }
for (int i = 0; i <= predHSize + multiRefIdx; i++)
{
ptrDst[i + predStride] = ptrSrc[i * srcStride];
}

Karsten Suehring
committed
}
else // reference samples are partially available
{
// Fill top-left sample(s) if available
ptrSrc = srcBuf - (1 + multiRefIdx) * srcStride - (1 + multiRefIdx);
ptrDst = refBufUnfiltered;
if (neighborFlags[totalLeftUnits])
{
ptrDst[0] = ptrSrc[0];
ptrDst[predStride] = ptrSrc[0];
for (int i = 1; i <= multiRefIdx; i++)
{
ptrDst[i] = ptrSrc[i];
ptrDst[i + predStride] = ptrSrc[i * srcStride];
}
}
// Fill left & below-left samples if available (downwards)
ptrSrc += (1 + multiRefIdx) * srcStride;
ptrDst += (1 + multiRefIdx) + predStride;
for (int unitIdx = totalLeftUnits - 1; unitIdx > 0; unitIdx--)
{
if (neighborFlags[unitIdx])
{
for (int i = 0; i < unitHeight; i++)
{
ptrDst[i] = ptrSrc[i * srcStride];
}
}
ptrSrc += unitHeight * srcStride;
ptrDst += unitHeight;
}
// Fill last below-left sample(s)
if (neighborFlags[0])
{
int lastSample = (predHSize % unitHeight == 0) ? unitHeight : predHSize % unitHeight;
for (int i = 0; i < lastSample; i++)
{
ptrDst[i] = ptrSrc[i * srcStride];
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
}
}
// Fill above & above-right samples if available (left-to-right)
ptrSrc = srcBuf - srcStride * (1 + multiRefIdx);
ptrDst = refBufUnfiltered + 1 + multiRefIdx;
for (int unitIdx = totalLeftUnits + 1; unitIdx < totalUnits - 1; unitIdx++)
{
if (neighborFlags[unitIdx])
{
for (int j = 0; j < unitWidth; j++)
{
ptrDst[j] = ptrSrc[j];
}
}
ptrSrc += unitWidth;
ptrDst += unitWidth;
}
// Fill last above-right sample(s)
if (neighborFlags[totalUnits - 1])
{
int lastSample = (predSize % unitWidth == 0) ? unitWidth : predSize % unitWidth;
for (int j = 0; j < lastSample; j++)
{
ptrDst[j] = ptrSrc[j];
}
}
// pad from first available down to the last below-left
ptrDst = refBufUnfiltered;
int lastAvailUnit = 0;
if (!neighborFlags[0])
{
int firstAvailUnit = 1;
while (firstAvailUnit < totalUnits && !neighborFlags[firstAvailUnit])
{
firstAvailUnit++;
}
// first available sample
int firstAvailRow = -1;
int firstAvailCol = 0;
if (firstAvailUnit < totalLeftUnits)
{
firstAvailRow = (totalLeftUnits - firstAvailUnit) * unitHeight + multiRefIdx;
}
else if (firstAvailUnit == totalLeftUnits)
{
firstAvailRow = multiRefIdx;
}
else
{
firstAvailCol = (firstAvailUnit - totalLeftUnits - 1) * unitWidth + 1 + multiRefIdx;
}
const Pel firstAvailSample = ptrDst[firstAvailRow < 0 ? firstAvailCol : firstAvailRow + predStride];
// last sample below-left (n.a.)
int lastRow = predHSize + multiRefIdx;
// fill left column
for (int i = lastRow; i > firstAvailRow; i--)
{
ptrDst[i + predStride] = firstAvailSample;
}
// fill top row
if (firstAvailCol > 0)
{
for (int j = 0; j < firstAvailCol; j++)
{
ptrDst[j] = firstAvailSample;
}
}
lastAvailUnit = firstAvailUnit;
}
// pad all other reference samples.
int currUnit = lastAvailUnit + 1;
while (currUnit < totalUnits)
{
if (!neighborFlags[currUnit]) // samples not available
{
// last available sample
int lastAvailRow = -1;
int lastAvailCol = 0;
if (lastAvailUnit < totalLeftUnits)
{
lastAvailRow = (totalLeftUnits - lastAvailUnit - 1) * unitHeight + multiRefIdx + 1;
}
else if (lastAvailUnit == totalLeftUnits)
{
lastAvailCol = multiRefIdx;
}
else
{
lastAvailCol = (lastAvailUnit - totalLeftUnits) * unitWidth + multiRefIdx;
}
const Pel lastAvailSample = ptrDst[lastAvailRow < 0 ? lastAvailCol : lastAvailRow + predStride];
// fill current unit with last available sample
if (currUnit < totalLeftUnits)
{
for (int i = lastAvailRow - 1; i >= lastAvailRow - unitHeight; i--)
ptrDst[i + predStride] = lastAvailSample;
}
}
else if (currUnit == totalLeftUnits)
{
for (int i = 0; i < multiRefIdx + 1; i++)
ptrDst[i + predStride] = lastAvailSample;
}
for (int j = 0; j < multiRefIdx + 1; j++)
{
ptrDst[j] = lastAvailSample;
}
}
else
{
int numSamplesInUnit = (currUnit == totalUnits - 1) ? ((predSize % unitWidth == 0) ? unitWidth : predSize % unitWidth) : unitWidth;
for (int j = lastAvailCol + 1; j <= lastAvailCol + numSamplesInUnit; j++)
{
ptrDst[j] = lastAvailSample;
}
}
}
lastAvailUnit = currUnit;
currUnit++;
}

Karsten Suehring
committed
}
void IntraPrediction::xFilterReferenceSamples(const Pel *refBufUnfiltered, Pel *refBufFiltered, const CompArea &area,
const SPS &sps, int multiRefIdx

Karsten Suehring
committed
{
if (area.compID != COMPONENT_Y)
{
multiRefIdx = 0;
}
const int predSize = m_topRefLength + multiRefIdx;
const int predHSize = m_leftRefLength + multiRefIdx;
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
const size_t predStride = m_refBufferStride[area.compID];
const Pel topLeft =
(refBufUnfiltered[0] + refBufUnfiltered[1] + refBufUnfiltered[predStride] + refBufUnfiltered[predStride + 1] + 2)
>> 2;
refBufFiltered[0] = topLeft;
for (int i = 1; i < predSize; i++)
{
refBufFiltered[i] = (refBufUnfiltered[i - 1] + 2 * refBufUnfiltered[i] + refBufUnfiltered[i + 1] + 2) >> 2;
}
refBufFiltered[predSize] = refBufUnfiltered[predSize];
refBufFiltered += predStride;
refBufUnfiltered += predStride;
refBufFiltered[0] = topLeft;
for (int i = 1; i < predHSize; i++)
{
refBufFiltered[i] = (refBufUnfiltered[i - 1] + 2 * refBufUnfiltered[i] + refBufUnfiltered[i + 1] + 2) >> 2;
}
refBufFiltered[predHSize] = refBufUnfiltered[predHSize];

Karsten Suehring
committed
}
bool isAboveLeftAvailable(const CodingUnit &cu, const ChannelType &chType, const Position &posLT)
{
const CodingStructure& cs = *cu.cs;
const Position refPos = posLT.offset(-1, -1);
if (!cs.isDecomp(refPos, chType))

Karsten Suehring
committed
{

Karsten Suehring
committed
}

Karsten Suehring
committed
}
int isAboveAvailable(const CodingUnit &cu, const ChannelType &chType, const Position &posLT, const uint32_t uiNumUnitsInPU, const uint32_t unitWidth, bool *bValidFlags)
{
const CodingStructure& cs = *cu.cs;
bool * validFlags = bValidFlags;
int numIntra = 0;
const int maxDx = uiNumUnitsInPU * unitWidth;
for (int dx = 0; dx < maxDx; dx += unitWidth)

Karsten Suehring
committed
{
const Position refPos = posLT.offset(dx, -1);
if (!cs.isDecomp(refPos, chType))

Karsten Suehring
committed
{

Karsten Suehring
committed
}
++numIntra;
*validFlags = true;

Karsten Suehring
committed
}
return numIntra;

Karsten Suehring
committed
}
int isLeftAvailable(const CodingUnit &cu, const ChannelType &chType, const Position &posLT, const uint32_t uiNumUnitsInPU, const uint32_t unitHeight, bool *bValidFlags)
{
const CodingStructure& cs = *cu.cs;
bool * validFlags = bValidFlags;
int numIntra = 0;
const int maxDy = uiNumUnitsInPU * unitHeight;
for (int dy = 0; dy < maxDy; dy += unitHeight)

Karsten Suehring
committed
{
const Position refPos = posLT.offset(-1, dy);
if (!cs.isDecomp(refPos, chType))

Karsten Suehring
committed
{

Karsten Suehring
committed
}
++numIntra;
*validFlags = true;

Karsten Suehring
committed
}

Karsten Suehring
committed
}
int isAboveRightAvailable(const CodingUnit &cu, const ChannelType &chType, const Position &posRT, const uint32_t uiNumUnitsInPU, const uint32_t unitWidth, bool *bValidFlags )
{
const CodingStructure& cs = *cu.cs;
bool * validFlags = bValidFlags;
int numIntra = 0;
const int maxDx = uiNumUnitsInPU * unitWidth;

Karsten Suehring
committed
for (int dx = 0; dx < maxDx; dx += unitWidth)

Karsten Suehring
committed
{
const Position refPos = posRT.offset(unitWidth + dx, -1);
if (!cs.isDecomp(refPos, chType))

Karsten Suehring
committed
{

Karsten Suehring
committed
}
++numIntra;
*validFlags = true;

Karsten Suehring
committed
}

Karsten Suehring
committed
}
int isBelowLeftAvailable(const CodingUnit &cu, const ChannelType &chType, const Position &posLB, const uint32_t uiNumUnitsInPU, const uint32_t unitHeight, bool *bValidFlags )
{
const CodingStructure& cs = *cu.cs;
bool * validFlags = bValidFlags;
int numIntra = 0;
const int maxDy = uiNumUnitsInPU * unitHeight;
for (int dy = 0; dy < maxDy; dy += unitHeight)

Karsten Suehring
committed
{
const Position refPos = posLB.offset(-1, unitHeight + dy);
if (!cs.isDecomp(refPos, chType))

Karsten Suehring
committed
{

Karsten Suehring
committed
}
++numIntra;
*validFlags = true;

Karsten Suehring
committed
}

Karsten Suehring
committed
}

Karsten Suehring
committed
// LumaRecPixels
void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chromaArea)
{
int iDstStride = 0;
Pel* pDst0 = 0;
int curChromaMode = pu.intraDir[1];
if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX))
{
iDstStride = 2 * MAX_CU_SIZE + 1;
pDst0 = m_pMdlmTemp + iDstStride + 1;
}
else
{
iDstStride = MAX_CU_SIZE + 1;
pDst0 = m_piTemp + iDstStride + 1; //MMLM_SAMPLE_NEIGHBOR_LINES;

Karsten Suehring
committed
//assert 420 chroma subsampling
CompArea lumaArea = CompArea( COMPONENT_Y, pu.chromaFormat, chromaArea.lumaPos(), recalcSize( pu.chromaFormat, CHANNEL_TYPE_CHROMA, CHANNEL_TYPE_LUMA, chromaArea.size() ) );//needed for correct pos/size (4x4 Tus)
CHECK(lumaArea.width == chromaArea.width && CHROMA_444 != pu.chromaFormat, "");
CHECK(lumaArea.height == chromaArea.height && CHROMA_444 != pu.chromaFormat && CHROMA_422 != pu.chromaFormat, "");

Karsten Suehring
committed
const SizeType uiCWidth = chromaArea.width;
const SizeType uiCHeight = chromaArea.height;
const CPelBuf Src = pu.cs->picture->getRecoBuf( lumaArea );
Pel const* pRecSrc0 = Src.bufAt( 0, 0 );
int iRecStride = Src.stride;
int logSubWidthC = getChannelTypeScaleX(CHANNEL_TYPE_CHROMA, pu.chromaFormat);
int logSubHeightC = getChannelTypeScaleY(CHANNEL_TYPE_CHROMA, pu.chromaFormat);
int iRecStride2 = iRecStride << logSubHeightC;
const int mult = 1 << logSubWidthC ;

Karsten Suehring
committed
const CodingUnit& lumaCU = isChroma( pu.chType ) ? *pu.cs->picture->cs->getCU( lumaArea.pos(), CH_L ) : *pu.cu;
const CodingUnit& cu = *pu.cu;
const CompArea& area = isChroma( pu.chType ) ? chromaArea : lumaArea;
const uint32_t uiTuWidth = area.width;
const uint32_t uiTuHeight = area.height;
int iBaseUnitSize = ( 1 << MIN_CU_LOG2 );
const int iUnitWidth = iBaseUnitSize >> getComponentScaleX( area.compID, area.chromaFormat );
const int iUnitHeight = iBaseUnitSize >> getComponentScaleY(area.compID, area.chromaFormat);
const int iTUWidthInUnits = uiTuWidth / iUnitWidth;

Karsten Suehring
committed
const int iTUHeightInUnits = uiTuHeight / iUnitHeight;
const int iAboveUnits = iTUWidthInUnits;
const int iLeftUnits = iTUHeightInUnits;
const int chromaUnitWidth = iBaseUnitSize >> getComponentScaleX(COMPONENT_Cb, area.chromaFormat);
const int chromaUnitHeight = iBaseUnitSize >> getComponentScaleY(COMPONENT_Cb, area.chromaFormat);
const int topTemplateSampNum = 2 * uiCWidth; // for MDLM, the number of template samples is 2W or 2H.
const int leftTemplateSampNum = 2 * uiCHeight;
assert(m_topRefLength >= topTemplateSampNum);
assert(m_leftRefLength >= leftTemplateSampNum);
const int totalAboveUnits = (topTemplateSampNum + (chromaUnitWidth - 1)) / chromaUnitWidth;
const int totalLeftUnits = (leftTemplateSampNum + (chromaUnitHeight - 1)) / chromaUnitHeight;
const int totalUnits = totalLeftUnits + totalAboveUnits + 1;
const int aboveRightUnits = totalAboveUnits - iAboveUnits;
const int leftBelowUnits = totalLeftUnits - iLeftUnits;
int avaiAboveRightUnits = 0;
int avaiLeftBelowUnits = 0;

Karsten Suehring
committed
bool bNeighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1];

Karsten Suehring
committed
bool bAboveAvaillable, bLeftAvaillable;
int availlableUnit = isLeftAvailable( isChroma( pu.chType ) ? cu : lumaCU, toChannelType( area.compID ), area.pos(), iLeftUnits, iUnitHeight,
( bNeighborFlags + iLeftUnits + leftBelowUnits - 1 ) );

Karsten Suehring
committed
bLeftAvaillable = availlableUnit == iTUHeightInUnits;

Christian Helmrich
committed
availlableUnit = isAboveAvailable( isChroma( pu.chType ) ? cu : lumaCU, toChannelType( area.compID ), area.pos(), iAboveUnits, iUnitWidth,
( bNeighborFlags + iLeftUnits + leftBelowUnits + 1 ) );

Karsten Suehring
committed
bAboveAvaillable = availlableUnit == iTUWidthInUnits;
if (bLeftAvaillable) // if left is not available, then the below left is not available
{
avaiLeftBelowUnits = isBelowLeftAvailable(isChroma(pu.chType) ? cu : lumaCU, toChannelType(area.compID), area.bottomLeftComp(area.compID), leftBelowUnits, iUnitHeight, (bNeighborFlags + leftBelowUnits - 1));
}

Karsten Suehring
committed
if (bAboveAvaillable) // if above is not available, then the above right is not available.
{
avaiAboveRightUnits = isAboveRightAvailable(isChroma(pu.chType) ? cu : lumaCU, toChannelType(area.compID), area.topRightComp(area.compID), aboveRightUnits, iUnitWidth, (bNeighborFlags + iLeftUnits + leftBelowUnits + iAboveUnits + 1));
}

Karsten Suehring
committed
Pel* pDst = nullptr;
Pel const* piSrc = nullptr;
bool isFirstRowOfCtu = ( lumaArea.y & ((pu.cs->sps)->getCTUSize() - 1) ) == 0;
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
const int strOffset = (CHROMA_444 == pu.chromaFormat) ? 0 : iRecStride;
int c0_2tap = 1, c1_2tap = 1, offset_2tap = 1, shift_2tap = 1; //sum = 2
int c0_3tap = 2, c1_3tap = 1, c2_3tap = 1, offset_3tap = 2, shift_3tap = 2; //sum = 4
int c0_5tap = 1, c1_5tap = 4, c2_5tap = 1, c3_5tap = 1, c4_5tap = 1, offset_5tap = 4, shift_5tap = 3; //sum = 8
int c0_6tap = 2, c1_6tap = 1, c2_6tap = 1, c3_6tap = 2, c4_6tap = 1, c5_6tap = 1, offset_6tap = 4, shift_6tap = 3; //sum = 8
switch (pu.chromaFormat)
{
case CHROMA_422: //overwrite filter coefficient values for 422
c0_2tap = 1, c1_2tap = 0, offset_2tap = 0, shift_2tap = 0; //sum = 1
c0_3tap = 2, c1_3tap = 1, c2_3tap = 1, offset_3tap = 2, shift_3tap = 2; //sum = 4
c0_5tap = 0, c1_5tap = 1, c2_5tap = 0, c3_5tap = 0, c4_5tap = 0, offset_5tap = 0, shift_5tap = 0; //sum = 1
c0_6tap = 2, c1_6tap = 1, c2_6tap = 1, c3_6tap = 0, c4_6tap = 0, c5_6tap = 0, offset_6tap = 2, shift_6tap = 2; //sum = 4
break;
case CHROMA_444: //overwrite filter coefficient values for 422
c0_2tap = 1, c1_2tap = 0, offset_2tap = 0, shift_2tap = 0; //sum = 1
c0_3tap = 1, c1_3tap = 0, c2_3tap = 0, offset_3tap = 0, shift_3tap = 0; //sum = 1
c0_5tap = 0, c1_5tap = 1, c2_5tap = 0, c3_5tap = 0, c4_5tap = 0, offset_5tap = 0, shift_5tap = 0; //sum = 1
c0_6tap = 1, c1_6tap = 0, c2_6tap = 0, c3_6tap = 0, c4_6tap = 0, c5_6tap = 0, offset_6tap = 0, shift_6tap = 0; //sum = 1
break;
default:
break;
}

Karsten Suehring
committed
if( bAboveAvaillable )
{
pDst = pDst0 - iDstStride;
int addedAboveRight = 0;
if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX))
{
addedAboveRight = avaiAboveRightUnits*chromaUnitWidth;
}
for (int i = 0; i < uiCWidth + addedAboveRight; i++)

Karsten Suehring
committed
{
if (isFirstRowOfCtu)
{
piSrc = pRecSrc0 - iRecStride;
if ((i == 0 && !bLeftAvaillable) || (i == uiCWidth + addedAboveRight - 1 + logSubWidthC))
{
pDst[i] = piSrc[mult * i];
}
else
{
pDst[i] = (piSrc[mult * i] * c0_3tap + piSrc[mult * i - 1] * c1_3tap + piSrc[mult * i + 1] * c2_3tap + offset_3tap) >> shift_3tap;
}

Christian Helmrich
committed
}
else if( pu.cs->sps->getCclmCollocatedChromaFlag() )
if ((i == 0 && !bLeftAvaillable) || (i == uiCWidth + addedAboveRight - 1 + logSubWidthC))
pDst[i] = (piSrc[mult * i] * c0_3tap + piSrc[mult * i - strOffset] * c1_3tap + piSrc[mult * i + strOffset] * c2_3tap + offset_3tap) >> shift_3tap;
pDst[i] = (piSrc[mult * i - strOffset] * c0_5tap
+ piSrc[mult * i] * c1_5tap + piSrc[mult * i - 1] * c2_5tap + piSrc[mult * i + 1] * c3_5tap
+ piSrc[mult * i + strOffset] * c4_5tap
+ offset_5tap) >> shift_5tap;
else
{
piSrc = pRecSrc0 - iRecStride2;
if ((i == 0 && !bLeftAvaillable) || (i == uiCWidth + addedAboveRight - 1 + logSubWidthC))
{
pDst[i] = (piSrc[mult * i] * c0_2tap + piSrc[mult * i + strOffset] * c1_2tap + offset_2tap) >> shift_2tap;
}
else
{
pDst[i] = ((piSrc[mult * i] * c0_6tap + piSrc[mult * i - 1] * c1_6tap + piSrc[mult * i + 1] * c2_6tap)
+ (piSrc[mult * i + strOffset] * c3_6tap + piSrc[mult * i - 1 + strOffset] * c4_6tap + piSrc[mult * i + 1 + strOffset] * c5_6tap)
+ offset_6tap) >> shift_6tap;
}
}

Karsten Suehring
committed
}
}
if( bLeftAvaillable )
{
pDst = pDst0 - 1;
piSrc = pRecSrc0 - 2 - logSubWidthC;
int addedLeftBelow = 0;
if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX))
{
addedLeftBelow = avaiLeftBelowUnits*chromaUnitHeight;
}
for (int j = 0; j < uiCHeight + addedLeftBelow; j++)

Karsten Suehring
committed
{
if( pu.cs->sps->getCclmCollocatedChromaFlag() )
if ((j == 0 && !bAboveAvaillable) || (j == uiCHeight + addedLeftBelow - 1 + logSubWidthC))
{
pDst[0] = ( piSrc[1] * c0_3tap + piSrc[0] * c1_3tap + piSrc[2] * c2_3tap + offset_3tap) >> shift_3tap;
pDst[0] = ( piSrc[1 - strOffset] * c0_5tap
+ piSrc[1 ] * c1_5tap + piSrc[0] * c2_5tap + piSrc[2] * c3_5tap
+ piSrc[1 + strOffset] * c4_5tap
+ offset_5tap ) >> shift_5tap;
pDst[0] = ((piSrc[1] * c0_6tap + piSrc[0] * c1_6tap + piSrc[2] * c2_6tap)
+ (piSrc[1 + strOffset] * c3_6tap + piSrc[strOffset] * c4_6tap + piSrc[2 + strOffset] * c5_6tap)
+ offset_6tap) >> shift_6tap;

Karsten Suehring
committed
piSrc += iRecStride2;
pDst += iDstStride;
}
}
// inner part from reconstructed picture buffer
for( int j = 0; j < uiCHeight; j++ )
{
for( int i = 0; i < uiCWidth; i++ )
{
if( pu.cs->sps->getCclmCollocatedChromaFlag() )

Karsten Suehring
committed
{
if ( j == 0 && !bAboveAvaillable )
pDst0[i] = pRecSrc0[mult * i];
pDst0[i] = (pRecSrc0[mult * i] * c0_3tap + pRecSrc0[mult * i - strOffset] * c1_3tap + pRecSrc0[mult * i + strOffset] * c2_3tap + offset_3tap) >> shift_3tap;
else if ( j == 0 && !bAboveAvaillable )
pDst0[i] = (pRecSrc0[mult * i] * c0_3tap + pRecSrc0[mult * i - 1] * c1_3tap + pRecSrc0[mult * i + 1] * c2_3tap + offset_3tap) >> shift_3tap;
pDst0[i] = (pRecSrc0[mult * i - strOffset] * c0_5tap
+ pRecSrc0[mult * i] * c1_5tap + pRecSrc0[mult * i - 1] * c2_5tap + pRecSrc0[mult * i + 1] * c3_5tap
+ pRecSrc0[mult * i + strOffset] * c4_5tap
+ offset_5tap) >> shift_5tap;

Karsten Suehring
committed
}
else
{
if ((i == 0 && !bLeftAvaillable) || (i == uiCWidth - 1 + logSubWidthC))
pDst0[i] = (pRecSrc0[mult * i] * c0_2tap + pRecSrc0[mult * i + strOffset] * c1_2tap + offset_2tap) >> shift_2tap;
int s = offset_6tap;
s += pRecSrc0[mult * i] * c0_6tap;
s += pRecSrc0[mult * i + 1] * c1_6tap;
s += pRecSrc0[mult * i - 1] * c2_6tap;
if (pu.chromaFormat == CHROMA_420)
{
s += pRecSrc0[mult * i + strOffset] * c3_6tap;
s += pRecSrc0[mult * i + 1 + strOffset] * c4_6tap;
s += pRecSrc0[mult * i - 1 + strOffset] * c5_6tap;
}
pDst0[i] = s >> shift_6tap;

Karsten Suehring
committed
}
}
pDst0 += iDstStride;
pRecSrc0 += iRecStride2;
}
}
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
void IntraPrediction::xGetLMParameters(const PredictionUnit &pu, const ComponentID compID,
const CompArea &chromaArea,
int &a, int &b, int &iShift)
{
CHECK(compID == COMPONENT_Y, "");
const SizeType cWidth = chromaArea.width;
const SizeType cHeight = chromaArea.height;
const Position posLT = chromaArea;
CodingStructure & cs = *(pu.cs);
const CodingUnit &cu = *(pu.cu);
const SPS & sps = *cs.sps;
const uint32_t tuWidth = chromaArea.width;
const uint32_t tuHeight = chromaArea.height;
const ChromaFormat nChromaFormat = sps.getChromaFormatIdc();
const int baseUnitSize = 1 << MIN_CU_LOG2;
const int unitWidth = baseUnitSize >> getComponentScaleX(chromaArea.compID, nChromaFormat);
Yang Wang
committed
const int unitHeight = baseUnitSize >> getComponentScaleY(chromaArea.compID, nChromaFormat);
const int tuWidthInUnits = tuWidth / unitWidth;
const int tuHeightInUnits = tuHeight / unitHeight;
const int aboveUnits = tuWidthInUnits;
const int leftUnits = tuHeightInUnits;
int topTemplateSampNum = 2 * cWidth; // for MDLM, the template sample number is 2W or 2H;
int leftTemplateSampNum = 2 * cHeight;
assert(m_topRefLength >= topTemplateSampNum);
assert(m_leftRefLength >= leftTemplateSampNum);
int totalAboveUnits = (topTemplateSampNum + (unitWidth - 1)) / unitWidth;
int totalLeftUnits = (leftTemplateSampNum + (unitHeight - 1)) / unitHeight;
int totalUnits = totalLeftUnits + totalAboveUnits + 1;
int aboveRightUnits = totalAboveUnits - aboveUnits;
int leftBelowUnits = totalLeftUnits - leftUnits;
int avaiAboveRightUnits = 0;
int avaiLeftBelowUnits = 0;
int avaiAboveUnits = 0;
int avaiLeftUnits = 0;
int curChromaMode = pu.intraDir[1];
bool neighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1];
bool aboveAvailable, leftAvailable;
int availableUnit =

Christian Helmrich
committed
isAboveAvailable(cu, CHANNEL_TYPE_CHROMA, posLT, aboveUnits, unitWidth,
(neighborFlags + leftUnits + leftBelowUnits + 1));
aboveAvailable = availableUnit == tuWidthInUnits;
availableUnit =

Christian Helmrich
committed
isLeftAvailable(cu, CHANNEL_TYPE_CHROMA, posLT, leftUnits, unitHeight,
(neighborFlags + leftUnits + leftBelowUnits - 1));
leftAvailable = availableUnit == tuHeightInUnits;
if (leftAvailable) // if left is not available, then the below left is not available
{
avaiLeftUnits = tuHeightInUnits;
avaiLeftBelowUnits = isBelowLeftAvailable(cu, CHANNEL_TYPE_CHROMA, chromaArea.bottomLeftComp(chromaArea.compID), leftBelowUnits, unitHeight, (neighborFlags + leftBelowUnits - 1));
}
if (aboveAvailable) // if above is not available, then the above right is not available.
{
avaiAboveUnits = tuWidthInUnits;
avaiAboveRightUnits = isAboveRightAvailable(cu, CHANNEL_TYPE_CHROMA, chromaArea.topRightComp(chromaArea.compID), aboveRightUnits, unitWidth, (neighborFlags + leftUnits + leftBelowUnits + aboveUnits + 1));
}
Pel *srcColor0, *curChroma0;
int srcStride;
PelBuf temp;
if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX))
{
srcStride = 2 * MAX_CU_SIZE + 1;
temp = PelBuf(m_pMdlmTemp + srcStride + 1, srcStride, Size(chromaArea));
}
else
{
srcStride = MAX_CU_SIZE + 1;
temp = PelBuf(m_piTemp + srcStride + 1, srcStride, Size(chromaArea));
srcColor0 = temp.bufAt(0, 0);
curChroma0 = getPredictorPtr(compID);
unsigned internalBitDepth = sps.getBitDepth(CHANNEL_TYPE_CHROMA);

Christian Helmrich
committed
int minLuma[2] = { MAX_INT, 0 };
int maxLuma[2] = { -MAX_INT, 0 };
Pel *src = srcColor0 - srcStride;
int actualTopTemplateSampNum = 0;
int actualLeftTemplateSampNum = 0;
if (curChromaMode == MDLM_T_IDX)
{
leftAvailable = 0;
avaiAboveRightUnits = avaiAboveRightUnits > (cHeight/unitWidth) ? cHeight/unitWidth : avaiAboveRightUnits;
actualTopTemplateSampNum = unitWidth*(avaiAboveUnits + avaiAboveRightUnits);
}
else if (curChromaMode == MDLM_L_IDX)
{
aboveAvailable = 0;
avaiLeftBelowUnits = avaiLeftBelowUnits > (cWidth/unitHeight) ? cWidth/unitHeight : avaiLeftBelowUnits;
actualLeftTemplateSampNum = unitHeight*(avaiLeftUnits + avaiLeftBelowUnits);
}
else if (curChromaMode == LM_CHROMA_IDX)
{
actualTopTemplateSampNum = cWidth;
actualLeftTemplateSampNum = cHeight;
}
int startPos[2]; //0:Above, 1: Left
int pickStep[2];
int aboveIs4 = leftAvailable ? 0 : 1;
int leftIs4 = aboveAvailable ? 0 : 1;
startPos[0] = actualTopTemplateSampNum >> (2 + aboveIs4);
pickStep[0] = std::max(1, actualTopTemplateSampNum >> (1 + aboveIs4));
startPos[1] = actualLeftTemplateSampNum >> (2 + leftIs4);
pickStep[1] = std::max(1, actualLeftTemplateSampNum >> (1 + leftIs4));
Pel selectLumaPix[4] = { 0, 0, 0, 0 };
Pel selectChromaPix[4] = { 0, 0, 0, 0 };
int cntT, cntL;
cntT = cntL = 0;
int cnt = 0;
if (aboveAvailable)
{
cntT = std::min(actualTopTemplateSampNum, (1 + aboveIs4) << 1);
src = srcColor0 - srcStride;
const Pel *cur = curChroma0 + 1;
for (int pos = startPos[0]; cnt < cntT; pos += pickStep[0], cnt++)
{
selectLumaPix[cnt] = src[pos];
selectChromaPix[cnt] = cur[pos];
}
if (leftAvailable)
{
cntL = std::min(actualLeftTemplateSampNum, ( 1 + leftIs4 ) << 1 );
src = srcColor0 - 1;
const Pel *cur = curChroma0 + m_refBufferStride[compID] + 1;
for (int pos = startPos[1], cnt = 0; cnt < cntL; pos += pickStep[1], cnt++)
{
selectLumaPix[cnt + cntT] = src[pos * srcStride];
selectChromaPix[cnt + cntT] = cur[pos];
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
if (cnt == 2)
{
selectLumaPix[3] = selectLumaPix[0]; selectChromaPix[3] = selectChromaPix[0];
selectLumaPix[2] = selectLumaPix[1]; selectChromaPix[2] = selectChromaPix[1];
selectLumaPix[0] = selectLumaPix[1]; selectChromaPix[0] = selectChromaPix[1];
selectLumaPix[1] = selectLumaPix[3]; selectChromaPix[1] = selectChromaPix[3];
}
int minGrpIdx[2] = { 0, 2 };
int maxGrpIdx[2] = { 1, 3 };
int *tmpMinGrp = minGrpIdx;
int *tmpMaxGrp = maxGrpIdx;
if (selectLumaPix[tmpMinGrp[0]] > selectLumaPix[tmpMinGrp[1]]) std::swap(tmpMinGrp[0], tmpMinGrp[1]);
if (selectLumaPix[tmpMaxGrp[0]] > selectLumaPix[tmpMaxGrp[1]]) std::swap(tmpMaxGrp[0], tmpMaxGrp[1]);
if (selectLumaPix[tmpMinGrp[0]] > selectLumaPix[tmpMaxGrp[1]]) std::swap(tmpMinGrp, tmpMaxGrp);
if (selectLumaPix[tmpMinGrp[1]] > selectLumaPix[tmpMaxGrp[0]]) std::swap(tmpMinGrp[1], tmpMaxGrp[0]);
minLuma[0] = (selectLumaPix[tmpMinGrp[0]] + selectLumaPix[tmpMinGrp[1]] + 1 )>>1;
minLuma[1] = (selectChromaPix[tmpMinGrp[0]] + selectChromaPix[tmpMinGrp[1]] + 1) >> 1;
maxLuma[0] = (selectLumaPix[tmpMaxGrp[0]] + selectLumaPix[tmpMaxGrp[1]] + 1 )>>1;
maxLuma[1] = (selectChromaPix[tmpMaxGrp[0]] + selectChromaPix[tmpMaxGrp[1]] + 1) >> 1;

Christian Helmrich
committed
if (leftAvailable || aboveAvailable)
int diff = maxLuma[0] - minLuma[0];
if (diff > 0)
{
int diffC = maxLuma[1] - minLuma[1];
int x = floorLog2( diff );
static const uint8_t DivSigTable[1 << 4] = {
// 4bit significands - 8 ( MSB is omitted )
0, 7, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1, 0
};
int normDiff = (diff << 4 >> x) & 15;
int v = DivSigTable[normDiff] | 8;
x += normDiff != 0;
int y = floorLog2( abs( diffC ) ) + 1;
int add = 1 << y >> 1;
a = (diffC * v + add) >> y;
iShift = 3 + x - y;
iShift = 1;
a = ( (a == 0)? 0: (a < 0)? -15 : 15 ); // a=Sign(a)*15
}
b = minLuma[1] - ((a * minLuma[0]) >> iShift);
}
else
{
a = 0;
b = minLuma[1];
iShift = 0;
}
}
else
{
a = 0;
b = 1 << (internalBitDepth - 1);
iShift = 0;
}
}

Karsten Suehring
committed
#if JVET_P0803_COMBINED_MIP_CLEANUP
void IntraPrediction::initIntraMip( const PredictionUnit &pu, const CompArea &area )
{
CHECK( area.width > MIP_MAX_WIDTH || area.height > MIP_MAX_HEIGHT, "Error: block size not supported for MIP" );
// prepare input (boundary) data for prediction
CHECK( m_ipaParam.refFilterFlag, "ERROR: unfiltered refs expected for MIP" );
Pel *ptrSrc = getPredictorPtr( COMPONENT_Y );
const int srcStride = m_refBufferStride[COMPONENT_Y];
const int srcHStride = 2;
m_matrixIntraPred.prepareInputForPred( CPelBuf( ptrSrc, srcStride, srcHStride ), area, pu.cu->slice->getSPS()->getBitDepth( CHANNEL_TYPE_LUMA ) );
}
#else
void IntraPrediction::initIntraMip( const PredictionUnit &pu )
{
CHECK( pu.lwidth() > pu.cs->sps->getMaxTbSize() || pu.lheight() > pu.cs->sps->getMaxTbSize(), "Error: block size not supported for MIP" );
// prepare input (boundary) data for prediction
CHECK(m_ipaParam.refFilterFlag, "ERROR: unfiltered refs expected for MIP");
Pel *ptrSrc = getPredictorPtr(COMPONENT_Y);
const int srcStride = m_refBufferStride[COMPONENT_Y];
const int srcHStride = 2;
m_matrixIntraPred.prepareInputForPred(CPelBuf(ptrSrc, srcStride, srcHStride), pu.Y(), pu.cu->slice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA));
void IntraPrediction::predIntraMip( const ComponentID compId, PelBuf &piPred, const PredictionUnit &pu )
{
CHECK( compId != COMPONENT_Y, "Error: chroma not supported" );
#if JVET_P0803_COMBINED_MIP_CLEANUP
CHECK( piPred.width > MIP_MAX_WIDTH || piPred.height > MIP_MAX_HEIGHT, "Error: block size not supported for MIP" );
CHECK( piPred.width != (1 << floorLog2(piPred.width)) || piPred.height != (1 << floorLog2(piPred.height)), "Error: expecting blocks of size 2^M x 2^N" );
// generate mode-specific prediction
const int bitDepth = pu.cu->slice->getSPS()->getBitDepth( CHANNEL_TYPE_LUMA );
static_vector<int, MIP_MAX_WIDTH* MIP_MAX_HEIGHT> predMip( piPred.width * piPred.height );
m_matrixIntraPred.predBlock( predMip.data(), pu.intraDir[CHANNEL_TYPE_LUMA], pu.mipTransposedFlag, bitDepth );
for( int y = 0; y < piPred.height; y++ )
{
for( int x = 0; x < piPred.width; x++ )
{
piPred.at( x, y ) = Pel(predMip[y * piPred.width + x]);
}
}
#else
CHECK( pu.lwidth() > pu.cs->sps->getMaxTbSize() || pu.lheight() > pu.cs->sps->getMaxTbSize(), "Error: block size not supported for MIP" );
CHECK( pu.lwidth() != (1 << floorLog2(pu.lwidth())) || pu.lheight() != (1 << floorLog2(pu.lheight())), "Error: expecting blocks of size 2^M x 2^N" );
// generate mode-specific prediction
const int bitDepth = pu.cu->slice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA);
static_vector<int, MIP_MAX_WIDTH * MIP_MAX_HEIGHT> predMip(pu.Y().area());
m_matrixIntraPred.predBlock(predMip.data(), pu.intraDir[CHANNEL_TYPE_LUMA], bitDepth);
for (int y = 0; y < pu.lheight(); y++)
{
for (int x = 0; x < pu.lwidth(); x++)
{
piPred.at(x, y) = Pel(predMip[y * pu.lwidth() + x]);
}
}
#if !JVET_P0077_LINE_CG_PALETTE
bool IntraPrediction::calCopyRun(CodingStructure &cs, Partitioner& partitioner, uint32_t startPos, uint32_t total, uint32_t &run, ComponentID compBegin)
Yung-Hsuan Chao (Jessie)
committed
{
CodingUnit &cu = *cs.getCU(partitioner.chType);
TransformUnit &tu = *cs.getTU(partitioner.chType);
PelBuf curPLTIdx = tu.getcurPLTIdx(compBegin);
PLTtypeBuf runType = tu.getrunType(compBegin);
uint32_t idx = startPos;
uint32_t xPos;
uint32_t yPos;
bool valid = false;
run = 0;
while (idx < total)
xPos = m_scanOrder[idx].x;
yPos = m_scanOrder[idx].y;
runType.at(xPos, yPos) = PLT_RUN_COPY;
if (yPos == 0 && !cu.useRotation[compBegin])
{
return false;
}
if (xPos == 0 && cu.useRotation[compBegin])
{
return false;
}
if (!cu.useRotation[compBegin] && curPLTIdx.at(xPos, yPos) == curPLTIdx.at(xPos, yPos - 1))
valid = true;
}
else if (cu.useRotation[compBegin] && curPLTIdx.at(xPos, yPos) == curPLTIdx.at(xPos - 1, yPos))
valid = true;
}
else
{
break;
}