diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 8baddf032aa8c6c52b4a23dd69a0c4d1a1f71d3d..a114201fa81eb8cb02c74a3ebc93985f8f08374c 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -2516,6 +2516,22 @@ bool EncAppCfg::xCheckParameter() xConfirmPara( m_cbQpOffsetDualTree > 12, "Max. Chroma Cb QP Offset for dual tree is 12" ); xConfirmPara( m_crQpOffsetDualTree < -12, "Min. Chroma Cr QP Offset for dual tree is -12" ); xConfirmPara( m_crQpOffsetDualTree > 12, "Max. Chroma Cr QP Offset for dual tree is 12" ); +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (m_dualTree && (m_chromaFormatIDC == CHROMA_400)) + { + msg( WARNING, "****************************************************************************\n"); + msg( WARNING, "** WARNING: --DualITree has been disabled because the chromaFormat is 400 **\n"); + msg( WARNING, "****************************************************************************\n"); + m_dualTree = false; + } + if (m_ccalf && (m_chromaFormatIDC == CHROMA_400)) + { + msg( WARNING, "****************************************************************************\n"); + msg( WARNING, "** WARNING: --CCALF has been disabled because the chromaFormat is 400 **\n"); + msg( WARNING, "****************************************************************************\n"); + m_ccalf = false; + } +#endif if (m_JointCbCrMode && (m_chromaFormatIDC == CHROMA_400)) { msg( WARNING, "****************************************************************************\n"); diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp index b9282a2e30d3d9393430d87f96d3e6e166b54300..b134d6cd30104f9943cbc93d60c4939c6542dbbd 100644 --- a/source/Lib/CommonLib/CodingStructure.cpp +++ b/source/Lib/CommonLib/CodingStructure.cpp @@ -964,7 +964,11 @@ void CodingStructure::createCoeffs(const bool isPLTused) if (isPLTused) { +#if JVET_Q0438_MONOCHROME_BUGFIXES + for (unsigned i = 0; i < (isChromaEnabled(area.chromaFormat) ? 2 : 1); i++) +#else for (unsigned i = 0; i < numCh - 1; i++) +#endif { unsigned _area = area.blocks[i].area(); diff --git a/source/Lib/CommonLib/Hash.cpp b/source/Lib/CommonLib/Hash.cpp index 5657f3cb3fd66b4aa877f0a03eba16ac9afd4a32..9750be390676f5f808744f2cd963a684d33b28aa 100644 --- a/source/Lib/CommonLib/Hash.cpp +++ b/source/Lib/CommonLib/Hash.cpp @@ -377,9 +377,17 @@ void TComHash::getPixelsIn1DCharArrayByBlock2x2(const PelUnitBuf &curPicBuf, uns if (bitDepths.recon[CHANNEL_TYPE_LUMA] == 8 && bitDepths.recon[CHANNEL_TYPE_CHROMA] == 8) { +#if JVET_Q0438_MONOCHROME_BUGFIXES + Pel* curPel[MAX_NUM_COMPONENT]={nullptr}; + int stride[MAX_NUM_COMPONENT]={0}; + const int maxComponent=includeAllComponent?MAX_NUM_COMPONENT:1; + + for (int id = 0; id < maxComponent; id++) +#else Pel* curPel[3]; int stride[3]; for (int id = 0; id < 3; id++) +#endif { ComponentID compID = ComponentID(id); stride[id] = (curPicBuf).get(compID).stride; @@ -410,10 +418,19 @@ void TComHash::getPixelsIn1DCharArrayByBlock2x2(const PelUnitBuf &curPicBuf, uns else { int shift = bitDepths.recon[CHANNEL_TYPE_LUMA] - 8; +#if JVET_Q0438_MONOCHROME_BUGFIXES + int shiftc = includeAllComponent ? (bitDepths.recon[CHANNEL_TYPE_CHROMA] - 8) : 0; + Pel* curPel[MAX_NUM_COMPONENT]={nullptr}; + int stride[MAX_NUM_COMPONENT]={0}; + const int maxComponent=includeAllComponent?MAX_NUM_COMPONENT:1; + + for (int id = 0; id < maxComponent; id++) +#else int shiftc = bitDepths.recon[CHANNEL_TYPE_CHROMA] - 8; Pel* curPel[3]; int stride[3]; for (int id = 0; id < 3; id++) +#endif { ComponentID compID = ComponentID(id); stride[id] = (curPicBuf).get(compID).stride; diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index ab4a35f8d3ab128b876e3de87312cc35b567260c..9b84b1a2a3e087ea00be1e857b725143e31f6826 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -1466,8 +1466,15 @@ void InterPrediction::xWeightedAverage(const PredictionUnit& pu, const CPelUnitB { if (bioApplied) { +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isChromaEnabled(yuvDstTmp->chromaFormat)) + { +#endif yuvDstTmp->bufs[1].copyFrom(pcYuvDst.bufs[1]); yuvDstTmp->bufs[2].copyFrom(pcYuvDst.bufs[2]); +#if JVET_Q0438_MONOCHROME_BUGFIXES + } +#endif } else yuvDstTmp->copyFrom(pcYuvDst, lumaOnly, chromaOnly); @@ -1519,6 +1526,11 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu , PelUnitBuf* predBufWOBIO /*= NULL*/ ) { +#if JVET_Q0438_MONOCHROME_BUGFIXES + // Note: there appears to be an interaction with weighted prediction that + // makes the code follow different paths if chroma is on or off (in the encoder). + // Therefore for 4:0:0, "chroma" is not changed to false. +#endif CHECK(predBufWOBIO && pu.ciipFlag, "the case should not happen!"); if (!pu.cs->pcv->isEncoder) @@ -1741,8 +1753,15 @@ void InterPrediction::weightedTriangleBlk( PredictionUnit &pu, const bool splitD else { m_if.weightedTriangleBlk( pu, pu.lumaSize().width, pu.lumaSize().height, COMPONENT_Y, splitDir, predDst, predSrc0, predSrc1 ); +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isChromaEnabled(pu.chromaFormat)) + { +#endif m_if.weightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, predDst, predSrc0, predSrc1 ); m_if.weightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 ); +#if JVET_Q0438_MONOCHROME_BUGFIXES + } +#endif } } #else @@ -1760,7 +1779,7 @@ void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx geoMrgCtx.setMergeInfo( pu, candIdx0 ); PU::spanMotionInfo( pu ); - motionCompensation(pu, tmpGeoBuf0, REF_PIC_LIST_X, true, isChromaEnabled(pu.chromaFormat)); + motionCompensation(pu, tmpGeoBuf0, REF_PIC_LIST_X, true, isChromaEnabled(pu.chromaFormat)); // TODO: check 4:0:0 interaction with weighted prediction. if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) ) { printf( "DECODER_GEO_PU: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() ); @@ -1768,7 +1787,7 @@ void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx geoMrgCtx.setMergeInfo( pu, candIdx1 ); PU::spanMotionInfo( pu ); - motionCompensation(pu, tmpGeoBuf1, REF_PIC_LIST_X, true, isChromaEnabled(pu.chromaFormat)); + motionCompensation(pu, tmpGeoBuf1, REF_PIC_LIST_X, true, isChromaEnabled(pu.chromaFormat)); // TODO: check 4:0:0 interaction with weighted prediction. if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) ) { printf( "DECODER_GEO_PU: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() ); @@ -1791,8 +1810,15 @@ void InterPrediction::weightedGeoBlk( PredictionUnit &pu, const uint8_t splitDir else { m_if.weightedGeoBlk( pu, pu.lumaSize().width, pu.lumaSize().height, COMPONENT_Y, splitDir, predDst, predSrc0, predSrc1 ); +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isChromaEnabled(pu.chromaFormat)) + { +#endif m_if.weightedGeoBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, predDst, predSrc0, predSrc1 ); m_if.weightedGeoBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 ); +#if JVET_Q0438_MONOCHROME_BUGFIXES + } +#endif } } #endif @@ -1848,7 +1874,11 @@ void InterPrediction::xPad(PredictionUnit& pu, PelUnitBuf &pcPad, RefPicList ref int offset = 0, width, height; int padsize; Mv cMv; +#if JVET_Q0438_MONOCHROME_BUGFIXES + for (int compID = 0; compID < getNumberValidComponents(pu.chromaFormat); compID++) +#else for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++) +#endif { int filtersize = (compID == (COMPONENT_Y)) ? NTAPS_LUMA : NTAPS_CHROMA; width = pcPad.bufs[compID].width; @@ -2011,7 +2041,11 @@ void InterPrediction::xFinalPaddedMCForDMVR(PredictionUnit& pu, PelUnitBuf &pcYu pu.lx(), pu.ly(), pu.lwidth(), pu.lheight(), startMv.getHor(), startMv.getVer(), tileArea.topLeft().x, tileArea.topLeft().y, tileArea.bottomRight().x, tileArea.bottomRight().y ); THROW( "MCTS constraint failed!" ); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + for (int compID = 0; compID < getNumberValidComponents(pu.chromaFormat); compID++) +#else for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++) +#endif { Pel *srcBufPelPtr = NULL; int pcPadstride = 0; @@ -2294,13 +2328,26 @@ void InterPrediction::xProcessDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvDst, con if (pu.mvdL0SubPu[num] != Mv(0, 0)) { blockMoved = true; +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isChromaEnabled(pu.chromaFormat)) + { +#endif xPrefetch(subPu, m_cYuvRefBuffDMVRL0, REF_PIC_LIST_0, 0); xPrefetch(subPu, m_cYuvRefBuffDMVRL1, REF_PIC_LIST_1, 0); +#if JVET_Q0438_MONOCHROME_BUGFIXES + } +#endif xPad(subPu, m_cYuvRefBuffDMVRL0, REF_PIC_LIST_0); xPad(subPu, m_cYuvRefBuffDMVRL1, REF_PIC_LIST_1); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + int dstStride[MAX_NUM_COMPONENT] = { pcYuvDst.bufs[COMPONENT_Y].stride, + isChromaEnabled(pu.chromaFormat) ? pcYuvDst.bufs[COMPONENT_Cb].stride : 0, + isChromaEnabled(pu.chromaFormat) ? pcYuvDst.bufs[COMPONENT_Cr].stride : 0}; +#else int dstStride[MAX_NUM_COMPONENT] = { pcYuvDst.bufs[COMPONENT_Y].stride, pcYuvDst.bufs[COMPONENT_Cb].stride, pcYuvDst.bufs[COMPONENT_Cr].stride }; +#endif subPu.mv[0] = mergeMv[REF_PIC_LIST_0] + pu.mvdL0SubPu[num]; subPu.mv[1] = mergeMv[REF_PIC_LIST_1] - pu.mvdL0SubPu[num]; @@ -2313,10 +2360,16 @@ void InterPrediction::xProcessDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvDst, con subPredBuf.bufs[COMPONENT_Y].buf = pcYuvDst.bufs[COMPONENT_Y].buf + xStart + yStart * dstStride[COMPONENT_Y]; +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isChromaEnabled(pu.chromaFormat)) + { +#endif subPredBuf.bufs[COMPONENT_Cb].buf = pcYuvDst.bufs[COMPONENT_Cb].buf + (xStart >> scaleX) + ((yStart >> scaleY) * dstStride[COMPONENT_Cb]); subPredBuf.bufs[COMPONENT_Cr].buf = pcYuvDst.bufs[COMPONENT_Cr].buf + (xStart >> scaleX) + ((yStart >> scaleY) * dstStride[COMPONENT_Cr]); - +#if JVET_Q0438_MONOCHROME_BUGFIXES + } +#endif xWeightedAverage(subPu, srcPred0, srcPred1, subPredBuf, subPu.cu->slice->getSPS()->getBitDepths(), subPu.cu->slice->clpRngs(), bioAppliedType[num]); num++; } diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp index 776a332baf4939a5722c71e5efe3c0106067c374..01e5cbcd60b672360c3a0523ae8b75058e896a8b 100644 --- a/source/Lib/CommonLib/IntraPrediction.cpp +++ b/source/Lib/CommonLib/IntraPrediction.cpp @@ -743,6 +743,12 @@ void IntraPrediction::geneIntrainterPred(const CodingUnit &cu) initIntraPatternChType(cu, pu->Y()); predIntraAng(COMPONENT_Y, cu.cs->getPredBuf(*pu).Y(), *pu); +#if JVET_Q0438_MONOCHROME_BUGFIXES + int maxCompID = 1; + if (isChromaEnabled(pu->chromaFormat)) + { + maxCompID = MAX_NUM_COMPONENT; +#endif if (pu->chromaSize().width > 2) { initIntraPatternChType(cu, pu->Cb()); @@ -751,10 +757,20 @@ void IntraPrediction::geneIntrainterPred(const CodingUnit &cu) initIntraPatternChType(cu, pu->Cr()); predIntraAng(COMPONENT_Cr, cu.cs->getPredBuf(*pu).Cr(), *pu); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + } + for (int currCompID = 0; currCompID < maxCompID; currCompID++) + { + if (currCompID > 0 && pu->chromaSize().width <= 2) + { + continue; + } +#else for (int currCompID = 0; currCompID < 3; currCompID++) { if (pu->chromaSize().width <= 2 && currCompID > 0) continue; +#endif ComponentID currCompID2 = (ComponentID)currCompID; PelBuf tmpBuf = currCompID == 0 ? cu.cs->getPredBuf(*pu).Y() : (currCompID == 1 ? cu.cs->getPredBuf(*pu).Cb() : cu.cs->getPredBuf(*pu).Cr()); switchBuffer(*pu, currCompID2, tmpBuf, getPredictorPtr2(currCompID2, 0)); diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp index e0d8d547b1f000c7fd40b3b54bc3d7ae699f7ee7..a9e3a60c8eda3283e83e2dd86452e9a5f6d4c174 100644 --- a/source/Lib/CommonLib/LoopFilter.cpp +++ b/source/Lib/CommonLib/LoopFilter.cpp @@ -397,7 +397,12 @@ void LoopFilter::xDeblockCU( CodingUnit& cu, const DeblockEdgeDir edgeDir ) { xEdgeFilterLuma( cu, edgeDir, edge ); } + +#if JVET_Q0438_MONOCHROME_BUGFIXES + if ( pcv.chrFormat != CHROMA_400 && cu.blocks[COMPONENT_Cb].valid() ) +#else if ( cu.blocks[COMPONENT_Cb].valid() && pcv.chrFormat != CHROMA_400 ) +#endif { if ( !cu.ispMode || edge == 0 ) { @@ -457,7 +462,11 @@ void LoopFilter::xSetMaxFilterLengthPQFromTransformSizes( const DeblockEdgeDir e if ( edgeDir == EDGE_HOR ) { +#if JVET_Q0438_MONOCHROME_BUGFIXES + for ( int cIdx = 0; cIdx < ::getNumberValidComponents(tuQ.chromaFormat); cIdx++ ) // per component +#else for ( int cIdx = 0; cIdx < MAX_NUM_COMPONENT; cIdx++ ) // per component +#endif { const ComponentID comp = ComponentID(cIdx); const ChannelType ch = toChannelType(comp); @@ -502,7 +511,11 @@ void LoopFilter::xSetMaxFilterLengthPQFromTransformSizes( const DeblockEdgeDir e } if ( edgeDir == EDGE_VER ) { +#if JVET_Q0438_MONOCHROME_BUGFIXES + for ( int cIdx = 0; cIdx < ::getNumberValidComponents(tuQ.chromaFormat); cIdx++ ) // per component +#else for ( int cIdx = 0; cIdx < MAX_NUM_COMPONENT; cIdx++ ) // per component +#endif { const ComponentID comp = ComponentID(cIdx); const ChannelType ch = toChannelType(comp); @@ -710,6 +723,10 @@ unsigned LoopFilter::xGetBoundaryStrengthSingle ( const CodingUnit& cu, const De { tmpBs += BsSet(1, COMPONENT_Y); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (pcv.chrFormat != CHROMA_400) + { +#endif // U if (m_aapucBS[edgeDir][rasterIdx] && (TU::getCbf(tuQ, COMPONENT_Cb) || TU::getCbf(tuP, COMPONENT_Cb) || tuQ.jointCbCr || tuP.jointCbCr)) { @@ -720,6 +737,9 @@ unsigned LoopFilter::xGetBoundaryStrengthSingle ( const CodingUnit& cu, const De { tmpBs += BsSet(1, COMPONENT_Cr); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + } +#endif if (BsGet(tmpBs, COMPONENT_Y) == 1) { return tmpBs; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 756850b86b059df6a67a94fd810dd00696bd4a68..7ad29c25d90c25146497705b0cc3ae9f8aff16dc 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,8 @@ #include <assert.h> #include <cassert> +#define JVET_Q0438_MONOCHROME_BUGFIXES 1 // JVET-Q0438: Monochrome bug fixes + #define JVET_Q0110_Q0785_CHROMA_BDPCM_420 1 // JVET-Q0110/Q0785: Enable chroma BDPCM for 420, separate contexts for chroma BDPCM and bug-fixes. #define JVET_Q0512_ENC_CHROMA_TS_ACT 1 // JVET-Q0512: encoder-side improvement on enabling chroma transform-skip for ACT diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 8a6d7c8d6af9f7ffacf47eff65c8cbf0d2b1d45c..304090f103a7c4a56b8645b6e3307cb42defbe2a 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -782,7 +782,12 @@ void TransformUnit::init(TCoeff **coeffs, Pel **pcmbuf, bool **runType) m_pcmbuf[i] = pcmbuf[i]; } +#if JVET_Q0438_MONOCHROME_BUGFIXES + // numBlocks is either 1 for 4:0:0, or 3 otherwise. It would perhaps be better to loop over getNumberValidChannels(*cs->pcv.chrFormat) for m_runType. + for (uint32_t i = 0; i < std::max<uint32_t>(2, numBlocks)-1; i++) +#else for (uint32_t i = 0; i < numBlocks - 1; i++) +#endif { m_runType[i] = runType[i]; } diff --git a/source/Lib/CommonLib/UnitPartitioner.cpp b/source/Lib/CommonLib/UnitPartitioner.cpp index 71b35c0b274b80d1913d2f3705fb67d415048ae5..65803b7063ac660785fe203b667e3df49efbf825 100644 --- a/source/Lib/CommonLib/UnitPartitioner.cpp +++ b/source/Lib/CommonLib/UnitPartitioner.cpp @@ -253,7 +253,11 @@ void QTBTPartitioner::initCtu( const UnitArea& ctuArea, const ChannelType _chTyp currQtDepth = 0; currSubdiv = 0; currQgPos = ctuArea.lumaPos(); +#if JVET_Q0438_MONOCHROME_BUGFIXES + currQgChromaPos = ctuArea.chromaFormat != CHROMA_400 ? ctuArea.chromaPos() : Position(); +#else currQgChromaPos = ctuArea.chromaPos(); +#endif currImplicitBtDepth = 0; chType = _chType; @@ -374,7 +378,11 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca // the minimal and maximal sizes are given in luma samples const CompArea& area = currArea().Y(); +#if JVET_Q0438_MONOCHROME_BUGFIXES + const CompArea *areaC = (chType == CHANNEL_TYPE_CHROMA) ? &(currArea().Cb()) : nullptr; +#else const CompArea& areaC = currArea().Cb(); +#endif PartLevel& level = m_partStack.back(); const PartSplit lastSplit = level.split; @@ -383,7 +391,11 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca // don't allow QT-splitting below a BT split if( lastSplit != CTU_LEVEL && lastSplit != CU_QUAD_SPLIT ) canQt = false; if( area.width <= minQtSize ) canQt = false; +#if JVET_Q0438_MONOCHROME_BUGFIXES + if( areaC && areaC->width <= MIN_DUALTREE_CHROMA_WIDTH ) canQt = false; +#else if( chType == CHANNEL_TYPE_CHROMA && areaC.width <= MIN_DUALTREE_CHROMA_WIDTH ) canQt = false; +#endif if( treeType == TREE_C ) { canQt = canBh = canTh = canBv = canTv = false; @@ -395,7 +407,11 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca canBh = implicitSplit == CU_HORZ_SPLIT; canBv = implicitSplit == CU_VERT_SPLIT; +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (areaC && areaC->width == 4) canBv = false; +#else if (chType == CHANNEL_TYPE_CHROMA && areaC.width == 4) canBv = false; +#endif return; } @@ -431,20 +447,37 @@ void QTBTPartitioner::canSplit( const CodingStructure &cs, bool& canNo, bool& ca // specific check for BT splits if( area.height <= minBtSize ) canBh = false; if( area.width > MAX_TB_SIZEY && area.height <= MAX_TB_SIZEY ) canBh = false; +#if JVET_Q0438_MONOCHROME_BUGFIXES + if( areaC && areaC->width * areaC->height <= MIN_DUALTREE_CHROMA_SIZE ) canBh = false; +#else if( chType == CHANNEL_TYPE_CHROMA && areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE ) canBh = false; +#endif if( area.width <= minBtSize ) canBv = false; if( area.width <= MAX_TB_SIZEY && area.height > MAX_TB_SIZEY ) canBv = false; +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (areaC && (areaC->width * areaC->height <= MIN_DUALTREE_CHROMA_SIZE || areaC->width == 4)) canBv = false; +#else if (chType == CHANNEL_TYPE_CHROMA && (areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE || areaC.width == 4)) canBv = false; +#endif if( modeType == MODE_TYPE_INTER && area.width * area.height == 32 ) canBv = canBh = false; if( area.height <= 2 * minTtSize || area.height > maxTtSize || area.width > maxTtSize ) canTh = false; if( area.width > MAX_TB_SIZEY || area.height > MAX_TB_SIZEY ) canTh = false; +#if JVET_Q0438_MONOCHROME_BUGFIXES + if( areaC && areaC->width * areaC->height <= MIN_DUALTREE_CHROMA_SIZE*2 ) canTh = false; +#else if( chType == CHANNEL_TYPE_CHROMA && areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE*2 ) canTh = false; +#endif if( area.width <= 2 * minTtSize || area.width > maxTtSize || area.height > maxTtSize ) canTv = false; if( area.width > MAX_TB_SIZEY || area.height > MAX_TB_SIZEY ) canTv = false; +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (areaC && (areaC->width * areaC->height <= MIN_DUALTREE_CHROMA_SIZE * 2 || areaC->width == 8)) canTv = false; +#else if (chType == CHANNEL_TYPE_CHROMA && (areaC.width * areaC.height <= MIN_DUALTREE_CHROMA_SIZE * 2 || areaC.width == 8)) canTv = false; +#endif if( modeType == MODE_TYPE_INTER && area.width * area.height == 64 ) canTv = canTh = false; + } bool QTBTPartitioner::canSplit( const PartSplit split, const CodingStructure &cs ) @@ -570,7 +603,11 @@ void QTBTPartitioner::exitCurrSplit() currSubdiv--; if( currQgEnable() ) currQgPos = currArea().lumaPos(); +#if JVET_Q0438_MONOCHROME_BUGFIXES + if( currArea().chromaFormat != CHROMA_400 && currQgChromaEnable() ) +#else if( currQgChromaEnable() ) +#endif currQgChromaPos = currArea().chromaPos(); #if _DEBUG m_currArea = m_partStack.back().parts[m_partStack.back().idx]; @@ -998,7 +1035,11 @@ void PartitionerImpl::getTUIntraSubPartitions( Partitioning &sub, const UnitArea THROW( "Unknown TU sub-partitioning" ); } //we only partition luma, so there is going to be only one chroma tu at the end (unless it is dual tree, in which case there won't be any chroma components) +#if JVET_Q0438_MONOCHROME_BUGFIXES + uint32_t partitionsWithoutChroma = (cs.area.chromaFormat == CHROMA_400) ? 0 : (isDualTree ? nPartitions : nPartitions - 1); +#else uint32_t partitionsWithoutChroma = isDualTree ? nPartitions : nPartitions - 1; +#endif for( uint32_t i = 0; i < partitionsWithoutChroma; i++ ) { CompArea& blkCb = sub[i].blocks[COMPONENT_Cb]; diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 9298a4cb2b9b42a1ba76a63a92f0dbf92e54d191..231476d8d3a07e1f7db7cf411c98844eaf8b5690 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -675,8 +675,13 @@ void DecCu::xReconInter(CodingUnit &cu) #endif CHECK(CU::isIBC(cu) && cu.firstPU->mmvdMergeFlag, "IBC and MMVD cannot be used together"); const bool luma = cu.Y().valid(); +#if JVET_Q0438_MONOCHROME_BUGFIXES + const bool chroma = isChromaEnabled(cu.chromaFormat) && cu.Cb().valid(); + if (luma && (chroma || !isChromaEnabled(cu.chromaFormat))) +#else const bool chroma = cu.Cb().valid(); if (luma && chroma) +#endif { m_pcInterPred->motionCompensation(cu); } @@ -698,7 +703,11 @@ void DecCu::xReconInter(CodingUnit &cu) cu.cs->getPredBuf(*cu.firstPU).Y().rspSignal(m_pcReshape->getFwdLUT()); } m_pcIntraPred->geneWeightedPred(COMPONENT_Y, cu.cs->getPredBuf(*cu.firstPU).Y(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Y, 0)); +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isChromaEnabled(cu.chromaFormat) && cu.chromaSize().width > 2) +#else if (cu.chromaSize().width > 2) +#endif { m_pcIntraPred->geneWeightedPred(COMPONENT_Cb, cu.cs->getPredBuf(*cu.firstPU).Cb(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Cb, 0)); m_pcIntraPred->geneWeightedPred(COMPONENT_Cr, cu.cs->getPredBuf(*cu.firstPU).Cr(), *cu.firstPU, m_pcIntraPred->getPredictorPtr2(COMPONENT_Cr, 0)); diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 5b851d934848790bc53284b1060affd058613456..1a366d48a6dcd2167a046e3a72e10a480fd57051 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -500,6 +500,10 @@ void CABACWriter::coding_tree(const CodingStructure& cs, Partitioner& partitione partitioner.exitCurrSplit(); if( chromaNotSplit ) { +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isChromaEnabled(cs.pcv->chrFormat)) + { +#endif CHECK( partitioner.chType != CHANNEL_TYPE_LUMA, "must be luma status" ); partitioner.chType = CHANNEL_TYPE_CHROMA; partitioner.treeType = TREE_C; @@ -508,6 +512,9 @@ void CABACWriter::coding_tree(const CodingStructure& cs, Partitioner& partitione { coding_tree( cs, partitioner, cuCtx ); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + } +#endif //recover partitioner.chType = CHANNEL_TYPE_LUMA; @@ -693,7 +700,11 @@ void CABACWriter::coding_unit( const CodingUnit& cu, Partitioner& partitioner, C } #if !JVET_Q0110_Q0785_CHROMA_BDPCM_420 bdpcm_mode( cu, ComponentID( partitioner.chType ) ); +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (!CS::isDualITree(cs) && isLuma(partitioner.chType) && isChromaEnabled(cu.chromaFormat)) +#else if (!CS::isDualITree(cs) && isLuma(partitioner.chType)) +#endif bdpcm_mode(cu, ComponentID(CHANNEL_TYPE_CHROMA)); #endif @@ -2485,12 +2496,21 @@ void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, Partiti const CodingUnit& cu = *tu.cu; const UnitArea& area = partitioner.currArea(); const unsigned trDepth = partitioner.currTrDepth; +#if !JVET_Q0438_MONOCHROME_BUGFIXES const bool chromaCbfISP = area.blocks[COMPONENT_Cb].valid() && cu.ispMode; +#endif ChromaCbfs chromaCbfs; CHECK(tu.depth != trDepth, " transform unit should be not be futher partitioned"); // cbf_cb & cbf_cr +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (area.chromaFormat != CHROMA_400) + { + const bool chromaCbfISP = area.blocks[COMPONENT_Cb].valid() && cu.ispMode; + if (area.blocks[COMPONENT_Cb].valid() && (!cu.isSepTree() || partitioner.chType == CHANNEL_TYPE_CHROMA) && (!cu.ispMode || chromaCbfISP)) +#else if (area.chromaFormat != CHROMA_400 && area.blocks[COMPONENT_Cb].valid() && (!cu.isSepTree() || partitioner.chType == CHANNEL_TYPE_CHROMA) && (!cu.ispMode || chromaCbfISP)) +#endif { { unsigned cbfDepth = chromaCbfISP ? trDepth - 1 : trDepth; @@ -2513,6 +2533,13 @@ void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, Partiti { chromaCbfs = ChromaCbfs(false); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + } + else if (cu.isSepTree()) + { + chromaCbfs = ChromaCbfs(false); + } +#endif if (!isChroma(partitioner.chType)) { diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp index 252cea9d5bd56f04beaf784fb88c2f9b69846e29..c64f4eb330e7ae0f22863318c6daac38d143239a 100644 --- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp +++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp @@ -1041,6 +1041,9 @@ void EncAdaptiveLoopFilter::ALFProcess(CodingStructure& cs, const double *lambda ); // derive filter (chroma) +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isChromaEnabled(cs.pcv->chrFormat)) +#endif { alfEncoder( cs, alfParam, orgYuv, recYuv, cs.getRecoBuf(), CHANNEL_TYPE_CHROMA #if ENABLE_QPA @@ -2922,6 +2925,10 @@ void EncAdaptiveLoopFilter::alfEncoderCtb(CodingStructure& cs, AlfParam& alfPar } //chroma +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isChromaEnabled(cs.pcv->chrFormat)) + { +#endif m_alfParamTemp = alfParamNewFiltersBest; if( m_alfParamTemp.numAlternativesChroma < 1 ) { @@ -3129,6 +3136,9 @@ void EncAdaptiveLoopFilter::alfEncoderCtb(CodingStructure& cs, AlfParam& alfPar } apss[cs.slice->getTileGroupApsIdChroma()] = m_apsMap->getPS((cs.slice->getTileGroupApsIdChroma() << NUM_APS_TYPE_LEN) + ALF_APS); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + } +#endif } void EncAdaptiveLoopFilter::alfReconstructor(CodingStructure& cs, const PelUnitBuf& recExtBuf) diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 452e7cec6ccee5bf79c0e3bc78fe05b03f3e43d8..6cdfb0425431986081ed2848c516af27ecc9c3b4 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -1512,6 +1512,10 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, tempCS->picture->cs->getNumCuPuTuOffset( numCuPuTu ); tempCS->picture->cs->useSubStructure( *tempCS, partitioner.chType, CS::getArea( *tempCS, partitioner.currArea(), partitioner.chType ), false, true, false, false ); +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isChromaEnabled(tempCS->pcv->chrFormat)) + { +#endif partitioner.chType = CHANNEL_TYPE_CHROMA; tempCS->treeType = partitioner.treeType = TREE_C; @@ -1536,9 +1540,15 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, tempCSChroma->releaseIntermediateData(); bestCSChroma->releaseIntermediateData(); //tempCS->picture->cs->releaseIntermediateData(); +#if JVET_Q0438_MONOCHROME_BUGFIXES + m_CurrCtx--; + } +#endif tempCS->picture->cs->clearCuPuTuIdxMap( partitioner.currArea(), numCuPuTu[0], numCuPuTu[1], numCuPuTu[2], numCuPuTu + 3 ); +#if !JVET_Q0438_MONOCHROME_BUGFIXES m_CurrCtx--; +#endif //recover luma tree status partitioner.chType = CHANNEL_TYPE_LUMA; @@ -1837,7 +1847,11 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS m_CABACEstimator->cu_pred_data ( cu ); #if !JVET_Q0110_Q0785_CHROMA_BDPCM_420 m_CABACEstimator->bdpcm_mode ( cu, ComponentID(partitioner.chType) ); +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (!CS::isDualITree(*cu.cs) && isLuma(partitioner.chType) && isChromaEnabled(cu.chromaFormat)) +#else if (!CS::isDualITree(*cu.cs) && isLuma(partitioner.chType)) +#endif m_CABACEstimator->bdpcm_mode(cu, ComponentID(CHANNEL_TYPE_CHROMA)); #endif @@ -1862,7 +1876,15 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS // Check if low frequency non-separable transform (LFNST) is too expensive if( lfnstIdx && !cuCtx.lfnstLastScanPos && !cu.ispMode ) { +#if JVET_Q0438_MONOCHROME_BUGFIXES + bool cbfAtZeroDepth = cu.isSepTree() ? + cu.rootCbf + : (tempCS->area.chromaFormat != CHROMA_400 && std::min( cu.firstTU->blocks[ 1 ].width, cu.firstTU->blocks[ 1 ].height ) < 4) ? + TU::getCbfAtDepth( *cu.firstTU, COMPONENT_Y, 0 ) + : cu.rootCbf; +#else bool cbfAtZeroDepth = cu.isSepTree() ? cu.rootCbf : std::min( cu.firstTU->blocks[ 1 ].width, cu.firstTU->blocks[ 1 ].height ) < 4 ? TU::getCbfAtDepth( *cu.firstTU, COMPONENT_Y, 0 ) : cu.rootCbf; +#endif if( cbfAtZeroDepth ) { tempCS->cost = MAX_DOUBLE; @@ -2626,7 +2648,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& setMergeBestSATDCost( candCostList[0] ); +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isIntrainterEnabled && isChromaEnabled(pu.cs->pcv->chrFormat)) +#else if (isIntrainterEnabled) +#endif { pu.ciipFlag = true; for (uint32_t mergeCnt = 0; mergeCnt < uiNumMrgSATDCand; mergeCnt++) @@ -2771,6 +2797,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& tmpBuf.rspSignal(m_pcReshape->getFwdLUT()); } m_pcIntraSearch->geneWeightedPred(COMPONENT_Y, tmpBuf, pu, m_pcIntraSearch->getPredictorPtr2(COMPONENT_Y, bufIdx)); +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isChromaEnabled(pu.chromaFormat)) + { +#endif if (pu.chromaSize().width > 2) { tmpBuf = tempCS->getPredBuf(pu).Cb(); @@ -2787,6 +2817,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& tmpBuf = tempCS->getPredBuf(pu).Cr(); tmpBuf.copyFrom(acMergeTmpBuffer[uiMergeCand].Cr()); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + } +#endif } else { @@ -3001,6 +3034,10 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru } // perform chroma weighting process +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (isChromaEnabled(pu.chromaFormat)) + { +#endif for( uint8_t i = 0; i < triangleNumMrgSATDCand; i++ ) { uint8_t mergeCand = triangleRdModeList[i]; @@ -3015,6 +3052,9 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru pu.regularMergeFlag = false; m_pcInterSearch->weightedTriangleBlk( pu, splitDir, CHANNEL_TYPE_CHROMA, triangleWeightedBuffer[mergeCand], triangleBuffer[candIdx0], triangleBuffer[candIdx1] ); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + } +#endif tempCS->initStructData( encTestMode.qp ); } diff --git a/source/Lib/EncoderLib/EncReshape.cpp b/source/Lib/EncoderLib/EncReshape.cpp index 27d5ae535f845188a40c21b020262bf7cf6d89ea..b697daf5fcf3dc91f90e6bfd8b518ff231dbf79d 100644 --- a/source/Lib/EncoderLib/EncReshape.cpp +++ b/source/Lib/EncoderLib/EncReshape.cpp @@ -366,6 +366,10 @@ void EncReshape::calcSeqStats(Picture *pcPic, SeqInfo &stats) } picY = pcPic->getOrigBuf(COMPONENT_Y); +#if JVET_Q0438_MONOCHROME_BUGFIXES + double avgY = 0.0; + double varY = 0.0; +#else PelBuf picU = pcPic->getOrigBuf(COMPONENT_Cb); PelBuf picV = pcPic->getOrigBuf(COMPONENT_Cr); const int widthC = picU.width; @@ -373,6 +377,7 @@ void EncReshape::calcSeqStats(Picture *pcPic, SeqInfo &stats) const int strideC = picU.stride; double avgY = 0.0, avgU = 0.0, avgV = 0.0; double varY = 0.0, varU = 0.0, varV = 0.0; +#endif for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) @@ -382,6 +387,20 @@ void EncReshape::calcSeqStats(Picture *pcPic, SeqInfo &stats) } picY.buf += stride; } +#if JVET_Q0438_MONOCHROME_BUGFIXES + avgY = avgY / (width * height); + varY = varY / (width * height) - avgY * avgY; + + if (isChromaEnabled(pcPic->chromaFormat)) + { + PelBuf picU = pcPic->getOrigBuf(COMPONENT_Cb); + PelBuf picV = pcPic->getOrigBuf(COMPONENT_Cr); + const int widthC = picU.width; + const int heightC = picU.height; + const int strideC = picU.stride; + double avgU = 0.0, avgV = 0.0; + double varU = 0.0, varV = 0.0; +#endif for (int y = 0; y < heightC; y++) { for (int x = 0; x < widthC; x++) @@ -394,10 +413,14 @@ void EncReshape::calcSeqStats(Picture *pcPic, SeqInfo &stats) picU.buf += strideC; picV.buf += strideC; } +#if !JVET_Q0438_MONOCHROME_BUGFIXES avgY = avgY / (width * height); +#endif avgU = avgU / (widthC * heightC); avgV = avgV / (widthC * heightC); +#if !JVET_Q0438_MONOCHROME_BUGFIXES varY = varY / (width * height) - avgY * avgY; +#endif varU = varU / (widthC * heightC) - avgU * avgU; varV = varV / (widthC * heightC) - avgV * avgV; if (varY > 0) @@ -405,6 +428,9 @@ void EncReshape::calcSeqStats(Picture *pcPic, SeqInfo &stats) stats.ratioStdU = sqrt(varU) / sqrt(varY); stats.ratioStdV = sqrt(varV) / sqrt(varY); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + } +#endif } void EncReshape::preAnalyzerLMCS(Picture *pcPic, const uint32_t signalType, const SliceType sliceType, const ReshapeCW& reshapeCW) { diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 5cb2192760e3cbd490b12f46305f48ab6c66c381..51ff99a7861f2842f10a4c8d09697415c6867e40 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -809,8 +809,15 @@ int InterSearch::xIBCSearchMVChromaRefine(PredictionUnit& pu, ) { +#if JVET_Q0438_MONOCHROME_BUGFIXES + if ( (!isChromaEnabled(pu.chromaFormat)) || (!pu.Cb().valid()) ) + { + return 0; + } +#else if (!pu.Cb().valid()) return 0; +#endif int bestCandIdx = 0; Distortion sadBest = std::numeric_limits<Distortion>::max(); @@ -6934,7 +6941,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par } } +#if JVET_Q0438_MONOCHROME_BUGFIXES + if ( chroma && isChromaEnabled(tu.chromaFormat) && tu.blocks[COMPONENT_Cb].valid() ) +#else if ( chroma && tu.blocks[COMPONENT_Cb].valid() ) +#endif { const CompArea& cbArea = tu.blocks[COMPONENT_Cb]; const CompArea& crArea = tu.blocks[COMPONENT_Cr]; @@ -7234,8 +7245,13 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par m_CABACEstimator->resetBits(); if( !tu.noResidual ) { +#if JVET_Q0438_MONOCHROME_BUGFIXES + static const ComponentID cbf_getComp[MAX_NUM_COMPONENT] = { COMPONENT_Cb, COMPONENT_Cr, COMPONENT_Y }; + for( unsigned c = isChromaEnabled(tu.chromaFormat)?0 : 2; c < MAX_NUM_COMPONENT; c++) +#else static const ComponentID cbf_getComp[3] = { COMPONENT_Cb, COMPONENT_Cr, COMPONENT_Y }; for( unsigned c = 0; c < numTBlocks; c++) +#endif { const ComponentID compID = cbf_getComp[c]; if (compID == COMPONENT_Y && !luma) @@ -7495,7 +7511,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa else cs.getResiBuf().bufs[0].subtract(cs.getPredBuf().bufs[0]); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (chroma && isChromaEnabled(cs.pcv->chrFormat)) +#else if (chroma) +#endif { cs.getResiBuf().bufs[1].copyFrom(cs.getOrgBuf().bufs[1]); cs.getResiBuf().bufs[2].copyFrom(cs.getOrgBuf().bufs[2]); @@ -7626,7 +7646,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa { cs.getOrgResiBuf().bufs[0].copyFrom(orgResidual.bufs[0]); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (chroma && isChromaEnabled(cs.pcv->chrFormat)) +#else if (chroma) +#endif { cs.getOrgResiBuf().bufs[1].copyFrom(orgResidual.bufs[1]); cs.getOrgResiBuf().bufs[2].copyFrom(orgResidual.bufs[2]); @@ -7739,7 +7763,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa { cs.getResiBuf().bufs[0].fill(0); // Clear the residual image, if we didn't code it. } +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (chroma && isChromaEnabled(cs.pcv->chrFormat)) +#else if (chroma) +#endif { cs.getResiBuf().bufs[1].fill(0); // Clear the residual image, if we didn't code it. cs.getResiBuf().bufs[2].fill(0); // Clear the residual image, if we didn't code it. @@ -7769,7 +7797,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa } } } +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (chroma && isChromaEnabled(cs.pcv->chrFormat)) +#else if (chroma) +#endif { cs.getRecoBuf().bufs[1].reconstruct(cs.getPredBuf().bufs[1], cs.getResiBuf().bufs[1], cs.slice->clpRngs().comp[1]); cs.getRecoBuf().bufs[2].reconstruct(cs.getPredBuf().bufs[2], cs.getResiBuf().bufs[2], cs.slice->clpRngs().comp[2]); diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index ecacd5094dba4314d59e64e6713fbfb2108f82f6..e850c0f084290c4d0ce583d3589e79329869a4aa 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -2596,7 +2596,11 @@ void IntraSearch::xEncIntraHeader( CodingStructure &cs, Partitioner &partitioner } #if !JVET_Q0110_Q0785_CHROMA_BDPCM_420 m_CABACEstimator->bdpcm_mode ( cu, ComponentID(partitioner.chType) ); +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (!CS::isDualITree(cs) && isLuma(partitioner.chType) && isChromaEnabled(cu.chromaFormat)) +#else if (!CS::isDualITree(cs) && isLuma(partitioner.chType)) +#endif m_CABACEstimator->bdpcm_mode(cu, ComponentID(CHANNEL_TYPE_CHROMA)); #endif } @@ -2641,7 +2645,9 @@ void IntraSearch::xEncSubdivCbfQT( CodingStructure &cs, Partitioner &partitioner const bool subdiv = currTU.depth > currDepth; ComponentID compID = partitioner.chType == CHANNEL_TYPE_LUMA ? COMPONENT_Y : COMPONENT_Cb; +#if !JVET_Q0438_MONOCHROME_BUGFIXES const bool chromaCbfISP = currArea.blocks[COMPONENT_Cb].valid() && currCU.ispMode && !subdiv; +#endif if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) ) { @@ -2652,7 +2658,14 @@ void IntraSearch::xEncSubdivCbfQT( CodingStructure &cs, Partitioner &partitioner CHECK( subdiv && !currCU.ispMode && isLuma( compID ), "No TU subdivision is allowed with QTBT" ); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (bChroma) + { + const bool chromaCbfISP = currArea.blocks[COMPONENT_Cb].valid() && currCU.ispMode && !subdiv; + if ( !currCU.ispMode || chromaCbfISP ) +#else if( bChroma && ( !currCU.ispMode || chromaCbfISP ) ) +#endif { const uint32_t numberValidComponents = getNumberValidComponents(currArea.chromaFormat); const uint32_t cbfDepth = ( chromaCbfISP ? currDepth - 1 : currDepth ); @@ -2669,6 +2682,9 @@ void IntraSearch::xEncSubdivCbfQT( CodingStructure &cs, Partitioner &partitioner } } } +#if JVET_Q0438_MONOCHROME_BUGFIXES + } +#endif if (subdiv) { @@ -3056,11 +3072,27 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp m_pcTrQuant->setLambda(m_pcTrQuant->getLambda() / (cResScale*cResScale)); } +#if JVET_Q0438_MONOCHROME_BUGFIXES + PelBuf crOrg; + PelBuf crPred; + PelBuf crResi; + PelBuf crReco; + + if (isChroma(compID)) + { + const CompArea &crArea = tu.blocks[ COMPONENT_Cr ]; + crOrg = cs.getOrgBuf ( crArea ); + crPred = cs.getPredBuf ( crArea ); + crResi = cs.getResiBuf ( crArea ); + crReco = cs.getRecoBuf ( crArea ); + } +#else const CompArea &crArea = tu.blocks [ COMPONENT_Cr ]; PelBuf crOrg = cs.getOrgBuf ( crArea ); PelBuf crPred = cs.getPredBuf ( crArea ); PelBuf crResi = cs.getResiBuf ( crArea ); PelBuf crReco = cs.getRecoBuf ( crArea ); +#endif if ( jointCbCr ) { diff --git a/source/Lib/Utilities/VideoIOYuv.cpp b/source/Lib/Utilities/VideoIOYuv.cpp index 720d06212579459767a676b6174502cee7cb3caa..018b5574841ae914fb949becb870f004f3cdc080 100644 --- a/source/Lib/Utilities/VideoIOYuv.cpp +++ b/source/Lib/Utilities/VideoIOYuv.cpp @@ -915,7 +915,12 @@ bool VideoIOYuv::read ( PelUnitBuf& pic, PelUnitBuf& picOrg, const InputColourSp const bool b709Compliance=(bClipToRec709) && (m_bitdepthShift[chType] < 0 && desired_bitdepth >= 8); /* ITU-R BT.709 compliant clipping for converting say 10b to 8b */ const Pel minval = b709Compliance? (( 1 << (desired_bitdepth - 8)) ) : 0; const Pel maxval = b709Compliance? ((0xff << (desired_bitdepth - 8)) -1) : (1 << desired_bitdepth) - 1; +#if JVET_Q0438_MONOCHROME_BUGFIXES + const bool processComponent = (size_t)compID < picOrg.bufs.size(); + Pel* const dst = processComponent ? picOrg.get(compID).bufAt(0,0) : nullptr; +#else Pel* const dst = picOrg.get(compID).bufAt(0,0); +#endif #if EXTENSION_360_VIDEO const uint32_t stride444 = picOrg.get(compID).stride; #endif @@ -924,6 +929,16 @@ bool VideoIOYuv::read ( PelUnitBuf& pic, PelUnitBuf& picOrg, const InputColourSp return false; } +#if JVET_Q0438_MONOCHROME_BUGFIXES + if (processComponent) + { + if (! verifyPlane( dst, stride444, width444, height444, pad_h444, pad_v444, compID, format, m_fileBitdepth[chType]) ) + { + EXIT("Source image contains values outside the specified bit range!"); + } + scalePlane( picOrg.get(compID), m_bitdepthShift[chType], minval, maxval); + } +#else if (! verifyPlane( dst, stride444, width444, height444, pad_h444, pad_v444, compID, format, m_fileBitdepth[chType]) ) { EXIT("Source image contains values outside the specified bit range!"); @@ -933,6 +948,7 @@ bool VideoIOYuv::read ( PelUnitBuf& pic, PelUnitBuf& picOrg, const InputColourSp { scalePlane( picOrg.get(compID), m_bitdepthShift[chType], minval, maxval); } +#endif } #if EXTENSION_360_VIDEO