diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index bee99bcb21e37dd80613583421f626a787c25a36..e134f2a4dbebcde5c07aaa145ced313786f706e1 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -884,7 +884,13 @@ static const int LM_SYMBOL_NUM = (1 + NUM_LMC_MODE); static const int MAX_NUM_MIP_MODE = 32; ///< maximum number of MIP pred. modes #if JVET_AB0155_SGPM +#if JVET_AJ0112_REGRESSION_SGPM +static const int RSGPM_CAND_NUM = 4; +static const int SGPM_CAND_NUM = 16; +static const int SGPM_NUM = RSGPM_CAND_NUM + SGPM_CAND_NUM; +#else static const int SGPM_NUM = 16; +#endif static const int FAST_UDI_MAX_RDMODE_NUM = (NUM_LUMA_MODE + MAX_NUM_MIP_MODE + SGPM_NUM); ///< maximum number of RD comparison in fast-UDI estimation loop #else diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp index cb57db0e926565c2c3104227b1f2f337a0829661..c18de13d3915495666cbab13239c6f23b7a7da89 100644 --- a/source/Lib/CommonLib/IntraPrediction.cpp +++ b/source/Lib/CommonLib/IntraPrediction.cpp @@ -445,7 +445,11 @@ void IntraPrediction::init(ChromaFormat chromaFormatIDC, const unsigned bitDepth } // the number of total temporal buffers can be adjusted by changing the number here +#if JVET_AJ0112_REGRESSION_SGPM + m_sgpmBuffer.resize(NUM_PRIMARY_MOST_PROBABLE_MODES + SGPM_NUM_BVS + 1); +#else m_sgpmBuffer.resize(1); +#endif for (auto &buffer: m_sgpmBuffer) { @@ -2669,18 +2673,21 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co #if JVET_AB0155_SGPM - if(PU::isSgpm(pu, channelType)) + if (PU::isSgpm(pu, channelType)) { - int width = piPred.width; + int width = piPred.width; int height = piPred.height; const UnitArea localUnitArea(pu.chromaFormat, Area(0, 0, width, height)); PelBuf predFusion = m_tempBuffer[1].getBuf(localUnitArea.Y()); IntraPredParam m_ipaParam2 = m_ipaParam; CompArea compArea = (compID == COMPONENT_Y) ? pu.Y() - : (compID == COMPONENT_Cb) ? pu.Cb() : pu.Cr(); + : (compID == COMPONENT_Cb) ? pu.Cb() : pu.Cr(); +#if JVET_AJ0112_REGRESSION_SGPM + initIntraPatternChType(*pu.cu, pu.Y(), true, 0, false); +#endif #if JVET_AG0152_SGPM_ITMP_IBC bool isBvPredicted = 0; - if (pu.cu->sgpmMode1 >= SGPM_BV_START_IDX && pu.cu->ispMode == 0 ) + if (pu.cu->sgpmMode1 >= SGPM_BV_START_IDX && pu.cu->ispMode == 0) { isBvPredicted = 1; Mv bv = pu.cu->sgpmBv1; @@ -2693,61 +2700,79 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co if (!isBvPredicted) { #endif - initIntraPatternChType(*pu.cu, compArea, false, 1); - const uint32_t uiDirMode2 = PU::getFinalIntraMode(pu, channelType, 1); - const CPelBuf &srcBuf2 = CPelBuf(getPredictorPtr(compID), srcStride, srcHStride); - switch (uiDirMode2) - { + initIntraPatternChType(*pu.cu, compArea, false, 1); + const uint32_t uiDirMode2 = PU::getFinalIntraMode(pu, channelType, 1); + const CPelBuf &srcBuf2 = CPelBuf(getPredictorPtr(compID), srcStride, srcHStride); + switch (uiDirMode2) + { #if JVET_AC0105_DIRECTIONAL_PLANAR - case (PLANAR_IDX): xPredIntraPlanar(srcBuf2, predFusion, 0); break; + case (PLANAR_IDX): xPredIntraPlanar(srcBuf2, predFusion, 0); break; #else - case (PLANAR_IDX): xPredIntraPlanar(srcBuf2, predFusion); break; + case (PLANAR_IDX): xPredIntraPlanar(srcBuf2, predFusion); break; #endif - case (DC_IDX): xPredIntraDc(srcBuf2, predFusion, channelType, false); break; + case (DC_IDX): xPredIntraDc(srcBuf2, predFusion, channelType, false); break; #if JVET_AB0157_INTRA_FUSION - default: - int weightMode = 4; - xPredIntraAng( + default: + int weightMode = 4; + xPredIntraAng( #if JVET_AJ0057_HL_INTRA_METHOD_CONTROL - pu, + pu, #endif - srcBuf2, predFusion, channelType, clpRng, bExtIntraDir, srcBuf2nd, pu.cu->ispMode!=NOT_INTRA_SUBPARTITIONS, weightMode); break; + srcBuf2, predFusion, channelType, clpRng, bExtIntraDir, srcBuf2nd, pu.cu->ispMode != NOT_INTRA_SUBPARTITIONS, weightMode); break; #else - default: xPredIntraAng( + default: xPredIntraAng( #if JVET_AJ0057_HL_INTRA_METHOD_CONTROL - pu, + pu, #endif - srcBuf2, predFusion, channelType, clpRng, bExtIntraDir); break; + srcBuf2, predFusion, channelType, clpRng, bExtIntraDir); break; #endif - } + } - #if JVET_X0148_TIMD_PDPC +#if JVET_X0148_TIMD_PDPC #if CIIP_PDPC - if ((m_ipaParam.applyPDPC || pu.ciipPDPC) && (uiDirMode2 == PLANAR_IDX || uiDirMode2 == DC_IDX)) + if ((m_ipaParam.applyPDPC || pu.ciipPDPC) && (uiDirMode2 == PLANAR_IDX || uiDirMode2 == DC_IDX)) #else - if (m_ipaParam.applyPDPC && (uiDirMode2 == PLANAR_IDX || uiDirMode2 == DC_IDX)) + if (m_ipaParam.applyPDPC && (uiDirMode2 == PLANAR_IDX || uiDirMode2 == DC_IDX)) #endif - { - xIntraPredPlanarDcPdpc(srcBuf2, m_tempBuffer[1].getBuf(localUnitArea.Y()).buf, - m_tempBuffer[1].getBuf(localUnitArea.Y()).stride, iWidth, iHeight + { + xIntraPredPlanarDcPdpc(srcBuf2, m_tempBuffer[1].getBuf(localUnitArea.Y()).buf, + m_tempBuffer[1].getBuf(localUnitArea.Y()).stride, iWidth, iHeight #if CIIP_PDPC - ,pu.ciipPDPC + , pu.ciipPDPC #endif - ); - } + ); + } #endif #if JVET_AG0152_SGPM_ITMP_IBC } #endif - - m_ipaParam = m_ipaParam2; - + + m_ipaParam = m_ipaParam2; + #if JVET_AJ0107_GPM_SHAPE_ADAPT - int splitDir = g_sgpmSplitDir[pu.cu->sgpmSplitDir]; + int splitDir = g_sgpmSplitDir[pu.cu->sgpmSplitDir]; #else - int splitDir = pu.cu->sgpmSplitDir; + int splitDir = pu.cu->sgpmSplitDir; #endif +#if JVET_AJ0112_REGRESSION_SGPM + if (PU::isRegressionSgpm(pu)) + { + PelUnitBuf pred = PelUnitBuf(pu.chromaFormat, piPred); + PelUnitBuf predTemp = PelUnitBuf(pu.chromaFormat, predFusion); + m_blendBuf.resize(pu.lwidth() * pu.lheight()); + int16_t* blendBuf = m_blendBuf.data(); + WeightBuf bufWeight = WeightBuf(blendBuf, pu.lumaSize()); + const int geoBlendingLog2WeightBase = 5; + m_if.m_weightAffineBlk(pu, bufWeight, geoBlendingLog2WeightBase, pu.cu->blendModel); + m_if.weightedBlendBlk(pu, pu.lumaSize().width, pu.lumaSize().height, COMPONENT_Y, pred, pred, predTemp, bufWeight, geoBlendingLog2WeightBase, false); + } + else + { + m_if.m_weightedSgpm(pu, width, height, compID, splitDir, piPred, piPred, predFusion); + } +#else m_if.m_weightedSgpm(pu, width, height, compID, splitDir, piPred, piPred, predFusion); +#endif } #endif @@ -8698,6 +8723,11 @@ void IntraPrediction::deriveSgpmModeOrdered(const CPelBuf &recoBuf, const CompAr bool sadPartsNeeded[NUM_LUMA_MODE + SGPM_NUM_BVS][GEO_NUM_PARTITION_MODE] = {}; #endif bool ipmNeeded[NUM_LUMA_MODE + SGPM_NUM_BVS] = {}; +#if JVET_AJ0112_REGRESSION_SGPM + bool ipmNeededforRsgpm[NUM_LUMA_MODE + SGPM_NUM_BVS] = {}; + int ipmIdxInList[NUM_LUMA_MODE]; + memset(ipmIdxInList, 0, NUM_LUMA_MODE * sizeof(int)); +#endif #if JVET_AH0200_INTRA_TMP_BV_REORDER int numBVs = (int)m_sgpmMvBasedMergeCandidates.size(); @@ -8760,6 +8790,12 @@ void IntraPrediction::deriveSgpmModeOrdered(const CPelBuf &recoBuf, const CompAr for (int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++) { #endif +#if JVET_AJ0112_REGRESSION_SGPM + if (!pu.cs->pcv->isEncoder && PU::isRegressionSgpm(pu)) + { + break; + } +#endif #if JVET_AJ0107_GPM_SHAPE_ADAPT #else if (!g_sgpmSplitDir[splitDir]) @@ -8813,17 +8849,60 @@ void IntraPrediction::deriveSgpmModeOrdered(const CPelBuf &recoBuf, const CompAr } } +#if JVET_AJ0112_REGRESSION_SGPM + const int numRegularMode = NUM_PRIMARY_MOST_PROBABLE_MODES; + uint8_t mpmList[numRegularMode]; + if (PU::isRegressionSgpmAllow(pu) && (pu.cs->pcv->isEncoder || PU::isRegressionSgpm(pu))) + { + int numCand = 0; + mpmList[numCand++] = PLANAR_IDX; + numCand += getSpatialIpm(pu, mpmList + 1, numRegularMode - 1 +#if JVET_AC0094_REF_SAMPLES_OPT + , true +#endif + ); + fillMPMList(pu, mpmList, numRegularMode, numCand, false); + for (int modeIdx = 0; modeIdx < numRegularMode; modeIdx++) + { + ipmNeededforRsgpm[mpmList[modeIdx]] = true; + ipmIdxInList[mpmList[modeIdx]] = modeIdx + 1; + } +#if JVET_AG0152_SGPM_ITMP_IBC + for (int modeIdx = 0; modeIdx < numItmpIbc; modeIdx++) + { + ipmNeededforRsgpm[SGPM_BV_START_IDX + modeIdx] = true; + } +#endif + } +#endif + for (int ipmIdx = 0; ipmIdx < NUM_LUMA_MODE; ipmIdx++) { +#if JVET_AJ0112_REGRESSION_SGPM + if (ipmNeeded[ipmIdx] || ipmNeededforRsgpm[ipmIdx]) +#else if (ipmNeeded[ipmIdx]) +#endif { int iMode = MAP67TO131(ipmIdx); initPredTimdIntraParams(pu, area, iMode, true); +#if JVET_AJ0112_REGRESSION_SGPM + Pel *tempPred = m_sgpmBuffer[ipmIdxInList[ipmIdx]].getBuf(localUnitArea.Y()).buf; +#else Pel *tempPred = m_sgpmBuffer[0].getBuf(localUnitArea.Y()).buf; +#endif predTimdIntraAng(COMPONENT_Y, pu, iMode, tempPred, uiPredStride, uiRealW, uiRealH, eTempType, (eTempType == ABOVE_NEIGHBOR) ? 0 : iTempWidth, (eTempType == LEFT_NEIGHBOR) ? 0 : iTempHeight); +#if JVET_AJ0112_REGRESSION_SGPM + if (!ipmNeeded[ipmIdx]) + { + continue; + } + PelBuf predBuf = m_sgpmBuffer[ipmIdxInList[ipmIdx]].getBuf(localUnitArea.Y()); +#else PelBuf predBuf = m_sgpmBuffer[0].getBuf(localUnitArea.Y()); +#endif PelBuf recBuf = cs.picture->getRecoBuf(area); PelBuf adBuf = m_sgpmBuffer[0].getBuf(localUnitArea.Y()); @@ -8856,27 +8935,55 @@ void IntraPrediction::deriveSgpmModeOrdered(const CPelBuf &recoBuf, const CompAr for (int i = 0; i < numItmpIbc; i++) { int ipmIdx = SGPM_BV_START_IDX + i; +#if JVET_AJ0112_REGRESSION_SGPM + if (ipmNeeded[ipmIdx] || ipmNeededforRsgpm[ipmIdx]) +#else if (ipmNeeded[ipmIdx]) +#endif { #if JVET_AH0200_INTRA_TMP_BV_REORDER +#if JVET_AJ0112_REGRESSION_SGPM + PelUnitBuf tempPUTopBufWithIdx(pu.chromaFormat, PelBuf(m_sgpmBuffer[NUM_PRIMARY_MOST_PROBABLE_MODES + 1 + i].getBuf(localUnitArea.Y()).buf + iTempWidth, uiPredStride, uiRealW - iTempWidth, iTempHeight)); + PelUnitBuf tempPULeftBufWithIdx(pu.chromaFormat, PelBuf(m_sgpmBuffer[NUM_PRIMARY_MOST_PROBABLE_MODES + 1 + i].getBuf(localUnitArea.Y()).buf + iTempHeight * uiPredStride, uiPredStride, iTempWidth, uiRealH - iTempHeight)); +#endif Mv tempMv(BVCostVec[i].first); Mv mvTop(0, -iTempHeight); mvTop.changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL); mvTop += tempMv; +#if JVET_AJ0112_REGRESSION_SGPM + m_pcInterPred->getPredIBCBlk(pu, COMPONENT_Y, pu.cs->picture, mvTop, tempPUTopBufWithIdx, true, true); +#else m_pcInterPred->getPredIBCBlk(pu, COMPONENT_Y, pu.cs->picture, mvTop, tempPUTopBuf, true, true); +#endif Mv mvLeft(-iTempWidth, 0); mvLeft.changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL); mvLeft += tempMv; +#if JVET_AJ0112_REGRESSION_SGPM + m_pcInterPred->getPredIBCBlk(pu, COMPONENT_Y, pu.cs->picture, mvLeft, tempPULeftBufWithIdx, true, true); +#else m_pcInterPred->getPredIBCBlk(pu, COMPONENT_Y, pu.cs->picture, mvLeft, tempPULeftBuf, true,true); +#endif +#else +#if JVET_AJ0112_REGRESSION_SGPM + Pel* tempPred = m_sgpmBuffer[NUM_PRIMARY_MOST_PROBABLE_MODES + 1 + i].getBuf(localUnitArea.Y()).buf; #else Pel* tempPred = m_sgpmBuffer[0].getBuf(localUnitArea.Y()).buf; +#endif Pel* piOrg = cs.picture->getRecoBuf(area).buf; int iOrgStride = cs.picture->getRecoBuf(area).stride; piOrg += (iRefY - iCurY) * iOrgStride + (iRefX - iCurX); predTimdIbcItmp(COMPONENT_Y, pu, BVCostVec[i].first, tempPred, uiPredStride, uiRealW, uiRealH, eTempType, iTempWidth, iTempHeight, piOrg, iOrgStride); #endif +#if JVET_AJ0112_REGRESSION_SGPM + if (!ipmNeeded[ipmIdx]) + { + continue; + } + PelBuf predBuf = m_sgpmBuffer[NUM_PRIMARY_MOST_PROBABLE_MODES + 1 + i].getBuf(localUnitArea.Y()); +#else PelBuf predBuf = m_sgpmBuffer[0].getBuf(localUnitArea.Y()); +#endif PelBuf recBuf = cs.picture->getRecoBuf(area); PelBuf adBuf = m_sgpmBuffer[0].getBuf(localUnitArea.Y()); @@ -8908,12 +9015,85 @@ void IntraPrediction::deriveSgpmModeOrdered(const CPelBuf &recoBuf, const CompAr #endif // check every possible combination uint32_t cntComb = 0; +#if JVET_AJ0112_REGRESSION_SGPM + static_vector<SgpmInfo, SGPM_CAND_NUM> tmpModeList; + static_vector<double, SGPM_CAND_NUM> tmpCostList; + const int bcwBlendingLog2WeightBase = 5; // BCW is 3, GEO is 5 + int min = 1; + int max = (1 << bcwBlendingLog2WeightBase) - 1; + AffineBlendingModel blendModel; + blendModel = AffineBlendingModel(bcwBlendingLog2WeightBase, min, max); // only positive weights + bool skipRsgpm = (!PU::isRegressionSgpmAllow(pu) || (!pu.cs->pcv->isEncoder && !PU::isRegressionSgpm(pu))); + if (!skipRsgpm) + { + for (int mode0Idx = 0; mode0Idx < numRegularMode + numItmpIbc - 1; mode0Idx++) + { + for (int mode1Idx = mode0Idx + 1; mode1Idx < numRegularMode + numItmpIbc; mode1Idx++) + { + if (mode0Idx == mode1Idx) + { + continue; + } + + int ipm0Idx = 0; + int ipm1Idx = 0; + Mv sgpmBv0 = Mv(0, 0); + Mv sgpmBv1 = Mv(0, 0); + PelBuf tempPred0; + PelBuf tempPred1; + + if (mode0Idx < numRegularMode) + { + ipm0Idx = mpmList[mode0Idx]; + tempPred0 = m_sgpmBuffer[mode0Idx + 1].getBuf(localUnitArea.Y()); + } + else + { + ipm0Idx = SGPM_BV_START_IDX + mode0Idx - numRegularMode; + sgpmBv0 = BVCostVec[ipm0Idx - SGPM_BV_START_IDX].first; + tempPred0 = m_sgpmBuffer[mode0Idx + 1].getBuf(localUnitArea.Y()); + } + if (mode1Idx < numRegularMode) + { + ipm1Idx = mpmList[mode1Idx]; + tempPred1 = m_sgpmBuffer[mode1Idx + 1].getBuf(localUnitArea.Y()); + } + else + { + ipm1Idx = SGPM_BV_START_IDX + mode1Idx - numRegularMode; + sgpmBv1 = BVCostVec[ipm1Idx - SGPM_BV_START_IDX].first; + tempPred1 = m_sgpmBuffer[mode1Idx + 1].getBuf(localUnitArea.Y()); + } + + PelBuf recBuf = cs.picture->getRecoBuf(area); + PelBuf adBuf = m_sgpmBuffer[0].getBuf(localUnitArea.Y()); + // derive weights + blendModel = AffineBlendingModel(bcwBlendingLog2WeightBase, min, max); // only positive weights + double cost = (double)deriveSgpmBlending(pu, tempPred0, tempPred1, recBuf, adBuf, blendModel); + + cntComb++; + + if ((cntComb > RSGPM_CAND_NUM && cost < candCostList[RSGPM_CAND_NUM - 1]) || cntComb <= RSGPM_CAND_NUM) + { + updateCandList(SgpmInfo(0, ipm0Idx, ipm1Idx, sgpmBv0, sgpmBv1, true, blendModel), cost, candModeList, candCostList, RSGPM_CAND_NUM); + } + } + } + cntComb = 0; + } +#endif #if JVET_AJ0107_GPM_SHAPE_ADAPT for (int splitDir = 0; splitDir < SGPM_TOTAL_NUM_PARTITIONS; splitDir++) #else for (int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++) #endif { +#if JVET_AJ0112_REGRESSION_SGPM + if (!pu.cs->pcv->isEncoder && PU::isRegressionSgpm(pu)) + { + break; + } +#endif #if JVET_AJ0107_GPM_SHAPE_ADAPT #else if (!g_sgpmSplitDir[splitDir]) @@ -8956,6 +9136,22 @@ void IntraPrediction::deriveSgpmModeOrdered(const CPelBuf &recoBuf, const CompAr cntComb++; +#if JVET_AJ0112_REGRESSION_SGPM + if (!PU::isRegressionSgpmAllow(pu)) + { + if ((cntComb > SGPM_NUM && cost < candCostList[SGPM_NUM - 1]) || cntComb <= SGPM_NUM) + { + updateCandList(SgpmInfo(splitDir, ipm0Idx, ipm1Idx, sgpmBv0, sgpmBv1, false, blendModel), cost, candModeList, candCostList, SGPM_NUM); + } + } + else + { + if ((cntComb > SGPM_CAND_NUM && cost < tmpCostList[SGPM_CAND_NUM - 1]) || cntComb <= SGPM_CAND_NUM) + { + updateCandList(SgpmInfo(splitDir, ipm0Idx, ipm1Idx, sgpmBv0, sgpmBv1, false, blendModel), cost, tmpModeList, tmpCostList, SGPM_CAND_NUM); + } + } +#else if ((cntComb > SGPM_NUM && cost < candCostList[SGPM_NUM - 1]) || cntComb <= SGPM_NUM) { #if JVET_AG0152_SGPM_ITMP_IBC @@ -8964,11 +9160,190 @@ void IntraPrediction::deriveSgpmModeOrdered(const CPelBuf &recoBuf, const CompAr updateCandList(SgpmInfo(splitDir, ipm0Idx, ipm1Idx), cost, candModeList, candCostList, SGPM_NUM); #endif } +#endif } } } + +#if JVET_AJ0112_REGRESSION_SGPM + if (PU::isRegressionSgpmAllow(pu)) + { + SgpmInfo sgpmInfo = SgpmInfo(); + if (!pu.cs->pcv->isEncoder && !PU::isRegressionSgpm(pu)) + { + for (int i = 0; i < RSGPM_CAND_NUM; i++) + { + candModeList.push_back(sgpmInfo); + candCostList.push_back(0); + } + } + if (pu.cs->pcv->isEncoder || !PU::isRegressionSgpm(pu)) + { + for (int i = 0; i < SGPM_CAND_NUM; i++) + { + candModeList.push_back(tmpModeList[i]); + candCostList.push_back(tmpCostList[i]); + } + } + } +#endif +} +#if JVET_AJ0112_REGRESSION_SGPM +int IntraPrediction::deriveSgpmBlending(PredictionUnit& pu, PelBuf &predBuf0, PelBuf &predBuf1, PelBuf &recBuf, PelBuf &adBuf, AffineBlendingModel &blendModel) +{ + int width = pu.lumaSize().width; + int height = pu.lumaSize().height; + const int channelBitDepth = pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA); + + Pel(*A)[CCCM_REF_SAMPLES_MAX] = m_a; + static Pel Y[BCW_MAX_REF_SAMPLES]; + + int sampleNum = 0; + const int iTempWidth = SGPM_TEMPLATE_SIZE, iTempHeight = SGPM_TEMPLATE_SIZE; + + // top template + Pel *piPred0 = predBuf0.buf + iTempWidth; + Pel *piPred1 = predBuf1.buf + iTempWidth; + Pel *piRec = recBuf.buf - iTempHeight * recBuf.stride; + + for (int y = 0; y < iTempHeight; y++) + { + for (int x = 0; x < width; x++) + { + int posX = x; + int posY = y - iTempHeight; + A[0][sampleNum] = ((piPred1[x + y * predBuf1.stride] - piPred0[x + y * predBuf0.stride]) * posX); + A[1][sampleNum] = ((piPred1[x + y * predBuf1.stride] - piPred0[x + y * predBuf0.stride]) * posY); + A[2][sampleNum] = (piPred1[x + y * predBuf1.stride] - piPred0[x + y * predBuf0.stride]); + Y[sampleNum++] = (piRec[x + y * recBuf.stride] - piPred0[x + y * predBuf0.stride]); + } + } + + // left template + piPred0 = predBuf0.buf + iTempHeight * predBuf0.stride; + piPred1 = predBuf1.buf + iTempHeight * predBuf1.stride; + piRec = recBuf.buf - iTempWidth; + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < iTempWidth; x++) + { + int posX = x - iTempWidth; + int posY = y; + A[0][sampleNum] = ((piPred1[x + y * predBuf1.stride] - piPred0[x + y * predBuf0.stride]) * posX); + A[1][sampleNum] = ((piPred1[x + y * predBuf1.stride] - piPred0[x + y * predBuf0.stride]) * posY); + A[2][sampleNum] = (piPred1[x + y * predBuf1.stride] - piPred0[x + y * predBuf0.stride]); + Y[sampleNum++] = (piRec[x + y * recBuf.stride] - piPred0[x + y * predBuf0.stride]); + } + } + CccmModel bcwModel(3, channelBitDepth); + CccmCovariance bcwSolver; + + if (!sampleNum) // should never happen + { + bcwModel.clearModel(); + } + else + { +#if JVET_AB0174_CCCM_DIV_FREE + bcwSolver.solve1(A, Y, sampleNum, 0, bcwModel); +#else + bcwSolver.solve2(A, Y, Y, sampleNum, bcwModel, bcwModel); +#endif + } + + const int bcwBlendingLog2WeightBase = 5; + + uint64_t maxParam = blendModel.params[0] > blendModel.params[1] ? blendModel.params[0] : blendModel.params[1]; + maxParam = blendModel.params[2] > maxParam ? blendModel.params[2] : maxParam; + int shiftA = floorLog2Uint64(maxParam) - 31; + shiftA = shiftA < 0 ? 0 : shiftA; + + int offsetA = shiftA ? 1 << (shiftA - 1) : 0; + blendModel.params[0] = (int)((bcwModel.params[0] + offsetA) >> shiftA); + blendModel.params[1] = (int)((bcwModel.params[1] + offsetA) >> shiftA); + blendModel.params[2] = (int)((bcwModel.params[2] + offsetA) >> shiftA); + + blendModel.shift = CCCM_DECIM_BITS - shiftA - bcwBlendingLog2WeightBase; + blendModel.offset = blendModel.shift ? (1 << (blendModel.shift - 1)) : 0; + if (blendModel.shift < 0) + { + printf("deriveRegressionSgpmBlending() failed.\n"); + exit(0); + } + + blendModel.valid = true; + + const int shiftBlend = bcwBlendingLog2WeightBase; + const int iOne = 1 << shiftBlend; + const int offBlend = 1 << (shiftBlend - 1); + + // check validity : + int cornerWeight[4]; + cornerWeight[0] = blendModel.compute(0, 0); + cornerWeight[1] = blendModel.compute(width - 1, 0); + cornerWeight[2] = blendModel.compute(0, height - 1); + cornerWeight[3] = blendModel.compute(width - 1, height - 1); + int minWeight = cornerWeight[0]; + int maxWeight = cornerWeight[0]; + for (int i = 0; i < 4; i++) + { + minWeight = std::min(minWeight, cornerWeight[i]); + maxWeight = std::max(maxWeight, cornerWeight[i]); + } + bool unvalid = abs(minWeight - maxWeight) <= 4; + if (unvalid) + { + blendModel.params[0] = (int)(0); + blendModel.params[1] = (int)(0); + blendModel.params[2] = (int)(16); + blendModel.shift = 0; + blendModel.offset = 0; + } + + // calculate SAD + // top template + piPred0 = predBuf0.buf + iTempWidth; + piPred1 = predBuf1.buf + iTempWidth; + piRec = recBuf.buf - iTempHeight * recBuf.stride; + Pel *piFinal = adBuf.buf + iTempWidth; + + int sad = 0; + + for (int y = 0; y < iTempHeight; y++) + { + for (int x = 0; x < width; x++) + { + int posX = x; + int posY = y - iTempHeight; + int iWeight = blendModel.compute(posX, posY); + piFinal[x + y * adBuf.stride] = ((iOne - iWeight) * piPred0[x + y * predBuf0.stride] + iWeight * piPred1[x + y * predBuf1.stride] + offBlend) >> shiftBlend; + sad += abs(piFinal[x + y * adBuf.stride] - piRec[x + y * recBuf.stride]); + } + } + + // left template + piPred0 = predBuf0.buf + iTempHeight * predBuf0.stride; + piPred1 = predBuf1.buf + iTempHeight * predBuf1.stride; + piRec = recBuf.buf - iTempWidth; + piFinal = adBuf.buf + iTempHeight * adBuf.stride; + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < iTempWidth; x++) + { + int posX = x - iTempWidth; + int posY = y; + int iWeight = blendModel.compute(posX, posY); + piFinal[x + y * adBuf.stride] = ((iOne - iWeight) * piPred0[x + y * predBuf0.stride] + iWeight * piPred1[x + y * predBuf1.stride] + offBlend) >> shiftBlend; + sad += abs(piFinal[x + y * adBuf.stride] - piRec[x + y * recBuf.stride]); + } + } + + return sad; } #endif +#endif #if JVET_AD0085_MPM_SORTING void IntraPrediction::deriveMPMSorted(const PredictionUnit& pu, uint8_t* mpm, int& sortedSize, int iStartIdx) diff --git a/source/Lib/CommonLib/IntraPrediction.h b/source/Lib/CommonLib/IntraPrediction.h index 8616bc643c30ebb160d5f0e9a48660649f07e1d8..9601371d850774aeb9dce09cf084b4f2e15f8909 100644 --- a/source/Lib/CommonLib/IntraPrediction.h +++ b/source/Lib/CommonLib/IntraPrediction.h @@ -314,6 +314,9 @@ public: #endif protected: +#if JVET_AJ0112_REGRESSION_SGPM + std::vector <int16_t> m_blendBuf; +#endif #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]; #else @@ -967,6 +970,9 @@ public: void deriveSgpmModeOrdered(const CPelBuf &recoBuf, const CompArea &area, CodingUnit &cu, static_vector<SgpmInfo, SGPM_NUM> &candModeList, static_vector<double, SGPM_NUM> & candCostList); +#if JVET_AJ0112_REGRESSION_SGPM + int deriveSgpmBlending(PredictionUnit& pu, PelBuf &predBuf0, PelBuf &predBuf1, PelBuf &recBuf, PelBuf &adBuf, AffineBlendingModel &blendModel); +#endif #endif #if JVET_AD0085_MPM_SORTING void deriveMPMSorted(const PredictionUnit& pu, uint8_t* mpm, int& sortedSize, int iStartIdx); diff --git a/source/Lib/CommonLib/TrQuant.cpp b/source/Lib/CommonLib/TrQuant.cpp index d10f3a8ba1f08d05a1b3ad3c127c9d7f6501f1b3..effbff74de9efcf3d32cdec8da33333cdf1bd20e 100644 --- a/source/Lib/CommonLib/TrQuant.cpp +++ b/source/Lib/CommonLib/TrQuant.cpp @@ -550,9 +550,17 @@ void TrQuant::xInvLfnst( const TransformUnit &tu, const ComponentID compID ) { #if JVET_AJ0107_GPM_SHAPE_ADAPT CHECK(tu.cu->sgpmSplitDir >= SGPM_TOTAL_NUM_PARTITIONS, "Invalid splitDir for SGPM"); +#if JVET_AJ0112_REGRESSION_SGPM + intraMode = PU::isRegressionSgpm(*tu.cs->getPU(area.pos(), toChannelType(compID))) ? tu.cu->sgpmDimdMode : g_geoAngle2IntraAng[g_geoParams[g_sgpmSplitDir[tu.cu->sgpmSplitDir]][0]]; +#else intraMode = g_geoAngle2IntraAng[g_geoParams[g_sgpmSplitDir[tu.cu->sgpmSplitDir]][0]]; +#endif +#else +#if JVET_AJ0112_REGRESSION_SGPM + intraMode = PU::isRegressionSgpm(*tu.cs->getPU(area.pos(), toChannelType(compID))) ? tu.cu->sgpmDimdMode : g_geoAngle2IntraAng[g_geoParams[tu.cu->sgpmSplitDir][0]]; #else intraMode = g_geoAngle2IntraAng[g_geoParams[tu.cu->sgpmSplitDir][0]]; +#endif #endif } #endif @@ -885,9 +893,17 @@ void TrQuant::xFwdLfnst( const TransformUnit &tu, const ComponentID compID, cons { #if JVET_AJ0107_GPM_SHAPE_ADAPT CHECK(tu.cu->sgpmSplitDir >= SGPM_TOTAL_NUM_PARTITIONS, "Invalid splitDir for SGPM"); +#if JVET_AJ0112_REGRESSION_SGPM + intraMode = PU::isRegressionSgpm(*tu.cs->getPU(area.pos(), toChannelType(compID))) ? tu.cu->sgpmDimdMode : g_geoAngle2IntraAng[g_geoParams[g_sgpmSplitDir[tu.cu->sgpmSplitDir]][0]]; +#else intraMode = g_geoAngle2IntraAng[g_geoParams[g_sgpmSplitDir[tu.cu->sgpmSplitDir]][0]]; +#endif +#else +#if JVET_AJ0112_REGRESSION_SGPM + intraMode = PU::isRegressionSgpm(*tu.cs->getPU(area.pos(), toChannelType(compID))) ? tu.cu->sgpmDimdMode : g_geoAngle2IntraAng[g_geoParams[tu.cu->sgpmSplitDir][0]]; #else intraMode = g_geoAngle2IntraAng[g_geoParams[tu.cu->sgpmSplitDir][0]]; +#endif #endif } #endif @@ -1362,9 +1378,17 @@ void TrQuant::getTrTypes(const TransformUnit tu, const ComponentID compID, int & { #if JVET_AJ0107_GPM_SHAPE_ADAPT CHECK(tu.cu->sgpmSplitDir >= SGPM_TOTAL_NUM_PARTITIONS, "Invalid splitDir for SGPM"); +#if JVET_AJ0112_REGRESSION_SGPM + predMode = PU::isRegressionSgpm(*tu.cs->getPU(area.pos(), toChannelType(compID))) ? tu.cu->sgpmDimdMode : g_geoAngle2IntraAng[g_geoParams[g_sgpmSplitDir[tu.cu->sgpmSplitDir]][0]]; +#else predMode = g_geoAngle2IntraAng[g_geoParams[g_sgpmSplitDir[tu.cu->sgpmSplitDir]][0]]; +#endif +#else +#if JVET_AJ0112_REGRESSION_SGPM + predMode = PU::isRegressionSgpm(*tu.cs->getPU(area.pos(), toChannelType(compID))) ? tu.cu->sgpmDimdMode : g_geoAngle2IntraAng[g_geoParams[tu.cu->sgpmSplitDir][0]]; #else predMode = g_geoAngle2IntraAng[g_geoParams[tu.cu->sgpmSplitDir][0]]; +#endif #endif } #endif @@ -3105,9 +3129,17 @@ int TrQuant::getLfnstIdx(const TransformUnit &tu, ComponentID compID) { #if JVET_AJ0107_GPM_SHAPE_ADAPT CHECK(tu.cu->sgpmSplitDir >= SGPM_TOTAL_NUM_PARTITIONS, "Invalid splitDir for SGPM"); +#if JVET_AJ0112_REGRESSION_SGPM + intraMode = PU::isRegressionSgpm(*tu.cs->getPU(area.pos(), toChannelType(compID))) ? tu.cu->sgpmDimdMode : g_geoAngle2IntraAng[g_geoParams[g_sgpmSplitDir[tu.cu->sgpmSplitDir]][0]]; +#else intraMode = g_geoAngle2IntraAng[g_geoParams[g_sgpmSplitDir[tu.cu->sgpmSplitDir]][0]]; +#endif +#else +#if JVET_AJ0112_REGRESSION_SGPM + intraMode = PU::isRegressionSgpm(*tu.cs->getPU(area.pos(), toChannelType(compID))) ? tu.cu->sgpmDimdMode : g_geoAngle2IntraAng[g_geoParams[tu.cu->sgpmSplitDir][0]]; #else intraMode = g_geoAngle2IntraAng[g_geoParams[tu.cu->sgpmSplitDir][0]]; +#endif #endif } #endif diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 3d4fabef4e11ceafea4ed3a66644e1428af45ae4..9cd2b8b16d619d0f641bf6f8efe2d36c5ddc8ecb 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -191,6 +191,7 @@ #define JVET_AB0155_SGPM 1 // JVET-AB0155: Spatial geometric partitioning mode #if JVET_AB0155_SGPM #define JVET_AC0189_SGPM_NO_BLENDING 1 // JVET-AC0189: Allow no blending for SGPM +#define JVET_AJ0112_REGRESSION_SGPM 1 // JVET-AJ0112: Regression-based SGPM blending #endif #define JVET_AB0157_TMRL 1 // JVET-AB0157: Template-based multiple reference line intra prediction #if JVET_AB0157_TMRL diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 8140f4f0d2c22c6e0acb40ceabf23d30a56c1d7f..154c49bbe7d5cac024142392bbe92ab27a9beb6e 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -476,6 +476,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other ) #if JVET_AB0067_MIP_DIMD_LFNST mipDimdMode = other.mipDimdMode; #endif +#if JVET_AJ0112_REGRESSION_SGPM + sgpmDimdMode = other.sgpmDimdMode; +#endif #if JVET_V0130_INTRA_TMP tmpFlag = other.tmpFlag; #if JVET_AC0115_INTRA_TMP_DIMD_MTS_LFNST @@ -786,6 +789,9 @@ void CodingUnit::initData() #if JVET_AB0067_MIP_DIMD_LFNST mipDimdMode = 0; #endif +#if JVET_AJ0112_REGRESSION_SGPM + sgpmDimdMode = 0; +#endif #if JVET_V0130_INTRA_TMP tmpFlag = false; #if JVET_AC0115_INTRA_TMP_DIMD_MTS_LFNST diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index 2f54ebf4431289fa3ef4df3f6f84e0e6ed73ed3d..9667e70b4ab7732fbab381322a03b92089277f5e 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -425,6 +425,9 @@ struct CodingUnit : public UnitArea #if JVET_AG0152_SGPM_ITMP_IBC Mv sgpmBv0; Mv sgpmBv1; +#endif +#if JVET_AJ0112_REGRESSION_SGPM + AffineBlendingModel sgpmBlendModel; #endif bool sgpm; int sgpmIdx; @@ -467,6 +470,9 @@ struct CodingUnit : public UnitArea #if JVET_AB0067_MIP_DIMD_LFNST int mipDimdMode; #endif +#if JVET_AJ0112_REGRESSION_SGPM + int sgpmDimdMode; +#endif #if JVET_V0130_INTRA_TMP bool tmpFlag; #if JVET_AC0115_INTRA_TMP_DIMD_MTS_LFNST @@ -1155,8 +1161,15 @@ struct SgpmInfo int sgpmMode1; Mv sgpmBv0; Mv sgpmBv1; +#if JVET_AJ0112_REGRESSION_SGPM + bool isRegression; + AffineBlendingModel blendModel; + SgpmInfo() : sgpmSplitDir(0), sgpmMode0(0), sgpmMode1(0), sgpmBv0(0, 0), sgpmBv1(0, 0), isRegression(false), blendModel(AffineBlendingModel(5, 1, 31)) {} + SgpmInfo(const int sd, const int sm0, const int sm1, const Mv sbv0, const Mv sbv1, bool isR, AffineBlendingModel bM) : sgpmSplitDir(sd), sgpmMode0(sm0), sgpmMode1(sm1), sgpmBv0(sbv0), sgpmBv1(sbv1), isRegression(isR), blendModel(bM){} +#else SgpmInfo() : sgpmSplitDir(0), sgpmMode0(0), sgpmMode1(0), sgpmBv0(0, 0), sgpmBv1(0, 0) {} SgpmInfo(const int sd, const int sm0, const int sm1, const Mv sbv0, const Mv sbv1) : sgpmSplitDir(sd), sgpmMode0(sm0), sgpmMode1(sm1), sgpmBv0(sbv0), sgpmBv1(sbv1) {} +#endif SgpmInfo& operator=(const SgpmInfo& other) { @@ -1165,6 +1178,10 @@ struct SgpmInfo sgpmMode1 = other.sgpmMode1; sgpmBv0 = other.sgpmBv0; sgpmBv1 = other.sgpmBv1; +#if JVET_AJ0112_REGRESSION_SGPM + isRegression = other.isRegression; + blendModel = other.blendModel; +#endif return *this; } }; diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 64f18539c302bcb4d5201a5cebf66123562e2113..8ddae2ea281aca9d55c3df92cf9de26f8fa76065 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -5104,6 +5104,16 @@ bool PU::isDMChromaSgpm(const PredictionUnit &pu) { return false; } +#if JVET_AJ0112_REGRESSION_SGPM +bool PU::isRegressionSgpm(const PredictionUnit &pu) +{ + return (pu.cu->sgpm && isRegressionSgpmAllow(pu) && pu.cu->sgpmIdx < RSGPM_CAND_NUM); +} +bool PU::isRegressionSgpmAllow(const PredictionUnit &pu) +{ + return (pu.lwidth() > 4 && pu.lheight() > 4); +} +#endif #endif #if JVET_AH0076_OBIC @@ -33602,9 +33612,17 @@ uint32_t PU::getFinalIntraModeForTransform( const TransformUnit &tu, const Compo if( PU::isSgpm( *tu.cs->getPU( area.pos(), toChannelType( compID ) ), toChannelType( compID ) ) ) { #if JVET_AJ0107_GPM_SHAPE_ADAPT +#if JVET_AJ0112_REGRESSION_SGPM + intraMode = PU::isRegressionSgpm(*tu.cs->getPU(area.pos(), toChannelType(compID))) ? tu.cu->sgpmDimdMode : g_geoAngle2IntraAng[g_geoParams[g_sgpmSplitDir[tu.cu->sgpmSplitDir]][0]]; +#else intraMode = g_geoAngle2IntraAng[g_geoParams[g_sgpmSplitDir[tu.cu->sgpmSplitDir]][0]]; +#endif +#else +#if JVET_AJ0112_REGRESSION_SGPM + intraMode = PU::isRegressionSgpm(*tu.cs->getPU(area.pos(), toChannelType(compID))) ? tu.cu->sgpmDimdMode : g_geoAngle2IntraAng[g_geoParams[tu.cu->sgpmSplitDir][0]]; #else intraMode = g_geoAngle2IntraAng[g_geoParams[tu.cu->sgpmSplitDir][0]]; +#endif #endif } #endif @@ -33760,9 +33778,17 @@ int getSpatialIpm(const PredictionUnit& pu, uint8_t* spatialIpm, const int maxCa if (neighborPu->cu->sgpm) { #if JVET_AJ0107_GPM_SHAPE_ADAPT +#if JVET_AJ0112_REGRESSION_SGPM + neighborMode = PU::isRegressionSgpm(*neighborPu) ? neighborPu->cu->sgpmDimdMode : g_geoAngle2IntraAng[g_geoParams[g_sgpmSplitDir[neighborPu->cu->sgpmSplitDir]][0]]; +#else neighborMode = g_geoAngle2IntraAng[g_geoParams[g_sgpmSplitDir[neighborPu->cu->sgpmSplitDir]][0]]; +#endif +#else +#if JVET_AJ0112_REGRESSION_SGPM + neighborMode = PU::isRegressionSgpm(*neighborPu) ? neighborPu->cu->sgpmDimdMode : g_geoAngle2IntraAng[g_geoParams[neighborPu->cu->sgpmSplitDir][0]]; #else - neighborMode = g_geoAngle2IntraAng[g_geoParams[neighborPu->cu->sgpmSplitDir][0]];; + neighborMode = g_geoAngle2IntraAng[g_geoParams[neighborPu->cu->sgpmSplitDir][0]]; +#endif #endif } #if JVET_AD0085_TMRL_EXTENSION diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index afbbdd79112e693e3e175cd138f23893dd59b8d1..20ffe3c56e57e314e3b79b6d1e99859dc6bfb414 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -279,6 +279,10 @@ namespace PU #if JVET_AB0155_SGPM bool isSgpm(const PredictionUnit &pu, const ChannelType &chType = CHANNEL_TYPE_LUMA); bool isDMChromaSgpm(const PredictionUnit &pu); +#if JVET_AJ0112_REGRESSION_SGPM + bool isRegressionSgpm(const PredictionUnit &pu); + bool isRegressionSgpmAllow(const PredictionUnit &pu); +#endif #endif #if JVET_AB0155_SGPM uint32_t getIntraDirLuma(const PredictionUnit &pu, const int partIdx = 0); diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 7bd40bc70c7429539b5e76ea91ac35107a2ca050..1cddbaa3a2216f42eb2da3d4271f895c812b9ae1 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -417,8 +417,11 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) static_vector<SgpmInfo, SGPM_NUM> sgpmInfoList; static_vector<double, SGPM_NUM> sgpmCostList; int sgpmIdx = currCU.sgpmIdx; - +#if JVET_AJ0112_REGRESSION_SGPM + if (currCU.lwidth() * currCU.lheight() <= 1024 && currCU.cs->sps->getUseTimd() && !PU::isRegressionSgpm(*pu)) +#else if (currCU.lwidth() * currCU.lheight() <= 1024 && currCU.cs->sps->getUseTimd() ) +#endif { m_pcIntraPred->deriveTimdMode(currCU.cs->picture->getRecoBuf(area), area, currCU, false, true); } @@ -432,6 +435,9 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) #if JVET_AG0152_SGPM_ITMP_IBC currCU.sgpmBv0 = sgpmInfoList[sgpmIdx].sgpmBv0; currCU.sgpmBv1 = sgpmInfoList[sgpmIdx].sgpmBv1; +#if JVET_AJ0112_REGRESSION_SGPM + currCU.blendModel = sgpmInfoList[sgpmIdx].blendModel; +#endif pu->intraDir[0] = currCU.sgpmMode0 >= SGPM_BV_START_IDX ? 0 : currCU.sgpmMode0; pu->intraDir1[0] = currCU.sgpmMode1 >= SGPM_BV_START_IDX ? 0 : currCU.sgpmMode1; #else @@ -1349,6 +1355,19 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID ) #endif ); } +#endif +#if JVET_AJ0112_REGRESSION_SGPM + if (compID == COMPONENT_Y && pu.cu->sgpm && PU::isRegressionSgpm(pu)) + { +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + m_pcIntraPred->IntraPrediction::deriveIpmForTransform(piPred, *pu.cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); + } #endif } } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 6e855806252e62bc396e503bc6ff6dc35b70725e..fe626ccb17c3cb6f4ebad8df625801874e5f728d 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -3862,6 +3862,9 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS m_pcIntraSearch->m_skipTimdLfnstMtsPass = false; m_modeCtrl->resetLfnstCost(); #endif +#if JVET_AJ0112_REGRESSION_SGPM + m_pcIntraSearch->m_skipSgpmLfnstMtsPass = false; +#endif #if JVET_AH0076_OBIC m_pcIntraSearch->m_skipObicLfnstMtsPass = false; m_pcIntraSearch->m_skipDimdLfnstMtsPass = false; diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index 6259405359ad5c627a5162b05631d33165144768..f8f9b5bd89983a90413a6f337362f2422fe2c0a6 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -633,6 +633,9 @@ void IntraSearch::init( EncCfg* pcEncCfg, #if INTRA_TRANS_ENC_OPT m_skipTimdLfnstMtsPass = false; #endif +#if JVET_AJ0112_REGRESSION_SGPM + m_skipSgpmLfnstMtsPass = false; +#endif #if JVET_AJ0061_TIMD_MERGE m_skipTimdMrgLfnstMtsPass = false; m_skipObicMode = false; @@ -988,6 +991,10 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c bool setSkipTimdControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag; double timdAngCost = MAX_DOUBLE; #endif +#if JVET_AJ0112_REGRESSION_SGPM + double sgpmCost = MAX_DOUBLE; + bool setSkipSgpmControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag; +#endif #if JVET_AJ0061_TIMD_MERGE bool setSkipTimdMrgControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag; double timdMrgAngCost[NUM_TIMD_MERGE_MODES]; @@ -1065,6 +1072,9 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c bool bestObicMode = false; int bestMipDimd = 0; #endif +#if JVET_AJ0112_REGRESSION_SGPM + int bestSgpmDimd = 0; +#endif #if JVET_W0123_TIMD_FUSION bool bestTimdMode = false; #if JVET_AJ0061_TIMD_MERGE @@ -2964,439 +2974,516 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c cu.dimd = false; cu.obicFlag = false; #endif -#if JVET_AB0155_SGPM - if (testSgpm) +#if JVET_AJ0112_REGRESSION_SGPM + if ((m_pcEncCfg->getUseFastLFNST() && !LFNSTLoadFlag) || !m_pcEncCfg->getUseFastLFNST()) { - if (SGPMSaveFlag) +#endif +#if JVET_AB0155_SGPM + if (testSgpm) { - m_uiSavedRdModeListSGPM.clear(); - m_dSavedModeCostSGPM.clear(); - m_uiSavedHadModeListSGPM.clear(); - m_dSavedHadListSGPM.clear(); + if (SGPMSaveFlag) + { + m_uiSavedRdModeListSGPM.clear(); + m_dSavedModeCostSGPM.clear(); + m_uiSavedHadModeListSGPM.clear(); + m_dSavedHadListSGPM.clear(); #if JVET_V0130_INTRA_TMP - cu.tmpFlag = false; + cu.tmpFlag = false; #endif - pu.multiRefIdx = 0; - cu.mipFlag = false; - + pu.multiRefIdx = 0; + cu.mipFlag = false; + #if JVET_AB0157_INTRA_FUSION - initIntraPatternChType(cu, pu.Y(), true, 0, false); + initIntraPatternChType(cu, pu.Y(), true, 0, false); #else - initIntraPatternChType(cu, pu.Y(), true); + initIntraPatternChType(cu, pu.Y(), true); #endif - // get single mode predictions - for (int sgpmIdx = 0; sgpmIdx < SGPM_NUM; sgpmIdx++) - { - int sgpmMode[2]; - sgpmMode[0] = sgpmInfoList[sgpmIdx].sgpmMode0; - sgpmMode[1] = sgpmInfoList[sgpmIdx].sgpmMode1; + // get single mode predictions + for (int sgpmIdx = 0; sgpmIdx < SGPM_NUM; sgpmIdx++) + { + int sgpmMode[2]; + sgpmMode[0] = sgpmInfoList[sgpmIdx].sgpmMode0; + sgpmMode[1] = sgpmInfoList[sgpmIdx].sgpmMode1; #if JVET_AG0152_SGPM_ITMP_IBC - Mv sgpmBV[2]; - sgpmBV[0] = sgpmInfoList[sgpmIdx].sgpmBv0; - sgpmBV[1] = sgpmInfoList[sgpmIdx].sgpmBv1; + Mv sgpmBV[2]; + sgpmBV[0] = sgpmInfoList[sgpmIdx].sgpmBv0; + sgpmBV[1] = sgpmInfoList[sgpmIdx].sgpmBv1; #endif - for (int idxIn2 = 0; idxIn2 < 2; idxIn2++) - { - if (!m_intraModeReady[sgpmMode[idxIn2]]) + for (int idxIn2 = 0; idxIn2 < 2; idxIn2++) { -#if JVET_AG0152_SGPM_ITMP_IBC - if (sgpmMode[idxIn2] >= SGPM_BV_START_IDX) + if (!m_intraModeReady[sgpmMode[idxIn2]]) { - // BV based mode - Mv timdBv = sgpmBV[idxIn2]; +#if JVET_AG0152_SGPM_ITMP_IBC + if (sgpmMode[idxIn2] >= SGPM_BV_START_IDX) + { + // BV based mode + Mv timdBv = sgpmBV[idxIn2]; #if JVET_AH0200_INTRA_TMP_BV_REORDER - predUsingBv(piPred.buf, piPred.stride, timdBv, cu, false); + predUsingBv(piPred.buf, piPred.stride, timdBv, cu, false); #else - predUsingBv(piPred.buf, piPred.stride, timdBv, cu); + predUsingBv(piPred.buf, piPred.stride, timdBv, cu); #endif - } - else - { + } + else + { #endif - pu.intraDir[0] = sgpmMode[idxIn2]; + pu.intraDir[0] = sgpmMode[idxIn2]; - initPredIntraParams(pu, pu.Y(), sps); + initPredIntraParams(pu, pu.Y(), sps); #if JVET_AH0209_PDP - predIntraAng(COMPONENT_Y, piPred, pu, false, false); + predIntraAng(COMPONENT_Y, piPred, pu, false, false); #elif JVET_AB0157_INTRA_FUSION - predIntraAng(COMPONENT_Y, piPred, pu, false); + predIntraAng(COMPONENT_Y, piPred, pu, false); #else - predIntraAng(COMPONENT_Y, piPred, pu); + predIntraAng(COMPONENT_Y, piPred, pu); #endif #if JVET_AG0152_SGPM_ITMP_IBC - } + } #endif - PelBuf predBuf(m_intraPredBuf[sgpmMode[idxIn2]], tmpArea); - predBuf.copyFrom(piPred); - m_intraModeReady[sgpmMode[idxIn2]] = 1; + PelBuf predBuf(m_intraPredBuf[sgpmMode[idxIn2]], tmpArea); + predBuf.copyFrom(piPred); + m_intraModeReady[sgpmMode[idxIn2]] = 1; + } } } - } - cu.sgpm = true; - // frac bits calculate once because all are the same - cu.sgpmIdx = 0; - cu.sgpmSplitDir = sgpmInfoList[0].sgpmSplitDir; - cu.sgpmMode0 = sgpmInfoList[0].sgpmMode0; - cu.sgpmMode1 = sgpmInfoList[0].sgpmMode1; + cu.sgpm = true; + // frac bits calculate once because all are the same + cu.sgpmIdx = 0; + cu.sgpmSplitDir = sgpmInfoList[0].sgpmSplitDir; + cu.sgpmMode0 = sgpmInfoList[0].sgpmMode0; + cu.sgpmMode1 = sgpmInfoList[0].sgpmMode1; #if JVET_AG0152_SGPM_ITMP_IBC - cu.sgpmBv0 = sgpmInfoList[0].sgpmBv0; - cu.sgpmBv1 = sgpmInfoList[0].sgpmBv1; - pu.intraDir[0] = cu.sgpmMode0 >= SGPM_BV_START_IDX ? 0 : cu.sgpmMode0; - pu.intraDir1[0] = cu.sgpmMode1 >= SGPM_BV_START_IDX ? 0 : cu.sgpmMode1; + cu.sgpmBv0 = sgpmInfoList[0].sgpmBv0; + cu.sgpmBv1 = sgpmInfoList[0].sgpmBv1; + pu.intraDir[0] = cu.sgpmMode0 >= SGPM_BV_START_IDX ? 0 : cu.sgpmMode0; + pu.intraDir1[0] = cu.sgpmMode1 >= SGPM_BV_START_IDX ? 0 : cu.sgpmMode1; #else - pu.intraDir[0] = cu.sgpmMode0; - pu.intraDir1[0] = cu.sgpmMode1; + pu.intraDir[0] = cu.sgpmMode0; + pu.intraDir1[0] = cu.sgpmMode1; #endif - - loadStartStates(); - - uint64_t fracModeBits = xFracModeBitsIntra(pu, 0, CHANNEL_TYPE_LUMA); +#if JVET_AJ0112_REGRESSION_SGPM + cu.blendModel = sgpmInfoList[0].blendModel; +#endif +#if !JVET_AJ0112_REGRESSION_SGPM + loadStartStates(); - for (int sgpmIdx = 0; sgpmIdx < SGPM_NUM; sgpmIdx++) - { - int sgpmMode0 = sgpmInfoList[sgpmIdx].sgpmMode0; - int sgpmMode1 = sgpmInfoList[sgpmIdx].sgpmMode1; - PelBuf src0(m_intraPredBuf[sgpmMode0], tmpArea); - PelBuf src1(m_intraPredBuf[sgpmMode1], tmpArea); + uint64_t fracModeBits = xFracModeBitsIntra(pu, 0, CHANNEL_TYPE_LUMA); +#endif + for (int sgpmIdx = 0; sgpmIdx < SGPM_NUM; sgpmIdx++) + { + int sgpmMode0 = sgpmInfoList[sgpmIdx].sgpmMode0; + int sgpmMode1 = sgpmInfoList[sgpmIdx].sgpmMode1; + PelBuf src0(m_intraPredBuf[sgpmMode0], tmpArea); + PelBuf src1(m_intraPredBuf[sgpmMode1], tmpArea); +#if JVET_AJ0112_REGRESSION_SGPM + cu.sgpmIdx = sgpmIdx; + loadStartStates(); + uint64_t fracModeBits = xFracModeBitsIntra(pu, 0, CHANNEL_TYPE_LUMA); + if (sgpmInfoList[sgpmIdx].isRegression) + { + PelUnitBuf pred = PelUnitBuf(pu.chromaFormat, piPred); + PelUnitBuf pred0 = PelUnitBuf(pu.chromaFormat, src0); + PelUnitBuf pred1 = PelUnitBuf(pu.chromaFormat, src1); + m_blendBuf.resize(pu.lwidth() * pu.lheight()); + int16_t* blendBuf = m_blendBuf.data(); + WeightBuf bufWeight = WeightBuf(blendBuf, pu.lumaSize()); + const int geoBlendingLog2WeightBase = 5; + pcInterPred->weightedAffineBlk(pu, bufWeight, geoBlendingLog2WeightBase, sgpmInfoList[sgpmIdx].blendModel); + pcInterPred->weightedBlendBlk(pu, 0, pred, pred0, pred1, bufWeight, geoBlendingLog2WeightBase, false); + } + else + { +#if JVET_AJ0107_GPM_SHAPE_ADAPT + m_if.m_weightedSgpm(pu, width, height, COMPONENT_Y, g_sgpmSplitDir[sgpmInfoList[sgpmIdx].sgpmSplitDir], piPred, src0, src1); +#else + m_if.m_weightedSgpm(pu, width, height, COMPONENT_Y, sgpmInfoList[sgpmIdx].sgpmSplitDir, piPred, src0, src1); +#endif + } +#else #if JVET_AJ0107_GPM_SHAPE_ADAPT - m_if.m_weightedSgpm(pu, width, height, COMPONENT_Y, g_sgpmSplitDir[sgpmInfoList[sgpmIdx].sgpmSplitDir], piPred, src0, src1); + m_if.m_weightedSgpm(pu, width, height, COMPONENT_Y, g_sgpmSplitDir[sgpmInfoList[sgpmIdx].sgpmSplitDir], piPred, src0, src1); #else - m_if.m_weightedSgpm(pu, width, height, COMPONENT_Y, sgpmInfoList[sgpmIdx].sgpmSplitDir, piPred, src0, src1); + m_if.m_weightedSgpm(pu, width, height, COMPONENT_Y, sgpmInfoList[sgpmIdx].sgpmSplitDir, piPred, src0, src1); +#endif #endif - PelBuf predBuf(m_sgpmPredBuf[sgpmIdx], tmpArea); - predBuf.copyFrom(piPred); + PelBuf predBuf(m_sgpmPredBuf[sgpmIdx], tmpArea); + predBuf.copyFrom(piPred); - Distortion minSadHad = 0; + Distortion minSadHad = 0; #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS - Distortion sadCost = distParamSad.distFunc(distParamSad); - minSadHad += std::min(sadCost * 2, distParamHad.distFunc(distParamHad)); + Distortion sadCost = distParamSad.distFunc(distParamSad); + minSadHad += std::min(sadCost * 2, distParamHad.distFunc(distParamHad)); #else - minSadHad += std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad)); + minSadHad += std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad)); #endif - double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass; + double cost = (double)minSadHad + (double)fracModeBits * sqrtLambdaForFirstPass; #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS - m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost); + m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost); #endif - updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, SGPM_IDX, + updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, SGPM_IDX, #if JVET_V0130_INTRA_TMP - false, //tmpFlag + false, //tmpFlag #endif #if JVET_AD0086_ENHANCED_INTRA_TMP - 0, false, false, + 0, false, false, #if JVET_AG0136_INTRA_TMP_LIC - false, 0, + false, 0, #endif - 0, 0, + 0, 0, #if JVET_AH0200_INTRA_TMP_BV_REORDER - -1, + - 1, #endif #endif - true, sgpmInfoList[sgpmIdx].sgpmSplitDir, sgpmInfoList[sgpmIdx].sgpmMode0, - sgpmInfoList[sgpmIdx].sgpmMode1, sgpmIdx + true, sgpmInfoList[sgpmIdx].sgpmSplitDir, sgpmInfoList[sgpmIdx].sgpmMode0, + sgpmInfoList[sgpmIdx].sgpmMode1, sgpmIdx #if JVET_AG0152_SGPM_ITMP_IBC - , sgpmInfoList[sgpmIdx].sgpmBv0, sgpmInfoList[sgpmIdx].sgpmBv1 + , sgpmInfoList[sgpmIdx].sgpmBv0, sgpmInfoList[sgpmIdx].sgpmBv1 #endif -), - cost, m_uiSavedRdModeListSGPM, m_dSavedModeCostSGPM, SGPM_NUM); - updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, SGPM_IDX, +#if JVET_AJ0112_REGRESSION_SGPM + , sgpmInfoList[sgpmIdx].isRegression, sgpmInfoList[sgpmIdx].blendModel +#endif + ), + cost, m_uiSavedRdModeListSGPM, m_dSavedModeCostSGPM, SGPM_NUM); + updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, SGPM_IDX, #if JVET_V0130_INTRA_TMP - false, //tmpFlag + false, //tmpFlag #endif #if JVET_AD0086_ENHANCED_INTRA_TMP - 0, false, false, + 0, false, false, #if JVET_AG0136_INTRA_TMP_LIC - false, 0, + false, 0, #endif - 0, 0, + 0, 0, #if JVET_AH0200_INTRA_TMP_BV_REORDER - -1, + - 1, #endif #endif - true, sgpmInfoList[sgpmIdx].sgpmSplitDir, sgpmInfoList[sgpmIdx].sgpmMode0, - sgpmInfoList[sgpmIdx].sgpmMode1, sgpmIdx + true, sgpmInfoList[sgpmIdx].sgpmSplitDir, sgpmInfoList[sgpmIdx].sgpmMode0, + sgpmInfoList[sgpmIdx].sgpmMode1, sgpmIdx #if JVET_AG0152_SGPM_ITMP_IBC - , sgpmInfoList[sgpmIdx].sgpmBv0, sgpmInfoList[sgpmIdx].sgpmBv1 + , sgpmInfoList[sgpmIdx].sgpmBv0, sgpmInfoList[sgpmIdx].sgpmBv1 #endif -), - double(minSadHad), m_uiSavedHadModeListSGPM, m_dSavedHadListSGPM, SGPM_NUM); - } - - cu.sgpm = false; - } - - int updateNum = std::min<int>( (numModesForFullRD + 1) / 2, (int)m_uiSavedRdModeListSGPM.size() ); +#if JVET_AJ0112_REGRESSION_SGPM + , sgpmInfoList[sgpmIdx].isRegression, sgpmInfoList[sgpmIdx].blendModel +#endif + ), + double(minSadHad), m_uiSavedHadModeListSGPM, m_dSavedHadListSGPM, SGPM_NUM); + } - for (auto listIdx = 0; listIdx < updateNum; listIdx++) - { - updateCandList(m_uiSavedRdModeListSGPM[listIdx], m_dSavedModeCostSGPM[listIdx], uiRdModeList, - candCostList, numModesForFullRD); - updateCandList(m_uiSavedHadModeListSGPM[listIdx], m_dSavedHadListSGPM[listIdx], uiHadModeList, - candHadList, numHadCand); + cu.sgpm = false; + } +#if JVET_AJ0112_REGRESSION_SGPM + numModesForFullRD++; + int updateNum = (int)m_uiSavedRdModeListSGPM.size(); +#else + int updateNum = std::min<int>((numModesForFullRD + 1) / 2, (int)m_uiSavedRdModeListSGPM.size()); +#endif + for (auto listIdx = 0; listIdx < updateNum; listIdx++) + { + updateCandList(m_uiSavedRdModeListSGPM[listIdx], m_dSavedModeCostSGPM[listIdx], uiRdModeList, + candCostList, numModesForFullRD); + updateCandList(m_uiSavedHadModeListSGPM[listIdx], m_dSavedHadListSGPM[listIdx], uiHadModeList, + candHadList, numHadCand); + } } - } #endif #if JVET_AG0058_EIP - if (testEip) - { - if (eipSaveFlag) + if (testEip) { - m_uiSavedRdModeListEip.clear(); - m_uiSavedHadModeListEip.clear(); - m_dSavedModeCostEip.clear(); - m_dSavedHadListEip.clear(); + if (eipSaveFlag) + { + m_uiSavedRdModeListEip.clear(); + m_uiSavedHadModeListEip.clear(); + m_dSavedModeCostEip.clear(); + m_dSavedHadListEip.clear(); #if JVET_AJ0082_MM_EIP - m_encBestEipCost = MAX_DOUBLE; - cu.eipMmFlag = false; - m_numSigEip = 0; + m_encBestEipCost = MAX_DOUBLE; + cu.eipMmFlag = false; + m_numSigEip = 0; #endif - cu.tmpFlag = false; - cu.mipFlag = false; - cu.sgpm = false; - pu.multiRefIdx = 0; + cu.tmpFlag = false; + cu.mipFlag = false; + cu.sgpm = false; + pu.multiRefIdx = 0; - cu.eipFlag = true; - cu.eipMerge = false; - initEipParams(pu, COMPONENT_Y); - static_vector<EipModelCandidate,NUM_DERIVED_EIP> eipModelCandList; - static_vector<EipModelCandidate, MAX_MERGE_EIP> eipMergeCandList; - getCurEipCands(pu, eipModelCandList); - getNeiEipCands(pu, eipMergeCandList); - reorderEipCands(pu, eipMergeCandList); - const int numRdEIP = std::max(NUM_EIP_MERGE_SIGNAL + NUM_DERIVED_EIP, (numModesForFullRD + 1) / 2); - for(int mergeFlag = 0; mergeFlag < 2; mergeFlag++) - { - cu.eipMerge = bool(mergeFlag); - for(int i = 0; i < (cu.eipMerge ? eipMergeCandList.size() : eipModelCandList.size()); i++) + cu.eipFlag = true; + cu.eipMerge = false; + initEipParams(pu, COMPONENT_Y); + static_vector<EipModelCandidate, NUM_DERIVED_EIP> eipModelCandList; + static_vector<EipModelCandidate, MAX_MERGE_EIP> eipMergeCandList; + getCurEipCands(pu, eipModelCandList); + getNeiEipCands(pu, eipMergeCandList); + reorderEipCands(pu, eipMergeCandList); + const int numRdEIP = std::max(NUM_EIP_MERGE_SIGNAL + NUM_DERIVED_EIP, (numModesForFullRD + 1) / 2); + for (int mergeFlag = 0; mergeFlag < 2; mergeFlag++) { - pu.intraDir[0] = i; -#if JVET_AJ0082_MM_EIP - cu.eipMmFlag = (!cu.eipMerge) && (i >= m_numSigEip); - if(cu.eipMmFlag) + cu.eipMerge = bool(mergeFlag); + for (int i = 0; i < (cu.eipMerge ? eipMergeCandList.size() : eipModelCandList.size()); i++) { - pu.intraDir[0] -= m_numSigEip; - } + pu.intraDir[0] = i; +#if JVET_AJ0082_MM_EIP + cu.eipMmFlag = (!cu.eipMerge) && (i >= m_numSigEip); + if (cu.eipMmFlag) + { + pu.intraDir[0] -= m_numSigEip; + } #endif - cu.eipModel = cu.eipMerge ? eipMergeCandList[i] : eipModelCandList[i]; - if(cu.eipMerge) - { - m_eipMergeModel[i] = cu.eipModel; + cu.eipModel = cu.eipMerge ? eipMergeCandList[i] : eipModelCandList[i]; + if (cu.eipMerge) + { + m_eipMergeModel[i] = cu.eipModel; #if JVET_AJ0082_MM_EIP - m_eipMergeModel[i].eipDimdMode = -1; + m_eipMergeModel[i].eipDimdMode = -1; #endif - } - else - { - m_eipModel[i] = cu.eipModel; - } - eipPred(pu, piPred); + } + else + { + m_eipModel[i] = cu.eipModel; + } + eipPred(pu, piPred); #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS - Distortion sadCost = distParamSad.distFunc(distParamSad); - Distortion minSadHad = std::min(sadCost * 2, distParamHad.distFunc(distParamHad)); + Distortion sadCost = distParamSad.distFunc(distParamSad); + Distortion minSadHad = std::min(sadCost * 2, distParamHad.distFunc(distParamHad)); #else - Distortion minSadHad = std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad)); + Distortion minSadHad = std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad)); #endif - loadStartStates(); + loadStartStates(); #if JVET_AJ0082_MM_EIP - uint64_t fracModeBits = xFracModeBitsIntra(pu, pu.intraDir[0], CHANNEL_TYPE_LUMA); + uint64_t fracModeBits = xFracModeBitsIntra(pu, pu.intraDir[0], CHANNEL_TYPE_LUMA); #else - uint64_t fracModeBits = xFracModeBitsIntra(pu, i, CHANNEL_TYPE_LUMA); + uint64_t fracModeBits = xFracModeBitsIntra(pu, i, CHANNEL_TYPE_LUMA); #endif - double cost = double(minSadHad) + double(fracModeBits) * sqrtLambdaForFirstPass; + double cost = double(minSadHad) + double(fracModeBits) * sqrtLambdaForFirstPass; #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS - m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost); + m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost); #endif - ModeInfo modeInfo(false, cu.eipMerge, 0, NOT_INTRA_SUBPARTITIONS, EIP_IDX + i); - PelBuf eipSaveBuf(cu.eipMerge ? m_eipMergePredBuf[i]: m_eipPredBuf[i], pu.Y()); - eipSaveBuf.copyFrom(piPred); + ModeInfo modeInfo(false, cu.eipMerge, 0, NOT_INTRA_SUBPARTITIONS, EIP_IDX + i); + PelBuf eipSaveBuf(cu.eipMerge ? m_eipMergePredBuf[i] : m_eipPredBuf[i], pu.Y()); + eipSaveBuf.copyFrom(piPred); #if JVET_AJ0082_MM_EIP - if(!cu.eipModel.bMm && cost < m_encBestEipCost) - { - m_encBestEipCost = cost; - } + if (!cu.eipModel.bMm && cost < m_encBestEipCost) + { + m_encBestEipCost = cost; + } #endif - updateCandList(modeInfo, cost, m_uiSavedRdModeListEip, m_dSavedModeCostEip, numRdEIP); - updateCandList(modeInfo, double(minSadHad * 0.8), m_uiSavedHadModeListEip, m_dSavedHadListEip, numRdEIP); + updateCandList(modeInfo, cost, m_uiSavedRdModeListEip, m_dSavedModeCostEip, numRdEIP); + updateCandList(modeInfo, double(minSadHad * 0.8), m_uiSavedHadModeListEip, m_dSavedHadListEip, numRdEIP); + } } - } #if !JVET_AJ0082_MM_EIP - for(const auto& modeInfo: m_uiSavedRdModeListEip) - { - CHECK(modeInfo.modeId < EIP_IDX || modeInfo.modeId >= EIP_IDX + std::max(NUM_DERIVED_EIP, MAX_MERGE_EIP), "A non-EIP mode is in EIP mode list") - const auto modeIdx = modeInfo.modeId - EIP_IDX; - if(modeInfo.mipTrFlg) + for (const auto& modeInfo : m_uiSavedRdModeListEip) { - PelBuf eipSaveBuf(m_eipMergePredBuf[modeIdx], pu.Y()); + CHECK(modeInfo.modeId < EIP_IDX || modeInfo.modeId >= EIP_IDX + std::max(NUM_DERIVED_EIP, MAX_MERGE_EIP), "A non-EIP mode is in EIP mode list") + const auto modeIdx = modeInfo.modeId - EIP_IDX; + if (modeInfo.mipTrFlg) + { + PelBuf eipSaveBuf(m_eipMergePredBuf[modeIdx], pu.Y()); #if JVET_AI0050_INTER_MTSS - int secondDimdIntraDir = 0; + int secondDimdIntraDir = 0; #endif - m_eipMergeModel[modeIdx].eipDimdMode = deriveIpmForTransform(eipSaveBuf, cu + m_eipMergeModel[modeIdx].eipDimdMode = deriveIpmForTransform(eipSaveBuf, cu #if JVET_AI0050_INTER_MTSS - , secondDimdIntraDir + , secondDimdIntraDir #endif - ); + ); #if JVET_AI0050_INTER_MTSS - cu.dimdDerivedIntraDir2nd = secondDimdIntraDir; + cu.dimdDerivedIntraDir2nd = secondDimdIntraDir; #endif - CHECK(modeIdx >= NUM_EIP_MERGE_SIGNAL, "modeIdx >= NUM_EIP_MERGE_SIGNAL"); - } - else - { - PelBuf eipSaveBuf(m_eipPredBuf[modeIdx], pu.Y()); + CHECK(modeIdx >= NUM_EIP_MERGE_SIGNAL, "modeIdx >= NUM_EIP_MERGE_SIGNAL"); + } + else + { + PelBuf eipSaveBuf(m_eipPredBuf[modeIdx], pu.Y()); #if JVET_AI0050_INTER_MTSS - int secondDimdIntraDir = 0; + int secondDimdIntraDir = 0; #endif - m_eipModel[modeIdx].eipDimdMode = deriveIpmForTransform(eipSaveBuf, cu + m_eipModel[modeIdx].eipDimdMode = deriveIpmForTransform(eipSaveBuf, cu #if JVET_AI0050_INTER_MTSS - , secondDimdIntraDir + , secondDimdIntraDir #endif - ); + ); #if JVET_AI0050_INTER_MTSS - cu.dimdDerivedIntraDir2nd = secondDimdIntraDir; + cu.dimdDerivedIntraDir2nd = secondDimdIntraDir; #endif - CHECK(modeIdx >= NUM_DERIVED_EIP, "modeIdx >= NUM_DERIVED_EIP"); - } - } + CHECK(modeIdx >= NUM_DERIVED_EIP, "modeIdx >= NUM_DERIVED_EIP"); + } + } #endif #if JVET_AJ0082_MM_EIP - if (m_dSavedModeCostEip.size() > 0) - { - isEipModeTested = true; - eipBestSatdCost = m_dSavedModeCostEip[0]; - } + if (m_dSavedModeCostEip.size() > 0) + { + isEipModeTested = true; + eipBestSatdCost = m_dSavedModeCostEip[0]; + } #endif - cu.eipFlag = false; - cu.eipMerge = false; + cu.eipFlag = false; + cu.eipMerge = false; #if JVET_AJ0082_MM_EIP - cu.eipMmFlag = false; + cu.eipMmFlag = false; #endif - } - for (auto i = 0; i < m_uiSavedRdModeListEip.size(); i++) - { - updateCandList(m_uiSavedRdModeListEip[i], m_dSavedModeCostEip[i], uiRdModeList, candCostList, numModesForFullRD); - updateCandList(m_uiSavedHadModeListEip[i], m_dSavedHadListEip[i], uiHadModeList, candHadList, numHadCand); - } - int numEip = 0; - for(int i = 0; i < numModesForFullRD - 1; i++) - { - bool isEip = (uiRdModeList[i].modeId >= EIP_IDX && uiRdModeList[i].modeId < EIP_IDX + std::max(NUM_DERIVED_EIP, MAX_MERGE_EIP)); - numEip += (isEip ? 1 : 0); - } - int numNonEip = numModesForFullRD - numEip; - int lastModeId = uiRdModeList[numModesForFullRD - 1].modeId; - bool lastModeIsEip = (lastModeId >= EIP_IDX && lastModeId < EIP_IDX + std::max(NUM_DERIVED_EIP, MAX_MERGE_EIP)) ; + } + for (auto i = 0; i < m_uiSavedRdModeListEip.size(); i++) + { + updateCandList(m_uiSavedRdModeListEip[i], m_dSavedModeCostEip[i], uiRdModeList, candCostList, numModesForFullRD); + updateCandList(m_uiSavedHadModeListEip[i], m_dSavedHadListEip[i], uiHadModeList, candHadList, numHadCand); + } + int numEip = 0; + for (int i = 0; i < numModesForFullRD - 1; i++) + { + bool isEip = (uiRdModeList[i].modeId >= EIP_IDX && uiRdModeList[i].modeId < EIP_IDX + std::max(NUM_DERIVED_EIP, MAX_MERGE_EIP)); + numEip += (isEip ? 1 : 0); + } + int numNonEip = numModesForFullRD - numEip; + int lastModeId = uiRdModeList[numModesForFullRD - 1].modeId; + bool lastModeIsEip = (lastModeId >= EIP_IDX && lastModeId < EIP_IDX + std::max(NUM_DERIVED_EIP, MAX_MERGE_EIP)); #if JVET_AJ0082_MM_EIP - bool reduceRD = m_dSavedModeCostEip.size() ? (pu.Y().area() < 256) && (m_encBestEipCost < candCostList[numModesForFullRD - 1]) && (lastModeIsEip || (numNonEip > 1)) : false; - if( reduceRD && m_pcEncCfg->getIntraPeriod() == 1) + bool reduceRD = m_dSavedModeCostEip.size() ? (pu.Y().area() < 256) && (m_encBestEipCost < candCostList[numModesForFullRD - 1]) && (lastModeIsEip || (numNonEip > 1)) : false; + if (reduceRD && m_pcEncCfg->getIntraPeriod() == 1) #else - bool reduceRD = m_dSavedModeCostEip.size() ? (pu.Y().area() < 256) && (m_dSavedModeCostEip[0] < candCostList[numModesForFullRD - 1]) && (lastModeIsEip || (numNonEip > 1)) : false; - if( reduceRD && pu.cs->slice->isIntra()) + bool reduceRD = m_dSavedModeCostEip.size() ? (pu.Y().area() < 256) && (m_dSavedModeCostEip[0] < candCostList[numModesForFullRD - 1]) && (lastModeIsEip || (numNonEip > 1)) : false; + if (reduceRD && pu.cs->slice->isIntra()) #endif - { - uiRdModeList.pop_back(); - candCostList.pop_back(); - numModesForFullRD = int(uiRdModeList.size()); + { + uiRdModeList.pop_back(); + candCostList.pop_back(); + numModesForFullRD = int(uiRdModeList.size()); + } } - } #endif #if JVET_AE0169_BIPREDICTIVE_IBC - m_bestIntraSADHADCost = candCostList[numModesForFullRD - 1]; + m_bestIntraSADHADCost = candCostList[numModesForFullRD - 1]; #if JVET_AH0200_INTRA_TMP_BV_REORDER - if(isTmpModeTestd) - { -#if JVET_AI0136_ADAPTIVE_DUAL_TREE - if(relatedCU && !relatedCU->skipFracTmp && (tmpBestSatdCost > m_bestIntraSADHADCost * TMP_ENC_REFINE_THRESHOLD)) + if (isTmpModeTestd) { - relatedCU->skipFracTmp = true; - } +#if JVET_AI0136_ADAPTIVE_DUAL_TREE + if (relatedCU && !relatedCU->skipFracTmp && (tmpBestSatdCost > m_bestIntraSADHADCost * TMP_ENC_REFINE_THRESHOLD)) + { + relatedCU->skipFracTmp = true; + } #else - if(!relatedCU.skipFracTmp && (tmpBestSatdCost > m_bestIntraSADHADCost * TMP_ENC_REFINE_THRESHOLD)) - { - relatedCU.skipFracTmp = true; - } + if (!relatedCU.skipFracTmp && (tmpBestSatdCost > m_bestIntraSADHADCost * TMP_ENC_REFINE_THRESHOLD)) + { + relatedCU.skipFracTmp = true; + } #endif } #endif #if JVET_AJ0082_MM_EIP - if(isEipModeTested && m_pcEncCfg->getIntraPeriod() == 1) - { -#if JVET_AI0136_ADAPTIVE_DUAL_TREE - if(relatedCU && !relatedCU->skipEip && (eipBestSatdCost > m_bestIntraSADHADCost * ENC_EIP_SAD_CHK_RATE)) + if (isEipModeTested && m_pcEncCfg->getIntraPeriod() == 1) { - relatedCU->skipEip = true; - } +#if JVET_AI0136_ADAPTIVE_DUAL_TREE + if (relatedCU && !relatedCU->skipEip && (eipBestSatdCost > m_bestIntraSADHADCost * ENC_EIP_SAD_CHK_RATE)) + { + relatedCU->skipEip = true; + } #else - if(!relatedCU.skipEip && (eipBestSatdCost > m_bestIntraSADHADCost * ENC_EIP_SAD_CHK_RATE)) - { - relatedCU.skipEip = true; - } + if (!relatedCU.skipEip && (eipBestSatdCost > m_bestIntraSADHADCost * ENC_EIP_SAD_CHK_RATE)) + { + relatedCU.skipEip = true; + } #endif - } + } #endif #endif - if (m_pcEncCfg->getFastUDIUseMPMEnabled()) - { + if (m_pcEncCfg->getFastUDIUseMPMEnabled()) + { #if SECONDARY_MPM - auto uiPreds = m_intraMPM; + auto uiPreds = m_intraMPM; #else - const int numMPMs = NUM_MOST_PROBABLE_MODES; - unsigned uiPreds[numMPMs]; + const int numMPMs = NUM_MOST_PROBABLE_MODES; + unsigned uiPreds[numMPMs]; #endif - pu.multiRefIdx = 0; + pu.multiRefIdx = 0; #if JVET_AB0157_TMRL - cu.tmrlFlag = false;; + cu.tmrlFlag = false;; #endif #if SECONDARY_MPM - int numCand = m_mpmListSize; - numCand = (numCand > 2) ? 2 : numCand; + int numCand = m_mpmListSize; + numCand = (numCand > 2) ? 2 : numCand; #else - const int numCand = PU::getIntraMPMs(pu, uiPreds); + const int numCand = PU::getIntraMPMs(pu, uiPreds); #endif - for (int j = 0; j < numCand; j++) - { - bool mostProbableModeIncluded = false; - ModeInfo mostProbableMode( false, false, 0, NOT_INTRA_SUBPARTITIONS, uiPreds[j] ); - - for (int i = 0; i < numModesForFullRD; i++) - { - mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]); - } - if (!mostProbableModeIncluded) - { - numModesForFullRD++; - uiRdModeList.push_back(mostProbableMode); - candCostList.push_back(0); - } - } - if (saveDataForISP) - { - // we add the MPMs to the list that contains only regular intra modes for (int j = 0; j < numCand; j++) { bool mostProbableModeIncluded = false; ModeInfo mostProbableMode(false, false, 0, NOT_INTRA_SUBPARTITIONS, uiPreds[j]); - for (int i = 0; i < m_ispCandListHor.size(); i++) + for (int i = 0; i < numModesForFullRD; i++) { - mostProbableModeIncluded |= (mostProbableMode == m_ispCandListHor[i]); + mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]); } if (!mostProbableModeIncluded) { - m_ispCandListHor.push_back(mostProbableMode); + numModesForFullRD++; + uiRdModeList.push_back(mostProbableMode); + candCostList.push_back(0); + } + } + if (saveDataForISP) + { + // we add the MPMs to the list that contains only regular intra modes + for (int j = 0; j < numCand; j++) + { + bool mostProbableModeIncluded = false; + ModeInfo mostProbableMode(false, false, 0, NOT_INTRA_SUBPARTITIONS, uiPreds[j]); + + for (int i = 0; i < m_ispCandListHor.size(); i++) + { + mostProbableModeIncluded |= (mostProbableMode == m_ispCandListHor[i]); + } + if (!mostProbableModeIncluded) + { + m_ispCandListHor.push_back(mostProbableMode); + } } } } +#if JVET_AJ0112_REGRESSION_SGPM } + if (m_pcEncCfg->getUseFastLFNST() && LFNSTLoadFlag && mtsUsageFlag == 1) + { + if (m_bestModeCostValid[0]) + { + numModesForFullRD = 0; + uiRdModeList.clear(); + std::vector<std::pair<ModeInfo, double>> modeInfoWithDCT2Cost(m_savedNumRdModes[0]); + for (int i = 0; i < m_savedNumRdModes[0]; i++) + { + modeInfoWithDCT2Cost[i] = { m_savedRdModeList[0][i], m_modeCostStore[0][i] }; + } + std::stable_sort(modeInfoWithDCT2Cost.begin(), modeInfoWithDCT2Cost.end(), [](const std::pair<ModeInfo, double> & l, const std::pair<ModeInfo, double> & r) {return l.second < r.second; }); + + // **Reorder the modes** and skip checking the modes with much larger R-D cost than the best mode + for (int i = 0; i < m_savedNumRdModes[0]; i++) + { + if (modeInfoWithDCT2Cost[i].second <= 1.3 * modeInfoWithDCT2Cost[0].second) + { + uiRdModeList.push_back(modeInfoWithDCT2Cost[i].first); + numModesForFullRD++; + } + } + } + else + { + // Restore the modes to be checked with RD + numModesForFullRD = m_savedNumRdModes[0]; + uiRdModeList.resize(numModesForFullRD); + std::copy_n(m_savedRdModeList[0], m_savedNumRdModes[0], uiRdModeList.begin()); + candCostList.resize(numModesForFullRD); + } + } +#endif } else { @@ -3905,6 +3992,13 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c cu.sgpm = uiOrgMode.sgpmFlag; if (cu.sgpm) { +#if JVET_AJ0112_REGRESSION_SGPM + if (m_skipSgpmLfnstMtsPass) + { + CHECK(!cu.lfnstIdx && !cu.mtsFlag, "invalid logic"); + continue; + } +#endif uiOrgMode.modeId = uiOrgMode.sgpmMode0; cu.sgpmSplitDir = uiOrgMode.sgpmSplitDir; cu.sgpmMode0 = uiOrgMode.sgpmMode0; @@ -3912,6 +4006,9 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c #if JVET_AG0152_SGPM_ITMP_IBC cu.sgpmBv0 = uiOrgMode.sgpmBv0; cu.sgpmBv1 = uiOrgMode.sgpmBv1; +#endif +#if JVET_AJ0112_REGRESSION_SGPM + cu.blendModel = uiOrgMode.sgpmBlendModel; #endif cu.sgpmIdx = uiOrgMode.sgpmIdx; #if JVET_AG0152_SGPM_ITMP_IBC @@ -4318,6 +4415,15 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c #endif } #endif +#if JVET_AJ0112_REGRESSION_SGPM + if (setSkipSgpmControl && cu.sgpm) + { + if (csTemp->cost < sgpmCost) + { + sgpmCost = csTemp->cost; + } + } +#endif #if JVET_AJ0061_TIMD_MERGE if (setSkipTimdMrgControl && cu.timdMrg) { @@ -4398,6 +4504,13 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c bestMipDimd = curCu->mipDimdMode; } #endif +#if JVET_AJ0112_REGRESSION_SGPM + if (cu.sgpm && PU::isRegressionSgpm(*cu.firstPU)) + { + CodingUnit* curCu = csBest->getCU(partitioner.currArea().lumaPos(), partitioner.chType); + bestSgpmDimd = curCu->sgpmDimdMode; + } +#endif #if JVET_AH0103_LOW_DELAY_LFNST_NSPT if( spsIntraLfnstEnabled && mtsUsageFlag == 1 && !cu.ispMode ) @@ -4480,6 +4593,15 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c } } #endif +#if JVET_AJ0112_REGRESSION_SGPM + if (setSkipSgpmControl) + { + if (regAngCost != MAX_DOUBLE && sgpmCost != MAX_DOUBLE && regAngCost * 1.5 < sgpmCost) + { + m_skipSgpmLfnstMtsPass = true; + } + } +#endif #if JVET_AJ0061_TIMD_MERGE for (int i = 0; i < NUM_TIMD_MERGE_MODES && setSkipTimdMrgControl; i++) { @@ -4580,6 +4702,9 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c pu.intraDir[ CHANNEL_TYPE_LUMA ] = cu.obicMode[0]; cu.dimd = true; } +#endif +#if JVET_AJ0112_REGRESSION_SGPM + cu.sgpmDimdMode = bestSgpmDimd; #endif cu.bdpcmMode = bestBDPCMMode; #if JVET_W0123_TIMD_FUSION @@ -4623,6 +4748,9 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c #if JVET_AG0152_SGPM_ITMP_IBC cu.sgpmBv0 = uiBestPUMode.sgpmBv0; cu.sgpmBv1 = uiBestPUMode.sgpmBv1; +#endif +#if JVET_AJ0112_REGRESSION_SGPM + cu.blendModel = uiBestPUMode.sgpmBlendModel; #endif } #endif @@ -10415,6 +10543,19 @@ void IntraSearch::xSelectAMTForFullRD(TransformUnit &tu CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size()); PelBuf predBuf(m_sgpmPredBuf[pu.cu->sgpmIdx], tmpArea); piPred.copyFrom(predBuf); +#if JVET_AJ0112_REGRESSION_SGPM + if (PU::isRegressionSgpm(pu)) + { +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + deriveIpmForTransform(piPred, *pu.cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); + } +#endif } else #endif @@ -10810,6 +10951,19 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size()); PelBuf predBuf(m_sgpmPredBuf[pu.cu->sgpmIdx], tmpArea); piPred.copyFrom(predBuf); +#if JVET_AJ0112_REGRESSION_SGPM + if (PU::isRegressionSgpm(pu)) + { +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + deriveIpmForTransform(piPred, *pu.cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); + } +#endif } else #endif diff --git a/source/Lib/EncoderLib/IntraSearch.h b/source/Lib/EncoderLib/IntraSearch.h index 48a7ba27a1e591d34b6afdb69eab3f55d3241c41..081574c43ee42f892c47b04dcbe3388518836d93 100644 --- a/source/Lib/EncoderLib/IntraSearch.h +++ b/source/Lib/EncoderLib/IntraSearch.h @@ -253,6 +253,10 @@ private: Mv sgpmBv0; Mv sgpmBv1; #endif +#if JVET_AJ0112_REGRESSION_SGPM + bool sgpmIsRegression; + AffineBlendingModel sgpmBlendModel; +#endif #endif #if JVET_AB0155_SGPM #if JVET_V0130_INTRA_TMP @@ -271,6 +275,10 @@ private: #if JVET_AG0152_SGPM_ITMP_IBC , sgpmBv0(0, 0), sgpmBv1(0, 0) #endif +#if JVET_AJ0112_REGRESSION_SGPM + , sgpmIsRegression(false) + , sgpmBlendModel(AffineBlendingModel(5,1,31)) +#endif {} ModeInfo(const bool mipf, const bool miptf, const int mrid, const uint8_t ispm, const uint32_t mode, const bool tmpf = 0 @@ -288,6 +296,10 @@ private: #if JVET_AG0152_SGPM_ITMP_IBC , const Mv sbv0 = Mv(0, 0), const Mv sbv1 = Mv(0, 0) #endif +#if JVET_AJ0112_REGRESSION_SGPM + , const bool sir = false + , const AffineBlendingModel sbm = AffineBlendingModel(5, 1, 31) +#endif ) #else ModeInfo() : mipFlg(false), mipTrFlg(false), mRefId(0), ispMod(NOT_INTRA_SUBPARTITIONS), modeId(0), sgpmFlag(0), sgpmSplitDir(0), sgpmMode0(0), sgpmMode1(0), sgpmIdx(0){} @@ -320,6 +332,10 @@ private: #if JVET_AG0152_SGPM_ITMP_IBC , sgpmBv0(sbv0) , sgpmBv1(sbv1) +#endif +#if JVET_AJ0112_REGRESSION_SGPM + , sgpmIsRegression(sir) + , sgpmBlendModel(sbm) #endif { } @@ -355,6 +371,10 @@ private: #if JVET_AG0152_SGPM_ITMP_IBC sgpmBv0 = other.sgpmBv0; sgpmBv1 = other.sgpmBv1; +#endif +#if JVET_AJ0112_REGRESSION_SGPM + sgpmIsRegression = other.sgpmIsRegression; + sgpmBlendModel = other.sgpmBlendModel; #endif return *this; } @@ -738,6 +758,9 @@ public: #if INTRA_TRANS_ENC_OPT bool m_skipTimdLfnstMtsPass; #endif +#if JVET_AJ0112_REGRESSION_SGPM + bool m_skipSgpmLfnstMtsPass; +#endif #if JVET_AJ0061_TIMD_MERGE bool m_skipTimdMrgLfnstMtsPass; bool m_skipObicMode;