Newer
Older
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];
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
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
}
}
// 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;
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
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
}
return (cs.getCURestricted(refPos, cu, chType) != NULL);

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
}
const bool valid = (cs.getCURestricted(refPos, cu, chType) != NULL);
numIntra += valid ? 1 : 0;
*validFlags = valid;

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
}
const bool valid = (cs.getCURestricted(refPos, cu, chType) != NULL);
numIntra += valid ? 1 : 0;
*validFlags = valid;

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
}
const bool valid = (cs.getCURestricted(refPos, cu, chType) != NULL);
numIntra += valid ? 1 : 0;
*validFlags = valid;

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
}
const bool valid = (cs.getCURestricted(refPos, cu, chType) != NULL);
numIntra += valid ? 1 : 0;
*validFlags = valid;

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;

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];
bool aboveIsAvailable, leftIsAvailable;

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

Karsten Suehring
committed
leftIsAvailable = 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
aboveIsAvailable = availlableUnit == iTUWidthInUnits;
if (leftIsAvailable) // 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 (aboveIsAvailable) // 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;
if (aboveIsAvailable)

Karsten Suehring
committed
{
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
{
const bool leftPadding = i == 0 && !leftIsAvailable;
if (pu.chromaFormat == CHROMA_444)
{
piSrc = pRecSrc0 - iRecStride;
pDst[i] = piSrc[i];
}
else if (isFirstRowOfCtu)
{
piSrc = pRecSrc0 - iRecStride;
pDst[i] = (piSrc[2 * i] * 2 + piSrc[2 * i - (leftPadding ? 0 : 1)] + piSrc[2 * i + 1] + 2) >> 2;
}
else if (pu.chromaFormat == CHROMA_422)
{
piSrc = pRecSrc0 - iRecStride2;
int s = 2;
s += piSrc[2 * i] * 2;
s += piSrc[2 * i - (leftPadding ? 0 : 1)];
s += piSrc[2 * i + 1];
pDst[i] = s >> 2;

Christian Helmrich
committed
}
else if (pu.cs->sps->getCclmCollocatedChromaFlag())
int s = 4;
s += piSrc[2 * i - iRecStride];
s += piSrc[2 * i] * 4;
s += piSrc[2 * i - (leftPadding ? 0 : 1)];
s += piSrc[2 * i + 1];
s += piSrc[2 * i + iRecStride];
pDst[i] = s >> 3;
else
{
piSrc = pRecSrc0 - iRecStride2;
int s = 4;
s += piSrc[2 * i] * 2;
s += piSrc[2 * i + 1];
s += piSrc[2 * i - (leftPadding ? 0 : 1)];
s += piSrc[2 * i + iRecStride] * 2;
s += piSrc[2 * i + 1 + iRecStride];
s += piSrc[2 * i + iRecStride - (leftPadding ? 0 : 1)];
pDst[i] = s >> 3;
}

Karsten Suehring
committed
}
}
if (leftIsAvailable)

Karsten Suehring
committed
{
pDst = pDst0 - 1;
piSrc = pRecSrc0 - 1 - 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.chromaFormat == CHROMA_444)
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
pDst[0] = piSrc[0];
}
else if (pu.chromaFormat == CHROMA_422)
{
int s = 2;
s += piSrc[0] * 2;
s += piSrc[-1];
s += piSrc[1];
pDst[0] = s >> 2;
}
else if (pu.cs->sps->getCclmCollocatedChromaFlag())
{
const bool abovePadding = j == 0 && !aboveIsAvailable;
int s = 4;
s += piSrc[-(abovePadding ? 0 : iRecStride)];
s += piSrc[0] * 4;
s += piSrc[-1];
s += piSrc[1];
s += piSrc[iRecStride];
pDst[0] = s >> 3;
int s = 4;
s += piSrc[0] * 2;
s += piSrc[1];
s += piSrc[-1];
s += piSrc[iRecStride] * 2;
s += piSrc[iRecStride + 1];
s += piSrc[iRecStride - 1];
pDst[0] = s >> 3;

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.chromaFormat == CHROMA_444)

