diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 6e853ecfc327faea9aaa70b5afd30c217019b08e..fa29acdb65935512952cd87569a8383242090d3c 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -188,7 +188,11 @@ static const int ADJ_DEQUANT_SHIFT = ( ADJ_QUANT_SHIFT + 1 ); static const int RVM_VCEGAM10_M = 4; static const int NUM_LUMA_MODE = 67; ///< Planar + DC + 65 directional mode (4*16 + 1) +#if JVET_L0338_MDLM +static const int NUM_LMC_MODE = 1 + 2; ///< LMC + MDLM_T + MDLM_L +#else static const int NUM_LMC_MODE = 1; ///< LMC +#endif static const int NUM_INTRA_MODE = (NUM_LUMA_MODE + NUM_LMC_MODE); static const int NUM_DIR = (((NUM_LUMA_MODE - 3) >> 2) + 1); @@ -202,6 +206,10 @@ static const int NOMODE_IDX = MAX_UCHAR; ///< indi static const int NUM_CHROMA_MODE = (5 + NUM_LMC_MODE); ///< total number of chroma modes static const int LM_CHROMA_IDX = NUM_LUMA_MODE; ///< chroma mode index for derived from LM mode +#if JVET_L0338_MDLM +static const int MDLM_L_IDX = LM_CHROMA_IDX + 1; ///< MDLM_L +static const int MDLM_T_IDX = LM_CHROMA_IDX + 2; ///< MDLM_T +#endif static const int DM_CHROMA_IDX = NUM_INTRA_MODE; ///< chroma mode index for derived from luma intra mode static const uint8_t INTER_MODE_IDX = 255; ///< index for inter modes diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp index 45a66514af173d329092688d2a6d9e9691f31022..1ef9df96235d2dccf100a7931e410e13d6d31eaf 100644 --- a/source/Lib/CommonLib/IntraPrediction.cpp +++ b/source/Lib/CommonLib/IntraPrediction.cpp @@ -143,6 +143,9 @@ IntraPrediction::IntraPrediction() } m_piTemp = nullptr; +#if JVET_L0338_MDLM + m_pMdlmTemp = nullptr; +#endif } IntraPrediction::~IntraPrediction() @@ -163,6 +166,10 @@ void IntraPrediction::destroy() delete[] m_piTemp; m_piTemp = nullptr; +#if JVET_L0338_MDLM + delete[] m_pMdlmTemp; + m_pMdlmTemp = nullptr; +#endif } void IntraPrediction::init(ChromaFormat chromaFormatIDC, const unsigned bitDepthY) @@ -197,6 +204,12 @@ void IntraPrediction::init(ChromaFormat chromaFormatIDC, const unsigned bitDepth { m_piTemp = new Pel[(MAX_CU_SIZE + 1) * (MAX_CU_SIZE + 1)]; } +#if JVET_L0338_MDLM + if (m_pMdlmTemp == nullptr) + { + m_pMdlmTemp = new Pel[(2 * MAX_CU_SIZE + 1)*(2 * MAX_CU_SIZE + 1)];//MDLM will use top-above and left-below samples. + } +#endif } // ==================================================================================================================== @@ -383,8 +396,20 @@ void IntraPrediction::predIntraChromaLM(const ComponentID compID, PelBuf &piPred { int iLumaStride = 0; PelBuf Temp; +#if JVET_L0338_MDLM + if ((intraDir == MDLM_L_IDX) || (intraDir == MDLM_T_IDX)) + { + iLumaStride = 2 * MAX_CU_SIZE + 1; + Temp = PelBuf(m_pMdlmTemp + iLumaStride + 1, iLumaStride, Size(chromaArea)); + } + else + { +#endif iLumaStride = MAX_CU_SIZE + 1; Temp = PelBuf(m_piTemp + iLumaStride + 1, iLumaStride, Size(chromaArea)); +#if JVET_L0338_MDLM + } +#endif int a, b, iShift; xGetLMParameters(pu, compID, chromaArea, a, b, iShift); @@ -1239,8 +1264,21 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom { int iDstStride = 0; Pel* pDst0 = 0; +#if JVET_L0338_MDLM + 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 + { +#endif iDstStride = MAX_CU_SIZE + 1; pDst0 = m_piTemp + iDstStride + 1; //MMLM_SAMPLE_NEIGHBOR_LINES; +#if JVET_L0338_MDLM + } +#endif //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) @@ -1280,13 +1318,36 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom const int iTUHeightInUnits = uiTuHeight / iUnitHeight; const int iAboveUnits = iTUWidthInUnits; const int iLeftUnits = iTUHeightInUnits; - +#if JVET_L0338_MDLM + const int chromaUnitWidth = iBaseUnitSize >> getComponentScaleX(COMPONENT_Cb, area.chromaFormat); + const int chromaUnitHeight = iBaseUnitSize >> getComponentScaleX(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; +#endif bool bNeighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1]; - +#if JVET_L0338_MDLM + memset(bNeighborFlags, 0, totalUnits); +#else memset( bNeighborFlags, 0, 1 + iLeftUnits + iAboveUnits ); +#endif bool bAboveAvaillable, bLeftAvaillable; - int availlableUnit = isLeftAvailable( isChroma( pu.chType ) ? cu : lumaCU, toChannelType( area.compID ), area.pos(), iLeftUnits, iUnitHeight, ( bNeighborFlags + iLeftUnits - 1 ) ); + int availlableUnit = isLeftAvailable( isChroma( pu.chType ) ? cu : lumaCU, toChannelType( area.compID ), area.pos(), iLeftUnits, iUnitHeight, +#if JVET_L0338_MDLM + ( bNeighborFlags + iLeftUnits + leftBelowUnits - 1 ) ); +#else + ( bNeighborFlags + iLeftUnits - 1 ) ); +#endif if( lumaCU.cs->pcv->rectCUs ) { @@ -1297,7 +1358,12 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom bLeftAvaillable = availlableUnit == iTUWidthInUnits; } - availlableUnit = isAboveAvailable( isChroma( pu.chType ) ? cu : lumaCU, toChannelType( area.compID ), area.pos(), iAboveUnits, iUnitWidth, ( bNeighborFlags + iLeftUnits + 1 ) ); + availlableUnit = isAboveAvailable( isChroma( pu.chType ) ? cu : lumaCU, toChannelType( area.compID ), area.pos(), iAboveUnits, iUnitWidth, +#if JVET_L0338_MDLM + ( bNeighborFlags + iLeftUnits + leftBelowUnits + 1 ) ); +#else + ( bNeighborFlags + iLeftUnits + 1 ) ); +#endif if( lumaCU.cs->pcv->rectCUs ) { @@ -1307,7 +1373,17 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom { bAboveAvaillable = availlableUnit == iTUHeightInUnits; } +#if JVET_L0338_MDLM + 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)); + } + 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)); + } +#endif Pel* pDst = nullptr; Pel const* piSrc = nullptr; @@ -1316,8 +1392,16 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom { pDst = pDst0 - iDstStride; piSrc = pRecSrc0 - iRecStride2; - +#if JVET_L0338_MDLM + int addedAboveRight = 0; + if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX)) + { + addedAboveRight = avaiAboveRightUnits*chromaUnitWidth; + } + for (int i = 0; i < uiCWidth + addedAboveRight; i++) +#else for( int i = 0; i < uiCWidth; i++ ) +#endif { if( i == 0 && !bLeftAvaillable ) { @@ -1336,8 +1420,16 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom { pDst = pDst0 - 1; piSrc = pRecSrc0 - 3; - +#if JVET_L0338_MDLM + int addedLeftBelow = 0; + if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX)) + { + addedLeftBelow = avaiLeftBelowUnits*chromaUnitHeight; + } + for (int j = 0; j < uiCHeight + addedLeftBelow; j++) +#else for( int j = 0; j < uiCHeight; j++ ) +#endif { pDst[0] = ( ( piSrc[1 ] * 2 + piSrc[0 ] + piSrc[2 ] ) + ( piSrc[1 + iRecStride] * 2 + piSrc[iRecStride] + piSrc[2 + iRecStride] ) @@ -1370,6 +1462,19 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom pRecSrc0 += iRecStride2; } } +#if JVET_L0338_MDLM && !JVET_L0191_LM_WO_LMS +void IntraPrediction::xPadMdlmTemplateSample(Pel*pSrc, Pel*pCur, int cWidth, int cHeight, int existSampNum, int targetSampNum) +{ + int sampNumToBeAdd = targetSampNum - existSampNum; + Pel*pTempSrc = pSrc + existSampNum; + Pel*pTempCur = pCur + existSampNum; + for (int i = 0; i < sampNumToBeAdd; i++) + { + pTempSrc[i] = pSrc[existSampNum - 1]; + pTempCur[i] = pCur[existSampNum - 1]; + } +} +#endif #if JVET_L0191_LM_WO_LMS void IntraPrediction::xGetLMParameters(const PredictionUnit &pu, const ComponentID compID, const CompArea &chromaArea, @@ -1398,27 +1503,79 @@ void IntraPrediction::xGetLMParameters(const PredictionUnit &pu, const Component const int tuHeightInUnits = tuHeight / unitHeight; const int aboveUnits = tuWidthInUnits; const int leftUnits = tuHeightInUnits; - +#if JVET_L0338_MDLM + 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]; +#endif bool neighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1]; - +#if JVET_L0338_MDLM + memset(neighborFlags, 0, totalUnits); +#else memset(neighborFlags, 0, 1 + leftUnits + aboveUnits); +#endif bool aboveAvailable, leftAvailable; int availableUnit = - isAboveAvailable(cu, CHANNEL_TYPE_CHROMA, posLT, aboveUnits, unitWidth, (neighborFlags + leftUnits + 1)); + isAboveAvailable(cu, CHANNEL_TYPE_CHROMA, posLT, aboveUnits, unitWidth, +#if JVET_L0338_MDLM + (neighborFlags + leftUnits + leftBelowUnits + 1)); +#else + (neighborFlags + leftUnits + 1)); +#endif aboveAvailable = availableUnit == tuWidthInUnits; availableUnit = - isLeftAvailable(cu, CHANNEL_TYPE_CHROMA, posLT, leftUnits, unitHeight, (neighborFlags + leftUnits - 1)); + isLeftAvailable(cu, CHANNEL_TYPE_CHROMA, posLT, leftUnits, unitHeight, +#if JVET_L0338_MDLM + (neighborFlags + leftUnits + leftBelowUnits - 1)); +#else + (neighborFlags + leftUnits - 1)); +#endif leftAvailable = availableUnit == tuHeightInUnits; - +#if JVET_L0338_MDLM + 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)); + } +#endif Pel *srcColor0, *curChroma0; int srcStride, curStride; PelBuf temp; +#if JVET_L0338_MDLM + 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 + { +#endif srcStride = MAX_CU_SIZE + 1; temp = PelBuf(m_piTemp + srcStride + 1, srcStride, Size(chromaArea)); +#if JVET_L0338_MDLM + } +#endif srcColor0 = temp.bufAt(0, 0); curChroma0 = getPredictorPtr(compID); @@ -1433,16 +1590,45 @@ void IntraPrediction::xGetLMParameters(const PredictionUnit &pu, const Component Pel *src = srcColor0 - srcStride; Pel *cur = curChroma0 - curStride; - +#if JVET_L0338_MDLM + int minDim = 1; + int actualTopTemplateSampNum = 0; + int actualLeftTemplateSampNum = 0; + if (curChromaMode == MDLM_T_IDX) + { + leftAvailable = 0; + actualTopTemplateSampNum = unitWidth*(avaiAboveUnits + avaiAboveRightUnits); + minDim = actualTopTemplateSampNum; + } + else if (curChromaMode == MDLM_L_IDX) + { + aboveAvailable = 0; + actualLeftTemplateSampNum = unitHeight*(avaiLeftUnits + avaiLeftBelowUnits); + minDim = actualLeftTemplateSampNum; + } + else if (curChromaMode == LM_CHROMA_IDX) + { + actualTopTemplateSampNum = cWidth; + actualLeftTemplateSampNum = cHeight; + minDim = leftAvailable && aboveAvailable ? 1 << g_aucPrevLog2[std::min(actualLeftTemplateSampNum, actualTopTemplateSampNum)] + : 1 << g_aucPrevLog2[leftAvailable ? actualLeftTemplateSampNum : actualTopTemplateSampNum]; + } +#endif +#if !JVET_L0338_MDLM int minDim = leftAvailable && aboveAvailable ? 1 << g_aucPrevLog2[std::min(cHeight, cWidth)] : 1 << g_aucPrevLog2[leftAvailable ? cHeight : cWidth]; +#endif int numSteps = minDim; if (aboveAvailable) { for (int j = 0; j < numSteps; j++) { +#if JVET_L0338_MDLM + int idx = (j * actualTopTemplateSampNum) / minDim; +#else int idx = (j * cWidth) / minDim; +#endif if (minLuma[0] > src[idx]) { @@ -1464,7 +1650,11 @@ void IntraPrediction::xGetLMParameters(const PredictionUnit &pu, const Component for (int i = 0; i < numSteps; i++) { +#if JVET_L0338_MDLM + int idx = (i * actualLeftTemplateSampNum) / minDim; +#else int idx = (i * cHeight) / minDim; +#endif if (minLuma[0] > src[srcStride * idx]) { @@ -1542,25 +1732,77 @@ void IntraPrediction::xGetLMParameters(const PredictionUnit &pu, const Component const int iTUHeightInUnits = uiTuHeight / iUnitHeight; const int iAboveUnits = iTUWidthInUnits; const int iLeftUnits = iTUHeightInUnits; - +#if JVET_L0338_MDLM + int topTemplateSampNum = 2 * uiCWidth; // for MDLM, the template sample number is 2W or 2H; + int leftTemplateSampNum = 2 * uiCHeight; + assert(m_topRefLength >= topTemplateSampNum); + assert(m_leftRefLength >= leftTemplateSampNum); + int totalAboveUnits = (topTemplateSampNum + (iUnitWidth - 1)) / iUnitWidth; + int totalLeftUnits = (leftTemplateSampNum + (iUnitHeight - 1)) / iUnitHeight; + int totalUnits = totalLeftUnits + totalAboveUnits + 1; + int aboveRightUnits = totalAboveUnits - iAboveUnits; + int leftBelowUnits = totalLeftUnits - iLeftUnits; + int avaiAboveRightUnits = 0; + int avaiLeftBelowUnits = 0; + int avaiAboveUnits = 0; + int avaiLeftUnits = 0; + + int curChromaMode = pu.intraDir[1]; +#endif bool bNeighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1]; - +#if JVET_L0338_MDLM + memset(bNeighborFlags, 0, totalUnits); +#else memset( bNeighborFlags, 0, 1 + iLeftUnits + iAboveUnits ); +#endif bool bAboveAvaillable, bLeftAvaillable; - int availlableUnit = isAboveAvailable( cu, CHANNEL_TYPE_CHROMA, posLT, iAboveUnits, iUnitWidth, ( bNeighborFlags + iLeftUnits + 1 ) ); + int availlableUnit = isAboveAvailable( cu, CHANNEL_TYPE_CHROMA, posLT, iAboveUnits, iUnitWidth, +#if JVET_L0338_MDLM + (bNeighborFlags + iLeftUnits + leftBelowUnits + 1 ) ); +#else + ( bNeighborFlags + iLeftUnits + 1 ) ); +#endif bAboveAvaillable = availlableUnit == iTUWidthInUnits; - availlableUnit = isLeftAvailable( cu, CHANNEL_TYPE_CHROMA, posLT, iLeftUnits, iUnitHeight, ( bNeighborFlags + iLeftUnits - 1 ) ); + availlableUnit = isLeftAvailable( cu, CHANNEL_TYPE_CHROMA, posLT, iLeftUnits, iUnitHeight, +#if JVET_L0338_MDLM + (bNeighborFlags + iLeftUnits + leftBelowUnits - 1 ) ); +#else + ( bNeighborFlags + iLeftUnits - 1 ) ); +#endif bLeftAvaillable = availlableUnit == iTUHeightInUnits; - +#if JVET_L0338_MDLM + if (bLeftAvaillable) // if left is not available, then the below left is not available + { + avaiLeftUnits = iTUHeightInUnits; + avaiLeftBelowUnits = isBelowLeftAvailable(cu, CHANNEL_TYPE_CHROMA, chromaArea.bottomLeftComp(chromaArea.compID), leftBelowUnits, iUnitHeight, (bNeighborFlags + leftBelowUnits - 1)); + } + if (bAboveAvaillable) // if above is not available, then the above right is not available. + { + avaiAboveUnits = iTUWidthInUnits; + avaiAboveRightUnits = isAboveRightAvailable(cu, CHANNEL_TYPE_CHROMA, chromaArea.topRightComp(chromaArea.compID), aboveRightUnits, iUnitWidth, (bNeighborFlags + iLeftUnits + leftBelowUnits + iAboveUnits + 1)); + } +#endif Pel *pSrcColor0, *pCurChroma0; int iSrcStride, iCurStride; PelBuf Temp; +#if JVET_L0338_MDLM + if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX)) + { + iSrcStride = 2 * MAX_CU_SIZE + 1; + Temp = PelBuf(m_pMdlmTemp + iSrcStride + 1, iSrcStride, Size(chromaArea)); + } + else + { +#endif iSrcStride = MAX_CU_SIZE + 1; Temp = PelBuf(m_piTemp + iSrcStride + 1, iSrcStride, Size(chromaArea)); +#if JVET_L0338_MDLM + } +#endif pSrcColor0 = Temp.bufAt(0, 0); pCurChroma0 = getPredictorPtr(compID); iCurStride = m_topRefLength + 1; @@ -1571,7 +1813,73 @@ void IntraPrediction::xGetLMParameters(const PredictionUnit &pu, const Component Pel *pSrc = pSrcColor0 - iSrcStride; Pel *pCur = pCurChroma0 - iCurStride; +#if JVET_L0338_MDLM + //get the temp buffer to store the downsampled luma and chroma + Pel* pTempBufferSrc = new Pel[2 * MAX_CU_SIZE]; // for MDLM, use tempalte size 2W or 2H, + Pel* pTempBufferCur = new Pel[2 * MAX_CU_SIZE]; + + int actualTopTemplateSampNum = iUnitWidth*(avaiAboveUnits + avaiAboveRightUnits); + int actualLeftTemplateSampNum = iUnitHeight*(avaiLeftUnits + avaiLeftBelowUnits); + + if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX)) + { + if (curChromaMode == MDLM_T_IDX) + { + if (bAboveAvaillable) + { + for (int j = 0; j < actualTopTemplateSampNum; j++) + { + pTempBufferSrc[j] = pSrc[j]; + pTempBufferCur[j] = pCur[j]; + } + } + } + else + { + if (bLeftAvaillable) + { + pSrc = pSrcColor0 - 1; + pCur = pCurChroma0 - 1; + for (int i = 0; i < actualLeftTemplateSampNum; i++) + { + pTempBufferSrc[i] = pSrc[iSrcStride *i]; + pTempBufferCur[i] = pCur[iCurStride *i]; + } + } + } + //pad the temple sample to targetSampNum. + int orgNumSample = (curChromaMode == MDLM_T_IDX) ? (avaiAboveUnits*iUnitWidth) : (avaiLeftUnits*iUnitHeight); + int existSampNum = (curChromaMode == MDLM_T_IDX) ? actualTopTemplateSampNum : actualLeftTemplateSampNum; + int targetSampNum = 1 << (g_aucLog2[existSampNum - 1] + 1); + if (orgNumSample == 0) + { + delete[] pTempBufferSrc; + delete[] pTempBufferCur; + pTempBufferSrc = nullptr; + pTempBufferCur = nullptr; + + a = 0; + b = 1 << (uiInternalBitDepth - 1); + iShift = 0; + return; + } + if (targetSampNum != existSampNum)//if existSampNum not a value of power of 2 + { + xPadMdlmTemplateSample(pTempBufferSrc, pTempBufferCur, uiCWidth, uiCHeight, existSampNum, targetSampNum); + } + for (int j = 0; j < targetSampNum; j++) + { + x += pTempBufferSrc[j]; + y += pTempBufferCur[j]; + xx += pTempBufferSrc[j] * pTempBufferSrc[j]; + xy += pTempBufferSrc[j] * pTempBufferCur[j]; + } + iCountShift = g_aucLog2[targetSampNum]; + } + else + { +#endif int minDim = bLeftAvaillable && bAboveAvaillable ? 1 << g_aucPrevLog2[std::min( uiCHeight, uiCWidth )] : 1 << g_aucPrevLog2[bLeftAvaillable ? uiCHeight : uiCWidth]; int minStep = 1; int numSteps = cs.pcv->rectCUs ? minDim / minStep : minDim; @@ -1607,7 +1915,28 @@ void IntraPrediction::xGetLMParameters(const PredictionUnit &pu, const Component iCountShift += bAboveAvaillable ? 1 : g_aucLog2[minDim / minStep]; } +#if JVET_L0338_MDLM + } + delete[] pTempBufferSrc; + delete[] pTempBufferCur; + pTempBufferSrc = nullptr; + pTempBufferCur = nullptr; +#endif +#if JVET_L0338_MDLM + if ((curChromaMode == MDLM_L_IDX) || (curChromaMode == MDLM_T_IDX)) + { + if ((curChromaMode == MDLM_L_IDX) ? (!bLeftAvaillable) : (!bAboveAvaillable)) + { + a = 0; + b = 1 << (uiInternalBitDepth - 1); + iShift = 0; + return; + } + } + else + { +#endif if( !bLeftAvaillable && !bAboveAvaillable ) { a = 0; @@ -1615,7 +1944,9 @@ void IntraPrediction::xGetLMParameters(const PredictionUnit &pu, const Component iShift = 0; return; } - +#if JVET_L0338_MDLM + } +#endif int iTempShift = uiInternalBitDepth + iCountShift - 15; if( iTempShift > 0 ) diff --git a/source/Lib/CommonLib/IntraPrediction.h b/source/Lib/CommonLib/IntraPrediction.h index 9d8002a8ce3d02c536ae836cb7c4fb8202fd241f..ee7a73aa7db52ecf5e5b7b459955e27c95c3ffbc 100644 --- a/source/Lib/CommonLib/IntraPrediction.h +++ b/source/Lib/CommonLib/IntraPrediction.h @@ -75,6 +75,9 @@ private: unsigned m_auShiftLM[32]; // Table for substituting division operation by multiplication Pel* m_piTemp; +#if JVET_L0338_MDLM + Pel* m_pMdlmTemp; // for MDLM mode +#endif protected: ChromaFormat m_currChromaFormat; @@ -109,6 +112,9 @@ protected: void xFilterGroup ( Pel* pMulDst[], int i, Pel const* const piSrc, int iRecStride, bool bAboveAvaillable, bool bLeftAvaillable); void xGetLMParameters(const PredictionUnit &pu, const ComponentID compID, const CompArea& chromaArea, int& a, int& b, int& iShift); +#if JVET_L0338_MDLM && !JVET_L0191_LM_WO_LMS + void xPadMdlmTemplateSample (Pel*pSrc, Pel*pCur, int cWidth, int cHeight, int existSampNum, int targetSampNum); +#endif public: IntraPrediction(); virtual ~IntraPrediction(); diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp index 8a2ac97f5aa77a099147081b89a9110d5130b39a..05d999c73ba73dd2a5f3f4d167dc5326cdd10905 100644 --- a/source/Lib/CommonLib/Rom.cpp +++ b/source/Lib/CommonLib/Rom.cpp @@ -246,7 +246,12 @@ int g_aiLMDivTableHigh[] = { 129, 129, 129, 129, 128, 128, 128, 128, }; #endif -const int g_aiNonLMPosThrs[] = { 3, 1, 0 }; +const int g_aiNonLMPosThrs[] = +#if JVET_L0338_MDLM +{ 0, 0, 0 }; // not use the useless threshold values.actually, these threshold values should be cleaned up +#else +{ 3, 1, 0 }; +#endif #if JVET_L0646_GBI const int8_t g_GbiLog2WeightBase = 3; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index d8e34d3bbdeeb7864ac7ad84f0b0e6bc8461d5f3..b19bb8a2217034c9e6d8f8fc602ff54c0d91aa73 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -69,6 +69,7 @@ #define JVET_L0274 1 #define JVET_L0274_ENCODER_SPEED_UP ( 1 && JVET_L0274 ) // encoder speed-up by pre-calculating position dependent parameters +#define JVET_L0338_MDLM 1 // multi-directional LM. L0338 test5.4.1,L0340 test5.6.1 diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 50a027e071af64297cd7c24ed9ea49e4c8c4366e..84597226ef90350901df3b01085342456f74cb51 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -388,7 +388,13 @@ void PU::getIntraChromaCandModes( const PredictionUnit &pu, unsigned modeList[NU modeList[ 2 ] = HOR_IDX; modeList[ 3 ] = DC_IDX; modeList[4] = LM_CHROMA_IDX; +#if JVET_L0338_MDLM + modeList[5] = MDLM_L_IDX; + modeList[6] = MDLM_T_IDX; + modeList[7] = DM_CHROMA_IDX; +#else modeList[5] = DM_CHROMA_IDX; +#endif const PredictionUnit *lumaPU = CS::isDualITree( *pu.cs ) ? pu.cs->picture->cs->getPU( pu.blocks[pu.chType].lumaPos(), CHANNEL_TYPE_LUMA ) : &pu; const uint32_t lumaMode = lumaPU->intraDir[CHANNEL_TYPE_LUMA]; @@ -406,7 +412,11 @@ void PU::getIntraChromaCandModes( const PredictionUnit &pu, unsigned modeList[NU bool PU::isLMCMode(unsigned mode) { +#if JVET_L0338_MDLM + return (mode >= LM_CHROMA_IDX && mode <= MDLM_T_IDX); +#else return (mode == LM_CHROMA_IDX); +#endif } bool PU::isLMCModeEnabled(const PredictionUnit &pu, unsigned mode) { @@ -456,7 +466,10 @@ int PU::getLMSymbolList(const PredictionUnit &pu, int *pModeList) pModeList[ iIdx++ ] = -1; bNonLMInsert = true; } - +#if JVET_L0338_MDLM + pModeList[iIdx++] = MDLM_L_IDX; + pModeList[iIdx++] = MDLM_T_IDX; +#endif if ( iCount >= g_aiNonLMPosThrs[1] && ! bNonLMInsert ) { pModeList[ iIdx++ ] = -1; diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index 0dffa353696d65086cb5c22f0d5f165770d5489a..e16f71a6161c3f9cd90bbd96e511dfd5790e0691 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -714,7 +714,108 @@ void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner) orgTUs.push_back( ptu ); } } +#if JVET_L0338_MDLM + // SATD pre-selecting. + int satdModeList[NUM_CHROMA_MODE]; + int64_t satdSortedCost[NUM_CHROMA_MODE]; + for (int i = 0; i < NUM_CHROMA_MODE; i++) + { + satdSortedCost[i] = 0; // for the mode not pre-select by SATD, do RDO by default, so set the initial value 0. + satdModeList[i] = 0; + } + bool modeIsEnable[NUM_INTRA_MODE + 1]; // use intra mode idx to check whether enable + for (int i = 0; i < NUM_INTRA_MODE + 1; i++) + { + modeIsEnable[i] = 1; + } + + DistParam distParam; + const bool useHadamard = true; + pu.intraDir[1] = MDLM_L_IDX; // temporary assigned, just to indicate this is a MDLM mode. for luma down-sampling operation. + + initIntraPatternChType(cu, pu.Cb()); + initIntraPatternChType(cu, pu.Cr()); + xGetLumaRecPixels(pu, pu.Cb()); + + for (int idx = uiMinMode; idx <= uiMaxMode - 1; idx++) + { + int mode = chromaCandModes[idx]; + satdModeList[idx] = mode; + if (PU::isLMCMode(mode) && !PU::isLMCModeEnabled(pu, mode)) + { + continue; + } + if (PU::isLMCMode(mode) || (mode == PLANAR_IDX) || (mode == DM_CHROMA_IDX)) // only pre-check regular mode, not including DM and Planar, and LM modes + { + continue; + } + pu.intraDir[1] = mode; // temporary assigned, for SATD checking. + + int64_t sad = 0; + CodingStructure& cs = *(pu.cs); + + CompArea areaCb = pu.Cb(); + PelBuf orgCb = cs.getOrgBuf(areaCb); + PelBuf predCb = cs.getPredBuf(areaCb); + + m_pcRdCost->setDistParam(distParam, orgCb, predCb, pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cb, useHadamard); + distParam.applyWeight = false; + + if (PU::isLMCMode(mode)) + { + predIntraChromaLM(COMPONENT_Cb, predCb, pu, areaCb, mode); + } + else + { + predIntraAng(COMPONENT_Cb, predCb, pu, false); + } + + sad += distParam.distFunc(distParam); + CompArea areaCr = pu.Cr(); + PelBuf orgCr = cs.getOrgBuf(areaCr); + PelBuf predCr = cs.getPredBuf(areaCr); + + m_pcRdCost->setDistParam(distParam, orgCr, predCr, pu.cs->sps->getBitDepth(CHANNEL_TYPE_CHROMA), COMPONENT_Cr, useHadamard); + distParam.applyWeight = false; + + if (PU::isLMCMode(mode)) + { + predIntraChromaLM(COMPONENT_Cr, predCr, pu, areaCr, mode); + } + else + { + predIntraAng(COMPONENT_Cr, predCr, pu, false); + } + sad += distParam.distFunc(distParam); + satdSortedCost[idx] = sad; + } + // sort the mode based on the cost from small to large. + int tempIdx = 0; + int64_t tempCost = 0; + for (int i = uiMinMode; i <= uiMaxMode - 1; i++) + { + for (int j = i + 1; j <= uiMaxMode - 1; j++) + { + if (satdSortedCost[j] < satdSortedCost[i]) + { + tempIdx = satdModeList[i]; + satdModeList[i] = satdModeList[j]; + satdModeList[j] = tempIdx; + + tempCost = satdSortedCost[i]; + satdSortedCost[i] = satdSortedCost[j]; + satdSortedCost[j] = tempCost; + + } + } + } + int reducedModeNumber = 2; // reduce the number of chroma modes + for (int i = 0; i < reducedModeNumber; i++) + { + modeIsEnable[satdModeList[uiMaxMode - 1 - i]] = 0; // disable the last reducedModeNumber modes + } +#endif // save the dist Distortion baseDist = cs.dist; @@ -726,7 +827,12 @@ void IntraSearch::estIntraPredChromaQT(CodingUnit &cu, Partitioner &partitioner) { continue; } - +#if JVET_L0338_MDLM + if (!modeIsEnable[chromaIntraMode] && PU::isLMCModeEnabled(pu, chromaIntraMode)) // when CCLM is disable, then MDLM is disable. not use satd checking + { + continue; + } +#endif cs.setDecomp( pu.Cb(), false ); cs.dist = baseDist; //----- restore context models -----