diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index ef1df8aed4967d581822b1729a85e5ddab2f853e..fa51ac28709c5bbf965a9024ae9c4fe63bd2dad1 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -416,6 +416,9 @@ public: violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; lfnstLastScanPos = false; violatesMtsCoeffConstraint = false; +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + mtsLastScanPos = false; +#endif } CUCtx(int _qp) : isDQPCoded(false), isChromaQpAdjCoded(false), qgStart(false), @@ -425,6 +428,9 @@ public: violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; lfnstLastScanPos = false; violatesMtsCoeffConstraint = false; +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + mtsLastScanPos = false; +#endif } ~CUCtx() {} public: @@ -435,6 +441,9 @@ public: int8_t qp; // used as a previous(last) QP and for QP prediction bool violatesLfnstConstrained[MAX_NUM_CHANNEL_TYPE]; bool violatesMtsCoeffConstraint; +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + bool mtsLastScanPos; +#endif }; class MergeCtx diff --git a/source/Lib/CommonLib/DepQuant.cpp b/source/Lib/CommonLib/DepQuant.cpp index af4a5757a7efbcb4a6074b813f4be1df3184acf1..96bf315ea65f216df939c1829844f3028fcfbff9 100644 --- a/source/Lib/CommonLib/DepQuant.cpp +++ b/source/Lib/CommonLib/DepQuant.cpp @@ -1587,7 +1587,12 @@ void DepQuant::quant( TransformUnit &tu, const ComponentID &compID, const CCoeff const uint32_t log2TrWidth = floorLog2(width); const uint32_t log2TrHeight = floorLog2(height); const bool disableSMForLFNST = tu.cs->picHeader->getScalingListPresentFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#if JVET_Q0784_LFNST_COMBINATION + const bool isLfnstApplied = tu.cu->lfnstIdx > 0 && (tu.cu->isSepTree() ? true : isLuma(compID)); + const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx[compID] == MTS_SKIP), isLfnstApplied, disableSMForLFNST); +#else const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx[compID] == MTS_SKIP), tu.cu->lfnstIdx > 0, disableSMForLFNST); +#endif static_cast<DQIntern::DepQuant*>(p)->quant( tu, pSrc, compID, cQP, Quant::m_dLambda, ctx, uiAbsSum, enableScalingLists, Quant::getQuantCoeff(scalingListType, qpRem, log2TrWidth, log2TrHeight) ); } else @@ -1611,7 +1616,12 @@ void DepQuant::dequant( const TransformUnit &tu, CoeffBuf &dstCoeff, const Compo const uint32_t log2TrWidth = floorLog2(width); const uint32_t log2TrHeight = floorLog2(height); const bool disableSMForLFNST = tu.cs->picHeader->getScalingListPresentFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#if JVET_Q0784_LFNST_COMBINATION + const bool isLfnstApplied = tu.cu->lfnstIdx > 0 && (tu.cu->isSepTree() ? true : isLuma(compID)); + const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx[compID] == MTS_SKIP), isLfnstApplied, disableSMForLFNST); +#else const bool enableScalingLists = getUseScalingList(width, height, (tu.mtsIdx[compID] == MTS_SKIP), tu.cu->lfnstIdx > 0, disableSMForLFNST); +#endif static_cast<DQIntern::DepQuant*>(p)->dequant( tu, dstCoeff, compID, cQP, enableScalingLists, Quant::getDequantCoeff(scalingListType, qpRem, log2TrWidth, log2TrHeight) ); } else diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index a7b92179c5de28fd0a1efdba73244dff261852e1..d749d78e90b73f8a2d74bff6661b3d1e2faf79da 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -539,7 +539,11 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co } else { +#if JVET_Q0128_DMVR_BDOF_ENABLING_CONDITION + const bool biocheck0 = !((wp0[COMPONENT_Y].bPresentFlag || wp0[COMPONENT_Cb].bPresentFlag || wp0[COMPONENT_Cr].bPresentFlag || wp1[COMPONENT_Y].bPresentFlag || wp1[COMPONENT_Cb].bPresentFlag || wp1[COMPONENT_Cr].bPresentFlag) && slice.getSliceType() == B_SLICE); +#else const bool biocheck0 = !((wp0[COMPONENT_Y].bPresentFlag || wp1[COMPONENT_Y].bPresentFlag) && slice.getSliceType() == B_SLICE); +#endif const bool biocheck1 = !(pps.getUseWP() && slice.getSliceType() == P_SLICE); if (biocheck0 && biocheck1 @@ -1400,6 +1404,14 @@ void InterPrediction::xWeightedAverage(const PredictionUnit& pu, const CPelUnitB yuvDstTmp->bufs[0].copyFrom(pcYuvDst.bufs[0]); } } +#if JVET_Q0128_DMVR_BDOF_ENABLING_CONDITION + if (!bioApplied && (lumaOnly || chromaOnly)) + { + pcYuvDst.addAvg(pcYuvSrc0, pcYuvSrc1, clpRngs, chromaOnly, lumaOnly); + } + else + pcYuvDst.addAvg(pcYuvSrc0, pcYuvSrc1, clpRngs, bioApplied); +#else if (pu.cs->pps->getWPBiPred()) { const int iRefIdx0 = pu.refIdx[0]; @@ -1427,6 +1439,7 @@ void InterPrediction::xWeightedAverage(const PredictionUnit& pu, const CPelUnitB else pcYuvDst.addAvg(pcYuvSrc0, pcYuvSrc1, clpRngs, bioApplied); } +#endif if (yuvDstTmp) { if (bioApplied) @@ -1539,7 +1552,11 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu } else { +#if JVET_Q0128_DMVR_BDOF_ENABLING_CONDITION + const bool biocheck0 = !((wp0[COMPONENT_Y].bPresentFlag || wp0[COMPONENT_Cb].bPresentFlag || wp0[COMPONENT_Cr].bPresentFlag || wp1[COMPONENT_Y].bPresentFlag || wp1[COMPONENT_Cb].bPresentFlag || wp1[COMPONENT_Cr].bPresentFlag) && slice.getSliceType() == B_SLICE); +#else const bool biocheck0 = !((wp0[COMPONENT_Y].bPresentFlag || wp1[COMPONENT_Y].bPresentFlag) && slice.getSliceType() == B_SLICE); +#endif const bool biocheck1 = !(pps.getUseWP() && slice.getSliceType() == P_SLICE); if (biocheck0 && biocheck1 diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp index e21148d8d11ebf2f308a6e28a2592ce5f61484d4..776a332baf4939a5722c71e5efe3c0106067c374 100644 --- a/source/Lib/CommonLib/IntraPrediction.cpp +++ b/source/Lib/CommonLib/IntraPrediction.cpp @@ -1406,8 +1406,9 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom bool isFirstRowOfCtu = ( lumaArea.y & ((pu.cs->sps)->getCTUSize() - 1) ) == 0; const int strOffset = (CHROMA_444 == pu.chromaFormat) ? 0 : iRecStride; - +#if !JVET_Q0500_CCLM_REF_PADDING int c0_2tap = 1, c1_2tap = 1, offset_2tap = 1, shift_2tap = 1; //sum = 2 +#endif int c0_3tap = 2, c1_3tap = 1, c2_3tap = 1, offset_3tap = 2, shift_3tap = 2; //sum = 4 int c0_5tap = 1, c1_5tap = 4, c2_5tap = 1, c3_5tap = 1, c4_5tap = 1, offset_5tap = 4, shift_5tap = 3; //sum = 8 int c0_6tap = 2, c1_6tap = 1, c2_6tap = 1, c3_6tap = 2, c4_6tap = 1, c5_6tap = 1, offset_6tap = 4, shift_6tap = 3; //sum = 8 @@ -1415,14 +1416,18 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom switch (pu.chromaFormat) { case CHROMA_422: //overwrite filter coefficient values for 422 +#if !JVET_Q0500_CCLM_REF_PADDING c0_2tap = 1, c1_2tap = 0, offset_2tap = 0, shift_2tap = 0; //sum = 1 +#endif c0_3tap = 2, c1_3tap = 1, c2_3tap = 1, offset_3tap = 2, shift_3tap = 2; //sum = 4 c0_5tap = 0, c1_5tap = 1, c2_5tap = 0, c3_5tap = 0, c4_5tap = 0, offset_5tap = 0, shift_5tap = 0; //sum = 1 c0_6tap = 2, c1_6tap = 1, c2_6tap = 1, c3_6tap = 0, c4_6tap = 0, c5_6tap = 0, offset_6tap = 2, shift_6tap = 2; //sum = 4 break; case CHROMA_444: //overwrite filter coefficient values for 422 +#if !JVET_Q0500_CCLM_REF_PADDING c0_2tap = 1, c1_2tap = 0, offset_2tap = 0, shift_2tap = 0; //sum = 1 +#endif c0_3tap = 1, c1_3tap = 0, c2_3tap = 0, offset_3tap = 0, shift_3tap = 0; //sum = 1 c0_5tap = 0, c1_5tap = 1, c2_5tap = 0, c3_5tap = 0, c4_5tap = 0, offset_5tap = 0, shift_5tap = 0; //sum = 1 c0_6tap = 1, c1_6tap = 0, c2_6tap = 0, c3_6tap = 0, c4_6tap = 0, c5_6tap = 0, offset_6tap = 0, shift_6tap = 0; //sum = 1 @@ -1448,7 +1453,11 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom if ((i == 0 && !bLeftAvaillable) || (i == uiCWidth + addedAboveRight - 1 + logSubWidthC)) { +#if JVET_Q0500_CCLM_REF_PADDING + pDst[i] = (piSrc[mult * i] * c0_3tap + piSrc[mult * i] * c1_3tap + piSrc[mult * i + 1] * c2_3tap + offset_3tap) >> shift_3tap; +#else pDst[i] = piSrc[mult * i]; +#endif } else { @@ -1461,7 +1470,14 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom if ((i == 0 && !bLeftAvaillable) || (i == uiCWidth + addedAboveRight - 1 + logSubWidthC)) { +#if JVET_Q0500_CCLM_REF_PADDING + pDst[i] = (piSrc[mult * i - strOffset] * c0_5tap + + piSrc[mult * i] * c1_5tap + piSrc[mult * i] * c2_5tap + piSrc[mult * i + 1] * c3_5tap + + piSrc[mult * i + strOffset] * c4_5tap + + offset_5tap) >> shift_5tap; +#else pDst[i] = (piSrc[mult * i] * c0_3tap + piSrc[mult * i - strOffset] * c1_3tap + piSrc[mult * i + strOffset] * c2_3tap + offset_3tap) >> shift_3tap; +#endif } else { @@ -1477,7 +1493,13 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom if ((i == 0 && !bLeftAvaillable) || (i == uiCWidth + addedAboveRight - 1 + logSubWidthC)) { +#if JVET_Q0500_CCLM_REF_PADDING + pDst[i] = ((piSrc[mult * i] * c0_6tap + piSrc[mult * i] * c1_6tap + piSrc[mult * i + 1] * c2_6tap) + + (piSrc[mult * i + strOffset] * c3_6tap + piSrc[mult * i + strOffset] * c4_6tap + piSrc[mult * i + 1 + strOffset] * c5_6tap) + + offset_6tap) >> shift_6tap; +#else pDst[i] = (piSrc[mult * i] * c0_2tap + piSrc[mult * i + strOffset] * c1_2tap + offset_2tap) >> shift_2tap; +#endif } else { @@ -1507,7 +1529,14 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom { if ((j == 0 && !bAboveAvaillable) || (j == uiCHeight + addedLeftBelow - 1 + logSubWidthC)) { +#if JVET_Q0500_CCLM_REF_PADDING + pDst[0] = ( piSrc[1 ] * c0_5tap + + piSrc[1 ] * c1_5tap + piSrc[0] * c2_5tap + piSrc[2] * c3_5tap + + piSrc[1 + strOffset] * c4_5tap + + offset_5tap ) >> shift_5tap; +#else pDst[0] = ( piSrc[1] * c0_3tap + piSrc[0] * c1_3tap + piSrc[2] * c2_3tap + offset_3tap) >> shift_3tap; +#endif } else { @@ -1540,16 +1569,37 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom { if ( j == 0 && !bAboveAvaillable ) { +#if JVET_Q0500_CCLM_REF_PADDING + pDst0[i] = (pRecSrc0[mult * i] * c0_5tap + + pRecSrc0[mult * i] * c1_5tap + pRecSrc0[mult * i] * c2_5tap + pRecSrc0[mult * i + 1] * c3_5tap + + pRecSrc0[mult * i + strOffset] * c4_5tap + + offset_5tap) >> shift_5tap; +#else pDst0[i] = pRecSrc0[mult * i]; +#endif } else { +#if JVET_Q0500_CCLM_REF_PADDING + pDst0[i] = (pRecSrc0[mult * i - strOffset] * c0_5tap + + pRecSrc0[mult * i] * c1_5tap + pRecSrc0[mult * i] * c2_5tap + pRecSrc0[mult * i + 1] * c3_5tap + + pRecSrc0[mult * i + strOffset] * c4_5tap + + offset_5tap) >> shift_5tap; +#else pDst0[i] = (pRecSrc0[mult * i] * c0_3tap + pRecSrc0[mult * i - strOffset] * c1_3tap + pRecSrc0[mult * i + strOffset] * c2_3tap + offset_3tap) >> shift_3tap; +#endif } } else if ( j == 0 && !bAboveAvaillable ) { +#if JVET_Q0500_CCLM_REF_PADDING + pDst0[i] = (pRecSrc0[mult * i] * c0_5tap + + pRecSrc0[mult * i] * c1_5tap + pRecSrc0[mult * i - 1] * c2_5tap + pRecSrc0[mult * i + 1] * c3_5tap + + pRecSrc0[mult * i + strOffset] * c4_5tap + + offset_5tap) >> shift_5tap; +#else pDst0[i] = (pRecSrc0[mult * i] * c0_3tap + pRecSrc0[mult * i - 1] * c1_3tap + pRecSrc0[mult * i + 1] * c2_3tap + offset_3tap) >> shift_3tap; +#endif } else { @@ -1564,7 +1614,21 @@ void IntraPrediction::xGetLumaRecPixels(const PredictionUnit &pu, CompArea chrom if ((i == 0 && !bLeftAvaillable) || (i == uiCWidth - 1 + logSubWidthC)) { +#if JVET_Q0500_CCLM_REF_PADDING + int s = offset_6tap; + s += pRecSrc0[mult * i] * c0_6tap; + s += pRecSrc0[mult * i + 1] * c1_6tap; + s += pRecSrc0[mult * i] * c2_6tap; + if (pu.chromaFormat == CHROMA_420) + { + s += pRecSrc0[mult * i + strOffset] * c3_6tap; + s += pRecSrc0[mult * i + 1 + strOffset] * c4_6tap; + s += pRecSrc0[mult * i + strOffset] * c5_6tap; + } + pDst0[i] = s >> shift_6tap; +#else pDst0[i] = (pRecSrc0[mult * i] * c0_2tap + pRecSrc0[mult * i + strOffset] * c1_2tap + offset_2tap) >> shift_2tap; +#endif } else { diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp index 387ec60c54ce03b303447138e5c0345850268eed..2821a7ef362fbbb8bf827976a1f04321ac4fe8ca 100644 --- a/source/Lib/CommonLib/Picture.cpp +++ b/source/Lib/CommonLib/Picture.cpp @@ -729,7 +729,7 @@ void Picture::rescalePicture( const std::pair<int, int> scalingRatio, beforeScale, scalingWindowBefore.getWindowLeftOffset(), scalingWindowBefore.getWindowTopOffset(), afterScale, scalingWindowAfter.getWindowLeftOffset(), scalingWindowAfter.getWindowTopOffset(), #endif - bitDepths.recon[comp], downsampling || useLumaFilter ? true : isLuma( compID ), downsampling, + bitDepths.recon[toChannelType(compID)], downsampling || useLumaFilter ? true : isLuma( compID ), downsampling, isLuma( compID ) ? 1 : horCollocatedChromaFlag, isLuma( compID ) ? 1 : verCollocatedChromaFlag ); } } diff --git a/source/Lib/CommonLib/Quant.cpp b/source/Lib/CommonLib/Quant.cpp index b46a46267666f9d44f13ca1d62e4ffd17e21f79a..f30351c8ece34e456fd51111ed6408b4044da9f6 100644 --- a/source/Lib/CommonLib/Quant.cpp +++ b/source/Lib/CommonLib/Quant.cpp @@ -365,7 +365,12 @@ void Quant::dequant(const TransformUnit &tu, const bool isTransformSkip = (tu.mtsIdx[compID] == MTS_SKIP); const bool disableSMForLFNST = tu.cs->picHeader->getScalingListPresentFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#if JVET_Q0784_LFNST_COMBINATION + const bool isLfnstApplied = tu.cu->lfnstIdx > 0 && (tu.cu->isSepTree() ? true : isLuma(compID)); + const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, isTransformSkip, isLfnstApplied, disableSMForLFNST); +#else const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, isTransformSkip, tu.cu->lfnstIdx > 0, disableSMForLFNST); +#endif const int scalingListType = getScalingListType(tu.cu->predMode, compID); const int channelBitDepth = sps->getBitDepth(toChannelType(compID)); @@ -967,7 +972,12 @@ void Quant::quant(TransformUnit &tu, const ComponentID &compID, const CCoeffBuf int *piQuantCoeff = getQuantCoeff(scalingListType, cQP.rem(useTransformSkip), uiLog2TrWidth, uiLog2TrHeight); const bool disableSMForLFNST = tu.cs->picHeader->getScalingListPresentFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#if JVET_Q0784_LFNST_COMBINATION + const bool isLfnstApplied = tu.cu->lfnstIdx > 0 && (tu.cu->isSepTree() ? true : isLuma(compID)); + const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, useTransformSkip, isLfnstApplied, disableSMForLFNST); +#else const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, useTransformSkip, tu.cu->lfnstIdx > 0, disableSMForLFNST); +#endif // for blocks that where width*height != 4^N, the effective scaling applied during transformation cannot be // compensated by a bit-shift (the quantised result will be sqrt(2) * larger than required). @@ -1041,7 +1051,12 @@ bool Quant::xNeedRDOQ(TransformUnit &tu, const ComponentID &compID, const CCoeff int *piQuantCoeff = getQuantCoeff(scalingListType, cQP.rem(useTransformSkip), uiLog2TrWidth, uiLog2TrHeight); const bool disableSMForLFNST = tu.cs->picHeader->getScalingListPresentFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#if JVET_Q0784_LFNST_COMBINATION + const bool isLfnstApplied = tu.cu->lfnstIdx > 0 && (tu.cu->isSepTree() ? true : isLuma(compID)); + const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, (useTransformSkip != 0), isLfnstApplied, disableSMForLFNST); +#else const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, (useTransformSkip != 0), tu.cu->lfnstIdx > 0, disableSMForLFNST); +#endif /* for 422 chroma blocks, the effective scaling applied during transformation is not a power of 2, hence it cannot be * implemented as a bit-shift (the quantised result will be sqrt(2) * larger than required). Alternatively, adjust the @@ -1091,7 +1106,12 @@ void Quant::transformSkipQuantOneSample(TransformUnit &tu, const ComponentID &co const int iTransformShift = getTransformShift(channelBitDepth, rect.size(), maxLog2TrDynamicRange); const int scalingListType = getScalingListType(tu.cu->predMode, compID); const bool disableSMForLFNST = tu.cs->picHeader->getScalingListPresentFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#if JVET_Q0784_LFNST_COMBINATION + const bool isLfnstApplied = tu.cu->lfnstIdx > 0 && (tu.cu->isSepTree() ? true : isLuma(compID)); + const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, true, isLfnstApplied, disableSMForLFNST); +#else const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, true, tu.cu->lfnstIdx > 0, disableSMForLFNST); +#endif const bool useTransformSkip = (tu.mtsIdx[compID] == MTS_SKIP); const int defaultQuantisationCoefficient = g_quantScales[0][cQP.rem(useTransformSkip)]; @@ -1150,8 +1170,12 @@ void Quant::invTrSkipDeQuantOneSample(TransformUnit &tu, const ComponentID &comp const int iTransformShift = getTransformShift(channelBitDepth, rect.size(), maxLog2TrDynamicRange); const int scalingListType = getScalingListType(tu.cu->predMode, compID); const bool disableSMForLFNST = tu.cs->picHeader->getScalingListPresentFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#if JVET_Q0784_LFNST_COMBINATION + const bool isLfnstApplied = tu.cu->lfnstIdx > 0 && (tu.cu->isSepTree() ? true : isLuma(compID)); + const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, true, isLfnstApplied, disableSMForLFNST); +#else const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, true, tu.cu->lfnstIdx > 0, disableSMForLFNST); - +#endif CHECK(scalingListType >= SCALING_LIST_NUM, "Invalid scaling list"); const bool isTransformSkip = (tu.mtsIdx[compID] == MTS_SKIP); diff --git a/source/Lib/CommonLib/QuantRDOQ.cpp b/source/Lib/CommonLib/QuantRDOQ.cpp index 7b3ffe927496a28c4bf07dabc9b8116da3e8ba60..a258d7665c4bdd540568094d750326530d65aa75 100644 --- a/source/Lib/CommonLib/QuantRDOQ.cpp +++ b/source/Lib/CommonLib/QuantRDOQ.cpp @@ -630,7 +630,12 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID, const double *const pdErrScale = xGetErrScaleCoeffSL(scalingListType, uiLog2BlockWidth, uiLog2BlockHeight, cQP.rem(isTransformSkip)); const int *const piQCoef = getQuantCoeff(scalingListType, cQP.rem(isTransformSkip), uiLog2BlockWidth, uiLog2BlockHeight); const bool disableSMForLFNST = tu.cs->picHeader->getScalingListPresentFlag() ? tu.cs->picHeader->getScalingListAPS()->getScalingList().getDisableScalingMatrixForLfnstBlks() : false; +#if JVET_Q0784_LFNST_COMBINATION + const bool isLfnstApplied = tu.cu->lfnstIdx > 0 && (tu.cu->isSepTree() ? true : isLuma(compID)); + const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, isTransformSkip, isLfnstApplied, disableSMForLFNST); +#else const bool enableScalingLists = getUseScalingList(uiWidth, uiHeight, isTransformSkip, tu.cu->lfnstIdx > 0, disableSMForLFNST); +#endif const int defaultQuantisationCoefficient = g_quantScales[ needSqrtAdjustment ?1:0][cQP.rem(isTransformSkip)]; const double defaultErrorScale = xGetErrScaleCoeffNoScalingList(scalingListType, uiLog2BlockWidth, uiLog2BlockHeight, cQP.rem(isTransformSkip)); const int iQBits = QUANT_SHIFT + cQP.per(isTransformSkip) + iTransformShift + (needSqrtAdjustment?-1:0); // Right shift of non-RDOQ quantizer; level = (coeff*uiQ + offset)>>q_bits diff --git a/source/Lib/CommonLib/TrQuant.cpp b/source/Lib/CommonLib/TrQuant.cpp index c4221f13644fe2ea8a3c9d4c2c2e37897cb0bd1e..02e7b138adb67827bb22873e0e34df7c99566684 100644 --- a/source/Lib/CommonLib/TrQuant.cpp +++ b/source/Lib/CommonLib/TrQuant.cpp @@ -313,8 +313,11 @@ void TrQuant::xInvLfnst( const TransformUnit &tu, const ComponentID compID ) const uint32_t width = area.width; const uint32_t height = area.height; const uint32_t lfnstIdx = tu.cu->lfnstIdx; - +#if JVET_Q0784_LFNST_COMBINATION + if( lfnstIdx && tu.mtsIdx[compID] != MTS_SKIP && (tu.cu->isSepTree() ? true : isLuma(compID)) ) +#else if (lfnstIdx && tu.mtsIdx[compID] != MTS_SKIP && width >= 4 && height >= 4) +#endif { const bool whge3 = width >= 8 && height >= 8; const ScanElement * scan = whge3 ? g_coefTopLeftDiagScan8x8[ gp_sizeIdxInfo->idxFrom( width ) ] : g_scanOrder[ SCAN_GROUPED_4x4 ][ SCAN_DIAG ][ gp_sizeIdxInfo->idxFrom( width ) ][ gp_sizeIdxInfo->idxFrom( height ) ]; @@ -405,8 +408,11 @@ void TrQuant::xFwdLfnst( const TransformUnit &tu, const ComponentID compID, cons const uint32_t width = area.width; const uint32_t height = area.height; const uint32_t lfnstIdx = tu.cu->lfnstIdx; - +#if JVET_Q0784_LFNST_COMBINATION + if( lfnstIdx && tu.mtsIdx[compID] != MTS_SKIP && (tu.cu->isSepTree() ? true : isLuma(compID)) ) +#else if( lfnstIdx && tu.mtsIdx[compID] != MTS_SKIP && width >= 4 && height >= 4) +#endif { const bool whge3 = width >= 8 && height >= 8; const ScanElement * scan = whge3 ? g_coefTopLeftDiagScan8x8[ gp_sizeIdxInfo->idxFrom( width ) ] : g_scanOrder[ SCAN_GROUPED_4x4 ][ SCAN_DIAG ][ gp_sizeIdxInfo->idxFrom( width ) ][ gp_sizeIdxInfo->idxFrom( height ) ]; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 37b9f79b2f1dffdeaa7271065d3e8731d93d27bb..892d1e776441b4bae9309af02d249fa3d85e0d55 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,12 @@ #include <assert.h> #include <cassert> +#define JVET_Q0500_CCLM_REF_PADDING 1 // JVET-Q0500: Reference samples padding for CCLM + +#define JVET_Q0128_DMVR_BDOF_ENABLING_CONDITION 1 // JVET-Q0128: Cleanup of enabling condition for DMVR and BDOF + +#define JVET_Q0784_LFNST_COMBINATION 1 // lfnst signaling, latency reduction and a bugfix for scaling from Q0106, Q0686, Q0133 + #define JVET_Q0147_JCCR_SIGNALLING 1 // JVET-Q0147: Conditional signaling of sps_joint_cbcr_enabled_flag based on ChromaArrayType #define JVET_Q0267_RESET_CHROMA_QP_OFFSET 1 // JVET-Q0267: Reset chroma QP offsets at the start of each chroma QP offset group @@ -72,6 +78,7 @@ #define JVET_Q0483_CLIP_TMVP 1 // JVET-Q0483: Clip TMVP when no scaling is applied +#define JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND 1 // JVET-Q0516/Q0685: disable MTS when there is only DC coefficient #define JVET_Q0055_MTS_SIGNALLING 1 // JVET-Q0055: Check for transform coefficients outside the 16x16 area #define JVET_Q0480_RASTER_RECT_SLICES 1 // JVET-Q0480: Eliminate redundant slice height syntax when in raster rectangular slice mode (tile_idx_delta_present_flag == 0) diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 5fde200345fb7a4930ba5eeaed4ceffd7e31d9c9..95e59ed1e139622e863bbd98a1355c0cc2079fe7 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -1247,7 +1247,11 @@ bool PU::checkDMVRCondition(const PredictionUnit& pu) && (pu.lwidth() >= 8) && ((pu.lheight() * pu.lwidth()) >= 128) && (pu.cu->BcwIdx == BCW_DEFAULT) +#if JVET_Q0128_DMVR_BDOF_ENABLING_CONDITION + && ((!wp0[COMPONENT_Y].bPresentFlag) && (!wp0[COMPONENT_Cb].bPresentFlag) && (!wp0[COMPONENT_Cr].bPresentFlag) && (!wp1[COMPONENT_Y].bPresentFlag) && (!wp1[COMPONENT_Cb].bPresentFlag) && (!wp1[COMPONENT_Cr].bPresentFlag)) +#else && ((!wp0[COMPONENT_Y].bPresentFlag) && (!wp1[COMPONENT_Y].bPresentFlag)) +#endif #if JVET_Q0487_SCALING_WINDOW_ISSUES && ( refIdx0 < 0 ? true : (pu.cu->slice->getRefPic( REF_PIC_LIST_0, refIdx0 )->isRefScaled( pu.cs->pps ) == false) ) && ( refIdx1 < 0 ? true : (pu.cu->slice->getRefPic( REF_PIC_LIST_1, refIdx1 )->isRefScaled( pu.cs->pps ) == false) ) diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 78827de8d4c1bbeb8e53a99ea9e8c1fb52fdf7dc..2b6e0688128e89e513a2b6886e71e9ec9375ee92 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -1470,6 +1470,9 @@ void CABACReader::cu_residual( CodingUnit& cu, Partitioner &partitioner, CUCtx& cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; cuCtx.lfnstLastScanPos = false; cuCtx.violatesMtsCoeffConstraint = false; +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + cuCtx.mtsLastScanPos = false; +#endif ChromaCbfs chromaCbfs; if( cu.ispMode && isLuma( partitioner.chType ) ) @@ -2837,6 +2840,12 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID, CUCtx& cuCtx.violatesMtsCoeffConstraint = true; } #endif +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + if (isLuma(compID) && tu.mtsIdx[compID] != MTS_SKIP) + { + cuCtx.mtsLastScanPos |= cctx.scanPosLast() >= 1; + } +#endif // parse subblocks const int stateTransTab = ( tu.cs->picHeader->getDepQuantEnabledFlag() ? 32040 : 0 ); @@ -2888,9 +2897,13 @@ void CABACReader::mts_idx( CodingUnit& cu, CUCtx& cuCtx ) { TransformUnit &tu = *cu.firstTU; int mtsIdx = tu.mtsIdx[COMPONENT_Y]; // Transform skip flag has already been decoded - + if( CU::isMTSAllowed( cu, COMPONENT_Y ) && !cuCtx.violatesMtsCoeffConstraint && +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + cuCtx.mtsLastScanPos && cu.lfnstIdx == 0 && mtsIdx != MTS_SKIP) +#else cu.lfnstIdx == 0 && mtsIdx != MTS_SKIP && TU::getCbf(tu, COMPONENT_Y) ) +#endif { RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2( STATS__CABAC_BITS__MTS_FLAGS, tu.blocks[COMPONENT_Y], COMPONENT_Y ); int ctxIdx = 0; @@ -2982,7 +2995,23 @@ void CABACReader::residual_lfnst_mode( CodingUnit& cu, CUCtx& cuCtx ) const bool lumaFlag = cu.isSepTree() ? ( isLuma( cu.chType ) ? true : false ) : true; const bool chromaFlag = cu.isSepTree() ? ( isChroma( cu.chType ) ? true : false ) : true; bool nonZeroCoeffNonTsCorner8x8 = ( lumaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_LUMA] ) || (chromaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] ); +#if JVET_Q0784_LFNST_COMBINATION + bool isTrSkip = false; + for (auto &currTU : CU::traverseTUs(cu)) + { + const uint32_t numValidComp = getNumberValidComponents(cu.chromaFormat); + for (uint32_t compID = COMPONENT_Y; compID < numValidComp; compID++) + { + if (currTU.blocks[compID].valid() && TU::getCbf(currTU, (ComponentID)compID) && currTU.mtsIdx[compID] == MTS_SKIP) + { + isTrSkip = true; + break; + } + } + } +#else const bool isTrSkip = TU::getCbf(*cu.firstTU, COMPONENT_Y) && cu.firstTU->mtsIdx[COMPONENT_Y] == MTS_SKIP; +#endif if ((!cuCtx.lfnstLastScanPos && !cu.ispMode) || nonZeroCoeffNonTsCorner8x8 || isTrSkip) { cu.lfnstIdx = 0; diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 51afcfbfca8ab039ac1b9c005cba1b62b2969b1e..c814c521abbd7ecf4bbcf7ab531873b0b10a268f 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -1295,6 +1295,9 @@ void CABACWriter::cu_residual( const CodingUnit& cu, Partitioner& partitioner, C cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; cuCtx.lfnstLastScanPos = false; cuCtx.violatesMtsCoeffConstraint = false; +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + cuCtx.mtsLastScanPos = false; +#endif if( cu.ispMode && isLuma( partitioner.chType ) ) { @@ -2655,7 +2658,14 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID, cuCtx->violatesMtsCoeffConstraint = true; } #endif - +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + if (cuCtx && isLuma(compID) && tu.mtsIdx[compID] != MTS_SKIP) + { + cuCtx->mtsLastScanPos |= cctx.scanPosLast() >= 1; + } +#endif + + // code last coeff position last_sig_coeff( cctx, tu, compID ); @@ -2706,8 +2716,12 @@ void CABACWriter::mts_idx( const CodingUnit& cu, CUCtx* cuCtx ) TransformUnit &tu = *cu.firstTU; int mtsIdx = tu.mtsIdx[COMPONENT_Y]; - if( CU::isMTSAllowed( cu, COMPONENT_Y ) && cuCtx && !cuCtx->violatesMtsCoeffConstraint && + if( CU::isMTSAllowed( cu, COMPONENT_Y ) && cuCtx && !cuCtx->violatesMtsCoeffConstraint && +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + cuCtx->mtsLastScanPos && cu.lfnstIdx == 0 && mtsIdx != MTS_SKIP) +#else cu.lfnstIdx == 0 && mtsIdx != MTS_SKIP && TU::getCbf(tu, COMPONENT_Y) ) +#endif { int symbol = mtsIdx != MTS_DCT2_DCT2 ? 1 : 0; int ctxIdx = 0; @@ -2790,8 +2804,23 @@ void CABACWriter::residual_lfnst_mode( const CodingUnit& cu, CUCtx& cuCtx ) const bool lumaFlag = cu.isSepTree() ? ( isLuma( cu.chType ) ? true : false ) : true; const bool chromaFlag = cu.isSepTree() ? ( isChroma( cu.chType ) ? true : false ) : true; bool nonZeroCoeffNonTsCorner8x8 = ( lumaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_LUMA] ) || (chromaFlag && cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] ); - +#if JVET_Q0784_LFNST_COMBINATION + bool isTrSkip = false; + for (auto &currTU : CU::traverseTUs(cu)) + { + const uint32_t numValidComp = getNumberValidComponents(cu.chromaFormat); + for (uint32_t compID = COMPONENT_Y; compID < numValidComp; compID++) + { + if (currTU.blocks[compID].valid() && TU::getCbf(currTU, (ComponentID)compID) && currTU.mtsIdx[compID] == MTS_SKIP) + { + isTrSkip = true; + break; + } + } + } +#else const bool isTrSkip = TU::getCbf(*cu.firstTU, COMPONENT_Y) && cu.firstTU->mtsIdx[COMPONENT_Y] == MTS_SKIP; +#endif if( (!cuCtx.lfnstLastScanPos && !cu.ispMode) || nonZeroCoeffNonTsCorner8x8 || isTrSkip ) { return; diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 45af5fb9ebda1fdb7fd101b1f2190ceeb2e029c9..664375b9067a73c1ed886417616ec5762d6b9fd7 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -1824,6 +1824,13 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS } } +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + if (isLuma(partitioner.chType) && cu.firstTU->mtsIdx[COMPONENT_Y] > MTS_SKIP) + { + CHECK(!cuCtx.mtsLastScanPos, "MTS is disallowed to only contain DC coefficient"); + } +#endif + if( mtsFlag == 0 && lfnstIdx == 0 ) { dct2Cost = tempCS->cost; diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 2a0f143d8303546ea456cb88082bb046efc50c11..ff5ae6e104bb6162beec220bde5f07cba0b431e6 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -6764,11 +6764,26 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par { m_CABACEstimator->cross_comp_pred( tu, compID ); } - m_CABACEstimator->residual_coding( tu, compID ); +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + CUCtx cuCtx; + cuCtx.isDQPCoded = true; + cuCtx.isChromaQpAdjCoded = true; + m_CABACEstimator->residual_coding(tu, compID, &cuCtx); + m_CABACEstimator->mts_idx(cu, &cuCtx); + + if (compID == COMPONENT_Y && tu.mtsIdx[compID] > MTS_SKIP && !cuCtx.mtsLastScanPos) + { + currCompCost = MAX_DOUBLE; + } + else + { +#else + m_CABACEstimator->residual_coding(tu, compID); +#endif currCompFracBits = m_CABACEstimator->getEstFracBits(); - PelBuf resiBuf = csFull->getResiBuf(compArea); + PelBuf resiBuf = csFull->getResiBuf(compArea); CPelBuf orgResiBuf = csFull->getOrgResiBuf(compArea); m_pcTrQuant->invTransformNxN(tu, compID, resiBuf, cQP); @@ -6779,7 +6794,7 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par if (bUseCrossCPrediction) { - crossComponentPrediction( tu, compID, lumaResi, resiBuf, resiBuf, true ); + crossComponentPrediction(tu, compID, lumaResi, resiBuf, resiBuf, true); } currCompDist = m_pcRdCost->getDistPart(orgResiBuf, resiBuf, channelBitDepth, compID, DF_SSE); @@ -6788,6 +6803,9 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par currCompCost = m_pcRdCost->calcRdCost(currCompFracBits, currCompDist, false); #else currCompCost = m_pcRdCost->calcRdCost(currCompFracBits, currCompDist); +#endif +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + } #endif } else if( transformMode > 0 && !bUseCrossCPrediction ) diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index ebc5ab44132e81daeafa53e611292b0ec49b2815..dd6f112b301ba4d98a1f72878fa01b6266bbf721 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -3637,6 +3637,9 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par } } +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + cuCtx.mtsLastScanPos = false; +#endif //----- determine rate and r-d cost ----- if( ( sps.getUseLFNST() ? ( modeId == lastCheckId && modeId != 0 && checkTransformSkip ) : ( trModes[ modeId ].first != 0 ) ) && !TU::getCbfAtDepth( tu, COMPONENT_Y, currDepth ) ) { @@ -3653,6 +3656,20 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par { singleTmpFracBits = xGetIntraFracBitsQT( *csFull, partitioner, true, false, subTuCounter, ispType, &cuCtx ); } +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + if (tu.mtsIdx[COMPONENT_Y] > MTS_SKIP) + { + if (!cuCtx.mtsLastScanPos) + { + singleCostTmp = MAX_DOUBLE; + } + else + { + singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma); + } + } + else +#endif singleCostTmp = m_pcRdCost->calcRdCost( singleTmpFracBits, singleDistTmpLuma ); } @@ -3830,6 +3847,9 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; cuCtx.lfnstLastScanPos = false; cuCtx.violatesMtsCoeffConstraint = false; +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + cuCtx.mtsLastScanPos = false; +#endif //----- determine rate and r-d cost ----- csSplit->fracBits = xGetIntraFracBitsQT( *csSplit, partitioner, true, false, cu.ispMode ? 0 : -1, ispType, &cuCtx ); @@ -4123,6 +4143,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti } } +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + CUCtx cuCtx; + cuCtx.isDQPCoded = true; + cuCtx.isChromaQpAdjCoded = true; +#endif //----- determine rate and r-d cost ----- if ((sps.getUseLFNST() ? (modeId == lastCheckId && modeId != 0 && checkTransformSkip) : (trModes[modeId].first != 0)) && !TU::getCbfAtDepth(tu, COMPONENT_Y, currDepth)) { @@ -4131,7 +4156,24 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti } else { +#if JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND + singleTmpFracBits = xGetIntraFracBitsQT(*csFull, partitioner, true, false, -1, TU_NO_ISP, &cuCtx); + + if (tu.mtsIdx[COMPONENT_Y] > MTS_SKIP) + { + if (!cuCtx.mtsLastScanPos) + { + singleCostTmp = MAX_DOUBLE; + } + else + { + singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma); + } + } + else +#else singleTmpFracBits = xGetIntraFracBitsQT(*csFull, partitioner, true, false, -1, TU_NO_ISP); +#endif singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma); } @@ -4617,7 +4659,11 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio Distortion singleDistCTmp = 0; double singleCostTmp = 0; const int crossCPredictionModesToTest = checkCrossComponentPrediction ? 2 : 1; +#if JVET_Q0784_LFNST_COMBINATION + const bool tsAllowed = TU::isTSAllowed(currTU, compID) && m_pcEncCfg->getUseChromaTS() && !currTU.cu->lfnstIdx; +#else const bool tsAllowed = TU::isTSAllowed(currTU, compID) && (m_pcEncCfg->getUseChromaTS()); +#endif uint8_t nNumTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests std::vector<TrMode> trModes; trModes.push_back(TrMode(0, true)); // DCT2