From fb9d75f55dc54fc66cf922bc589b604dfcb024d6 Mon Sep 17 00:00:00 2001 From: Philipp Merkle <philipp.merkle@hhi.fraunhofer.de> Date: Wed, 29 Apr 2020 16:39:36 +0200 Subject: [PATCH 1/2] JVET-R0350: MIP for chroma in case of 4:4:4 format and single tree --- source/Lib/CommonLib/IntraPrediction.cpp | 41 +++++++++++++++++ .../Lib/CommonLib/MatrixIntraPrediction.cpp | 18 ++++++++ source/Lib/CommonLib/MatrixIntraPrediction.h | 10 +++++ source/Lib/CommonLib/TypeDef.h | 2 + source/Lib/CommonLib/UnitTools.cpp | 44 +++++++++++++++++++ source/Lib/CommonLib/UnitTools.h | 6 +++ source/Lib/EncoderLib/IntraSearch.cpp | 10 +++++ 7 files changed, 131 insertions(+) diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp index 1c042ca699..61ce6ae0e5 100644 --- a/source/Lib/CommonLib/IntraPrediction.cpp +++ b/source/Lib/CommonLib/IntraPrediction.cpp @@ -217,6 +217,9 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co const int iWidth = piPred.width; const int iHeight = piPred.height; CHECK(iWidth == 2, "Width of 2 is not supported"); +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE + CHECK(PU::isMIP(pu, toChannelType(compId)), "We should not get here for MIP."); +#endif const uint32_t uiDirMode = isLuma( compId ) && pu.cu->bdpcmMode ? BDPCM_IDX : !isLuma(compId) && pu.cu->bdpcmModeChroma ? BDPCM_IDX : PU::getFinalIntraMode(pu, channelType); CHECK( floorLog2(iWidth) < 2 && pu.cs->pcv->noChroma2x2, "Size not allowed" ); @@ -1836,24 +1839,62 @@ void IntraPrediction::initIntraMip( const PredictionUnit &pu, const CompArea &ar // prepare input (boundary) data for prediction CHECK( m_ipaParam.refFilterFlag, "ERROR: unfiltered refs expected for MIP" ); +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE + 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); +#else 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 ) ); +#endif } void IntraPrediction::predIntraMip( const ComponentID compId, PelBuf &piPred, const PredictionUnit &pu ) { +#if !JVET_R0350_MIP_CHROMA_444_SINGLETREE CHECK( compId != COMPONENT_Y, "Error: chroma not supported" ); +#endif 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 +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE + 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: Invalid mode."); +#else const int bitDepth = pu.cu->slice->getSPS()->getBitDepth( CHANNEL_TYPE_LUMA ); +#endif static_vector<int, MIP_MAX_WIDTH* MIP_MAX_HEIGHT> predMip( piPred.width * piPred.height ); +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE + m_matrixIntraPred.predBlock(predMip.data(), modeIdx, transposeFlag, bitDepth, compId); +#else m_matrixIntraPred.predBlock( predMip.data(), pu.intraDir[CHANNEL_TYPE_LUMA], pu.mipTransposedFlag, bitDepth ); +#endif for( int y = 0; y < piPred.height; y++ ) { diff --git a/source/Lib/CommonLib/MatrixIntraPrediction.cpp b/source/Lib/CommonLib/MatrixIntraPrediction.cpp index 9ddb6bac7e..cad260400e 100644 --- a/source/Lib/CommonLib/MatrixIntraPrediction.cpp +++ b/source/Lib/CommonLib/MatrixIntraPrediction.cpp @@ -43,6 +43,9 @@ MatrixIntraPrediction::MatrixIntraPrediction(): +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE + m_component(MAX_NUM_COMPONENT), +#endif m_reducedBoundary (MIP_MAX_INPUT_SIZE), m_reducedBoundaryTransposed(MIP_MAX_INPUT_SIZE), m_inputOffset ( 0 ), @@ -58,9 +61,16 @@ MatrixIntraPrediction::MatrixIntraPrediction(): { } +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE +void MatrixIntraPrediction::prepareInputForPred(const CPelBuf &pSrc, const Area &block, const int bitDepth, + const ComponentID compId) +{ + m_component = compId; +#else void MatrixIntraPrediction::prepareInputForPred(const CPelBuf &pSrc, const Area& block, const int bitDepth) { +#endif // Step 1: Save block size and calculate dependent values initPredBlockParams(block); @@ -114,8 +124,16 @@ void MatrixIntraPrediction::prepareInputForPred(const CPelBuf &pSrc, const Area& } } +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE +void MatrixIntraPrediction::predBlock(int *const result, const int modeIdx, const bool transpose, const int bitDepth, + const ComponentID compId) +{ + CHECK(m_component != compId, "Boundary has not been prepared for this component."); + +#else void MatrixIntraPrediction::predBlock(int* const result, const int modeIdx, const bool transpose, const int bitDepth) { +#endif const bool needUpsampling = ( m_upsmpFactorHor > 1 ) || ( m_upsmpFactorVer > 1 ); const uint8_t* matrix = getMatrixData(modeIdx); diff --git a/source/Lib/CommonLib/MatrixIntraPrediction.h b/source/Lib/CommonLib/MatrixIntraPrediction.h index d9b3b377bd..2b69661e3b 100644 --- a/source/Lib/CommonLib/MatrixIntraPrediction.h +++ b/source/Lib/CommonLib/MatrixIntraPrediction.h @@ -50,10 +50,20 @@ class MatrixIntraPrediction public: MatrixIntraPrediction(); +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE + void prepareInputForPred(const CPelBuf &pSrc, const Area &block, const int bitDepth, const ComponentID compId); + void predBlock(int *const result, const int modeIdx, const bool transpose, const int bitDepth, + const ComponentID compId); +#else void prepareInputForPred(const CPelBuf &pSrc, const Area& block, const int bitDepth); void predBlock(int* const result, const int modeIdx, const bool transpose, const int bitDepth); +#endif private: +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE + ComponentID m_component; + +#endif static_vector<int, MIP_MAX_INPUT_SIZE> m_reducedBoundary; // downsampled boundary of a block static_vector<int, MIP_MAX_INPUT_SIZE> m_reducedBoundaryTransposed; // downsampled, transposed boundary of a block int m_inputOffset; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index fd000c8a19..c89950cd2b 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -81,6 +81,8 @@ #define JVET_R0156_ASPECT3_SPS_CLEANUP 1 // Condition sps_sublayer_dpb_params_flag on sps_ptl_dpb_hrd_params_present_flag, in addition to sps_max_sublayer_minus1, JVET-R0156 proposal 3, JVET-R0170, JVET-R0222 proposal 2 +#define JVET_R0350_MIP_CHROMA_444_SINGLETREE 1 // JVET-R0350: MIP for chroma in case of 4:4:4 format and single tree + //########### place macros to be be kept below this line ############### #define JVET_R0164_MEAN_SCALED_SATD 1 // JVET-R0164: Use a mean scaled version of SATD in encoder decisions diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 0c191dc742..114323451f 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -553,9 +553,27 @@ int PU::getIntraMPMs( const PredictionUnit &pu, unsigned* mpm, const ChannelType bool PU::isMIP(const PredictionUnit &pu, const ChannelType &chType) { +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE + if (chType == CHANNEL_TYPE_LUMA) + { + // Default case if chType is omitted. + return pu.cu->mipFlag; + } + else + { + return isDMChromaMIP(pu) && (pu.intraDir[CHANNEL_TYPE_CHROMA] == DM_CHROMA_IDX); + } +#else return (chType == CHANNEL_TYPE_LUMA && pu.cu->mipFlag); +#endif } +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE +bool PU::isDMChromaMIP(const PredictionUnit &pu) +{ + return !pu.cu->isSepTree() && (pu.chromaFormat == CHROMA_444) && getCoLocatedLumaPU(pu).cu->mipFlag; +} +#endif uint32_t PU::getIntraDirLuma( const PredictionUnit &pu ) { @@ -582,6 +600,14 @@ void PU::getIntraChromaCandModes( const PredictionUnit &pu, unsigned modeList[NU modeList[6] = MDLM_T_IDX; modeList[7] = DM_CHROMA_IDX; +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE + // If Direct Mode is MIP, mode cannot be already in the list. + if (isDMChromaMIP(pu)) + { + return; + } + +#endif const uint32_t lumaMode = getCoLocatedIntraLumaMode(pu); for( int i = 0; i < 4; i++ ) { @@ -638,6 +664,23 @@ uint32_t PU::getFinalIntraMode( const PredictionUnit &pu, const ChannelType &chT return uiIntraMode; } +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE +const PredictionUnit &PU::getCoLocatedLumaPU(const PredictionUnit &pu) +{ + Position topLeftPos = pu.blocks[pu.chType].lumaPos(); + Position refPos = topLeftPos.offset(pu.blocks[pu.chType].lumaSize().width >> 1, + pu.blocks[pu.chType].lumaSize().height >> 1); + const PredictionUnit &lumaPU = pu.cu->isSepTree() ? *pu.cs->picture->cs->getPU(refPos, CHANNEL_TYPE_LUMA) + : *pu.cs->getPU(topLeftPos, CHANNEL_TYPE_LUMA); + + return lumaPU; +} + +uint32_t PU::getCoLocatedIntraLumaMode(const PredictionUnit &pu) +{ + return PU::getIntraDirLuma(PU::getCoLocatedLumaPU(pu)); +} +#else uint32_t PU::getCoLocatedIntraLumaMode( const PredictionUnit &pu ) { Position topLeftPos = pu.blocks[pu.chType].lumaPos(); @@ -646,6 +689,7 @@ uint32_t PU::getCoLocatedIntraLumaMode( const PredictionUnit &pu ) return PU::getIntraDirLuma( lumaPU ); } +#endif int PU::getWideAngIntraMode( const TransformUnit &tu, const uint32_t dirMode, const ComponentID compID ) { diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 2df81f6ee6..9f6f0cfcf1 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -129,8 +129,14 @@ namespace PU int getLMSymbolList(const PredictionUnit &pu, int *modeList); int getIntraMPMs(const PredictionUnit &pu, unsigned *mpm, const ChannelType &channelType = CHANNEL_TYPE_LUMA); bool isMIP (const PredictionUnit &pu, const ChannelType &chType = CHANNEL_TYPE_LUMA); +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE + bool isDMChromaMIP (const PredictionUnit &pu); +#endif uint32_t getIntraDirLuma (const PredictionUnit &pu); void getIntraChromaCandModes (const PredictionUnit &pu, unsigned modeList[NUM_CHROMA_MODE]); +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE + const PredictionUnit &getCoLocatedLumaPU(const PredictionUnit &pu); +#endif uint32_t getFinalIntraMode (const PredictionUnit &pu, const ChannelType &chType); uint32_t getCoLocatedIntraLumaMode (const PredictionUnit &pu); int getWideAngIntraMode ( const TransformUnit &tu, const uint32_t dirMode, const ComponentID compID ); diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index d5e4c502e5..b8b2966501 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -4956,6 +4956,16 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio predIntraChromaLM( COMPONENT_Cb, piPredCb, pu, cbArea, predMode ); predIntraChromaLM( COMPONENT_Cr, piPredCr, pu, crArea, predMode ); } +#if JVET_R0350_MIP_CHROMA_444_SINGLETREE + else if (PU::isMIP(pu, CHANNEL_TYPE_CHROMA)) + { + initIntraMip(pu, cbArea); + predIntraMip(COMPONENT_Cb, piPredCb, pu); + + initIntraMip(pu, crArea); + predIntraMip(COMPONENT_Cr, piPredCr, pu); + } +#endif else { predIntraAng( COMPONENT_Cb, piPredCb, pu); -- GitLab From c5bc23ea727280ddfc104f911500ab2ec4cc0ec7 Mon Sep 17 00:00:00 2001 From: Philipp Merkle <philipp.merkle@hhi.fraunhofer.de> Date: Thu, 30 Apr 2020 07:51:21 +0200 Subject: [PATCH 2/2] updated error message --- source/Lib/CommonLib/IntraPrediction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp index 61ce6ae0e5..3a24c156f1 100644 --- a/source/Lib/CommonLib/IntraPrediction.cpp +++ b/source/Lib/CommonLib/IntraPrediction.cpp @@ -1884,7 +1884,7 @@ void IntraPrediction::predIntraMip( const ComponentID compId, PelBuf &piPred, co } const int bitDepth = pu.cu->slice->getSPS()->getBitDepth(toChannelType(compId)); - CHECK(modeIdx >= getNumModesMip(piPred), "Error: Invalid mode."); + CHECK(modeIdx >= getNumModesMip(piPred), "Error: Wrong MIP mode index"); #else const int bitDepth = pu.cu->slice->getSPS()->getBitDepth( CHANNEL_TYPE_LUMA ); #endif -- GitLab