diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index 50bfe7562ff26d0ea4f615d19152a4751a4ea459..537392c947b6289c6b1fd214b749ae86c5649743 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -363,271 +363,6 @@ unsigned DeriveCtx::CtxIBCFlag(const CodingUnit& cu) return ctxId; } -#if JVET_AC0139_UNIFIED_MERGE -void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) const -#else -void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) -#endif -{ - CHECK( candIdx >= numValidMergeCand, "Merge candidate does not exist" ); - pu.regularMergeFlag = !(pu.ciipFlag || pu.cu->geoFlag); - pu.mergeFlag = true; - pu.mmvdMergeFlag = false; - pu.interDir = interDirNeighbours[candIdx]; - pu.cu->imv = (!pu.cu->geoFlag && useAltHpelIf[candIdx]) ? IMV_HPEL : 0; - pu.mergeIdx = candIdx; - pu.mergeType = CU::isIBC(*pu.cu) ? MergeType::IBC : MergeType::DEFAULT_N; - - for (const auto l: { REF_PIC_LIST_0, REF_PIC_LIST_1 }) - { - pu.mv[l] = mvFieldNeighbours[candIdx][l].mv; - pu.mvd[l] = Mv(); - pu.refIdx[l] = mvFieldNeighbours[candIdx][l].refIdx; - pu.mvpIdx[l] = NOT_VALID; - pu.mvpNum[l] = NOT_VALID; - } -#if GDR_ENABLED - CodingStructure &cs = *pu.cs; - const bool isEncodeGdrClean = - cs.sps->getGDREnabledFlag() && cs.pcv->isEncoder - && ((cs.picture->gdrParam.inGdrInterval && cs.isClean(pu.Y().topRight(), ChannelType::LUMA)) - || (cs.picture->gdrParam.verBoundary == -1)); - - if (isEncodeGdrClean) - { - for (const auto l: { REF_PIC_LIST_0, REF_PIC_LIST_1 }) - { - Mv mv = pu.mv[l]; - - int refIdx = pu.refIdx[l]; - - pu.mvSolid[l] = mvSolid[candIdx][l]; - pu.mvValid[l] = cs.isClean(pu.Y().topRight(), mv, l, refIdx); - } - } -#endif - - if (CU::isIBC(*pu.cu)) - { - pu.bv = pu.mv[REF_PIC_LIST_0]; - pu.bv.changePrecision(MvPrecision::INTERNAL, MvPrecision::ONE); // used for only integer resolution - pu.cu->imv = pu.cu->imv == IMV_HPEL ? 0 : pu.cu->imv; - } - pu.cu->bcwIdx = (interDirNeighbours[candIdx] == 3) ? bcwIdx[candIdx] : BCW_DEFAULT; - - PU::restrictBiPredMergeCandsOne(pu); - pu.mmvdEncOptMode = 0; -} - -void MergeCtx::getMmvdDeltaMv(const Slice& slice, const MmvdIdx candIdx, Mv deltaMv[NUM_REF_PIC_LIST_01]) const -{ - const int mvdBaseIdx = candIdx.pos.baseIdx; - const int mvdStep = candIdx.pos.step; - const int mvdPosition = candIdx.pos.position; - - int offset = 1 << (mvdStep + MV_FRACTIONAL_BITS_DIFF); - if (slice.getPicHeader()->getDisFracMMVD()) - { - offset <<= 2; - } - const int refList0 = mmvdBaseMv[mvdBaseIdx][REF_PIC_LIST_0].refIdx; - const int refList1 = mmvdBaseMv[mvdBaseIdx][REF_PIC_LIST_1].refIdx; - - const Mv dMvTable[4] = { Mv(offset,0), Mv(-offset,0), Mv(0, offset), Mv(0, -offset) }; - if ((refList0 != -1) && (refList1 != -1)) - { - const int poc0 = slice.getRefPOC(REF_PIC_LIST_0, refList0); - const int poc1 = slice.getRefPOC(REF_PIC_LIST_1, refList1); - const int currPoc = slice.getPOC(); - deltaMv[0] = dMvTable[mvdPosition]; - - if ((poc0 - currPoc) == (poc1 - currPoc)) - { - deltaMv[1] = deltaMv[0]; - } - else if (abs(poc1 - currPoc) > abs(poc0 - currPoc)) - { - const int scale = PU::getDistScaleFactor(currPoc, poc0, currPoc, poc1); - deltaMv[1] = deltaMv[0]; - const bool isL0RefLongTerm = slice.getRefPic(REF_PIC_LIST_0, refList0)->longTerm; - const bool isL1RefLongTerm = slice.getRefPic(REF_PIC_LIST_1, refList1)->longTerm; - if (isL0RefLongTerm || isL1RefLongTerm) - { - if ((poc1 - currPoc)*(poc0 - currPoc) > 0) - { - deltaMv[0] = deltaMv[1]; - } - else - { - deltaMv[0].set(-1 * deltaMv[1].getHor(), -1 * deltaMv[1].getVer()); - } - } - else - { - deltaMv[0] = deltaMv[1].getScaledMv(scale); - } - } - else - { - const int scale = PU::getDistScaleFactor(currPoc, poc1, currPoc, poc0); - const bool isL0RefLongTerm = slice.getRefPic(REF_PIC_LIST_0, refList0)->longTerm; - const bool isL1RefLongTerm = slice.getRefPic(REF_PIC_LIST_1, refList1)->longTerm; - if (isL0RefLongTerm || isL1RefLongTerm) - { - if ((poc1 - currPoc)*(poc0 - currPoc) > 0) - { - deltaMv[1] = deltaMv[0]; - } - else - { - deltaMv[1].set(-1 * deltaMv[0].getHor(), -1 * deltaMv[0].getVer()); - } - } - else - { - deltaMv[1] = deltaMv[0].getScaledMv(scale); - } - } - } - else if (refList0 != -1) - { - deltaMv[0] = dMvTable[mvdPosition]; - } - else if (refList1 != -1) - { - deltaMv[1] = dMvTable[mvdPosition]; - } -} - -void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit &pu, const MmvdIdx candIdx) -{ - Mv tempMv[NUM_REF_PIC_LIST_01]; - -#if GDR_ENABLED - const CodingStructure &cs = *pu.cs; - const bool isEncodeGdrClean = - cs.sps->getGDREnabledFlag() && cs.pcv->isEncoder - && ((cs.picture->gdrParam.inGdrInterval && cs.isClean(pu.Y().topRight(), ChannelType::LUMA)) - || (cs.picture->gdrParam.verBoundary == -1)); -#endif - - getMmvdDeltaMv(*pu.cs->slice, candIdx, tempMv); - const int mvdBaseIdx = candIdx.pos.baseIdx; - - const int refList0 = mmvdBaseMv[mvdBaseIdx][0].refIdx; - const int refList1 = mmvdBaseMv[mvdBaseIdx][1].refIdx; - - if ((refList0 != -1) && (refList1 != -1)) - { - pu.interDir = 3; - pu.mv[REF_PIC_LIST_0] = mmvdBaseMv[mvdBaseIdx][0].mv + tempMv[0]; - pu.refIdx[REF_PIC_LIST_0] = refList0; - pu.mv[REF_PIC_LIST_1] = mmvdBaseMv[mvdBaseIdx][1].mv + tempMv[1]; - pu.refIdx[REF_PIC_LIST_1] = refList1; -#if GDR_ENABLED - if (isEncodeGdrClean) - { - Mv mv0 = pu.mv[REF_PIC_LIST_0]; - Mv mv1 = pu.mv[REF_PIC_LIST_1]; - - int refIdx0 = pu.refIdx[REF_PIC_LIST_0]; - int refIdx1 = pu.refIdx[REF_PIC_LIST_1]; - - mmvdValid[mvdBaseIdx][0] = cs.isClean(pu.Y().topRight(), mv0, REF_PIC_LIST_0, refIdx0); - mmvdValid[mvdBaseIdx][1] = cs.isClean(pu.Y().topRight(), mv1, REF_PIC_LIST_1, refIdx1); - - pu.mvSolid[REF_PIC_LIST_0] = mmvdSolid[mvdBaseIdx][0]; - pu.mvSolid[REF_PIC_LIST_1] = mmvdSolid[mvdBaseIdx][1]; - - pu.mvValid[REF_PIC_LIST_0] = mmvdValid[mvdBaseIdx][0]; - pu.mvValid[REF_PIC_LIST_1] = mmvdValid[mvdBaseIdx][1]; - } -#endif - } - else if (refList0 != -1) - { - pu.interDir = 1; - pu.mv[REF_PIC_LIST_0] = mmvdBaseMv[mvdBaseIdx][0].mv + tempMv[0]; - pu.refIdx[REF_PIC_LIST_0] = refList0; - pu.mv[REF_PIC_LIST_1] = Mv(0, 0); - pu.refIdx[REF_PIC_LIST_1] = -1; - -#if GDR_ENABLED - if (isEncodeGdrClean) - { - Mv mv0 = pu.mv[REF_PIC_LIST_0]; - //Mv mv1 = pu.mv[REF_PIC_LIST_1]; - - int refIdx0 = pu.refIdx[REF_PIC_LIST_0]; - //int refIdx1 = pu.refIdx[REF_PIC_LIST_1]; - - pu.mvSolid[REF_PIC_LIST_0] = mmvdSolid[mvdBaseIdx][0]; - pu.mvSolid[REF_PIC_LIST_1] = true; - - mmvdValid[mvdBaseIdx][0] = cs.isClean(pu.Y().topRight(), mv0, REF_PIC_LIST_0, refIdx0); - mmvdValid[mvdBaseIdx][1] = true; - - pu.mvValid[REF_PIC_LIST_0] = mmvdValid[mvdBaseIdx][0]; - pu.mvValid[REF_PIC_LIST_1] = true; - } -#endif - } - else if (refList1 != -1) - { - pu.interDir = 2; - pu.mv[REF_PIC_LIST_0] = Mv(0, 0); - pu.refIdx[REF_PIC_LIST_0] = -1; - pu.mv[REF_PIC_LIST_1] = mmvdBaseMv[mvdBaseIdx][1].mv + tempMv[1]; - pu.refIdx[REF_PIC_LIST_1] = refList1; -#if GDR_ENABLED - if (isEncodeGdrClean) - { - // Mv mv0 = pu.mv[REF_PIC_LIST_0]; - Mv mv1 = pu.mv[REF_PIC_LIST_1]; - - // int refIdx0 = pu.refIdx[REF_PIC_LIST_0]; - int refIdx1 = pu.refIdx[REF_PIC_LIST_1]; - - mmvdValid[mvdBaseIdx][0] = true; - mmvdValid[mvdBaseIdx][1] = cs.isClean(pu.Y().topRight(), mv1, REF_PIC_LIST_1, refIdx1); - - pu.mvSolid[REF_PIC_LIST_0] = true; - pu.mvSolid[REF_PIC_LIST_1] = mmvdSolid[mvdBaseIdx][1]; - - pu.mvValid[REF_PIC_LIST_0] = true; - pu.mvValid[REF_PIC_LIST_1] = mmvdValid[mvdBaseIdx][1]; - } -#endif - } - - pu.mmvdMergeFlag = true; - pu.mmvdMergeIdx = candIdx; - pu.mergeFlag = true; - pu.regularMergeFlag = true; - pu.mergeIdx = candIdx.val; - pu.mergeType = MergeType::DEFAULT_N; - - pu.mvd[REF_PIC_LIST_0] = Mv(); - pu.mvd[REF_PIC_LIST_1] = Mv(); - pu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID; - pu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID; - pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID; - pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID; - pu.cu->imv = mmvdUseAltHpelIf[mvdBaseIdx] ? IMV_HPEL : 0; - - pu.cu->bcwIdx = (interDirNeighbours[mvdBaseIdx] == 3) ? bcwIdx[mvdBaseIdx] : BCW_DEFAULT; - - for (int refList = 0; refList < 2; refList++) - { - if (pu.refIdx[refList] >= 0) - { - pu.mv[refList].clipToStorageBitDepth(); - } - } - - PU::restrictBiPredMergeCandsOne(pu); -} - unsigned DeriveCtx::CtxMipFlag( const CodingUnit& cu ) { const CodingStructure *cs = cu.cs; @@ -657,300 +392,3 @@ unsigned DeriveCtx::CtxPltCopyFlag( const unsigned prevRunType, const unsigned d } } -#if JVET_AC0139_UNIFIED_MERGE -MergeItem::MergeItem() -{ - -} -MergeItem::~MergeItem() -{ - -} - -void MergeItem::create(ChromaFormat chromaFormat, const Area& area) -{ - if (m_pelStorage.bufs.empty()) - { - m_pelStorage.create(chromaFormat, area); - m_mvStorage.resize(area.area() >> (MIN_CU_LOG2 << 1)); - } - - // reset data - cost = MAX_DOUBLE; - mergeIdx = 0; - bcwIdx = 0; - interDir = 0; - useAltHpelIf = false; - affineType = AffineModel::_4_PARAMS; - mergeItemType = MergeItemType::NUM; - - noBdofRefine = false; - noResidual = false; - - lumaPredReady = false; - chromaPredReady = false; -} - -void MergeItem::importMergeInfo(const MergeCtx& mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, PredictionUnit& pu) -{ - mergeIdx = _mergeIdx; - mergeItemType = _mergeItemType; - - if (mergeItemType != MergeItemType::GPM) - { - mvField[0][REF_PIC_LIST_0] = mergeCtx.mvFieldNeighbours[mergeIdx][REF_PIC_LIST_0]; - mvField[0][REF_PIC_LIST_1] = mergeCtx.mvFieldNeighbours[mergeIdx][REF_PIC_LIST_1]; - interDir = mergeCtx.interDirNeighbours[mergeIdx]; - bcwIdx = mergeCtx.bcwIdx[mergeIdx]; - useAltHpelIf = mergeCtx.useAltHpelIf[mergeIdx]; - } - - switch (_mergeItemType) - { - case MergeItemType::REGULAR: - break; - - case MergeItemType::CIIP: - break; - - case MergeItemType::MMVD: - { - MmvdIdx candIdx; - candIdx.val = mergeIdx; - const int mmvdBaseIdx = candIdx.pos.baseIdx; - mvField[0][REF_PIC_LIST_0] = mergeCtx.mmvdBaseMv[mmvdBaseIdx][REF_PIC_LIST_0]; - mvField[0][REF_PIC_LIST_1] = mergeCtx.mmvdBaseMv[mmvdBaseIdx][REF_PIC_LIST_1]; - Mv tempMv[NUM_REF_PIC_LIST_01]; - mergeCtx.getMmvdDeltaMv(*pu.cs->slice, candIdx, tempMv); - mvField[0][REF_PIC_LIST_0].mv += tempMv[REF_PIC_LIST_0]; - mvField[0][REF_PIC_LIST_1].mv += tempMv[REF_PIC_LIST_1]; - interDir = mergeCtx.interDirNeighbours[mmvdBaseIdx]; - bcwIdx = mergeCtx.bcwIdx[mmvdBaseIdx]; - useAltHpelIf = mergeCtx.useAltHpelIf[mmvdBaseIdx]; - break; - } - case MergeItemType::GPM: - mvField[0][REF_PIC_LIST_0].setMvField(Mv(0, 0), -1); - mvField[0][REF_PIC_LIST_1].setMvField(Mv(0, 0), -1); - bcwIdx = BCW_DEFAULT; - useAltHpelIf = false; - MergeItem::updateGpmIdx(mergeIdx, pu.geoSplitDir, pu.geoMergeIdx); - pu.mergeFlag = true; - pu.cu->affine = false; - pu.cu->geoFlag = true; - pu.mergeType = MergeType::DEFAULT_N; - PU::spanMotionInfo(pu, getMvBuf(pu)); - PU::spanGeoMotionInfo(pu, mergeCtx, pu.geoSplitDir, pu.geoMergeIdx); - getMvBuf(pu).copyFrom(pu.getMotionBuf()); - break; - - case MergeItemType::IBC: - default: - THROW("Wrong merge item type"); - } -} - -void MergeItem::importMergeInfo(const AffineMergeCtx& mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, const UnitArea& unitArea) -{ - mergeIdx = _mergeIdx; - mergeItemType = _mergeItemType; - - affineType = mergeCtx.affineType[mergeIdx]; - interDir = mergeCtx.interDirNeighbours[mergeIdx]; - bcwIdx = mergeCtx.bcwIdx[mergeIdx]; - useAltHpelIf = false; - - switch (_mergeItemType) - { - case MergeItemType::SBTMVP: - mvField = mergeCtx.mvFieldNeighbours[mergeIdx]; - getMvBuf(unitArea).copyFrom(mergeCtx.mrgCtx->subPuMvpMiBuf); - break; - - case MergeItemType::AFFINE: - mvField = mergeCtx.mvFieldNeighbours[mergeIdx]; - break; - - default: - THROW("Wrong merge item type"); - } -} - -bool MergeItem::exportMergeInfo(PredictionUnit& pu, bool forceNoResidual) -{ - pu.mergeFlag = true; - pu.regularMergeFlag = false; - pu.mmvdMergeFlag = false; - pu.interDir = interDir; - pu.mergeIdx = mergeIdx; - pu.mergeType = MergeType::DEFAULT_N; - pu.mv[REF_PIC_LIST_0] = mvField[0][REF_PIC_LIST_0].mv; - pu.mv[REF_PIC_LIST_1] = mvField[0][REF_PIC_LIST_1].mv; - pu.refIdx[REF_PIC_LIST_0] = mvField[0][REF_PIC_LIST_0].refIdx; - pu.refIdx[REF_PIC_LIST_1] = mvField[0][REF_PIC_LIST_1].refIdx; - pu.mvd[REF_PIC_LIST_0] = Mv(); - pu.mvd[REF_PIC_LIST_1] = Mv(); - pu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID; - pu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID; - pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID; - pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID; - pu.cu->bcwIdx = (interDir == 3) ? bcwIdx : BCW_DEFAULT; - pu.mmvdEncOptMode = 0; - pu.cu->mmvdSkip = false; - pu.cu->affine = false; - pu.cu->affineType = AffineModel::_4_PARAMS; - pu.cu->geoFlag = false; - pu.cu->mtsFlag = false; - pu.ciipFlag = false; - pu.cu->imv = (!pu.cu->geoFlag && useAltHpelIf) ? IMV_HPEL : 0; - - const bool resetCiip2Regular = mergeItemType == MergeItemType::CIIP && forceNoResidual; - MergeItemType updatedType = resetCiip2Regular ? MergeItemType::REGULAR : mergeItemType; - switch (updatedType) - { - case MergeItemType::REGULAR: - pu.regularMergeFlag = true; - PU::restrictBiPredMergeCandsOne(pu); - break; - - case MergeItemType::CIIP: - CHECK(forceNoResidual, "Cannot force no residuals for CIIP"); - pu.ciipFlag = true; - pu.intraDir[ChannelType::LUMA] = PLANAR_IDX; - pu.intraDir[ChannelType::CHROMA] = DM_CHROMA_IDX; - break; - - case MergeItemType::MMVD: - pu.mmvdMergeFlag = true; - pu.mmvdMergeIdx.val = mergeIdx; - pu.regularMergeFlag = true; - if (forceNoResidual) - { - pu.cu->mmvdSkip = true; - } - PU::restrictBiPredMergeCandsOne(pu); - break; - - case MergeItemType::SBTMVP: - pu.cu->affine = true; - pu.mergeType = MergeType::SUBPU_ATMVP; - break; - - case MergeItemType::AFFINE: - pu.cu->affine = true; - pu.cu->affineType = affineType; - PU::setAllAffineMvField(pu, mvField, REF_PIC_LIST_0); - PU::setAllAffineMvField(pu, mvField, REF_PIC_LIST_1); - break; - - case MergeItemType::GPM: - pu.mergeIdx = -1; - pu.cu->geoFlag = true; - pu.cu->bcwIdx = BCW_DEFAULT; - MergeItem::updateGpmIdx(mergeIdx, pu.geoSplitDir, pu.geoMergeIdx); - pu.cu->imv = 0; - break; - - case MergeItemType::IBC: - default: - THROW("Wrong merge item type"); - } - - if (mergeItemType == MergeItemType::GPM) - { - pu.getMotionBuf().copyFrom(getMvBuf(pu)); - } - else - { - PU::spanMotionInfo(pu, getMvBuf(pu)); - } - -#if GDR_ENABLED - CodingStructure &cs = *pu.cs; - const bool isEncodeGdrClean = cs.sps->getGDREnabledFlag() && cs.pcv->isEncoder - && ((cs.picture->gdrParam.inGdrInterval && cs.isClean(pu.Y().topRight(), ChannelType::LUMA)) - || (cs.picture->gdrParam.verBoundary == -1)); - if (isEncodeGdrClean) - { - Mv mv0 = pu.mv[REF_PIC_LIST_0]; - Mv mv1 = pu.mv[REF_PIC_LIST_1]; - - int refIdx0 = pu.refIdx[REF_PIC_LIST_0]; - int refIdx1 = pu.refIdx[REF_PIC_LIST_1]; - - pu.mvSolid[REF_PIC_LIST_0] = mvSolid[0]; - pu.mvSolid[REF_PIC_LIST_1] = mvSolid[1]; - pu.mvValid[REF_PIC_LIST_0] = cs.isClean(pu.Y().topRight(), mv0, REF_PIC_LIST_0, refIdx0); - pu.mvValid[REF_PIC_LIST_1] = cs.isClean(pu.Y().topRight(), mv1, REF_PIC_LIST_1, refIdx1); - } -#endif - - return resetCiip2Regular; -} - -MergeItemList::MergeItemList() -{ - -} - -MergeItemList::~MergeItemList() -{ -} - -void MergeItemList::init(size_t maxSize, ChromaFormat chromaFormat, int ctuWidth, int ctuHeight) -{ - m_list.reserve(maxSize + 1); // to avoid reallocation when inserting a new item - m_chromaFormat = chromaFormat; - m_ctuArea.x = 0; - m_ctuArea.y = 0; - m_ctuArea.width = ctuWidth; - m_ctuArea.height = ctuHeight; -} - -MergeItem* MergeItemList::allocateNewMergeItem() -{ - MergeItem* p = m_mergeItemPool.get(); - p->create(m_chromaFormat, m_ctuArea); - - return p; -} - -void MergeItemList::insertMergeItemToList(MergeItem* p) -{ - if (m_list.empty()) - { - m_list.push_back(p); - } - else if (m_list.size() == m_maxTrackingNum && p->cost >= m_list.back()->cost) - { - m_mergeItemPool.giveBack(p); - } - else - { - if (m_list.size() == m_maxTrackingNum) - { - m_mergeItemPool.giveBack(m_list.back()); - m_list.pop_back(); - } - auto it = std::find_if(m_list.begin(), m_list.end(), [&p](const MergeItem *mi) { return p->cost < mi->cost; }); - m_list.insert(it, p); - } -} - -MergeItem* MergeItemList::getMergeItemInList(size_t index) -{ - return index < m_maxTrackingNum ? m_list[index] : nullptr; -} - -void MergeItemList::resetList(size_t maxTrackingNum) -{ - for (auto p : m_list) - { - m_mergeItemPool.giveBack(p); - } - m_list.clear(); - m_list.reserve(maxTrackingNum); - m_maxTrackingNum = maxTrackingNum; -} - -#endif \ No newline at end of file diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index aba6f57080a6e13703306107f5ec1b8ac9030c7c..919aa548a9788ff975c53e3c1223ac742527004d 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -584,177 +584,6 @@ public: bool mtsLastScanPos; }; -class MergeCtx -{ -public: - MergeCtx() : numValidMergeCand(0), hasMergedCandList(false) {} - ~MergeCtx() {} -public: - MvField mvFieldNeighbours[MRG_MAX_NUM_CANDS][2]; -#if GDR_ENABLED - // note : check if source of mv and mv itself is valid - bool mvSolid[MRG_MAX_NUM_CANDS][2]; - bool mvValid[MRG_MAX_NUM_CANDS][2]; - Position mvPos[MRG_MAX_NUM_CANDS][2]; - MvpType mvType[MRG_MAX_NUM_CANDS][2]; -#endif - uint8_t bcwIdx[MRG_MAX_NUM_CANDS]; - unsigned char interDirNeighbours[ MRG_MAX_NUM_CANDS ]; - int numValidMergeCand; - bool hasMergedCandList; - - MotionBuf subPuMvpMiBuf; - MvField mmvdBaseMv[MmvdIdx::BASE_MV_NUM][2]; -#if GDR_ENABLED - bool mmvdSolid[MmvdIdx::BASE_MV_NUM][2]; - bool mmvdValid[MmvdIdx::BASE_MV_NUM][2]; -#endif - void setMmvdMergeCandiInfo(PredictionUnit &pu, MmvdIdx candIdx); - void getMmvdDeltaMv(const Slice& slice, const MmvdIdx candIdx, Mv deltaMv[NUM_REF_PIC_LIST_01]) const; - bool mmvdUseAltHpelIf[MmvdIdx::BASE_MV_NUM]; - bool useAltHpelIf [ MRG_MAX_NUM_CANDS ]; -#if JVET_AC0139_UNIFIED_MERGE - void setMergeInfo( PredictionUnit& pu, int candIdx ) const; -#else - void setMergeInfo( PredictionUnit& pu, int candIdx ); -#endif -}; - -class AffineMergeCtx -{ -public: - AffineMergeCtx() : numValidMergeCand(0) - { - for (int i = 0; i < AFFINE_MRG_MAX_NUM_CANDS; i++) - { - affineType[i] = AffineModel::_4_PARAMS; - } - } - ~AffineMergeCtx() {} -public: - std::array<MvField[2], AFFINE_MAX_NUM_CP> mvFieldNeighbours[AFFINE_MRG_MAX_NUM_CANDS]; -#if GDR_ENABLED - std::array<bool[2], AFFINE_MAX_NUM_CP> mvSolid[AFFINE_MRG_MAX_NUM_CANDS]; - std::array<bool[2], AFFINE_MAX_NUM_CP> mvValid[AFFINE_MRG_MAX_NUM_CANDS]; - - bool isSolid(const int idx, const int l) - { - bool solid = true; - for (auto &c: mvSolid[idx]) - { - solid &= c[l]; - } - return solid; - } - - bool isValid(const int idx, const int l) - { - bool valid = true; - for (auto &c: mvValid[idx]) - { - valid &= c[l]; - } - return valid; - } -#endif - unsigned char interDirNeighbours[AFFINE_MRG_MAX_NUM_CANDS]; - AffineModel affineType[AFFINE_MRG_MAX_NUM_CANDS]; - uint8_t bcwIdx[AFFINE_MRG_MAX_NUM_CANDS]; - int numValidMergeCand; - int maxNumMergeCand; - - MergeCtx *mrgCtx; - MergeType mergeType[AFFINE_MRG_MAX_NUM_CANDS]; -}; - -#if JVET_AC0139_UNIFIED_MERGE -class MergeItem -{ -private: - PelStorage m_pelStorage; - std::vector<MotionInfo> m_mvStorage; - -public: - enum class MergeItemType - { - REGULAR, - SBTMVP, - AFFINE, - MMVD, - CIIP, - GPM, - IBC, - NUM, - }; - - double cost; - std::array<MvField[2], AFFINE_MAX_NUM_CP> mvField; - int mergeIdx; - uint8_t bcwIdx; - uint8_t interDir; - bool useAltHpelIf; - AffineModel affineType; - - bool noResidual; - bool noBdofRefine; - - bool lumaPredReady; - bool chromaPredReady; - - MergeItemType mergeItemType; - MotionBuf mvBuf; - -#if GDR_ENABLED - bool mvSolid[2]; - bool mvValid[2]; -#endif - - MergeItem(); - ~MergeItem(); - - void create(ChromaFormat chromaFormat, const Area& area); - void importMergeInfo(const MergeCtx& mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, PredictionUnit& pu); - void importMergeInfo(const AffineMergeCtx& mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, const UnitArea& unitArea); - bool exportMergeInfo(PredictionUnit& pu, bool forceNoResidual); - PelUnitBuf getPredBuf(const UnitArea& unitArea) { return m_pelStorage.getBuf(unitArea); } - MotionBuf getMvBuf(const UnitArea& unitArea) { return MotionBuf(m_mvStorage.data(), g_miScaling.scale(unitArea.lumaSize())); } - - static int getGpmUnfiedIndex(int splitDir, const MergeIdxPair& geoMergeIdx) - { - return (splitDir << 8) | (geoMergeIdx[0] << 4) | geoMergeIdx[1]; - } - static void updateGpmIdx(int mergeIdx, uint8_t& splitDir, MergeIdxPair& geoMergeIdx) - { - splitDir = (mergeIdx >> 8) & 0xFF; - geoMergeIdx[0] = (mergeIdx >> 4) & 0xF; - geoMergeIdx[1] = mergeIdx & 0xF; - } -}; - -class MergeItemList -{ -private: - Pool<MergeItem> m_mergeItemPool; - std::vector<MergeItem *> m_list; - size_t m_maxTrackingNum = 0; - ChromaFormat m_chromaFormat; - Area m_ctuArea; - -public: - MergeItemList(); - ~MergeItemList(); - - void init(size_t maxSize, ChromaFormat chromaFormat, int ctuWidth, int ctuHeight); - MergeItem* allocateNewMergeItem(); - void insertMergeItemToList(MergeItem* p); - void resetList(size_t maxTrackingNum); - MergeItem* getMergeItemInList(size_t index); - size_t size() { return m_list.size(); } - -}; - -#endif - namespace DeriveCtx { void CtxSplit ( const CodingStructure& cs, Partitioner& partitioner, unsigned& ctxSpl, unsigned& ctxQt, unsigned& ctxHv, unsigned& ctxHorBt, unsigned& ctxVerBt, bool* canSplit = nullptr ); diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 895ac31133ec7e65816c96bdb03a3005ab046e6e..237c79440953ceed692d47996f73f7fdee1b01fd 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -2255,3 +2255,268 @@ bool InterPrediction::xPredInterBlkRPR(const ScalingRatio scalingRatio, const PP return scaled; } + +#if JVET_AC0139_UNIFIED_MERGE +void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) const +#else +void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) +#endif +{ + CHECK( candIdx >= numValidMergeCand, "Merge candidate does not exist" ); + pu.regularMergeFlag = !(pu.ciipFlag || pu.cu->geoFlag); + pu.mergeFlag = true; + pu.mmvdMergeFlag = false; + pu.interDir = interDirNeighbours[candIdx]; + pu.cu->imv = (!pu.cu->geoFlag && useAltHpelIf[candIdx]) ? IMV_HPEL : 0; + pu.mergeIdx = candIdx; + pu.mergeType = CU::isIBC(*pu.cu) ? MergeType::IBC : MergeType::DEFAULT_N; + + for (const auto l: { REF_PIC_LIST_0, REF_PIC_LIST_1 }) + { + pu.mv[l] = mvFieldNeighbours[candIdx][l].mv; + pu.mvd[l] = Mv(); + pu.refIdx[l] = mvFieldNeighbours[candIdx][l].refIdx; + pu.mvpIdx[l] = NOT_VALID; + pu.mvpNum[l] = NOT_VALID; + } +#if GDR_ENABLED + CodingStructure &cs = *pu.cs; + const bool isEncodeGdrClean = + cs.sps->getGDREnabledFlag() && cs.pcv->isEncoder + && ((cs.picture->gdrParam.inGdrInterval && cs.isClean(pu.Y().topRight(), ChannelType::LUMA)) + || (cs.picture->gdrParam.verBoundary == -1)); + + if (isEncodeGdrClean) + { + for (const auto l: { REF_PIC_LIST_0, REF_PIC_LIST_1 }) + { + Mv mv = pu.mv[l]; + + int refIdx = pu.refIdx[l]; + + pu.mvSolid[l] = mvSolid[candIdx][l]; + pu.mvValid[l] = cs.isClean(pu.Y().topRight(), mv, l, refIdx); + } + } +#endif + + if (CU::isIBC(*pu.cu)) + { + pu.bv = pu.mv[REF_PIC_LIST_0]; + pu.bv.changePrecision(MvPrecision::INTERNAL, MvPrecision::ONE); // used for only integer resolution + pu.cu->imv = pu.cu->imv == IMV_HPEL ? 0 : pu.cu->imv; + } + pu.cu->bcwIdx = (interDirNeighbours[candIdx] == 3) ? bcwIdx[candIdx] : BCW_DEFAULT; + + PU::restrictBiPredMergeCandsOne(pu); + pu.mmvdEncOptMode = 0; +} + +void MergeCtx::getMmvdDeltaMv(const Slice& slice, const MmvdIdx candIdx, Mv deltaMv[NUM_REF_PIC_LIST_01]) const +{ + const int mvdBaseIdx = candIdx.pos.baseIdx; + const int mvdStep = candIdx.pos.step; + const int mvdPosition = candIdx.pos.position; + + int offset = 1 << (mvdStep + MV_FRACTIONAL_BITS_DIFF); + if (slice.getPicHeader()->getDisFracMMVD()) + { + offset <<= 2; + } + const int refList0 = mmvdBaseMv[mvdBaseIdx][REF_PIC_LIST_0].refIdx; + const int refList1 = mmvdBaseMv[mvdBaseIdx][REF_PIC_LIST_1].refIdx; + + const Mv dMvTable[4] = { Mv(offset,0), Mv(-offset,0), Mv(0, offset), Mv(0, -offset) }; + if ((refList0 != -1) && (refList1 != -1)) + { + const int poc0 = slice.getRefPOC(REF_PIC_LIST_0, refList0); + const int poc1 = slice.getRefPOC(REF_PIC_LIST_1, refList1); + const int currPoc = slice.getPOC(); + deltaMv[0] = dMvTable[mvdPosition]; + + if ((poc0 - currPoc) == (poc1 - currPoc)) + { + deltaMv[1] = deltaMv[0]; + } + else if (abs(poc1 - currPoc) > abs(poc0 - currPoc)) + { + const int scale = PU::getDistScaleFactor(currPoc, poc0, currPoc, poc1); + deltaMv[1] = deltaMv[0]; + const bool isL0RefLongTerm = slice.getRefPic(REF_PIC_LIST_0, refList0)->longTerm; + const bool isL1RefLongTerm = slice.getRefPic(REF_PIC_LIST_1, refList1)->longTerm; + if (isL0RefLongTerm || isL1RefLongTerm) + { + if ((poc1 - currPoc)*(poc0 - currPoc) > 0) + { + deltaMv[0] = deltaMv[1]; + } + else + { + deltaMv[0].set(-1 * deltaMv[1].getHor(), -1 * deltaMv[1].getVer()); + } + } + else + { + deltaMv[0] = deltaMv[1].getScaledMv(scale); + } + } + else + { + const int scale = PU::getDistScaleFactor(currPoc, poc1, currPoc, poc0); + const bool isL0RefLongTerm = slice.getRefPic(REF_PIC_LIST_0, refList0)->longTerm; + const bool isL1RefLongTerm = slice.getRefPic(REF_PIC_LIST_1, refList1)->longTerm; + if (isL0RefLongTerm || isL1RefLongTerm) + { + if ((poc1 - currPoc)*(poc0 - currPoc) > 0) + { + deltaMv[1] = deltaMv[0]; + } + else + { + deltaMv[1].set(-1 * deltaMv[0].getHor(), -1 * deltaMv[0].getVer()); + } + } + else + { + deltaMv[1] = deltaMv[0].getScaledMv(scale); + } + } + } + else if (refList0 != -1) + { + deltaMv[0] = dMvTable[mvdPosition]; + } + else if (refList1 != -1) + { + deltaMv[1] = dMvTable[mvdPosition]; + } +} + +void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit &pu, const MmvdIdx candIdx) +{ + Mv tempMv[NUM_REF_PIC_LIST_01]; + +#if GDR_ENABLED + const CodingStructure &cs = *pu.cs; + const bool isEncodeGdrClean = + cs.sps->getGDREnabledFlag() && cs.pcv->isEncoder + && ((cs.picture->gdrParam.inGdrInterval && cs.isClean(pu.Y().topRight(), ChannelType::LUMA)) + || (cs.picture->gdrParam.verBoundary == -1)); +#endif + + getMmvdDeltaMv(*pu.cs->slice, candIdx, tempMv); + const int mvdBaseIdx = candIdx.pos.baseIdx; + + const int refList0 = mmvdBaseMv[mvdBaseIdx][0].refIdx; + const int refList1 = mmvdBaseMv[mvdBaseIdx][1].refIdx; + + if ((refList0 != -1) && (refList1 != -1)) + { + pu.interDir = 3; + pu.mv[REF_PIC_LIST_0] = mmvdBaseMv[mvdBaseIdx][0].mv + tempMv[0]; + pu.refIdx[REF_PIC_LIST_0] = refList0; + pu.mv[REF_PIC_LIST_1] = mmvdBaseMv[mvdBaseIdx][1].mv + tempMv[1]; + pu.refIdx[REF_PIC_LIST_1] = refList1; +#if GDR_ENABLED + if (isEncodeGdrClean) + { + Mv mv0 = pu.mv[REF_PIC_LIST_0]; + Mv mv1 = pu.mv[REF_PIC_LIST_1]; + + int refIdx0 = pu.refIdx[REF_PIC_LIST_0]; + int refIdx1 = pu.refIdx[REF_PIC_LIST_1]; + + mmvdValid[mvdBaseIdx][0] = cs.isClean(pu.Y().topRight(), mv0, REF_PIC_LIST_0, refIdx0); + mmvdValid[mvdBaseIdx][1] = cs.isClean(pu.Y().topRight(), mv1, REF_PIC_LIST_1, refIdx1); + + pu.mvSolid[REF_PIC_LIST_0] = mmvdSolid[mvdBaseIdx][0]; + pu.mvSolid[REF_PIC_LIST_1] = mmvdSolid[mvdBaseIdx][1]; + + pu.mvValid[REF_PIC_LIST_0] = mmvdValid[mvdBaseIdx][0]; + pu.mvValid[REF_PIC_LIST_1] = mmvdValid[mvdBaseIdx][1]; + } +#endif + } + else if (refList0 != -1) + { + pu.interDir = 1; + pu.mv[REF_PIC_LIST_0] = mmvdBaseMv[mvdBaseIdx][0].mv + tempMv[0]; + pu.refIdx[REF_PIC_LIST_0] = refList0; + pu.mv[REF_PIC_LIST_1] = Mv(0, 0); + pu.refIdx[REF_PIC_LIST_1] = -1; + +#if GDR_ENABLED + if (isEncodeGdrClean) + { + Mv mv0 = pu.mv[REF_PIC_LIST_0]; + //Mv mv1 = pu.mv[REF_PIC_LIST_1]; + + int refIdx0 = pu.refIdx[REF_PIC_LIST_0]; + //int refIdx1 = pu.refIdx[REF_PIC_LIST_1]; + + pu.mvSolid[REF_PIC_LIST_0] = mmvdSolid[mvdBaseIdx][0]; + pu.mvSolid[REF_PIC_LIST_1] = true; + + mmvdValid[mvdBaseIdx][0] = cs.isClean(pu.Y().topRight(), mv0, REF_PIC_LIST_0, refIdx0); + mmvdValid[mvdBaseIdx][1] = true; + + pu.mvValid[REF_PIC_LIST_0] = mmvdValid[mvdBaseIdx][0]; + pu.mvValid[REF_PIC_LIST_1] = true; + } +#endif + } + else if (refList1 != -1) + { + pu.interDir = 2; + pu.mv[REF_PIC_LIST_0] = Mv(0, 0); + pu.refIdx[REF_PIC_LIST_0] = -1; + pu.mv[REF_PIC_LIST_1] = mmvdBaseMv[mvdBaseIdx][1].mv + tempMv[1]; + pu.refIdx[REF_PIC_LIST_1] = refList1; +#if GDR_ENABLED + if (isEncodeGdrClean) + { + // Mv mv0 = pu.mv[REF_PIC_LIST_0]; + Mv mv1 = pu.mv[REF_PIC_LIST_1]; + + // int refIdx0 = pu.refIdx[REF_PIC_LIST_0]; + int refIdx1 = pu.refIdx[REF_PIC_LIST_1]; + + mmvdValid[mvdBaseIdx][0] = true; + mmvdValid[mvdBaseIdx][1] = cs.isClean(pu.Y().topRight(), mv1, REF_PIC_LIST_1, refIdx1); + + pu.mvSolid[REF_PIC_LIST_0] = true; + pu.mvSolid[REF_PIC_LIST_1] = mmvdSolid[mvdBaseIdx][1]; + + pu.mvValid[REF_PIC_LIST_0] = true; + pu.mvValid[REF_PIC_LIST_1] = mmvdValid[mvdBaseIdx][1]; + } +#endif + } + + pu.mmvdMergeFlag = true; + pu.mmvdMergeIdx = candIdx; + pu.mergeFlag = true; + pu.regularMergeFlag = true; + pu.mergeIdx = candIdx.val; + pu.mergeType = MergeType::DEFAULT_N; + + pu.mvd[REF_PIC_LIST_0] = Mv(); + pu.mvd[REF_PIC_LIST_1] = Mv(); + pu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID; + pu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID; + pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID; + pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID; + pu.cu->imv = mmvdUseAltHpelIf[mvdBaseIdx] ? IMV_HPEL : 0; + + pu.cu->bcwIdx = (interDirNeighbours[mvdBaseIdx] == 3) ? bcwIdx[mvdBaseIdx] : BCW_DEFAULT; + + for (int refList = 0; refList < 2; refList++) + { + if (pu.refIdx[refList] >= 0) + { + pu.mv[refList].clipToStorageBitDepth(); + } + } + + PU::restrictBiPredMergeCandsOne(pu); +} diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index f5b0d771a6662c12735a99c803454a8e0d368ce2..58958b9c074f1c18d962e3a156e88e3833e26616 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -48,7 +48,6 @@ #include "Picture.h" #include "RdCost.h" -#include "ContextModelling.h" // forward declaration class Mv; @@ -60,6 +59,89 @@ class Mv; // Class definition // ==================================================================================================================== +class MergeCtx +{ +public: + MergeCtx() : numValidMergeCand(0), hasMergedCandList(false) {} + ~MergeCtx() {} +public: + MvField mvFieldNeighbours[MRG_MAX_NUM_CANDS][2]; +#if GDR_ENABLED + // note : check if source of mv and mv itself is valid + bool mvSolid[MRG_MAX_NUM_CANDS][2]; + bool mvValid[MRG_MAX_NUM_CANDS][2]; + Position mvPos[MRG_MAX_NUM_CANDS][2]; + MvpType mvType[MRG_MAX_NUM_CANDS][2]; +#endif + uint8_t bcwIdx[MRG_MAX_NUM_CANDS]; + unsigned char interDirNeighbours[ MRG_MAX_NUM_CANDS ]; + int numValidMergeCand; + bool hasMergedCandList; + + MotionBuf subPuMvpMiBuf; + MvField mmvdBaseMv[MmvdIdx::BASE_MV_NUM][2]; +#if GDR_ENABLED + bool mmvdSolid[MmvdIdx::BASE_MV_NUM][2]; + bool mmvdValid[MmvdIdx::BASE_MV_NUM][2]; +#endif + void setMmvdMergeCandiInfo(PredictionUnit &pu, MmvdIdx candIdx); + void getMmvdDeltaMv(const Slice& slice, const MmvdIdx candIdx, Mv deltaMv[NUM_REF_PIC_LIST_01]) const; + bool mmvdUseAltHpelIf[MmvdIdx::BASE_MV_NUM]; + bool useAltHpelIf [ MRG_MAX_NUM_CANDS ]; +#if JVET_AC0139_UNIFIED_MERGE + void setMergeInfo( PredictionUnit& pu, int candIdx ) const; +#else + void setMergeInfo( PredictionUnit& pu, int candIdx ); +#endif +}; + +class AffineMergeCtx +{ +public: + AffineMergeCtx() : numValidMergeCand(0) + { + for (int i = 0; i < AFFINE_MRG_MAX_NUM_CANDS; i++) + { + affineType[i] = AffineModel::_4_PARAMS; + } + } + ~AffineMergeCtx() {} +public: + std::array<MvField[2], AFFINE_MAX_NUM_CP> mvFieldNeighbours[AFFINE_MRG_MAX_NUM_CANDS]; +#if GDR_ENABLED + std::array<bool[2], AFFINE_MAX_NUM_CP> mvSolid[AFFINE_MRG_MAX_NUM_CANDS]; + std::array<bool[2], AFFINE_MAX_NUM_CP> mvValid[AFFINE_MRG_MAX_NUM_CANDS]; + + bool isSolid(const int idx, const int l) + { + bool solid = true; + for (auto &c: mvSolid[idx]) + { + solid &= c[l]; + } + return solid; + } + + bool isValid(const int idx, const int l) + { + bool valid = true; + for (auto &c: mvValid[idx]) + { + valid &= c[l]; + } + return valid; + } +#endif + unsigned char interDirNeighbours[AFFINE_MRG_MAX_NUM_CANDS]; + AffineModel affineType[AFFINE_MRG_MAX_NUM_CANDS]; + uint8_t bcwIdx[AFFINE_MRG_MAX_NUM_CANDS]; + int numValidMergeCand; + int maxNumMergeCand; + + MergeCtx *mrgCtx; + MergeType mergeType[AFFINE_MRG_MAX_NUM_CANDS]; +}; + class InterPrediction : public WeightPrediction { private: diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 25adf4ec35fd53c56e04c5fec888d92eeb5ce737..bdfa640b2a20c895ca6e92895dcb563b27d9cc79 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -889,8 +889,7 @@ void CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx& { cu.colorTransform = false; cs.addEmptyTUs( partitioner ); - MergeCtx mrgCtx; - prediction_unit ( pu, mrgCtx ); + prediction_unit ( pu ); end_of_ctu( cu, cuCtx ); return; } @@ -1023,7 +1022,7 @@ void CABACReader::cu_skip_flag( CodingUnit& cu ) } } -void CABACReader::imv_mode( CodingUnit& cu, MergeCtx& mrgCtx ) +void CABACReader::imv_mode( CodingUnit& cu ) { RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__OTHER ); @@ -1077,7 +1076,7 @@ void CABACReader::imv_mode( CodingUnit& cu, MergeCtx& mrgCtx ) DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() IMVFlag=%d\n", cu.imv ); } -void CABACReader::affine_amvr_mode( CodingUnit& cu, MergeCtx& mrgCtx ) +void CABACReader::affine_amvr_mode( CodingUnit& cu ) { RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__OTHER ); @@ -1270,15 +1269,14 @@ void CABACReader::cu_pred_data( CodingUnit &cu ) cu.predMode = MODE_IBC; return; } - MergeCtx mrgCtx; for( auto &pu : CU::traversePUs( cu ) ) { - prediction_unit( pu, mrgCtx ); + prediction_unit( pu ); } - imv_mode ( cu, mrgCtx ); - affine_amvr_mode( cu, mrgCtx ); + imv_mode ( cu ); + affine_amvr_mode( cu ); cu_bcw_flag( cu ); } @@ -2084,7 +2082,7 @@ void CABACReader::xAdjustPLTIndex(CodingUnit& cu, Pel curLevel, uint32_t idx, Pe // void mvp_flag ( pu, refList ); //================================================================================ -void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx ) +void CABACReader::prediction_unit( PredictionUnit& pu ) { if( pu.cu->skip ) { diff --git a/source/Lib/DecoderLib/CABACReader.h b/source/Lib/DecoderLib/CABACReader.h index e8fcf54ebf35dbb2aebdd869642c86b727a8a07b..98704b00f3cdc3453bc53a03c69b1d091ad2af6f 100644 --- a/source/Lib/DecoderLib/CABACReader.h +++ b/source/Lib/DecoderLib/CABACReader.h @@ -106,15 +106,15 @@ public: void cu_palette_info ( CodingUnit& cu, ComponentID compBegin, uint32_t numComp, CUCtx& cuCtx ); void cuPaletteSubblockInfo ( CodingUnit& cu, ComponentID compBegin, uint32_t numComp, int subSetId, uint32_t& prevRunPos, unsigned& prevRunType ); // prediction unit (clause 7.3.8.6) - void prediction_unit ( PredictionUnit& pu, MergeCtx& mrgCtx ); + void prediction_unit ( PredictionUnit& pu ); void merge_flag ( PredictionUnit& pu ); void merge_data ( PredictionUnit& pu ); void affine_flag ( CodingUnit& cu ); void subblock_merge_flag ( CodingUnit& cu ); void merge_idx ( PredictionUnit& pu ); void mmvd_merge_idx(PredictionUnit& pu); - void imv_mode ( CodingUnit& cu, MergeCtx& mrgCtx ); - void affine_amvr_mode ( CodingUnit& cu, MergeCtx& mrgCtx ); + void imv_mode ( CodingUnit& cu ); + void affine_amvr_mode ( CodingUnit& cu ); void inter_pred_idc ( PredictionUnit& pu ); void ref_idx ( PredictionUnit& pu, RefPicList eRefList ); void mvp_flag ( PredictionUnit& pu, RefPicList eRefList ); diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 86cd7eabad3cf8ef96c6e3c88f40ab59233b12f8..7f865ad6483d930ff3aaa2f2f057f1ee1d67ad85 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -5791,5 +5791,301 @@ void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&best } #endif +#if JVET_AC0139_UNIFIED_MERGE +MergeItem::MergeItem() +{ + +} +MergeItem::~MergeItem() +{ + +} + +void MergeItem::create(ChromaFormat chromaFormat, const Area& area) +{ + if (m_pelStorage.bufs.empty()) + { + m_pelStorage.create(chromaFormat, area); + m_mvStorage.resize(area.area() >> (MIN_CU_LOG2 << 1)); + } + + // reset data + cost = MAX_DOUBLE; + mergeIdx = 0; + bcwIdx = 0; + interDir = 0; + useAltHpelIf = false; + affineType = AffineModel::_4_PARAMS; + mergeItemType = MergeItemType::NUM; + + noBdofRefine = false; + noResidual = false; + + lumaPredReady = false; + chromaPredReady = false; +} + +void MergeItem::importMergeInfo(const MergeCtx& mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, PredictionUnit& pu) +{ + mergeIdx = _mergeIdx; + mergeItemType = _mergeItemType; + + if (mergeItemType != MergeItemType::GPM) + { + mvField[0][REF_PIC_LIST_0] = mergeCtx.mvFieldNeighbours[mergeIdx][REF_PIC_LIST_0]; + mvField[0][REF_PIC_LIST_1] = mergeCtx.mvFieldNeighbours[mergeIdx][REF_PIC_LIST_1]; + interDir = mergeCtx.interDirNeighbours[mergeIdx]; + bcwIdx = mergeCtx.bcwIdx[mergeIdx]; + useAltHpelIf = mergeCtx.useAltHpelIf[mergeIdx]; + } + + switch (_mergeItemType) + { + case MergeItemType::REGULAR: + break; + + case MergeItemType::CIIP: + break; + + case MergeItemType::MMVD: + { + MmvdIdx candIdx; + candIdx.val = mergeIdx; + const int mmvdBaseIdx = candIdx.pos.baseIdx; + mvField[0][REF_PIC_LIST_0] = mergeCtx.mmvdBaseMv[mmvdBaseIdx][REF_PIC_LIST_0]; + mvField[0][REF_PIC_LIST_1] = mergeCtx.mmvdBaseMv[mmvdBaseIdx][REF_PIC_LIST_1]; + Mv tempMv[NUM_REF_PIC_LIST_01]; + mergeCtx.getMmvdDeltaMv(*pu.cs->slice, candIdx, tempMv); + mvField[0][REF_PIC_LIST_0].mv += tempMv[REF_PIC_LIST_0]; + mvField[0][REF_PIC_LIST_1].mv += tempMv[REF_PIC_LIST_1]; + interDir = mergeCtx.interDirNeighbours[mmvdBaseIdx]; + bcwIdx = mergeCtx.bcwIdx[mmvdBaseIdx]; + useAltHpelIf = mergeCtx.useAltHpelIf[mmvdBaseIdx]; + break; + } + case MergeItemType::GPM: + mvField[0][REF_PIC_LIST_0].setMvField(Mv(0, 0), -1); + mvField[0][REF_PIC_LIST_1].setMvField(Mv(0, 0), -1); + bcwIdx = BCW_DEFAULT; + useAltHpelIf = false; + MergeItem::updateGpmIdx(mergeIdx, pu.geoSplitDir, pu.geoMergeIdx); + pu.mergeFlag = true; + pu.cu->affine = false; + pu.cu->geoFlag = true; + pu.mergeType = MergeType::DEFAULT_N; + PU::spanMotionInfo(pu, getMvBuf(pu)); + PU::spanGeoMotionInfo(pu, mergeCtx, pu.geoSplitDir, pu.geoMergeIdx); + getMvBuf(pu).copyFrom(pu.getMotionBuf()); + break; + + case MergeItemType::IBC: + default: + THROW("Wrong merge item type"); + } +} + +void MergeItem::importMergeInfo(const AffineMergeCtx& mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, const UnitArea& unitArea) +{ + mergeIdx = _mergeIdx; + mergeItemType = _mergeItemType; + + affineType = mergeCtx.affineType[mergeIdx]; + interDir = mergeCtx.interDirNeighbours[mergeIdx]; + bcwIdx = mergeCtx.bcwIdx[mergeIdx]; + useAltHpelIf = false; + + switch (_mergeItemType) + { + case MergeItemType::SBTMVP: + mvField = mergeCtx.mvFieldNeighbours[mergeIdx]; + getMvBuf(unitArea).copyFrom(mergeCtx.mrgCtx->subPuMvpMiBuf); + break; + + case MergeItemType::AFFINE: + mvField = mergeCtx.mvFieldNeighbours[mergeIdx]; + break; + + default: + THROW("Wrong merge item type"); + } +} + +bool MergeItem::exportMergeInfo(PredictionUnit& pu, bool forceNoResidual) +{ + pu.mergeFlag = true; + pu.regularMergeFlag = false; + pu.mmvdMergeFlag = false; + pu.interDir = interDir; + pu.mergeIdx = mergeIdx; + pu.mergeType = MergeType::DEFAULT_N; + pu.mv[REF_PIC_LIST_0] = mvField[0][REF_PIC_LIST_0].mv; + pu.mv[REF_PIC_LIST_1] = mvField[0][REF_PIC_LIST_1].mv; + pu.refIdx[REF_PIC_LIST_0] = mvField[0][REF_PIC_LIST_0].refIdx; + pu.refIdx[REF_PIC_LIST_1] = mvField[0][REF_PIC_LIST_1].refIdx; + pu.mvd[REF_PIC_LIST_0] = Mv(); + pu.mvd[REF_PIC_LIST_1] = Mv(); + pu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID; + pu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID; + pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID; + pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID; + pu.cu->bcwIdx = (interDir == 3) ? bcwIdx : BCW_DEFAULT; + pu.mmvdEncOptMode = 0; + pu.cu->mmvdSkip = false; + pu.cu->affine = false; + pu.cu->affineType = AffineModel::_4_PARAMS; + pu.cu->geoFlag = false; + pu.cu->mtsFlag = false; + pu.ciipFlag = false; + pu.cu->imv = (!pu.cu->geoFlag && useAltHpelIf) ? IMV_HPEL : 0; + + const bool resetCiip2Regular = mergeItemType == MergeItemType::CIIP && forceNoResidual; + MergeItemType updatedType = resetCiip2Regular ? MergeItemType::REGULAR : mergeItemType; + switch (updatedType) + { + case MergeItemType::REGULAR: + pu.regularMergeFlag = true; + PU::restrictBiPredMergeCandsOne(pu); + break; + + case MergeItemType::CIIP: + CHECK(forceNoResidual, "Cannot force no residuals for CIIP"); + pu.ciipFlag = true; + pu.intraDir[ChannelType::LUMA] = PLANAR_IDX; + pu.intraDir[ChannelType::CHROMA] = DM_CHROMA_IDX; + break; + + case MergeItemType::MMVD: + pu.mmvdMergeFlag = true; + pu.mmvdMergeIdx.val = mergeIdx; + pu.regularMergeFlag = true; + if (forceNoResidual) + { + pu.cu->mmvdSkip = true; + } + PU::restrictBiPredMergeCandsOne(pu); + break; + + case MergeItemType::SBTMVP: + pu.cu->affine = true; + pu.mergeType = MergeType::SUBPU_ATMVP; + break; + + case MergeItemType::AFFINE: + pu.cu->affine = true; + pu.cu->affineType = affineType; + PU::setAllAffineMvField(pu, mvField, REF_PIC_LIST_0); + PU::setAllAffineMvField(pu, mvField, REF_PIC_LIST_1); + break; + + case MergeItemType::GPM: + pu.mergeIdx = -1; + pu.cu->geoFlag = true; + pu.cu->bcwIdx = BCW_DEFAULT; + MergeItem::updateGpmIdx(mergeIdx, pu.geoSplitDir, pu.geoMergeIdx); + pu.cu->imv = 0; + break; + + case MergeItemType::IBC: + default: + THROW("Wrong merge item type"); + } + + if (mergeItemType == MergeItemType::GPM) + { + pu.getMotionBuf().copyFrom(getMvBuf(pu)); + } + else + { + PU::spanMotionInfo(pu, getMvBuf(pu)); + } + +#if GDR_ENABLED + CodingStructure &cs = *pu.cs; + const bool isEncodeGdrClean = cs.sps->getGDREnabledFlag() && cs.pcv->isEncoder + && ((cs.picture->gdrParam.inGdrInterval && cs.isClean(pu.Y().topRight(), ChannelType::LUMA)) + || (cs.picture->gdrParam.verBoundary == -1)); + if (isEncodeGdrClean) + { + Mv mv0 = pu.mv[REF_PIC_LIST_0]; + Mv mv1 = pu.mv[REF_PIC_LIST_1]; + + int refIdx0 = pu.refIdx[REF_PIC_LIST_0]; + int refIdx1 = pu.refIdx[REF_PIC_LIST_1]; + + pu.mvSolid[REF_PIC_LIST_0] = mvSolid[0]; + pu.mvSolid[REF_PIC_LIST_1] = mvSolid[1]; + pu.mvValid[REF_PIC_LIST_0] = cs.isClean(pu.Y().topRight(), mv0, REF_PIC_LIST_0, refIdx0); + pu.mvValid[REF_PIC_LIST_1] = cs.isClean(pu.Y().topRight(), mv1, REF_PIC_LIST_1, refIdx1); + } +#endif + + return resetCiip2Regular; +} + +MergeItemList::MergeItemList() +{ + +} + +MergeItemList::~MergeItemList() +{ +} + +void MergeItemList::init(size_t maxSize, ChromaFormat chromaFormat, int ctuWidth, int ctuHeight) +{ + m_list.reserve(maxSize + 1); // to avoid reallocation when inserting a new item + m_chromaFormat = chromaFormat; + m_ctuArea.x = 0; + m_ctuArea.y = 0; + m_ctuArea.width = ctuWidth; + m_ctuArea.height = ctuHeight; +} + +MergeItem* MergeItemList::allocateNewMergeItem() +{ + MergeItem* p = m_mergeItemPool.get(); + p->create(m_chromaFormat, m_ctuArea); + + return p; +} + +void MergeItemList::insertMergeItemToList(MergeItem* p) +{ + if (m_list.empty()) + { + m_list.push_back(p); + } + else if (m_list.size() == m_maxTrackingNum && p->cost >= m_list.back()->cost) + { + m_mergeItemPool.giveBack(p); + } + else + { + if (m_list.size() == m_maxTrackingNum) + { + m_mergeItemPool.giveBack(m_list.back()); + m_list.pop_back(); + } + auto it = std::find_if(m_list.begin(), m_list.end(), [&p](const MergeItem *mi) { return p->cost < mi->cost; }); + m_list.insert(it, p); + } +} + +MergeItem* MergeItemList::getMergeItemInList(size_t index) +{ + return index < m_maxTrackingNum ? m_list[index] : nullptr; +} + +void MergeItemList::resetList(size_t maxTrackingNum) +{ + for (auto p : m_list) + { + m_mergeItemPool.giveBack(p); + } + m_list.clear(); + m_list.reserve(maxTrackingNum); + m_maxTrackingNum = maxTrackingNum; +} +#endif //! \} diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h index f855765796bfd2f07b3fa2c95de86dade1d3c641..164791e031b2d5bc901b3e1cf3181a0b43151e95 100644 --- a/source/Lib/EncoderLib/EncCu.h +++ b/source/Lib/EncoderLib/EncCu.h @@ -135,6 +135,93 @@ public: } }; +#if JVET_AC0139_UNIFIED_MERGE +class MergeItem +{ +private: + PelStorage m_pelStorage; + std::vector<MotionInfo> m_mvStorage; + +public: + enum class MergeItemType + { + REGULAR, + SBTMVP, + AFFINE, + MMVD, + CIIP, + GPM, + IBC, + NUM, + }; + + double cost; + std::array<MvField[2], AFFINE_MAX_NUM_CP> mvField; + int mergeIdx; + uint8_t bcwIdx; + uint8_t interDir; + bool useAltHpelIf; + AffineModel affineType; + + bool noResidual; + bool noBdofRefine; + + bool lumaPredReady; + bool chromaPredReady; + + MergeItemType mergeItemType; + MotionBuf mvBuf; + +#if GDR_ENABLED + bool mvSolid[2]; + bool mvValid[2]; +#endif + + MergeItem(); + ~MergeItem(); + + void create(ChromaFormat chromaFormat, const Area& area); + void importMergeInfo(const MergeCtx& mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, PredictionUnit& pu); + void importMergeInfo(const AffineMergeCtx& mergeCtx, int _mergeIdx, MergeItemType _mergeItemType, const UnitArea& unitArea); + bool exportMergeInfo(PredictionUnit& pu, bool forceNoResidual); + PelUnitBuf getPredBuf(const UnitArea& unitArea) { return m_pelStorage.getBuf(unitArea); } + MotionBuf getMvBuf(const UnitArea& unitArea) { return MotionBuf(m_mvStorage.data(), g_miScaling.scale(unitArea.lumaSize())); } + + static int getGpmUnfiedIndex(int splitDir, const MergeIdxPair& geoMergeIdx) + { + return (splitDir << 8) | (geoMergeIdx[0] << 4) | geoMergeIdx[1]; + } + static void updateGpmIdx(int mergeIdx, uint8_t& splitDir, MergeIdxPair& geoMergeIdx) + { + splitDir = (mergeIdx >> 8) & 0xFF; + geoMergeIdx[0] = (mergeIdx >> 4) & 0xF; + geoMergeIdx[1] = mergeIdx & 0xF; + } +}; + +class MergeItemList +{ +private: + Pool<MergeItem> m_mergeItemPool; + std::vector<MergeItem *> m_list; + size_t m_maxTrackingNum = 0; + ChromaFormat m_chromaFormat; + Area m_ctuArea; + +public: + MergeItemList(); + ~MergeItemList(); + + void init(size_t maxSize, ChromaFormat chromaFormat, int ctuWidth, int ctuHeight); + MergeItem* allocateNewMergeItem(); + void insertMergeItemToList(MergeItem* p); + void resetList(size_t maxTrackingNum); + MergeItem* getMergeItemInList(size_t index); + size_t size() { return m_list.size(); } + +}; +#endif + class EncCu : DecCu {