Karsten Suehring
committed
{
pDst0[i] = pRecSrc0[i];

Karsten Suehring
committed
}
else if (pu.chromaFormat == CHROMA_422)

Karsten Suehring
committed
{
const bool leftPadding = i == 0 && !leftIsAvailable;
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
int s = 2;
s += pRecSrc0[2 * i] * 2;
s += pRecSrc0[2 * i - (leftPadding ? 0 : 1)];
s += pRecSrc0[2 * i + 1];
pDst0[i] = s >> 2;
}
else if (pu.cs->sps->getCclmCollocatedChromaFlag())
{
const bool leftPadding = i == 0 && !leftIsAvailable;
const bool abovePadding = j == 0 && !aboveIsAvailable;
int s = 4;
s += pRecSrc0[2 * i - (abovePadding ? 0 : iRecStride)];
s += pRecSrc0[2 * i] * 4;
s += pRecSrc0[2 * i - (leftPadding ? 0 : 1)];
s += pRecSrc0[2 * i + 1];
s += pRecSrc0[2 * i + iRecStride];
pDst0[i] = s >> 3;
}
else
{
CHECK(pu.chromaFormat != CHROMA_420, "Chroma format must be 4:2:0 for vertical filtering");
const bool leftPadding = i == 0 && !leftIsAvailable;
int s = 4;
s += pRecSrc0[2 * i] * 2;
s += pRecSrc0[2 * i + 1];
s += pRecSrc0[2 * i - (leftPadding ? 0 : 1)];
s += pRecSrc0[2 * i + iRecStride] * 2;
s += pRecSrc0[2 * i + 1 + iRecStride];
s += pRecSrc0[2 * i + iRecStride - (leftPadding ? 0 : 1)];
pDst0[i] = s >> 3;

Karsten Suehring
committed
}
}
pDst0 += iDstStride;
pRecSrc0 += iRecStride2;
}
}
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
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];
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
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
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(area.compID);
const int srcStride = m_refBufferStride[area.compID];
const int srcHStride = 2;
m_matrixIntraPred.prepareInputForPred(CPelBuf(ptrSrc, srcStride, srcHStride), area,
pu.cu->slice->getSPS()->getBitDepth(toChannelType(area.compID)), area.compID);
void IntraPrediction::predIntraMip( const ComponentID compId, PelBuf &piPred, const PredictionUnit &pu )
{
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
uint32_t modeIdx = MAX_NUM_MIP_MODE;
bool transposeFlag = false;
if (compId == COMPONENT_Y)
{
modeIdx = pu.intraDir[CHANNEL_TYPE_LUMA];
transposeFlag = pu.mipTransposedFlag;
}
else
{
const PredictionUnit &coLocatedLumaPU = PU::getCoLocatedLumaPU(pu);
CHECK(pu.intraDir[CHANNEL_TYPE_CHROMA] != DM_CHROMA_IDX, "Error: MIP is only supported for chroma with DM_CHROMA.");
CHECK(!coLocatedLumaPU.cu->mipFlag, "Error: Co-located luma CU should use MIP.");
modeIdx = coLocatedLumaPU.intraDir[CHANNEL_TYPE_LUMA];
transposeFlag = coLocatedLumaPU.mipTransposedFlag;
}
const int bitDepth = pu.cu->slice->getSPS()->getBitDepth(toChannelType(compId));
CHECK(modeIdx >= getNumModesMip(piPred), "Error: Wrong MIP mode index");
static_vector<int, MIP_MAX_WIDTH* MIP_MAX_HEIGHT> predMip( piPred.width * piPred.height );
m_matrixIntraPred.predBlock(predMip.data(), modeIdx, transposeFlag, bitDepth, compId);
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]);
}
}
void IntraPrediction::reorderPLT(CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp)
Yung-Hsuan Chao (Jessie)
committed
{
CodingUnit &cu = *cs.getCU(partitioner.chType);
uint8_t reusePLTSizetmp = 0;
uint8_t pltSizetmp = 0;
Pel curPLTtmp[MAX_NUM_COMPONENT][MAXPLTSIZE];
bool curPLTpred[MAXPLTPREDSIZE];
for (int idx = 0; idx < MAXPLTPREDSIZE; idx++)
{
curPLTpred[idx] = false;
cu.reuseflag[compBegin][idx] = false;
}
for (int idx = 0; idx < MAXPLTSIZE; idx++)
{
curPLTpred[idx] = false;
}
for (int predidx = 0; predidx < cs.prevPLT.curPLTSize[compBegin]; predidx++)
{
bool match = false;
int curidx = 0;
for (curidx = 0; curidx < cu.curPLTSize[compBegin]; curidx++)
{
if( curPLTpred[curidx] )
continue;
bool matchTmp = true;
for (int comp = compBegin; comp < (compBegin + numComp); comp++)
{
matchTmp = matchTmp && (cu.curPLT[comp][curidx] == cs.prevPLT.curPLT[comp][predidx]);
}
if (matchTmp)
{
match = true;
break;
}
}
if (match)
{
cu.reuseflag[compBegin][predidx] = true;
curPLTpred[curidx] = true;
if( cu.isLocalSepTree() )
{
cu.reuseflag[COMPONENT_Y][predidx] = true;
for( int comp = COMPONENT_Y; comp < MAX_NUM_COMPONENT; comp++ )
{
curPLTtmp[comp][reusePLTSizetmp] = cs.prevPLT.curPLT[comp][predidx];
}
}
else
{
for (int comp = compBegin; comp < (compBegin + numComp); comp++)
{
curPLTtmp[comp][reusePLTSizetmp] = cs.prevPLT.curPLT[comp][predidx];
}
reusePLTSizetmp++;
}
}
cu.reusePLTSize[compBegin] = reusePLTSizetmp;
for (int curidx = 0; curidx < cu.curPLTSize[compBegin]; curidx++)
{
if (!curPLTpred[curidx])
{
if( cu.isLocalSepTree() )
{
for( int comp = compBegin; comp < (compBegin + numComp); comp++ )
{
curPLTtmp[comp][pltSizetmp] = cu.curPLT[comp][curidx];
}
if( isLuma(partitioner.chType) )
{
curPLTtmp[COMPONENT_Cb][pltSizetmp] = 1 << (cs.sps->getBitDepth(CHANNEL_TYPE_CHROMA) - 1);
curPLTtmp[COMPONENT_Cr][pltSizetmp] = 1 << (cs.sps->getBitDepth(CHANNEL_TYPE_CHROMA) - 1);
}
else
{
curPLTtmp[COMPONENT_Y][pltSizetmp] = 1 << (cs.sps->getBitDepth(CHANNEL_TYPE_LUMA) - 1);
}
}
else
{
for (int comp = compBegin; comp < (compBegin + numComp); comp++)
{
curPLTtmp[comp][pltSizetmp] = cu.curPLT[comp][curidx];
}
}
assert(pltSizetmp == cu.curPLTSize[compBegin]);
for (int curidx = 0; curidx < cu.curPLTSize[compBegin]; curidx++)
{
if( cu.isLocalSepTree() )
{
for( int comp = COMPONENT_Y; comp < MAX_NUM_COMPONENT; comp++ )
{
cu.curPLT[comp][curidx] = curPLTtmp[comp][curidx];
}
}
else
{
for (int comp = compBegin; comp < (compBegin + numComp); comp++)
{
cu.curPLT[comp][curidx] = curPLTtmp[comp][curidx];
}
Yung-Hsuan Chao (Jessie)
committed
}