From a016844eaa1bc2f566f367d574a17b5a8bba2d47 Mon Sep 17 00:00:00 2001 From: Xiang Li <xlxiangli@google.com> Date: Mon, 29 Apr 2024 22:50:07 +0000 Subject: [PATCH] JVET-AH0066 & JVET-AH0202: Inter CCP merge with zero luma CBF --- source/App/EncoderApp/EncApp.cpp | 5 + source/App/EncoderApp/EncAppCfg.cpp | 11 ++ source/App/EncoderApp/EncAppCfg.h | 5 + source/Lib/CommonLib/CommonDef.h | 3 + source/Lib/CommonLib/Contexts.h | 3 + source/Lib/CommonLib/Contexts_ecm12.inl | 38 ++++ source/Lib/CommonLib/Contexts_ecm13.inl | 49 +++++ source/Lib/CommonLib/InterPrediction.cpp | 25 +++ source/Lib/CommonLib/IntraPrediction.cpp | 39 +++- source/Lib/CommonLib/IntraPrediction.h | 7 +- source/Lib/CommonLib/Slice.cpp | 1 - source/Lib/CommonLib/Slice.h | 7 + source/Lib/CommonLib/TypeDef.h | 1 + source/Lib/CommonLib/Unit.cpp | 6 + source/Lib/CommonLib/Unit.h | 3 + source/Lib/CommonLib/UnitTools.cpp | 90 ++++++++- source/Lib/CommonLib/UnitTools.h | 3 + source/Lib/DecoderLib/CABACReader.cpp | 28 ++- source/Lib/DecoderLib/CABACReader.h | 4 +- source/Lib/DecoderLib/DecCu.cpp | 28 ++- source/Lib/DecoderLib/DecSlice.h | 3 + source/Lib/DecoderLib/VLCReader.cpp | 3 + source/Lib/EncoderLib/CABACWriter.cpp | 30 ++- source/Lib/EncoderLib/CABACWriter.h | 3 + source/Lib/EncoderLib/EncCfg.h | 12 ++ source/Lib/EncoderLib/EncCu.cpp | 1 - source/Lib/EncoderLib/EncLib.cpp | 3 + source/Lib/EncoderLib/EncSlice.cpp | 16 +- source/Lib/EncoderLib/InterSearch.cpp | 227 ++++++++++++++++++++++- source/Lib/EncoderLib/InterSearch.h | 1 + source/Lib/EncoderLib/VLCWriter.cpp | 3 + 31 files changed, 631 insertions(+), 27 deletions(-) diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index f8fbb124d..a5b279385 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -1069,7 +1069,12 @@ void EncApp::xInitLibCfg() #if JVET_AF0073_INTER_CCP_MERGE m_cEncLib.setUseInterCcpMerge ( m_interCcpMerge ); m_cEncLib.setInterCcpMergeFastMode ( m_interCcpMergeFastMode ); +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + m_cEncLib.setUseInterCcpMergeZeroLumaCbf ( m_interCcpMergeZeroLumaCbf ); + m_cEncLib.setInterCcpMergeZeroLumaCbfFastMode ( m_interCcpMergeZeroLumaCbfFastMode ); #endif +#endif + // ADD_NEW_TOOL : (encoder app) add setting of tool enabling flags and associated parameters here m_cEncLib.setVirtualBoundariesEnabledFlag ( m_virtualBoundariesEnabledFlag ); if( m_cEncLib.getVirtualBoundariesEnabledFlag() ) diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 8673ac2ed..c1dd33f8a 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1309,6 +1309,10 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) #if JVET_AF0073_INTER_CCP_MERGE ("InterCcpMerge", m_interCcpMerge, true, "Cross-component prediction merge for inter prediction (0: off, 1:on) [default: on]") ("InterCcpMergeFastMode", m_interCcpMergeFastMode, 0, "Fast mode of cross-component prediction merge for inter prediction") +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + ("InterCcpMergeZeroLumaCbf", m_interCcpMergeZeroLumaCbf, true, "Cross-component prediction merge for inter prediction when lumaCbf equal to 0 (0: off, 1:on) [default: on]") + ("InterCcpMergeZeroLumaCbfFastMode", m_interCcpMergeZeroLumaCbfFastMode, 0, "Fast mode of cross-component prediction merge for inter prediction when lumaCbf equal to 0") +#endif #endif #if JVET_V0094_BILATERAL_FILTER ("BIF", m_BIF, true, "bilateral filter (0: off, 1:on) [default: on]") @@ -3124,7 +3128,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) #endif #if JVET_AF0073_INTER_CCP_MERGE m_interCcpMergeFastMode = (m_sourceHeight > 1080) ? 1 : 0; +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + m_interCcpMergeZeroLumaCbfFastMode = (m_sourceHeight < 1080) ? 1 : 0; +#endif #endif + if (m_chromaFormatIDC != CHROMA_420) { if (!m_horCollocatedChromaFlag) @@ -5881,6 +5889,9 @@ void EncAppCfg::xPrintParameter() #if JVET_AF0073_INTER_CCP_MERGE msg( VERBOSE, "InterCcpMerge:%d ", m_interCcpMerge ); #endif +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + msg( VERBOSE, "InterCcpMergeZeroLumaCbf:%d ", m_interCcpMergeZeroLumaCbf ); +#endif #if !JVET_AA0132_CONFIGURABLE_TM_TOOLS #if JVET_W0090_ARMC_TM msg( VERBOSE, "AML:%d ", m_AML ); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 2f41e4ed7..8a5dd011f 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -622,7 +622,12 @@ protected: #if JVET_AF0073_INTER_CCP_MERGE bool m_interCcpMerge; ///< Cross-component prediction merge for inter prediction int m_interCcpMergeFastMode; +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + bool m_interCcpMergeZeroLumaCbf; + int m_interCcpMergeZeroLumaCbfFastMode; #endif +#endif + #if JVET_AE0100_BVGCCCM bool m_bvgCccm; ///< Block vector guided CCCM #endif diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 2f61085e4..f648cfcf7 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -1638,6 +1638,9 @@ static const int NUM_CCP_PARAMS = CCCM_NO_SUB_NUM_PARAMS; static const int NUM_CCP_PARAMS = CCCM_NUM_PARAMS; #endif #endif +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 +static const int MAX_CCP_MERGE_WEIGHT_IDX = 2; +#endif #if JVET_AD0140_MVD_PREDICTION static const int MVD_PREDICTION_SIGN_SUFFIX_BIN_THR = 2; static const int MVD_PREDICTION_EGC_OFFSET = 1; diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h index 2ca8497de..ae31d29cc 100644 --- a/source/Lib/CommonLib/Contexts.h +++ b/source/Lib/CommonLib/Contexts.h @@ -797,6 +797,9 @@ public: #if JVET_AG0059_CCP_MERGE_ENHANCEMENT static const CtxSet CCPMergeFusionFlag; static const CtxSet CCPMergeFusionType; +#endif +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + static const CtxSet InterCcpMergeZeroRootCbfIdc; #endif static const unsigned NumberOfContexts; diff --git a/source/Lib/CommonLib/Contexts_ecm12.inl b/source/Lib/CommonLib/Contexts_ecm12.inl index e86c2e8a0..66a8f4044 100644 --- a/source/Lib/CommonLib/Contexts_ecm12.inl +++ b/source/Lib/CommonLib/Contexts_ecm12.inl @@ -4923,6 +4923,23 @@ const CtxSet ContextSetCfg::InterCccmFlag = ContextSetCfg::addCtxSet({ #if JVET_AF0073_INTER_CCP_MERGE const CtxSet ContextSetCfg::InterCcpMergeFlag = ContextSetCfg::addCtxSet({ // ctx 1585 1585 +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + { 40, CNU,}, + { 40, CNU,}, + { 35, CNU,}, + { 5, DWS,}, + { 2, DWS,}, + { 8, DWS,}, + { 25, DWE,}, + { 18, DWE,}, + { 18, DWE,}, + { 99, DWO,}, + { 98, DWO,}, + {115, DWO,}, + {162, DWO,}, + {119, DWO,}, + {119, DWO,}, +#else { 40 }, { 40 }, { 35 }, @@ -4938,8 +4955,29 @@ const CtxSet ContextSetCfg::InterCcpMergeFlag = ContextSetCfg::addCtxSet({ { 162 }, { 119 }, { 119 }, +#endif }); #endif +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 +const CtxSet ContextSetCfg::InterCcpMergeZeroRootCbfIdc = ContextSetCfg::addCtxSet +({ + { CNU, CNU, }, + { CNU, CNU, }, + { CNU, CNU, }, + { DWS, DWS, }, + { DWS, DWS, }, + { DWS, DWS, }, + { DWE, DWE, }, + { DWE, DWE, }, + { DWE, DWE, }, + { DWO, DWO, }, + { DWO, DWO, }, + { DWO, DWO, }, + { DWO, DWO, }, + { DWO, DWO, }, + { DWO, DWO, }, + }); +#endif #if JVET_AG0058_EIP const CtxSet ContextSetCfg::EipFlag = ContextSetCfg::addCtxSet diff --git a/source/Lib/CommonLib/Contexts_ecm13.inl b/source/Lib/CommonLib/Contexts_ecm13.inl index 7eed3bfce..3b62afb68 100644 --- a/source/Lib/CommonLib/Contexts_ecm13.inl +++ b/source/Lib/CommonLib/Contexts_ecm13.inl @@ -6198,6 +6198,28 @@ const CtxSet ContextSetCfg::InterCccmFlag = ContextSetCfg::addCtxSet({ #if JVET_AF0073_INTER_CCP_MERGE const CtxSet ContextSetCfg::InterCcpMergeFlag = ContextSetCfg::addCtxSet({ // ctx 1585 1585 +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + { 40, CNU,}, + { 40, CNU,}, + { 35, CNU,}, + { 40, CNU,}, + { 5, DWS,}, + { 2, DWS,}, + { 8, DWS,}, + { 5, DWS,}, + { 25, DWE,}, + { 18, DWE,}, + { 18, DWE,}, + { 25, DWE,}, + { 99, DWO,}, + { 98, DWO,}, + {115, DWO,}, + {162, DWO,}, + {119, DWO,}, + {119, DWO,}, + { 99, DWO,}, + {114, DWO,}, +#else { 40 }, { 40 }, { 35 }, @@ -6218,9 +6240,36 @@ const CtxSet ContextSetCfg::InterCcpMergeFlag = ContextSetCfg::addCtxSet({ { 119 }, { 99 }, { 114 }, +#endif }); #endif +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 +const CtxSet ContextSetCfg::InterCcpMergeZeroRootCbfIdc = ContextSetCfg::addCtxSet +({ + { CNU, CNU, }, + { CNU, CNU, }, + { CNU, CNU, }, + { CNU, CNU, }, + { DWS, DWS, }, + { DWS, DWS, }, + { DWS, DWS, }, + { DWS, DWS, }, + { DWE, DWE, }, + { DWE, DWE, }, + { DWE, DWE, }, + { DWE, DWE, }, + { DWO, DWO, }, + { DWO, DWO, }, + { DWO, DWO, }, + { DWO, DWO, }, + { DWO, DWO, }, + { DWO, DWO, }, + { DWO, DWO, }, + { DWO, DWO, }, + }); +#endif + #if JVET_AG0058_EIP const CtxSet ContextSetCfg::EipFlag = ContextSetCfg::addCtxSet ({ diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index b40470313..6c9982e03 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -37653,7 +37653,19 @@ std::vector<Mv> InterPrediction::deriveMVDFromMVSDIdxAffineSI(PredictionUnit& pu bool InterPrediction::deriveInterCcpMergePrediction( TransformUnit* tu, const PelBuf& lumaReconstruction, PelBuf& inBufCb, PelBuf& inBufCr, PelBuf& outBufCb, PelBuf& outBufCr, CCPModelCandidate interCcpMergeList[], int validNum) { PredictionUnit* pu = tu->cu->firstPU; +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + CompArea area; + if(tu->cu->interCcpMergeZeroRootCbfIdc) + { + area = tu->cu->blocks[COMPONENT_Cb]; + } + else + { + area = tu->blocks[COMPONENT_Cb]; + } +#else const CompArea &area = tu->blocks[COMPONENT_Cb]; +#endif CCPModelCandidate candList[MAX_CCP_CAND_LIST_SIZE]; tu->cu->firstPU->idxNonLocalCCP = 1; const int candIdx = tu->cu->firstPU->idxNonLocalCCP - 1; @@ -37784,9 +37796,22 @@ std::vector<Mv> InterPrediction::deriveMVDFromMVSDIdxAffineSI(PredictionUnit& pu pu->curCand = candList[candIdx]; m_pcIntraPred->combineCcpAndInter(*pu, inBufCb, inBufCr, outBufCb, outBufCr); } +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + if (pu->cu->interCcpMergeZeroRootCbfIdc) + { + pu->idxNonLocalCCP = 0; + } + else + { + tu->curCand = candList[candIdx]; + tu->cu->firstPU->curCand.type = 0; + tu->cu->firstPU->idxNonLocalCCP = 0; + } +#else tu->curCand = candList[candIdx]; tu->cu->firstPU->curCand.type = 0; tu->cu->firstPU->idxNonLocalCCP = 0; +#endif return true; } #endif diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp index 57b1fcc33..d29044c58 100644 --- a/source/Lib/CommonLib/IntraPrediction.cpp +++ b/source/Lib/CommonLib/IntraPrediction.cpp @@ -11196,8 +11196,13 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom const int topTemplateSampNum = 2 * uiCWidth; // for MDLM, the number of template samples is 2W or 2H. const int leftTemplateSampNum = 2 * uiCHeight; #if JVET_AF0073_INTER_CCP_MERGE +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + assert((!pu.cu->rootCbf) || (pu.cu->firstTU->interCcpMerge) || (m_topRefLength >= topTemplateSampNum)); + assert((!pu.cu->rootCbf) || (pu.cu->firstTU->interCcpMerge) || (m_leftRefLength >= leftTemplateSampNum)); +#else assert((pu.cu->firstTU->interCcpMerge) || (m_topRefLength >= topTemplateSampNum)); assert((pu.cu->firstTU->interCcpMerge) || (m_leftRefLength >= leftTemplateSampNum)); +#endif #else assert(m_topRefLength >= topTemplateSampNum); assert(m_leftRefLength >= leftTemplateSampNum); @@ -17584,7 +17589,6 @@ int IntraPrediction::xGetOneCCPCandCost( PredictionUnit &pu, CCPModelCandidate & void IntraPrediction::predCCPCandidate(PredictionUnit &pu, PelBuf &predCb, PelBuf &predCr) { const int bitDepth = pu.cu->slice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA); - if (pu.idxNonLocalCCP) { CompArea chromaArea = pu.Cb(); @@ -18183,13 +18187,20 @@ void IntraPrediction::selectCcpMergeCand(PredictionUnit& pu, CCPModelCandidate c } return; } -void IntraPrediction::combineCcpAndInter(PredictionUnit& pu, PelBuf& inPredCb, PelBuf& inPredCr, PelBuf& outPredCb, PelBuf& outPredCr) +void IntraPrediction::combineCcpAndInter(PredictionUnit& pu, PelBuf& inPredCb, PelBuf& inPredCr, PelBuf& outPredCb, PelBuf& outPredCr +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + , bool useExistCcp +#endif +) { CompArea chromaArea = pu.Cb(); int predCbStride = MAX_CU_SIZE + 1; PelBuf predCbIntra = PelBuf(m_pCcpMerge[0] + predCbStride + 1, predCbStride, Size(chromaArea)); int predCrStride = MAX_CU_SIZE + 1; PelBuf predCrIntra = PelBuf(m_pCcpMerge[1] + predCrStride + 1, predCrStride, Size(chromaArea)); +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + if (!useExistCcp) +#endif predCCPCandidate(pu, predCbIntra, predCrIntra); Pel* predCbIntraBuf = predCbIntra.buf; @@ -18209,12 +18220,36 @@ void IntraPrediction::combineCcpAndInter(PredictionUnit& pu, PelBuf& inPredCb, P const ClpRng& clpRngCb = pu.cu->cs->slice->clpRng(COMPONENT_Cb); const ClpRng& clpRngCr = pu.cu->cs->slice->clpRng(COMPONENT_Cr); +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + constexpr int shift = 2; + constexpr int offset = shift << 1 >> 1; + constexpr int one = 1 << shift; + constexpr int ccpWeighting[one + 1] = { 0, 3, 4, 1, 2 }; + CHECK(pu.cu->interCcpMergeZeroRootCbfIdc > MAX_CCP_MERGE_WEIGHT_IDX, "Wrong interCcpMergeZeroRootCbfIdc"); + const auto tu = *pu.cu->firstTU; + const bool lumaCbf = TU::getCbf(tu, COMPONENT_Y); + int wCc = 3; + if (tu.interCcpMerge) + { + wCc = lumaCbf || MAX_CCP_MERGE_WEIGHT_IDX == 1 ? 3 : 4; + } + else + { + wCc = ccpWeighting[pu.cu->interCcpMergeZeroRootCbfIdc]; + } + const int wInter = one - wCc; +#endif for (int cntH = 0; cntH < outPredCb.height; cntH++) { for (int cntW = 0; cntW < outPredCb.width; cntW++) { +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + predCbDstBuf[cntH * predCbDstStride + cntW] = ClipPel(((wCc * predCbIntraBuf[cntH * predCbIntraStride + cntW] + wInter * predCbInterBuf[cntH * predCbInterStride + cntW] + offset) >> shift), clpRngCb); + predCrDstBuf[cntH * predCrDstStride + cntW] = ClipPel(((wCc * predCrIntraBuf[cntH * predCrIntraStride + cntW] + wInter * predCrInterBuf[cntH * predCrInterStride + cntW] + offset) >> shift), clpRngCr); +#else predCbDstBuf[cntH * predCbDstStride + cntW] = ClipPel(((3 * predCbIntraBuf[cntH * predCbIntraStride + cntW] + predCbInterBuf[cntH * predCbInterStride + cntW] + 2) >> 2), clpRngCb); predCrDstBuf[cntH * predCrDstStride + cntW] = ClipPel(((3 * predCrIntraBuf[cntH * predCrIntraStride + cntW] + predCrInterBuf[cntH * predCrInterStride + cntW] + 2) >> 2), clpRngCr); +#endif } } } diff --git a/source/Lib/CommonLib/IntraPrediction.h b/source/Lib/CommonLib/IntraPrediction.h index eb8b6da01..d5549712c 100644 --- a/source/Lib/CommonLib/IntraPrediction.h +++ b/source/Lib/CommonLib/IntraPrediction.h @@ -250,6 +250,7 @@ public: uint8_t m_intraMPM[NUM_MOST_PROBABLE_MODES]; uint8_t m_intraNonMPM[NUM_NON_MPM_MODES]; #endif + protected: #if JVET_AC0094_REF_SAMPLES_OPT Pel m_refBuffer[MAX_NUM_COMPONENT][NUM_PRED_BUF][((MAX_CU_SIZE << 3) + 1 + MAX_REF_LINE_IDX) * 2]; @@ -729,7 +730,11 @@ public: void xAddOnTheFlyCalcCCPCands4InterBlk(const PredictionUnit &pu, CompArea chromaArea, CCPModelCandidate candList[], int &validNum); void selectCcpMergeCand(PredictionUnit &pu, CCPModelCandidate candList[], int reorderlistSize); - void combineCcpAndInter(PredictionUnit &pu, PelBuf &inPredCb, PelBuf &inPredCr, PelBuf &outPredCb, PelBuf &outPredCr); + void combineCcpAndInter(PredictionUnit &pu, PelBuf &inPredCb, PelBuf &inPredCr, PelBuf &outPredCb, PelBuf &outPredCr +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + , bool useExistCcp = false +#endif + ); #endif #if ENABLE_DIMD diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index bcdf4383d..eb9c43a78 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -224,7 +224,6 @@ void Slice::initSlice() m_biDirPred = false; m_symRefIdx[0] = -1; m_symRefIdx[1] = -1; - for (uint32_t component = 0; component < MAX_NUM_COMPONENT; component++) { m_iSliceChromaQpDelta[component] = 0; diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 1837666f9..73b38bf22 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1850,6 +1850,9 @@ private: #if JVET_AF0073_INTER_CCP_MERGE bool m_interCcpMerge; +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + bool m_interCcpMergeZeroLumaCbf; +#endif #endif #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET @@ -2564,6 +2567,10 @@ void setCCALFEnabledFlag( bool b ) #if JVET_AF0073_INTER_CCP_MERGE void setUseInterCcpMerge ( bool b ) { m_interCcpMerge = b; } bool getUseInterCcpMerge () const { return m_interCcpMerge; } +#endif +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + void setUseInterCcpMergeZeroLumaCbf ( bool b ) { m_interCcpMergeZeroLumaCbf = b; } + bool getUseInterCcpMergeZeroLumaCbf () const { return m_interCcpMergeZeroLumaCbf; } #endif void setUseMRL ( bool b ) { m_MRL = b; } bool getUseMRL () const { return m_MRL; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 25a24b186..72561986a 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -333,6 +333,7 @@ #define JVET_AG0067_DMVR_EXTENSIONS 1 // JVET-AG0067: On DMVR Extensions #define JVET_AH0069_CMVP 1 // JVET-AH0069: Chained motion vector prediction #define JVET_AH0314_ADAPTIVE_GPM_BLENDING_IMPROV 1 // JVET-AH0314: Adaptive GPM blending +#define JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 1 // JVET-AH0066 & JVET-AH0202: Inter CCP merge mode with zero luma CBF // Inter template matching tools #define ENABLE_INTER_TEMPLATE_MATCHING 1 // It controls whether template matching is enabled for inter prediction diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 4e0de0fe5..a051d7c65 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -262,6 +262,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other ) mtDepth = other.mtDepth; splitSeries = other.splitSeries; skip = other.skip; +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + interCcpMergeZeroRootCbfIdc = other.interCcpMergeZeroRootCbfIdc; +#endif mmvdSkip = other.mmvdSkip; affine = other.affine; affineType = other.affineType; @@ -517,6 +520,9 @@ void CodingUnit::initData() mtDepth = 0; splitSeries = 0; skip = false; +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + interCcpMergeZeroRootCbfIdc = 0; +#endif mmvdSkip = false; affine = false; affineType = 0; diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index b20c7c12d..769b3c2b2 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -307,6 +307,9 @@ struct CodingUnit : public UnitArea ModeTypeSeries modeTypeSeries; #endif bool skip; +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + int8_t interCcpMergeZeroRootCbfIdc; +#endif bool mmvdSkip; bool affine; int8_t affineType; diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index d1f97ce9a..dc517dba0 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -1093,38 +1093,107 @@ bool CU::interCcpMergeSearchAllowed(const CodingUnit& cu) { return false; } - if (cu.predMode != MODE_INTER) + +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + if (!cu.cs->slice->getSPS()->getUseInterCcpMergeZeroLumaCbf()) + { +#endif + if (cu.predMode != MODE_INTER) + { + return false; + } + if (cu.blocks[COMPONENT_Cb].area() < 16) + { + return false; + } + if (cu.firstTU->blocks[COMPONENT_Cb].width != cu.blocks[COMPONENT_Cb].width || cu.firstTU->blocks[COMPONENT_Cb].height != cu.blocks[COMPONENT_Cb].height) + { + return false; + } + if (!cu.firstTU->blocks[COMPONENT_Cb].valid()) + { + return false; + } + if (!cu.firstTU->blocks[COMPONENT_Cr].valid()) + { + return false; + } + if (cu.blocks[COMPONENT_Cb].area() > 1024) + { + return false; + } + if (!cu.firstPU->mergeFlag) + { + return false; + } +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + } + else + { + if (!cu.firstTU->blocks[COMPONENT_Cb].valid()) + { + return false; + } + if (!cu.firstTU->blocks[COMPONENT_Cr].valid()) + { + return false; + } + if (cu.firstTU->blocks[COMPONENT_Cb].width != cu.blocks[COMPONENT_Cb].width || cu.firstTU->blocks[COMPONENT_Cb].height != cu.blocks[COMPONENT_Cb].height) + { + return false; + } + if (cu.predMode != MODE_INTER) + { + return false; + } + if (!cu.firstPU->mergeFlag && (cu.blocks[COMPONENT_Cb].area() < 16 || cu.blocks[COMPONENT_Cb].area() > 1024)) + { + return false; + } + } +#endif + + return true; +} +#endif + +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 +bool CU::interCcpMergeZeroRootCbfAllowed(const CodingUnit& cu) +{ + if (!cu.cs->slice->getSPS()->getUseInterCcpMerge()) { return false; } - if (cu.blocks[COMPONENT_Cb].area() < 16) + if (!cu.cs->slice->getSPS()->getUseInterCcpMergeZeroLumaCbf()) { return false; } - if (cu.firstTU->blocks[COMPONENT_Cb].width != cu.blocks[COMPONENT_Cb].width || cu.firstTU->blocks[COMPONENT_Cb].height != cu.blocks[COMPONENT_Cb].height) + if(cu.rootCbf) { return false; } - if (!cu.firstTU->blocks[COMPONENT_Cb].valid()) + if (cu.colorTransform) { return false; } - if (!cu.firstTU->blocks[COMPONENT_Cr].valid()) + if (cu.chromaFormat == CHROMA_400 || !cu.blocks[COMPONENT_Cb].valid()) { return false; } - if (cu.blocks[COMPONENT_Cb].area() > 1024) + if (cu.predMode != MODE_INTER) { return false; } - if (!cu.firstPU->mergeFlag) + if (!cu.slice->getCheckLDB() && !cu.skip && cu.blocks[COMPONENT_Cb].area() > 1024) { return false; } + return true; } #endif + #if JVET_AC0094_REF_SAMPLES_OPT void CU::getNbModesRemovedFirstLast(const bool &areAboveRightUnavail, const bool &areBelowLeftUnavail, const SizeType &height, const SizeType &width, int &nbRemovedFirst, int &nbRemovedLast) { @@ -28452,14 +28521,21 @@ bool TU::interCcpMergeAllowed(const TransformUnit& tu) { return false; } + if (!CU::interCcpMergeSearchAllowed(*tu.cu)) { return false; } +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + if ((!tu.cs->slice->getSPS()->getUseInterCcpMergeZeroLumaCbf() && !TU::getCbf(tu, COMPONENT_Y)) || + (tu.cs->slice->getSPS()->getUseInterCcpMergeZeroLumaCbf() && TU::getCbf(tu, COMPONENT_Y) && tu.cu->blocks[COMPONENT_Cb].area() > 1024 && !tu.cu->slice->getCheckLDB())) +#else if (!TU::getCbf(tu, COMPONENT_Y)) +#endif { return false; } + return true; } #endif diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 9c02f9385..7e0a44301 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -192,6 +192,9 @@ namespace CU #if JVET_AG0112_REGRESSION_BASED_GPM_BLENDING bool isGeoBlendAvailable(const CodingUnit& cu); #endif +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + bool interCcpMergeZeroRootCbfAllowed(const CodingUnit& cu); +#endif } // PU tools namespace PU diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index fe70ad864..c394fb3f0 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -1239,7 +1239,6 @@ void CABACReader::cu_skip_flag( CodingUnit& cu ) cu.rootCbf = false; cu.predMode = MODE_INTRA; cu.mmvdSkip = false; - #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS if( !cu.slice->getSPS()->getUseIbcMerge() ) { @@ -1350,6 +1349,12 @@ void CABACReader::cu_skip_flag( CodingUnit& cu ) cu.rootCbf = false; cu.predMode = MODE_INTER; } +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + if (skip && CU::interCcpMergeZeroRootCbfAllowed(cu)) + { + inter_ccp_merge_root_cbf_zero(cu); + } +#endif } void CABACReader::imv_mode( CodingUnit& cu, MergeCtx& mrgCtx ) @@ -3035,6 +3040,13 @@ void CABACReader::cu_residual( CodingUnit& cu, Partitioner &partitioner, CUCtx& { cu.colorTransform = false; cu.cs->addEmptyTUs( partitioner ); +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + cu.interCcpMergeZeroRootCbfIdc = 0; + if (CU::interCcpMergeZeroRootCbfAllowed(cu)) + { + inter_ccp_merge_root_cbf_zero(cu); + } +#endif return; } } @@ -3111,6 +3123,15 @@ void CABACReader::rqt_root_cbf( CodingUnit& cu ) DTRACE( g_trace_ctx, D_SYNTAX, "rqt_root_cbf() ctx=0 root_cbf=%d pos=(%d,%d)\n", cu.rootCbf ? 1 : 0, cu.lumaPos().x, cu.lumaPos().y ); } +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 +void CABACReader::inter_ccp_merge_root_cbf_zero(CodingUnit &cu) +{ + cu.interCcpMergeZeroRootCbfIdc = unary_max_symbol(Ctx::InterCcpMergeZeroRootCbfIdc(0), Ctx::InterCcpMergeZeroRootCbfIdc(1), + MAX_CCP_MERGE_WEIGHT_IDX); + DTRACE(g_trace_ctx, D_SYNTAX, "inter_ccp_merge_root_cbf_zero() pos=(%d,%d) inter_ccp_merge_root_cbf_zero_flag=%d\n", cu.blocks[cu.chType].x, cu.blocks[cu.chType].y, cu.interCcpMergeZeroRootCbfIdc); +} +#endif + void CABACReader::adaptive_color_transform(CodingUnit& cu) { if (!cu.slice->getSPS()->getUseColorTrans()) @@ -8264,6 +8285,7 @@ void CABACReader::transform_unit(TransformUnit& tu, CUCtx& cuCtx, Partitioner& p TU::setCbfAtDepth(tu, COMPONENT_Cb, trDepth, (chromaCbfs.Cb ? 1 : 0)); TU::setCbfAtDepth(tu, COMPONENT_Cr, trDepth, (chromaCbfs.Cr ? 1 : 0)); } + bool lumaOnly = (cu.chromaFormat == CHROMA_400 || !tu.blocks[COMPONENT_Cb].valid()); bool cbfLuma = (tu.cbf[COMPONENT_Y] != 0); bool cbfChroma = (lumaOnly ? false : (chromaCbfs.Cb || chromaCbfs.Cr)); @@ -10021,7 +10043,11 @@ void CABACReader::interCcpMerge(TransformUnit& tu) { if (TU::interCcpMergeAllowed(tu)) { +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + tu.interCcpMerge = m_BinDecoder.decodeBin(Ctx::InterCcpMergeFlag(tu.cbf[COMPONENT_Y] ? 0 : 1)); +#else tu.interCcpMerge = m_BinDecoder.decodeBin(Ctx::InterCcpMergeFlag(0)); +#endif DTRACE(g_trace_ctx, D_SYNTAX, "inter_ccp_merge() pos=(%d,%d) inter_ccp_merge_flag=%d\n", tu.blocks[tu.chType].x, tu.blocks[tu.chType].y, tu.interCcpMerge); } } diff --git a/source/Lib/DecoderLib/CABACReader.h b/source/Lib/DecoderLib/CABACReader.h index 76bb3c56a..1465c72a7 100644 --- a/source/Lib/DecoderLib/CABACReader.h +++ b/source/Lib/DecoderLib/CABACReader.h @@ -149,7 +149,9 @@ public: #endif void cu_residual ( CodingUnit& cu, Partitioner& pm, CUCtx& cuCtx ); void rqt_root_cbf ( CodingUnit& cu ); - +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + void inter_ccp_merge_root_cbf_zero( CodingUnit& cu ); +#endif void adaptive_color_transform(CodingUnit& cu); void sbt_mode ( CodingUnit& cu ); void end_of_ctu ( CodingUnit& cu, CUCtx& cuCtx ); diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 467f5d0c7..13a54cf83 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -270,6 +270,7 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) } #endif } + switch( currCU.predMode ) { case MODE_INTER: @@ -566,7 +567,6 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) THROW( "Invalid prediction mode" ); break; } - m_pcInterPred->xFillIBCBuffer(currCU); #if JVET_Z0118_GDR // decompressCtu cs.updateReconMotIPM( currCU ); // decompressCtu : need @@ -2478,7 +2478,6 @@ void DecCu::xDecodeInterTexture(CodingUnit &cu) { cs.getRecoBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT()); } - #if JVET_AG0145_ADAPTIVE_CLIPPING ClpRng clpRng = cs.slice->clpRng(COMPONENT_Y); if (cs.slice->getSPS()->getUseLmcs() && cs.slice->getLmcsEnabledFlag()) @@ -2494,10 +2493,33 @@ void DecCu::xDecodeInterTexture(CodingUnit &cu) } cs.getRecoBuf(cu).get(COMPONENT_Y).reconstruct(cs.getRecoBuf(cu).get(COMPONENT_Y), cs.getResiBuf(cu).get(COMPONENT_Y), clpRng); #endif +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + if (CU::isIBC(cu) && cu.rribcFlipType) + { + cu.cs->getRecoBuf(cu).get(COMPONENT_Y).flipSignal(cu.rribcFlipType == 1); + } + if (cu.interCcpMergeZeroRootCbfIdc) + { + int validNum = 0; + CCPModelCandidate interCcpMergeList[MAX_CCP_CAND_LIST_SIZE]; + m_pcIntraPred->xAddOnTheFlyCalcCCPCands4InterBlk(*cu.firstPU, cu.blocks[COMPONENT_Cb], interCcpMergeList, validNum); + PelBuf bufCb = cs.getPredBuf( cu.blocks[COMPONENT_Cb] ); + PelBuf bufCr = cs.getPredBuf( cu.blocks[COMPONENT_Cr] ); + const bool valid = m_pcInterPred->deriveInterCcpMergePrediction(cu.firstTU, cs.getRecoBuf(cu.blocks[COMPONENT_Y]), bufCb, bufCr, bufCb, bufCr, interCcpMergeList, validNum); + CHECK( !valid, "invalid inter ccp merge for rootCbf = 0" ); + cs.getRecoBuf(cu.blocks[COMPONENT_Cb]).copyClip(cs.getPredBuf(cu.blocks[COMPONENT_Cb]), cs.slice->clpRng(COMPONENT_Cb)); + cs.getRecoBuf(cu.blocks[COMPONENT_Cr]).copyClip(cs.getPredBuf(cu.blocks[COMPONENT_Cr]), cs.slice->clpRng(COMPONENT_Cr)); + cu.firstPU->idxNonLocalCCP = 0; + cu.firstTU->curCand ={}; + cu.firstTU->curCand.type = CCP_TYPE_NONE; + } +#endif #if JVET_AA0070_RRIBC if (CU::isIBC(cu) && cu.rribcFlipType) { +#if !JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 cu.cs->getRecoBuf(cu).get(COMPONENT_Y).flipSignal(cu.rribcFlipType == 1); +#endif if (isChromaEnabled(cu.chromaFormat) && cu.Cb().valid()) { cu.cs->getRecoBuf(cu).get(COMPONENT_Cb).flipSignal(cu.rribcFlipType == 1); @@ -2506,8 +2528,6 @@ void DecCu::xDecodeInterTexture(CodingUnit &cu) } #endif #endif - - return; } diff --git a/source/Lib/DecoderLib/DecSlice.h b/source/Lib/DecoderLib/DecSlice.h index bb75c9e3c..edd6c74a0 100644 --- a/source/Lib/DecoderLib/DecSlice.h +++ b/source/Lib/DecoderLib/DecSlice.h @@ -46,6 +46,9 @@ #include "CommonLib/BitStream.h" #include "DecCu.h" #include "CABACReader.h" +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 +using namespace std; +#endif //! \ingroup DecoderLib //! \{ diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 5187e816c..208049f3b 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -2656,6 +2656,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) #if JVET_AG0058_EIP READ_FLAG(uiCode, "sps_eip_enabled_flag"); pcSPS->setUseEip(uiCode != 0); #endif +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + READ_FLAG(uiCode, "sps_inter_ccp_merge_zero_luma_cbf"); pcSPS->setUseInterCcpMergeZeroLumaCbf( uiCode != 0 ); +#endif #if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL if (pcSPS->getTMnoninterToolsEnableFlag()) { diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index b3286014d..f29cb4a1f 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -955,8 +955,8 @@ void CABACWriter::cu_skip_flag( const CodingUnit& cu ) if (cu.lwidth() < 128 && cu.lheight() < 128) // disable IBC mode larger than 64x64 { - m_BinEncoder.encodeBin((cu.skip), Ctx::SkipFlag(ctxId)); - DTRACE(g_trace_ctx, D_SYNTAX, "cu_skip_flag() ctx=%d skip=%d\n", ctxId, cu.skip ? 1 : 0); + m_BinEncoder.encodeBin((cu.skip), Ctx::SkipFlag(ctxId)); + DTRACE(g_trace_ctx, D_SYNTAX, "cu_skip_flag() ctx=%d skip=%d\n", ctxId, cu.skip ? 1 : 0); } return; } @@ -1014,9 +1014,14 @@ void CABACWriter::cu_skip_flag( const CodingUnit& cu ) DTRACE(g_trace_ctx, D_SYNTAX, "ibc() ctx=%d cu.predMode=%d\n", ctxidx, cu.predMode); } } +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + if (cu.skip && CU::interCcpMergeZeroRootCbfAllowed(cu)) + { + inter_ccp_merge_root_cbf_zero(cu); + } +#endif } - void CABACWriter::pred_mode( const CodingUnit& cu ) { #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS @@ -2681,6 +2686,12 @@ void CABACWriter::cu_residual( const CodingUnit& cu, Partitioner& partitioner, C if( !cu.rootCbf ) { +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + if (CU::interCcpMergeZeroRootCbfAllowed(cu)) + { + inter_ccp_merge_root_cbf_zero(cu); + } +#endif CHECK(cu.colorTransform, "ACT should not be enabled for root_cbf = 0"); return; } @@ -2764,6 +2775,15 @@ void CABACWriter::rqt_root_cbf( const CodingUnit& cu ) DTRACE( g_trace_ctx, D_SYNTAX, "rqt_root_cbf() ctx=0 root_cbf=%d pos=(%d,%d)\n", cu.rootCbf ? 1 : 0, cu.lumaPos().x, cu.lumaPos().y ); } +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 +void CABACWriter::inter_ccp_merge_root_cbf_zero(const CodingUnit &cu) +{ + unary_max_symbol(cu.interCcpMergeZeroRootCbfIdc, Ctx::InterCcpMergeZeroRootCbfIdc(0), + Ctx::InterCcpMergeZeroRootCbfIdc(1), MAX_CCP_MERGE_WEIGHT_IDX); + DTRACE(g_trace_ctx, D_SYNTAX, "inter_ccp_merge_root_cbf_zero() pos=(%d,%d) inter_ccp_merge_root_cbf_zero_flag=%d\n", cu.blocks[cu.chType].x, cu.blocks[cu.chType].y, cu.interCcpMergeZeroRootCbfIdc > 0 ? 1 : 0); +} +#endif + void CABACWriter::adaptive_color_transform(const CodingUnit& cu) { if (!cu.slice->getSPS()->getUseColorTrans()) @@ -9929,7 +9949,11 @@ void CABACWriter::interCcpMerge(const TransformUnit& tu) { if (TU::interCcpMergeAllowed(tu)) { +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + m_BinEncoder.encodeBin(tu.interCcpMerge > 0 ? 1 : 0, Ctx::InterCcpMergeFlag(tu.cbf[COMPONENT_Y] ? 0 : 1)); +#else m_BinEncoder.encodeBin(tu.interCcpMerge > 0 ? 1 : 0, Ctx::InterCcpMergeFlag(0)); +#endif DTRACE(g_trace_ctx, D_SYNTAX, "inter_ccp_merge() pos=(%d,%d) inter_ccp_merge_flag=%d\n", tu.blocks[tu.chType].x, tu.blocks[tu.chType].y, tu.interCcpMerge > 0 ? 1 : 0); } } diff --git a/source/Lib/EncoderLib/CABACWriter.h b/source/Lib/EncoderLib/CABACWriter.h index 2627ae635..598949f2a 100644 --- a/source/Lib/EncoderLib/CABACWriter.h +++ b/source/Lib/EncoderLib/CABACWriter.h @@ -163,6 +163,9 @@ public: void cu_residual ( const CodingUnit& cu, Partitioner& pm, CUCtx& cuCtx ); void rqt_root_cbf ( const CodingUnit& cu ); +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + void inter_ccp_merge_root_cbf_zero(const CodingUnit& cu); +#endif void adaptive_color_transform(const CodingUnit& cu); void sbt_mode ( const CodingUnit& cu ); void end_of_ctu ( const CodingUnit& cu, CUCtx& cuCtx ); diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 210f16fdf..2f0ffbe9d 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -1044,7 +1044,12 @@ protected: #if JVET_AF0073_INTER_CCP_MERGE bool m_interCcpMerge; int m_interCcpMergeFastMode; +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + bool m_interCcpMergeZeroLumaCbf; + int m_interCcpMergeZeroLumaCbfFastMode; #endif +#endif + #if JVET_AE0100_BVGCCCM bool m_bvgCccm; #endif @@ -1865,7 +1870,14 @@ public: bool getUseInterCcpMerge() const { return m_interCcpMerge; } void setInterCcpMergeFastMode(int currMode) { m_interCcpMergeFastMode = currMode; } int getInterCcpMergeFastMode() const { return m_interCcpMergeFastMode; } +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + void setUseInterCcpMergeZeroLumaCbf(bool b) { m_interCcpMergeZeroLumaCbf = b; } + bool getUseInterCcpMergeZeroLumaCbf() const { return m_interCcpMergeZeroLumaCbf; } + void setInterCcpMergeZeroLumaCbfFastMode(int currMode) { m_interCcpMergeZeroLumaCbfFastMode = currMode; } + bool getInterCcpMergeZeroLumaCbfFastMode() const { return m_interCcpMergeZeroLumaCbfFastMode; } #endif +#endif + #if JVET_V0094_BILATERAL_FILTER void setUseBIF ( bool b ) { m_BIF = b; } bool getUseBIF () const { return m_BIF; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 8438496e6..f9b563790 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -3421,7 +3421,6 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS } } } //trGrpIdx - if(!adaptiveColorTrans) m_modeCtrl->setBestNonDCT2Cost(bestNonDCT2Cost); return foundZeroRootCbf; diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index f1ee20cc4..6b3710387 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -2099,6 +2099,9 @@ void EncLib::xInitSPS( SPS& sps ) #endif #if JVET_AF0073_INTER_CCP_MERGE sps.setUseInterCcpMerge(m_interCcpMerge); +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + sps.setUseInterCcpMergeZeroLumaCbf(m_interCcpMergeZeroLumaCbf); +#endif #endif // ADD_NEW_TOOL : (encoder lib) set tool enabling flags and associated parameters here sps.setUseISP ( m_ISP ); diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index cecad938a..e7b8689fe 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -2015,7 +2015,7 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons prevQP[0] = prevQP[1] = pcSlice->getSliceQp(); -#if (JVET_AC0335_CONTENT_ADAPTIVE_OBMC_ENABLING && ENABLE_OBMC) || JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS +#if (JVET_AC0335_CONTENT_ADAPTIVE_OBMC_ENABLING && ENABLE_OBMC) || JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS || JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 int hashBlkHitPerc = -1; #endif @@ -2059,6 +2059,7 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons } } #endif + #if JVET_AE0159_FIBC if (m_pcCuEncoder->getEncCfg()->getIbcFilter()) { @@ -2080,6 +2081,19 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons #endif } #endif + +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + if (m_pcCuEncoder->getEncCfg()->getUseInterCcpMerge()) + { + if (cs.slice->getPOC() == 0 || cs.slice->getSliceType() == I_SLICE) // ensure sequential and parallel simulation generate same output + { + hashBlkHitPerc = (hashBlkHitPerc == -1) ? m_pcCuEncoder->getIbcHashMap().calHashBlkMatchPerc(cs.area.Y()) : hashBlkHitPerc; + SPS* spsTmp = const_cast<SPS*>(cs.sps); + spsTmp->setUseInterCcpMergeZeroLumaCbf(hashBlkHitPerc > 40); + } + } +#endif + #if JVET_AD0188_CCP_MERGE if ((pCfg->getSwitchPOC() != pcPic->poc || -1 == pCfg->getDebugCTU())) { diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index fce10e84a..a3b4d7206 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -13026,7 +13026,18 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par { interCcpMergeOrgResiBuf[i-1] = PelBuf(m_interCcpMergeStorage[i+1], tu.blocks[ComponentID(i)]); } +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + bool interCcpMergeRdSearch = luma && chroma && !colorTransFlag && CU::interCcpMergeSearchAllowed(*tu.cu); + if (cu.slice->getSPS()->getUseInterCcpMergeZeroLumaCbf() && interCcpMergeRdSearch && m_pcEncCfg->getInterCcpMergeZeroLumaCbfFastMode()) + { + if (tu.cu->blocks[COMPONENT_Cb].area() < 16 || tu.cu->blocks[COMPONENT_Cb].area() > 1024) + { + interCcpMergeRdSearch = false; + } + } +#else const bool interCcpMergeRdSearch = luma && chroma && !colorTransFlag && CU::interCcpMergeSearchAllowed(*tu.cu); +#endif bool interCcpMergeOk = false; bool lumaRecoReady = false; bool skipInterCccm2 = false; @@ -13318,7 +13329,12 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par #if JVET_AF0073_INTER_CCP_MERGE if (tu.interCcpMerge && compID == COMPONENT_Cb) { +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + if ((!tu.cs->slice->getSPS()->getUseInterCcpMergeZeroLumaCbf() && !TU::getCbf(tu, COMPONENT_Y)) || + (tu.cs->slice->getSPS()->getUseInterCcpMergeZeroLumaCbf() && TU::getCbf(tu, COMPONENT_Y) && tu.cu->blocks[COMPONENT_Cb].area() > 1024 && !tu.cu->slice->getCheckLDB())) +#else if (!TU::getCbf(tu, COMPONENT_Y)) +#endif { break; } @@ -13329,7 +13345,23 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par { lumaPredBuf.rspSignal(m_pcReshape->getFwdLUT()); } +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 && JVET_AG0145_ADAPTIVE_CLIPPING + ClpRng clpRng = tu.cs->slice->clpRng(COMPONENT_Y); + if (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) + { + std::vector<Pel>& fwdLUT = m_pcReshape->getFwdLUT(); + clpRng.min = fwdLUT[tu.cu->cs->slice->getLumaPelMin()]; + clpRng.max = fwdLUT[tu.cu->cs->slice->getLumaPelMax()]; + } + else + { + clpRng.min = tu.cu->cs->slice->getLumaPelMin(); + clpRng.max = tu.cu->cs->slice->getLumaPelMax(); + } + lumaRecoBuf.reconstruct(lumaPredBuf, csFull->getResiBuf(tu.blocks[COMPONENT_Y]), clpRng); +#else lumaRecoBuf.reconstruct(lumaPredBuf, csFull->getResiBuf(tu.blocks[COMPONENT_Y]), cs.slice->clpRng(COMPONENT_Y)); +#endif if (CU::isIBC(cu) && cu.rribcFlipType) { lumaRecoBuf.flipSignal(cu.rribcFlipType == 1); @@ -14058,7 +14090,12 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par } } #if JVET_AF0073_INTER_CCP_MERGE - if (interCccmRdSearch && interCcpMergeRdSearch && interCccm == 1) + if (interCccmRdSearch && interCcpMergeRdSearch && interCccm == 1 +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + && ( !tu.cs->slice->getSPS()->getUseInterCcpMergeZeroLumaCbf() || TU::getCbf(tu, COMPONENT_Y)) +#endif + ) + { const double reducedCurCost = curCost - (curCost / 2.0); if (reducedCurCost > bestCost) @@ -14720,6 +14757,15 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa CHECK(cu.modeType != MODE_TYPE_ALL || partitioner.modeType != MODE_TYPE_ALL, "localtree should not be applied when adaptive color transform is enabled"); } #endif +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + cu.interCcpMergeZeroRootCbfIdc = false; + PelBuf interCcpMergePredBuf[2]; + for( int i = 1; i < MAX_NUM_COMPONENT; i++ ) + { + interCcpMergePredBuf[i-1] = PelBuf( m_interCcpMergeStorage[i-1], cu.blocks[ComponentID(i)] ); // borrow the interCcpMergeStorage + } +#endif + if( skipResidual ) // No residual coding : SKIP mode { cu.skip = true; @@ -14769,7 +14815,9 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa // add empty TU(s) cs.addEmptyTUs( partitioner ); Distortion distortion = 0; - +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + Distortion distortionLuma = 0; +#endif for (int comp = 0; comp < numValidComponents; comp++) { const ComponentID compID = ComponentID(comp); @@ -14798,8 +14846,85 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa else #endif distortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE ); +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + if(compID == COMPONENT_Y) + { + distortionLuma = distortion; + } +#endif } +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + bool isInterCcpMergeRootCbfZeroAllowed = CU::interCcpMergeZeroRootCbfAllowed(cu); + if(isInterCcpMergeRootCbfZeroAllowed && m_pcEncCfg->getInterCcpMergeZeroLumaCbfFastMode()) + { + if(cu.blocks[COMPONENT_Cb].area() < 16 || cu.blocks[COMPONENT_Cb].area() > 1024) + { + if ((cu.skip && !cu.slice->getCheckLDB()) || !cu.skip) + { + isInterCcpMergeRootCbfZeroAllowed = false; + } + } + } + + if (isInterCcpMergeRootCbfZeroAllowed) + { + PelBuf bufCb = cs.getPredBuf( cu.blocks[COMPONENT_Cb] ); + PelBuf bufCr = cs.getPredBuf( cu.blocks[COMPONENT_Cr] ); + if (m_isInterCcpModelReady == false) + { + m_pcIntraPred->xAddOnTheFlyCalcCCPCands4InterBlk(*cu.firstPU, cu.blocks[COMPONENT_Cb], m_interCcpMergeList, m_validNum); + m_isInterCcpModelReady = true; + } + const TempCtx ctxStart(m_ctxCache, m_CABACEstimator->getCtx()); + double bestCost = MAX_DOUBLE; + int8_t bestWIdx = 0; + for (int8_t wIdx = 0; wIdx <= MAX_CCP_MERGE_WEIGHT_IDX; wIdx++) + { + cu.interCcpMergeZeroRootCbfIdc = wIdx; + if (wIdx == 0) + { + const bool valid = deriveInterCcpMergePrediction(cu.firstTU, cs.getRecoBuf(cu.blocks[COMPONENT_Y]), bufCb, bufCr, interCcpMergePredBuf[0], interCcpMergePredBuf[1], m_interCcpMergeList, m_validNum); + CHECK(!valid, "invalid inter ccp merge for rootCbf = 0"); + } + else + { + m_pcIntraPred->combineCcpAndInter(*cu.firstPU, bufCb, bufCr, interCcpMergePredBuf[0], interCcpMergePredBuf[1], true); + } +#if JVET_AA0070_RRIBC + if (CU::isIBC(cu) && cu.rribcFlipType) + { + interCcpMergePredBuf[0].flipSignal(cu.rribcFlipType == 1); + interCcpMergePredBuf[1].flipSignal(cu.rribcFlipType == 1); + } +#endif + Distortion distortionChromaTmp = 0; + for (int comp = 1; comp < numValidComponents; comp++) + { + const ComponentID compID = ComponentID(comp); + distortionChromaTmp += m_pcRdCost->getDistPart(cs.getOrgBuf(compID), interCcpMergePredBuf[comp - 1], sps.getBitDepth(toChannelType(compID)), compID, DF_SSE); + } + m_CABACEstimator->getCtx() = ctxStart; + m_CABACEstimator->resetBits(); + m_CABACEstimator->inter_ccp_merge_root_cbf_zero(cu); + const uint64_t bits = m_CABACEstimator->getEstFracBits(); + double cost = m_pcRdCost->calcRdCost(bits, distortionChromaTmp); + if (cost < bestCost) + { + bestCost = cost; + bestWIdx = wIdx; + distortion = distortionChromaTmp + distortionLuma; + cs.getRecoBuf(cu.blocks[COMPONENT_Cb]).copyClip(interCcpMergePredBuf[0], cs.slice->clpRng(COMPONENT_Cb)); + cs.getRecoBuf(cu.blocks[COMPONENT_Cr]).copyClip(interCcpMergePredBuf[1], cs.slice->clpRng(COMPONENT_Cr)); + } + } + cu.interCcpMergeZeroRootCbfIdc = bestWIdx; + cu.firstPU->idxNonLocalCCP = 0; + cu.firstTU->curCand = {}; + cu.firstTU->curCand.type = CCP_TYPE_NONE; + m_CABACEstimator->getCtx() = ctxStart; + } +#endif m_CABACEstimator->resetBits(); PredictionUnit &pu = *cs.getPU( partitioner.chType ); @@ -15141,11 +15266,14 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa cs.getResiBuf(curUnitArea).copyFrom(saveCS.getResiBuf(curUnitArea)); } +#if !JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 // all decisions now made. Fully encode the CU, including the headers: m_CABACEstimator->getCtx() = ctxStart; uint64_t finalFracBits = xGetSymbolFracBitsInter( cs, partitioner ); // we've now encoded the CU, and so have a valid bit cost +#endif + if (!cu.rootCbf) { if (luma) @@ -15271,6 +15399,87 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa #endif } } + +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 +#if MULTI_HYP_PRED + if (cu.cs->slice->getSPS()->getUseInterCcpMergeZeroLumaCbf() && cu.firstPU->mergeFlag && !cu.rootCbf && cu.firstPU->numMergedAddHyps == cu.firstPU->addHypData.size()) +#else + if (cu.firstPU->mergeFlag && !cu.rootCbf) +#endif + { + cu.skip = true; + } + bool isInterCcpMergeRootCbfZeroAllowed = CU::interCcpMergeZeroRootCbfAllowed(cu); + if(isInterCcpMergeRootCbfZeroAllowed && m_pcEncCfg->getInterCcpMergeZeroLumaCbfFastMode()) + { + if(cu.blocks[COMPONENT_Cb].area() < 16 || cu.blocks[COMPONENT_Cb].area() > 1024) + { + if ((cu.skip && !cu.slice->getCheckLDB()) || !cu.skip) + { + isInterCcpMergeRootCbfZeroAllowed = false; + } + } + } + + if (chroma && isChromaEnabled(cs.pcv->chrFormat) && isInterCcpMergeRootCbfZeroAllowed) + { + PelBuf bufCb = cs.getPredBuf(cu.blocks[COMPONENT_Cb]); + PelBuf bufCr = cs.getPredBuf(cu.blocks[COMPONENT_Cr]); + if (m_isInterCcpModelReady == false) + { + m_pcIntraPred->xAddOnTheFlyCalcCCPCands4InterBlk(*cu.firstPU, cu.blocks[COMPONENT_Cb], m_interCcpMergeList, m_validNum); + m_isInterCcpModelReady = true; + } + const TempCtx ctxStart(m_ctxCache, m_CABACEstimator->getCtx()); + double bestCost = MAX_DOUBLE; + int8_t bestWIdx = 0; + for (int8_t wIdx = 0; wIdx <= MAX_CCP_MERGE_WEIGHT_IDX; wIdx++) + { + cu.interCcpMergeZeroRootCbfIdc = wIdx; + if (wIdx == 0) + { + const bool valid = deriveInterCcpMergePrediction(cu.firstTU, cs.getRecoBuf(cu.blocks[COMPONENT_Y]), bufCb, bufCr, interCcpMergePredBuf[0], interCcpMergePredBuf[1], m_interCcpMergeList, m_validNum); + CHECK(!valid, "invalid inter ccp merge for rootCbf=0"); + } + else + { + m_pcIntraPred->combineCcpAndInter(*cu.firstPU, bufCb, bufCr, interCcpMergePredBuf[0], interCcpMergePredBuf[1], true); + } +#if JVET_AA0070_RRIBC + if (CU::isIBC(cu) && cu.rribcFlipType) + { + interCcpMergePredBuf[0].flipSignal(cu.rribcFlipType == 1); + interCcpMergePredBuf[1].flipSignal(cu.rribcFlipType == 1); + } +#endif + // given zero root cbf, we should not have residuals here + Distortion distChroma = 0; + for (int comp = 1; comp < numValidComponents; comp++) + { + const ComponentID compID = ComponentID(comp); + distChroma += m_pcRdCost->getDistPart(cs.getOrgBuf(compID), interCcpMergePredBuf[comp - 1], sps.getBitDepth(toChannelType(compID)), compID, DF_SSE); + } + m_CABACEstimator->getCtx() = ctxStart; + m_CABACEstimator->resetBits(); + m_CABACEstimator->inter_ccp_merge_root_cbf_zero(cu); + const uint64_t bits = m_CABACEstimator->getEstFracBits(); + double cost = m_pcRdCost->calcRdCost(bits, distChroma); + if (cost < bestCost) + { + bestCost = cost; + bestWIdx = wIdx; + cs.getRecoBuf(cu.blocks[COMPONENT_Cb]).copyClip(interCcpMergePredBuf[0], cs.slice->clpRng(COMPONENT_Cb)); + cs.getRecoBuf(cu.blocks[COMPONENT_Cr]).copyClip(interCcpMergePredBuf[1], cs.slice->clpRng(COMPONENT_Cr)); + } + } + cu.interCcpMergeZeroRootCbfIdc = bestWIdx; + + cu.firstPU->idxNonLocalCCP = 0; + cu.firstTU->curCand = {}; + cu.firstTU->curCand.type = CCP_TYPE_NONE; + } + else +#endif if (chroma && isChromaEnabled(cs.pcv->chrFormat)) { #if JVET_AE0059_INTER_CCCM @@ -15311,13 +15520,14 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa { PelBuf bufCb = cs.getPredBuf( tuTmp->blocks[COMPONENT_Cb] ); PelBuf bufCr = cs.getPredBuf( tuTmp->blocks[COMPONENT_Cr] ); +#if !JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 PelBuf interCcpMergePredBuf[2]; for( int i = 1; i < MAX_NUM_COMPONENT; i++ ) { interCcpMergePredBuf[i-1] = PelBuf( m_interCcpMergeStorage[i-1], tuTmp->blocks[ComponentID(i)] ); } - +#endif const bool valid = deriveInterCcpMergePrediction(tuTmp, cs.getRecoBuf( tuTmp->blocks[COMPONENT_Y] ), bufCb, bufCr, interCcpMergePredBuf[0], interCcpMergePredBuf[1], m_interCcpMergeList, m_validNum); CHECK( !valid, "invalid inter ccp merge" ); @@ -15328,8 +15538,8 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa #endif else { - cs.getRecoBuf( tuTmp->blocks[COMPONENT_Cb] ).reconstruct( cs.getPredBuf( tuTmp->blocks[COMPONENT_Cb] ), cs.getResiBuf( tuTmp->blocks[COMPONENT_Cb] ), cs.slice->clpRngs().comp[COMPONENT_Cb] ); - cs.getRecoBuf( tuTmp->blocks[COMPONENT_Cr] ).reconstruct( cs.getPredBuf( tuTmp->blocks[COMPONENT_Cr] ), cs.getResiBuf( tuTmp->blocks[COMPONENT_Cr] ), cs.slice->clpRngs().comp[COMPONENT_Cr] ); + cs.getRecoBuf(tuTmp->blocks[COMPONENT_Cb]).reconstruct(cs.getPredBuf(tuTmp->blocks[COMPONENT_Cb]), cs.getResiBuf(tuTmp->blocks[COMPONENT_Cb]),cs.slice->clpRngs().comp[COMPONENT_Cb]); + cs.getRecoBuf(tuTmp->blocks[COMPONENT_Cr]).reconstruct(cs.getPredBuf(tuTmp->blocks[COMPONENT_Cr]), cs.getResiBuf(tuTmp->blocks[COMPONENT_Cr]), cs.slice->clpRngs().comp[COMPONENT_Cr]); } } #else @@ -15344,6 +15554,13 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa } #endif } +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + // all decisions now made. Fully encode the CU, including the headers: + m_CABACEstimator->getCtx() = ctxStart; + + uint64_t finalFracBits = xGetSymbolFracBitsInter( cs, partitioner ); + // we've now encoded the CU, and so have a valid bit cost +#endif // update with clipped distortion and cost (previously unclipped reconstruction values were used) Distortion finalDistortion = 0; diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h index 0574ce27e..c4ec09d4a 100644 --- a/source/Lib/EncoderLib/InterSearch.h +++ b/source/Lib/EncoderLib/InterSearch.h @@ -892,6 +892,7 @@ public: int m_validNum; CCPModelCandidate m_interCcpMergeList[MAX_CCP_CAND_LIST_SIZE]; #endif + #if JVET_X0083_BM_AMVP_MERGE_MODE public: Distortion m_amvpOnlyCost; diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 5d4de4d4d..c907da30b 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -1696,6 +1696,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) #if JVET_AG0058_EIP WRITE_FLAG(pcSPS->getUseEip() ? 1 : 0, "sps_eip_enabled_flag"); #endif +#if JVET_AH0066_JVET_AH0202_CCP_MERGE_LUMACBF0 + WRITE_FLAG( pcSPS->getUseInterCcpMergeZeroLumaCbf() ? 1 : 0, "sps_inter_ccp_merge_zero_luma_cbf"); +#endif #if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL if (pcSPS->getTMnoninterToolsEnableFlag()) { -- GitLab