diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp index 76aea6cf4d7b188d1ca2640710cecad749057901..9e6a4e368e42edf0d1c27b24406eeb4198ca4f3a 100644 --- a/source/Lib/CommonLib/CodingStructure.cpp +++ b/source/Lib/CommonLib/CodingStructure.cpp @@ -831,7 +831,11 @@ void CodingStructure::useSubStructure( const CodingStructure& subStruct, const C if( cpyResi ) picture->getResiBuf( clippedArea ).copyFrom( subResiBuf ); if( cpyReco ) picture->getRecoBuf( clippedArea ).copyFrom( subRecoBuf ); +#if JVET_M0483_IBC + if (!subStruct.m_isTuEnc && ((!slice->isIntra() || slice->getSPS()->getIBCFlag()) && subStruct.chType != CHANNEL_TYPE_CHROMA)) +#else if (!subStruct.m_isTuEnc && (!slice->isIntra() && subStruct.chType != CHANNEL_TYPE_CHROMA)) +#endif { // copy motion buffer MotionBuf ownMB = getMotionBuf ( clippedArea ); @@ -1011,7 +1015,11 @@ void CodingStructure::copyStructure( const CodingStructure& other, const Channel pu = *ppu; } +#if JVET_M0483_IBC + if (!other.slice->isIntra() || other.slice->getSPS()->getIBCFlag()) +#else if( !other.slice->isIntra() ) +#endif { // copy motion buffer MotionBuf ownMB = getMotionBuf(); @@ -1074,7 +1082,11 @@ void CodingStructure::initStructData( const int &QP, const bool &_isLosses, cons isLossless = _isLosses; } +#if JVET_M0483_IBC + if (!skipMotBuf && (!parent || ((!slice->isIntra() || slice->getSPS()->getIBCFlag()) && !m_isTuEnc))) +#else if( !skipMotBuf && ( !parent || ( ( slice->getSliceType() != I_SLICE ) && !m_isTuEnc ) ) ) +#endif { getMotionBuf() .memset( 0 ); } diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index 2f75ce0a3759ed2f93c5643cf59cb26d191fe0e0..386c1733c566a41d5317f7744c417fbb74693e16 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -482,6 +482,20 @@ unsigned DeriveCtx::CtxPredModeFlag( const CodingUnit& cu ) } #endif +#if JVET_M0483_IBC +unsigned DeriveCtx::CtxIBCFlag(const CodingUnit& cu) +{ + const CodingStructure *cs = cu.cs; + unsigned ctxId = 0; + const CodingUnit *cuLeft = cs->getCURestricted(cu.lumaPos().offset(-1, 0), cu, CH_L); + ctxId = (cuLeft && CU::isIBC(*cuLeft)) ? 1 : 0; + + const CodingUnit *cuAbove = cs->getCURestricted(cu.lumaPos().offset(0, -1), cu, CH_L); + ctxId = (cuAbove && CU::isIBC(*cuAbove)) ? 1 : 0; + return ctxId; +} +#endif + void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) { CHECK( candIdx >= numValidMergeCand, "Merge candidate does not exist" ); @@ -501,12 +515,20 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) pu.mvpIdx [REF_PIC_LIST_1] = NOT_VALID; pu.mvpNum [REF_PIC_LIST_0] = NOT_VALID; pu.mvpNum [REF_PIC_LIST_1] = NOT_VALID; +#if JVET_M0483_IBC + if (CU::isIBC(*pu.cu)) + { + pu.bv = pu.mv[REF_PIC_LIST_0]; + pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); // used for only integer resolution + } +#else if (interDirNeighbours[candIdx] == 1 && pu.cs->slice->getRefPic(REF_PIC_LIST_0, mvFieldNeighbours[candIdx << 1].refIdx)->getPOC() == pu.cs->slice->getPOC()) { pu.cu->ibc = true; pu.bv = pu.mv[REF_PIC_LIST_0]; pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); // used for only integer resolution } +#endif pu.cu->GBiIdx = ( interDirNeighbours[candIdx] == 3 ) ? GBiIdx[candIdx] : GBI_DEFAULT; #if JVET_M0068_M0171_MMVD_CLEANUP diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index 90ca2477514aed8a76d6d4ec8d3c8bb11c79eb21..e187f42429b453ffb1fefad9ccce2b6ffb86ec2c 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -321,6 +321,9 @@ unsigned CtxTriangleFlag( const CodingUnit& cu ); #if JVET_M0502_PRED_MODE_CTX unsigned CtxPredModeFlag( const CodingUnit& cu ); #endif +#if JVET_M0483_IBC +unsigned CtxIBCFlag(const CodingUnit& cu); +#endif } #endif // __CONTEXTMODELLING__ diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp index 72c26adcc6b40c338d30e036a24ca7f237ecd4be..558720f5c5e86671fef3a7ed66b9b9d1eb50d1ea 100644 --- a/source/Lib/CommonLib/Contexts.cpp +++ b/source/Lib/CommonLib/Contexts.cpp @@ -1370,6 +1370,22 @@ const CtxSet ContextSetCfg::TriangleIdx = ContextSetCfg::addCtxSet }); // clang-format on +#if JVET_M0483_IBC +const CtxSet ContextSetCfg::IBCFlag = ContextSetCfg::addCtxSet +({ +#if JVET_M0453_CABAC_ENGINE + { 149, 137, 137, }, + { 165, 151, 137, }, + { CNU, CNU, CNU, }, + { 9, 13, 10, }, +#else + { 165, 137, 153, }, + { 106, 122, 138, }, + { CNU, CNU, CNU, }, +#endif +}); +#endif + const unsigned ContextSetCfg::NumberOfContexts = (unsigned)ContextSetCfg::sm_InitTables[0].size(); diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h index c3f5dc50599288223ca2cc560f1250c80046fb28..994d44bae4ad3c85b1ab1a3f3937f06d9f70de6e 100644 --- a/source/Lib/CommonLib/Contexts.h +++ b/source/Lib/CommonLib/Contexts.h @@ -307,6 +307,9 @@ public: #if JVET_M0444_SMVD static const CtxSet SmvdFlag; #endif +#if JVET_M0483_IBC + static const CtxSet IBCFlag; +#endif #if JVET_M0102_INTRA_SUBPARTITIONS static const CtxSet ISPMode; #endif diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 0b426e3c004a72e2e0b2734d2d110bed8aed9d27..241cb9766411b4ec8b01d5e211321c9ef9e5f22f 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -414,7 +414,11 @@ void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList& int iRefIdx = pu.refIdx[eRefPicList]; Mv mv[3]; bool isIBC = false; +#if JVET_M0483_IBC + if (CU::isIBC(*pu.cu)) +#else if (pu.cs->slice->getRefPic(eRefPicList, iRefIdx)->getPOC() == pu.cs->slice->getPOC()) +#endif { isIBC = true; } @@ -454,11 +458,27 @@ void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList& } else { +#if JVET_M0483_IBC + if (isIBC) + { + xPredInterBlk(compID, pu, pu.cu->slice->getPic(), mv[0], pcYuvPred, bi, pu.cu->slice->clpRng(compID) + , bioApplied + , isIBC + ); + } + else + { + xPredInterBlk(compID, pu, pu.cu->slice->getRefPic(eRefPicList, iRefIdx), mv[0], pcYuvPred, bi, pu.cu->slice->clpRng(compID) + , bioApplied + , isIBC + ); + } +#else xPredInterBlk( compID, pu, pu.cu->slice->getRefPic( eRefPicList, iRefIdx ), mv[0], pcYuvPred, bi, pu.cu->slice->clpRng( compID ) , bioApplied , isIBC ); - +#endif } } } @@ -519,7 +539,13 @@ void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred) RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); +#if JVET_M0483_IBC + CHECK(CU::isIBC(*pu.cu) && eRefPicList != REF_PIC_LIST_0, "Invalid interdir for ibc mode"); + CHECK(CU::isIBC(*pu.cu) && pu.refIdx[refList] != MAX_NUM_REF, "Invalid reference index for ibc mode"); + CHECK((CU::isInter(*pu.cu) && pu.refIdx[refList] >= slice.getNumRefIdx(eRefPicList)), "Invalid reference index"); +#else CHECK( pu.refIdx[refList] >= slice.getNumRefIdx( eRefPicList ), "Invalid reference index" ); +#endif m_iRefListIdx = refList; PelUnitBuf pcMbBuf = ( pu.chromaFormat == CHROMA_400 ? diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp index a9c41af40a240bb5b0fbb5e320a0c4c48061d913..fb92e137ff10f93e26be04d47a30ce2b0aba802d 100644 --- a/source/Lib/CommonLib/LoopFilter.cpp +++ b/source/Lib/CommonLib/LoopFilter.cpp @@ -599,11 +599,17 @@ unsigned LoopFilter::xGetBoundaryStrengthSingle ( const CodingUnit& cu, const De if (sliceQ.isInterB() || sliceP.isInterB()) { +#if JVET_M0483_IBC + const Picture *piRefP0 = (CU::isIBC(cuP) ? sliceP.getPic() : ((0 > miP.refIdx[0]) ? NULL : sliceP.getRefPic(REF_PIC_LIST_0, miP.refIdx[0]))); + const Picture *piRefP1 = (CU::isIBC(cuP) ? NULL : ((0 > miP.refIdx[1]) ? NULL : sliceP.getRefPic(REF_PIC_LIST_1, miP.refIdx[1]))); + const Picture *piRefQ0 = (CU::isIBC(cuQ) ? sliceQ.getPic() : ((0 > miQ.refIdx[0]) ? NULL : sliceQ.getRefPic(REF_PIC_LIST_0, miQ.refIdx[0]))); + const Picture *piRefQ1 = (CU::isIBC(cuQ) ? NULL : ((0 > miQ.refIdx[1]) ? NULL : sliceQ.getRefPic(REF_PIC_LIST_1, miQ.refIdx[1]))); +#else const Picture *piRefP0 = ( 0 > miP.refIdx[0] ) ? NULL : sliceP.getRefPic( REF_PIC_LIST_0, miP.refIdx[0] ); const Picture *piRefP1 = ( 0 > miP.refIdx[1] ) ? NULL : sliceP.getRefPic( REF_PIC_LIST_1, miP.refIdx[1] ); const Picture *piRefQ0 = ( 0 > miQ.refIdx[0] ) ? NULL : sliceQ.getRefPic( REF_PIC_LIST_0, miQ.refIdx[0] ); const Picture *piRefQ1 = ( 0 > miQ.refIdx[1] ) ? NULL : sliceQ.getRefPic( REF_PIC_LIST_1, miQ.refIdx[1] ); - +#endif Mv mvP0, mvP1, mvQ0, mvQ1; if( 0 <= miP.refIdx[0] ) { mvP0 = miP.mv[0]; } @@ -655,11 +661,17 @@ unsigned LoopFilter::xGetBoundaryStrengthSingle ( const CodingUnit& cu, const De // pcSlice->isInterP() +#if JVET_M0483_IBC + CHECK(CU::isInter(cuP) && 0 > miP.refIdx[0], "Invalid reference picture list index"); + CHECK(CU::isInter(cuP) && 0 > miQ.refIdx[0], "Invalid reference picture list index"); + const Picture *piRefP0 = (CU::isIBC(cuP) ? sliceP.getPic() : sliceP.getRefPic(REF_PIC_LIST_0, miP.refIdx[0])); + const Picture *piRefQ0 = (CU::isIBC(cuQ) ? sliceQ.getPic() : sliceQ.getRefPic(REF_PIC_LIST_0, miQ.refIdx[0])); +#else CHECK(0 > miP.refIdx[0], "Invalid reference picture list index"); CHECK(0 > miQ.refIdx[0], "Invalid reference picture list index"); const Picture *piRefP0 = sliceP.getRefPic(REF_PIC_LIST_0, miP.refIdx[0]); const Picture *piRefQ0 = sliceQ.getRefPic(REF_PIC_LIST_0, miQ.refIdx[0]); - +#endif if (piRefP0 != piRefQ0) { #if JVET_M0471_LONG_DEBLOCKING_FILTERS diff --git a/source/Lib/CommonLib/MotionInfo.h b/source/Lib/CommonLib/MotionInfo.h index c193228a79b0c9523180c969f7199c7e18a2fb8e..2bc0f935d5e2d8bf49adb725e4c51a4092a060d7 100644 --- a/source/Lib/CommonLib/MotionInfo.h +++ b/source/Lib/CommonLib/MotionInfo.h @@ -101,30 +101,49 @@ struct MvField struct MotionInfo { bool isInter; +#if JVET_M0483_IBC + bool isIBCmot; +#endif char interDir; uint16_t sliceIdx; - Mv mv [ NUM_REF_PIC_LIST_01 ]; int16_t refIdx [ NUM_REF_PIC_LIST_01 ]; - Mv bv; #if JVET_M0264_HMVP_WITH_GBIIDX uint8_t GBiIdx; #endif + Mv bv; +#if JVET_M0483_IBC #if JVET_M0264_HMVP_WITH_GBIIDX - MotionInfo() : isInter( false ), interDir( 0 ), sliceIdx( 0 ), refIdx{ NOT_VALID, NOT_VALID }, GBiIdx( 0 ) { } + MotionInfo() : isInter(false), isIBCmot(false), interDir(0), sliceIdx(0), refIdx{ NOT_VALID, NOT_VALID }, GBiIdx(0) { } #else - MotionInfo() : isInter( false ), interDir( 0 ), sliceIdx( 0 ), refIdx{ NOT_VALID, NOT_VALID } { } + MotionInfo() : isInter(false), isIBCmot(false), interDir(0), sliceIdx(0), refIdx{ NOT_VALID, NOT_VALID } { } #endif // ensure that MotionInfo(0) produces '\x000....' bit pattern - needed to work with AreaBuf - don't use this constructor for anything else #if JVET_M0264_HMVP_WITH_GBIIDX - MotionInfo( int i ) : isInter( i != 0 ), interDir( 0 ), sliceIdx( 0 ), refIdx{ 0, 0 }, GBiIdx( 0 ) { CHECKD( i != 0, "The argument for this constructor has to be '0'" ); } + MotionInfo(int i) : isInter(i != 0), isIBCmot(false), interDir(0), sliceIdx(0), refIdx{ 0, 0 }, GBiIdx(0) { CHECKD(i != 0, "The argument for this constructor has to be '0'"); } +#else + MotionInfo(int i) : isInter(i != 0), isIBCmot(false), interDir(0), sliceIdx(0), refIdx{ 0, 0 } { CHECKD(i != 0, "The argument for this constructor has to be '0'"); } +#endif +#else +#if JVET_M0264_HMVP_WITH_GBIIDX + MotionInfo() : isInter(false), interDir(0), sliceIdx(0), refIdx{ NOT_VALID, NOT_VALID }, GBiIdx(0) { } +#else + MotionInfo() : isInter(false), interDir( 0 ), sliceIdx( 0 ), refIdx{ NOT_VALID, NOT_VALID } { } +#endif + // ensure that MotionInfo(0) produces '\x000....' bit pattern - needed to work with AreaBuf - don't use this constructor for anything else +#if JVET_M0264_HMVP_WITH_GBIIDX + MotionInfo(int i) : isInter(i != 0), interDir(0), sliceIdx(0), refIdx{ 0, 0 }, GBiIdx(0) { CHECKD(i != 0, "The argument for this constructor has to be '0'"); } #else MotionInfo( int i ) : isInter( i != 0 ), interDir( 0 ), sliceIdx( 0 ), refIdx{ 0, 0 } { CHECKD( i != 0, "The argument for this constructor has to be '0'" ); } +#endif #endif bool operator==( const MotionInfo& mi ) const { if( isInter != mi.isInter ) return false; +#if JVET_M0483_IBC + if (isIBCmot != mi.isIBCmot) return false; +#endif if( isInter ) { if( sliceIdx != mi.sliceIdx ) return false; @@ -242,5 +261,8 @@ struct LutMotionCand { MotionInfo* motionCand; int currCnt; +#if JVET_M0483_IBC + int currCntIBC; +#endif }; #endif // __MOTIONINFO__ diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 260ca2ecde1e1787b1275fcde2de946a95cc321d..372aa0899671e6ae4f7e0c0cc042dcbaee4cda06 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -450,6 +450,7 @@ void Slice::setRefPicList( PicList& rcListPic, bool checkNumPocTotalCurr, bool b pcRefPic = xGetLongTermRefPic(rcListPic, m_pRPS->getPOC(i), m_pRPS->getCheckLTMSBPresent(i)); } } +#if JVET_M0483_IBC==0 if (getSPS()->getSpsNext().getIBCMode()) { RefPicSetLtCurr[NumPicLtCurr] = getPic(); @@ -457,6 +458,7 @@ void Slice::setRefPicList( PicList& rcListPic, bool checkNumPocTotalCurr, bool b getPic()->longTerm = true; NumPicLtCurr++; } +#endif // ref_pic_list_init Picture* rpsCurrList0[MAX_NUM_REF+1]; Picture* rpsCurrList1[MAX_NUM_REF+1]; @@ -469,11 +471,13 @@ void Slice::setRefPicList( PicList& rcListPic, bool checkNumPocTotalCurr, bool b // - Otherwise, when the current picture contains a P or B slice, the value of NumPocTotalCurr shall not be equal to 0. if (getRapPicFlag()) { +#if JVET_M0483_IBC==0 if (getSPS()->getSpsNext().getIBCMode()) { CHECK(numPicTotalCurr != 1, "Invalid state"); } else +#endif CHECK(numPicTotalCurr != 0, "Invalid state"); } @@ -544,11 +548,13 @@ void Slice::setRefPicList( PicList& rcListPic, bool checkNumPocTotalCurr, bool b m_bIsUsedAsLongTerm[REF_PIC_LIST_1][rIdx] = ( cIdx >= NumPicStCurr0 + NumPicStCurr1 ); } } +#if JVET_M0483_IBC==0 if (getSPS()->getSpsNext().getIBCMode()) { m_apcRefPicList[REF_PIC_LIST_0][m_aiNumRefIdx[REF_PIC_LIST_0] - 1] = getPic(); m_bIsUsedAsLongTerm[REF_PIC_LIST_0][m_aiNumRefIdx[REF_PIC_LIST_0] - 1] = true; } +#endif // For generalized B // note: maybe not existed case (always L0 is copied to L1 if L1 is empty) if( bCopyL0toL1ErrorCase && isInterB() && getNumRefIdx(REF_PIC_LIST_1) == 0) @@ -579,7 +585,11 @@ int Slice::getNumRpsCurrTempList() const numRpsCurrTempList++; } } +#if JVET_M0483_IBC + if (getSPS()->getIBCFlag()) +#else if (getSPS()->getSpsNext().getIBCMode()) +#endif { return numRpsCurrTempList + 1; } @@ -1642,14 +1652,28 @@ void Slice::initMotionLUTs() { m_MotionCandLut = new LutMotionCand; m_MotionCandLut->currCnt = 0; +#if JVET_M0483_IBC + m_MotionCandLut->currCntIBC = 0; +#endif m_MotionCandLut->motionCand = nullptr; +#if JVET_M0483_IBC + m_MotionCandLut->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS * 2]; +#else m_MotionCandLut->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS]; +#endif #if JVET_M0170_MRG_SHARELIST m_MotionCandLuTsBkup = new LutMotionCand; m_MotionCandLuTsBkup->currCnt = 0; +#if JVET_M0483_IBC + m_MotionCandLuTsBkup->currCntIBC = 0; +#endif m_MotionCandLuTsBkup->motionCand = nullptr; +#if JVET_M0483_IBC + m_MotionCandLuTsBkup->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS * 2]; +#else m_MotionCandLuTsBkup->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS]; #endif +#endif } void Slice::destroyMotionLUTs() { @@ -1667,8 +1691,14 @@ void Slice::destroyMotionLUTs() void Slice::resetMotionLUTs() { m_MotionCandLut->currCnt = 0; +#if JVET_M0483_IBC + m_MotionCandLut->currCntIBC = 0; +#endif #if JVET_M0170_MRG_SHARELIST m_MotionCandLuTsBkup->currCnt = 0; +#if JVET_M0483_IBC + m_MotionCandLuTsBkup->currCntIBC = 0; +#endif #endif } @@ -1683,8 +1713,46 @@ MotionInfo Slice::getMotionInfoFromLUTBkup(int MotCandIdx) const } #endif +#if JVET_M0483_IBC +void Slice::addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi, bool ibcflag) +#else void Slice::addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi) +#endif { +#if JVET_M0483_IBC + int currCntIBC = ibcflag ? lutMC->currCntIBC : lutMC->currCnt; + int offset = ibcflag ? MAX_NUM_HMVP_CANDS : 0; + bool pruned = false; + int sameCandIdx = 0; + for (int idx = 0; idx < currCntIBC; idx++) + { + if (lutMC->motionCand[idx + offset] == newMi) + { + sameCandIdx = idx; + pruned = true; + break; + } + } + if (pruned || currCntIBC == MAX_NUM_HMVP_CANDS) + { + memmove(&lutMC->motionCand[sameCandIdx + offset], &lutMC->motionCand[sameCandIdx + offset + 1], + sizeof(MotionInfo) * (currCntIBC - sameCandIdx - 1)); + memcpy(&lutMC->motionCand[currCntIBC + offset - 1], &newMi, sizeof(MotionInfo)); + } + else + { + if (ibcflag) + { + memcpy(&lutMC->motionCand[currCntIBC + offset], &newMi, sizeof(MotionInfo)); + lutMC->currCntIBC++; + } + else + { + memcpy(&lutMC->motionCand[currCntIBC], &newMi, sizeof(MotionInfo)); + lutMC->currCnt++; + } + } +#else int currCnt = lutMC->currCnt ; bool pruned = false; @@ -1708,6 +1776,7 @@ void Slice::addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi) { memcpy(&lutMC->motionCand[lutMC->currCnt++], &newMi, sizeof(MotionInfo)); } +#endif } void Slice::updateMotionLUTs(LutMotionCand* lutMC, CodingUnit & cu) @@ -1716,22 +1785,37 @@ void Slice::updateMotionLUTs(LutMotionCand* lutMC, CodingUnit & cu) if (cu.affine) { return; } if (cu.triangle) { return; } - MotionInfo newMi = selectedPU->getMotionInfo(); + MotionInfo newMi = selectedPU->getMotionInfo(); #if JVET_M0264_HMVP_WITH_GBIIDX newMi.GBiIdx = (newMi.interDir == 3) ? cu.GBiIdx : GBI_DEFAULT; #endif +#if JVET_M0483_IBC + addMotionInfoToLUTs(lutMC, newMi, CU::isIBC(cu)); +#else addMotionInfoToLUTs(lutMC, newMi); +#endif } void Slice::copyMotionLUTs(LutMotionCand* Src, LutMotionCand* Dst) { memcpy(Dst->motionCand, Src->motionCand, sizeof(MotionInfo)*(std::min(Src->currCnt, MAX_NUM_HMVP_CANDS))); Dst->currCnt = Src->currCnt; +#if JVET_M0483_IBC + memcpy(Dst->motionCand + MAX_NUM_HMVP_CANDS, Src->motionCand + MAX_NUM_HMVP_CANDS, sizeof(MotionInfo)*(std::min(Src->currCntIBC, MAX_NUM_HMVP_CANDS))); + Dst->currCntIBC = Src->currCntIBC; +#endif } unsigned Slice::getMinPictureDistance() const { int minPicDist = MAX_INT; +#if JVET_M0483_IBC + if (getSPS()->getIBCFlag()) + { + minPicDist = 0; + } + else +#endif if( ! isIntra() ) { const int currPOC = getPOC(); @@ -1916,6 +2000,9 @@ SPS::SPS() , m_spsNextExtension (*this) , m_wrapAroundEnabledFlag (false) , m_wrapAroundOffset ( 0) +#if JVET_M0483_IBC +, m_IBCFlag ( 0) +#endif #if JVET_M0427_INLOOP_RESHAPER , m_lumaReshapeEnable (false) #endif diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index b4ab4227da91904131bca169551c933b8428997e..6dc1c6302e68ac5879c2f183e8812ce6dbc391ea 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1080,9 +1080,14 @@ private: bool m_wrapAroundEnabledFlag; unsigned m_wrapAroundOffset; +#if JVET_M0483_IBC + unsigned m_IBCFlag; +#endif + #if JVET_M0427_INLOOP_RESHAPER bool m_lumaReshapeEnable; #endif + public: SPS(); @@ -1308,6 +1313,10 @@ public: void setUseReshaper(bool b) { m_lumaReshapeEnable = b; } bool getUseReshaper() const { return m_lumaReshapeEnable; } #endif +#if JVET_M0483_IBC + void setIBCFlag(unsigned IBCFlag) { m_IBCFlag = IBCFlag; } + unsigned getIBCFlag() const { return m_IBCFlag; } +#endif }; @@ -2027,6 +2036,9 @@ public: void initMotionLUTs (); void destroyMotionLUTs (); void resetMotionLUTs(); +#if JVET_M0483_IBC + int getAvailableLUTIBCMrgNum() const { return m_MotionCandLut->currCntIBC; } +#endif int getAvailableLUTMrgNum() const { return m_MotionCandLut->currCnt; } #if JVET_M0170_MRG_SHARELIST int getAvailableLUTBkupMrgNum() const { return m_MotionCandLuTsBkup->currCnt; } @@ -2035,8 +2047,11 @@ public: MotionInfo getMotionInfoFromLUTs(int MotCandIdx) const; LutMotionCand* getMotionLUTs() { return m_MotionCandLut; } - +#if JVET_M0483_IBC + void addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi, bool ibcflag); +#else void addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi); +#endif void updateMotionLUTs(LutMotionCand* lutMC, CodingUnit & cu); void copyMotionLUTs(LutMotionCand* Src, LutMotionCand* Dst); diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 2e57ed508b3d9107767009e4c6204438b546c222..e189aed16649653ae612dd0d0bdb8440dd30fb11 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,8 @@ #include <assert.h> #include <cassert> +#define JVET_M0483_IBC 1 // Block level flag signaling and independent IBC mode + #define JVET_M0102_INTRA_SUBPARTITIONS 1 #define JVET_M0303_IMPLICIT_MTS 1 // Implicit transform selection (can be enabled with MTSImplicit encoder config parameter) @@ -507,7 +509,12 @@ enum PredMode { MODE_INTER = 0, ///< inter-prediction mode MODE_INTRA = 1, ///< intra-prediction mode +#if JVET_M0483_IBC + MODE_IBC = 2, ///< ibc-prediction mode + NUMBER_OF_PREDICTION_MODES = 3, +#else NUMBER_OF_PREDICTION_MODES = 2, +#endif }; /// reference list index diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 0f11344e0e1a69784337fff1eaf7c89cbd8fd4b8..0ff1f5a6ab864ba27a7359503eebc6faced203e8 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -287,7 +287,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other ) shareParentPos = other.shareParentPos; shareParentSize = other.shareParentSize; #endif +#if JVET_M0483_IBC==0 ibc = other.ibc; +#endif #if JVET_M0444_SMVD smvdMode = other.smvdMode; #endif @@ -331,7 +333,9 @@ void CodingUnit::initData() shareParentSize.width = -1; shareParentSize.height = -1; #endif +#if JVET_M0483_IBC==0 ibc = false; +#endif #if JVET_M0444_SMVD smvdMode = 0; #endif diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index 8cb246d99791b5838187ac6bf9a98181a40c2381..78624986944a2e0c34f16755c4d3daadf1ee6705 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -322,7 +322,9 @@ struct CodingUnit : public UnitArea Position shareParentPos; Size shareParentSize; #endif +#if JVET_M0483_IBC ==0 bool ibc; +#endif #if JVET_M0444_SMVD uint8_t smvdMode; #endif diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index f2ebcfbaf7bde7a7da230894f10ce0be525c151e..f7775517e42fac2db47baad9d002e4a4aae3f244 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -110,6 +110,13 @@ bool CU::isInter(const CodingUnit &cu) return cu.predMode == MODE_INTER; } +#if JVET_M0483_IBC +bool CU::isIBC(const CodingUnit &cu) +{ + return cu.predMode == MODE_IBC; +} +#endif + bool CU::isRDPCMEnabled(const CodingUnit& cu) { return cu.cs->sps->getSpsRangeExtension().getRdpcmEnabledFlag(cu.predMode == MODE_INTRA ? RDPCM_SIGNAL_IMPLICIT : RDPCM_SIGNAL_EXPLICIT); @@ -1025,7 +1032,12 @@ bool PU::xCheckSimilarMotion(const int mergeCandIndex, const int prevCnt, const #if JVET_L0090_PAIR_AVG bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool canFastExit, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const int prevCnt, bool isAvailableSubPu, unsigned subPuMvpPos +#if JVET_M0483_IBC==0 , int mmvdList +#endif +#if JVET_M0483_IBC + , bool ibcFlag +#endif #if JVET_M0170_MRG_SHARELIST , bool isShared #endif @@ -1037,7 +1049,9 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter ) #endif { +#if JVET_M0483_IBC==0 int mrgCandIdxIBC = mrgCandIdx; +#endif MotionInfo miNeighbor; bool hasPruned[MRG_MAX_NUM_CANDS]; memset(hasPruned, 0, MRG_MAX_NUM_CANDS * sizeof(bool)); @@ -1046,21 +1060,40 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter hasPruned[subPuMvpPos] = true; } #if JVET_M0170_MRG_SHARELIST +#if JVET_M0483_IBC + int num_avai_candInLUT = ibcFlag ? slice.getAvailableLUTIBCMrgNum() : (isShared ? slice.getAvailableLUTBkupMrgNum() : slice.getAvailableLUTMrgNum()); + int offset = ibcFlag ? MAX_NUM_HMVP_CANDS : 0; +#else int num_avai_candInLUT = (isShared ? slice.getAvailableLUTBkupMrgNum() : slice.getAvailableLUTMrgNum()); +#endif +#else +#if JVET_M0483_IBC + int num_avai_candInLUT = ibcFlag ? slice.getAvailableLUTIBCMrgNum() : slice.getAvailableLUTMrgNum(); + int offset = ibcFlag ? MAX_NUM_HMVP_CANDS : 0; #else int num_avai_candInLUT = slice.getAvailableLUTMrgNum(); +#endif #endif for (int mrgIdx = 1; mrgIdx <= num_avai_candInLUT; mrgIdx++) { #if JVET_M0170_MRG_SHARELIST +#if JVET_M0483_IBC + miNeighbor = ibcFlag ? slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx + offset) + : (isShared ? slice.getMotionInfoFromLUTBkup(num_avai_candInLUT - mrgIdx) : slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx)); +#else miNeighbor = isShared ? slice.getMotionInfoFromLUTBkup(num_avai_candInLUT - mrgIdx) : slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx); +#endif +#else +#if JVET_M0483_IBC + miNeighbor = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx + offset); #else miNeighbor = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx); +#endif #endif mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; #if JVET_M0264_HMVP_WITH_GBIIDX - mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? miNeighbor.GBiIdx: GBI_DEFAULT; + mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? miNeighbor.GBiIdx : GBI_DEFAULT; #endif mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); if (slice.isInterB()) @@ -1072,6 +1105,7 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter #if !JVET_L0090_PAIR_AVG isCandInter[cnt] = true; #endif +#if JVET_M0483_IBC==0 if (miNeighbor.interDir == 1 && slice.getRefPic(REF_PIC_LIST_0, miNeighbor.refIdx[0])->getPOC() == slice.getPOC()) { mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC; @@ -1079,6 +1113,9 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter mrgCandIdxIBC++; } if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return true; } @@ -1092,6 +1129,265 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter return false; } +#if JVET_M0483_IBC +void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx) +{ + const CodingStructure &cs = *pu.cs; + const Slice &slice = *pu.cs->slice; + const uint32_t maxNumMergeCand = slice.getMaxNumMergeCand(); + const bool canFastExit = pu.cs->pps->getLog2ParallelMergeLevelMinus2() == 0; + + for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) + { + mrgCtx.GBiIdx[ui] = GBI_DEFAULT; + mrgCtx.interDirNeighbours[ui] = 0; + mrgCtx.mrgTypeNeighbours[ui] = MRG_TYPE_IBC; + mrgCtx.mvFieldNeighbours[ui * 2].refIdx = NOT_VALID; + mrgCtx.mvFieldNeighbours[ui * 2 + 1].refIdx = NOT_VALID; + } + + mrgCtx.numValidMergeCand = maxNumMergeCand; + // compute the location of the current PU + + int cnt = 0; + + const Position posLT = pu.Y().topLeft(); + const Position posRT = pu.Y().topRight(); + const Position posLB = pu.Y().bottomLeft(); + + MotionInfo miAbove, miLeft, miAboveLeft, miAboveRight, miBelowLeft; + + //left + const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType); + const bool isAvailableA1 = puLeft && isDiffMER(pu, *puLeft) && pu.cu != puLeft->cu && CU::isIBC(*puLeft->cu); + if (isAvailableA1) + { + miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0)); + + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miLeft.interDir; + // get Mv from Left + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]); + if (mrgCandIdx == cnt && canFastExit) + { + return; + } + cnt++; + } + + // early termination + if (cnt == maxNumMergeCand) + { + return; + } + + + // above + const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType); + bool isAvailableB1 = puAbove && isDiffMER(pu, *puAbove) && pu.cu != puAbove->cu && CU::isIBC(*puAbove->cu); + if (isAvailableB1) + { + miAbove = puAbove->getMotionInfo(posRT.offset(0, -1)); + + if (!isAvailableA1 || (miAbove != miLeft)) + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miAbove.interDir; + // get Mv from Above + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[0], miAbove.refIdx[0]); + if (mrgCandIdx == cnt && canFastExit) + { + return; + } + + cnt++; + } + } + + // early termination + if (cnt == maxNumMergeCand) + { + return; + } + + // above right + const PredictionUnit *puAboveRight = cs.getPURestricted(posRT.offset(1, -1), pu, pu.chType); + bool isAvailableB0 = puAboveRight && isDiffMER(pu, *puAboveRight) && CU::isIBC(*puAboveRight->cu); + if (isAvailableB0) + { + miAboveRight = puAboveRight->getMotionInfo(posRT.offset(1, -1)); + +#if HM_JEM_MERGE_CANDS + if ((!isAvailableB1 || (miAbove != miAboveRight)) && (!isAvailableA1 || (miLeft != miAboveRight))) +#else + if (!isAvailableB1 || (miAbove != miAboveRight)) +#endif + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir; + // get Mv from Above-right + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveRight.mv[0], miAboveRight.refIdx[0]); + + if (mrgCandIdx == cnt && canFastExit) + { + return; + } + + cnt++; + } + } + // early termination + if (cnt == maxNumMergeCand) + { + return; + } + + //left bottom + const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType); + bool isAvailableA0 = puLeftBottom && isDiffMER(pu, *puLeftBottom) && CU::isIBC(*puLeftBottom->cu); + if (isAvailableA0) + { + miBelowLeft = puLeftBottom->getMotionInfo(posLB.offset(-1, 1)); + +#if HM_JEM_MERGE_CANDS + if ((!isAvailableA1 || (miBelowLeft != miLeft)) && (!isAvailableB1 || (miBelowLeft != miAbove)) && (!isAvailableB0 || (miBelowLeft != miAboveRight))) +#else + if (!isAvailableA1 || (miBelowLeft != miLeft)) +#endif + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir; + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miBelowLeft.mv[0], miBelowLeft.refIdx[0]); + if (mrgCandIdx == cnt && canFastExit) + { + return; + } + + cnt++; + } + } + // early termination + if (cnt == maxNumMergeCand) + { + return; + } + + // above left + if (cnt < 4) + { + const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType); + bool isAvailableB2 = puAboveLeft && isDiffMER(pu, *puAboveLeft) && CU::isIBC(*puAboveLeft->cu); + if (isAvailableB2) + { + miAboveLeft = puAboveLeft->getMotionInfo(posLT.offset(-1, -1)); + +#if HM_JEM_MERGE_CANDS + if ((!isAvailableA1 || (miLeft != miAboveLeft)) && (!isAvailableB1 || (miAbove != miAboveLeft)) && (!isAvailableA0 || (miBelowLeft != miAboveLeft)) && (!isAvailableB0 || (miAboveRight != miAboveLeft))) +#else + if ((!isAvailableA1 || (miLeft != miAboveLeft)) && (!isAvailableB1 || (miAbove != miAboveLeft))) +#endif + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir; + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveLeft.mv[0], miAboveLeft.refIdx[0]); + if (mrgCandIdx == cnt && canFastExit) + { + return; + } + + cnt++; + } + } + } + // early termination + if (cnt == maxNumMergeCand) + { + return; + } + + int maxNumMergeCandMin1 = maxNumMergeCand - 1; + if (cnt != maxNumMergeCandMin1) + { + bool isAvailableSubPu = false; + unsigned subPuMvpPos = 0; + +#if JVET_L0090_PAIR_AVG + bool bFound = addMergeHMVPCand(slice, mrgCtx, canFastExit + , mrgCandIdx + , maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos +#if JVET_M0483_IBC + , true +#endif +#if JVET_M0170_MRG_SHARELIST + , false +#endif + ); +#else + bool bFound = addMergeHMVPCand(slice, mrgCtx, isCandInter, canFastExit + , mrgCandIdx + , maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos + ); +#endif + if (bFound) + { + return; + } + } + +#if JVET_L0090_PAIR_AVG + // pairwise-average candidates +#if JVET_M0193_PAIR_AVG_REDUCTION==0 + const int cutoff = std::min(cnt, 4); + const int end = cutoff * (cutoff - 1) / 2; + constexpr int PRIORITY_LIST0[] = { 0, 0, 1, 0, 1, 2 }; + constexpr int PRIORITY_LIST1[] = { 1, 2, 2, 3, 3, 3 }; + + for (int idx = 0; idx < end && cnt != maxNumMergeCand; idx++) + { + const int i = PRIORITY_LIST0[idx]; + const int j = PRIORITY_LIST1[idx]; +#else + if (cnt>1 && cnt <maxNumMergeCand) + { +#endif + mrgCtx.mvFieldNeighbours[cnt * 2 ].setMvField(Mv(0, 0), NOT_VALID); + mrgCtx.mvFieldNeighbours[cnt * 2 + 1].setMvField(Mv(0, 0), NOT_VALID); + +#if JVET_M0193_PAIR_AVG_REDUCTION + const Mv& MvI = mrgCtx.mvFieldNeighbours[0 * 2].mv; + const Mv& MvJ = mrgCtx.mvFieldNeighbours[1 * 2].mv; +#else + const Mv& MvI = mrgCtx.mvFieldNeighbours[i * 2 ].mv; + const Mv& MvJ = mrgCtx.mvFieldNeighbours[j * 2 ].mv; +#endif + // average two MVs + Mv avgMv = MvI; + + avgMv += MvJ; + mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC; +#if JVET_M0265_MV_ROUNDING_CLEANUP + roundAffineMv(avgMv.hor, avgMv.ver, 1); +#else + avgMv.setHor(avgMv.getHor() / 2); + avgMv.setVer(avgMv.getVer() / 2); +#endif + mrgCtx.mvFieldNeighbours[cnt * 2 ].setMvField(avgMv, MAX_NUM_REF); + mrgCtx.interDirNeighbours[cnt] = 1; + cnt++; + } + + // early termination + if (cnt == maxNumMergeCand) + { + return; + } +#endif + + mrgCtx.numValidMergeCand = cnt; + +} +#endif + void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, int mmvdList, const int& mrgCandIdx ) @@ -1123,8 +1419,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, int cnt = 0; - +#if JVET_M0483_IBC==0 int mrgCandIdxIBC = mrgCandIdx; +#endif #if JVET_M0170_MRG_SHARELIST const Position posLT = pu.shareParentPos; @@ -1154,19 +1451,25 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.interDirNeighbours[cnt] = miLeft.interDir; mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->GBiIdx : GBI_DEFAULT; // get Mv from Left +#if JVET_M0483_IBC==0 if (puLeft->cu->ibc) { mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC; if (mmvdList != 0 && mrgCandIdx != -1) mrgCandIdxIBC++; } +#endif mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]); if (slice.isInterB()) { mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miLeft.mv[1], miLeft.refIdx[1]); } +#if JVET_M0483_IBC==0 if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return; } @@ -1200,19 +1503,25 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.interDirNeighbours[cnt] = miAbove.interDir; // get Mv from Above mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->GBiIdx : GBI_DEFAULT; +#if JVET_M0483_IBC==0 if (puAbove->cu->ibc) { mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC; if (mmvdList != 0 && mrgCandIdx != -1) mrgCandIdxIBC++; } +#endif mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAbove.mv[0], miAbove.refIdx[0] ); if( slice.isInterB() ) { mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAbove.mv[1], miAbove.refIdx[1] ); } +#if JVET_M0483_IBC==0 if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return; } @@ -1250,12 +1559,14 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir; // get Mv from Above-right mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->GBiIdx : GBI_DEFAULT; +#if JVET_M0483_IBC==0 if (puAboveRight->cu->ibc) { mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC; if (mmvdList != 0 && mrgCandIdx != -1) mrgCandIdxIBC++; } +#endif mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveRight.mv[0], miAboveRight.refIdx[0] ); if( slice.isInterB() ) @@ -1263,7 +1574,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAboveRight.mv[1], miAboveRight.refIdx[1] ); } +#if JVET_M0483_IBC==0 if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return; } @@ -1300,12 +1615,14 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir; mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->GBiIdx : GBI_DEFAULT; // get Mv from Bottom-Left +#if JVET_M0483_IBC==0 if (puLeftBottom->cu->ibc) { mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC; if (mmvdList != 0 && mrgCandIdx != -1) mrgCandIdxIBC++; } +#endif mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miBelowLeft.mv[0], miBelowLeft.refIdx[0] ); if( slice.isInterB() ) @@ -1313,7 +1630,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miBelowLeft.mv[1], miBelowLeft.refIdx[1] ); } +#if JVET_M0483_IBC==0 if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return; } @@ -1353,12 +1674,14 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir; mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->GBiIdx : GBI_DEFAULT; // get Mv from Above-Left +#if JVET_M0483_IBC==0 if (puAboveLeft->cu->ibc) { mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC; if (mmvdList != 0 && mrgCandIdx != -1) mrgCandIdxIBC++; } +#endif mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveLeft.mv[0], miAboveLeft.refIdx[0] ); if( slice.isInterB() ) @@ -1366,7 +1689,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAboveLeft.mv[1], miAboveLeft.refIdx[1] ); } +#if JVET_M0483_IBC==0 if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return; } @@ -1487,7 +1814,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, isCandInter [uiArrayAddr] = true; #endif mrgCtx.GBiIdx[uiArrayAddr] = GBI_DEFAULT; +#if JVET_M0483_IBC==0 if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return; } @@ -1513,9 +1844,18 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, bool isShared = ((pu.Y().lumaSize().width != pu.shareParentSize.width) || (pu.Y().lumaSize().height != pu.shareParentSize.height)); #endif bool bFound = addMergeHMVPCand(slice, mrgCtx, canFastExit +#if JVET_M0483_IBC==0 , (mmvdList != 0 && mrgCandIdx != -1) ? (const int) mrgCandIdxIBC : mrgCandIdx +#else + , mrgCandIdx +#endif , maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos +#if JVET_M0483_IBC==0 , mmvdList +#endif +#if JVET_M0483_IBC + , CU::isIBC(*pu.cu) +#endif #if JVET_M0170_MRG_SHARELIST , isShared #endif @@ -1544,8 +1884,12 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, #endif #if JVET_M0193_PAIR_AVG_REDUCTION +#if JVET_M0483_IBC + if (cnt > 1 && cnt < maxNumMergeCand) +#else // skip when only 1 candidate is added so far or one is BV and one is MV if( cnt > 1 && cnt < maxNumMergeCand && !(mrgCtx.mrgTypeNeighbours[0] != mrgCtx.mrgTypeNeighbours[1] && pu.cs->sps->getSpsNext().getIBCMode())) +#endif #else for( int idx = 0; idx < end && cnt != maxNumMergeCand; idx++ ) #endif @@ -1561,7 +1905,7 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, unsigned char interDir = 0; -#if !JVET_M0193_PAIR_AVG_REDUCTION +#if !JVET_M0193_PAIR_AVG_REDUCTION && JVET_M0483_IBC==0 // skip when one is BV and one is MV if (mrgCtx.mrgTypeNeighbours[i] != mrgCtx.mrgTypeNeighbours[j] && pu.cs->sps->getSpsNext().getIBCMode()) { @@ -1606,7 +1950,7 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, avgMv.setVer( avgMv.getVer() / 2 ); #endif - +#if JVET_M0483_IBC==0 #if JVET_M0193_PAIR_AVG_REDUCTION if (mrgCtx.mrgTypeNeighbours[0] == MRG_TYPE_IBC && mrgCtx.mrgTypeNeighbours[1] == MRG_TYPE_IBC && pu.cs->sps->getSpsNext().getIBCMode()) #else @@ -1617,7 +1961,7 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, avgMv.setHor((avgMv.getHor() / 16) << 4); avgMv.setVer((avgMv.getVer() / 16) << 4); } - +#endif mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( avgMv, refIdxI ); } // only one MV is valid, take the only one MV @@ -1996,7 +2340,17 @@ bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList { return false; } +#if JVET_M0483_IBC + if (mi.isIBCmot) + { + return false; + } +#endif +#if JVET_M0483_IBC + if (CU::isIBC(*pu.cu)) +#else if (eRefPicList == REF_PIC_LIST_0 && pu.cs->slice->getRefPic(eRefPicList, refIdx)->getPOC() == pu.cs->slice->getPOC()) +#endif { return false; } @@ -2103,7 +2457,11 @@ void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred) //left const PredictionUnit *neibLeftPU = NULL; neibLeftPU = pu.cs->getPURestricted(posLB.offset(-1, 0), pu, pu.cs->chType); +#if JVET_M0483_IBC + left = (neibLeftPU) ? CU::isIBC(*neibLeftPU->cu) : 0; +#else left = (neibLeftPU) ? neibLeftPU->cu->ibc : 0; +#endif if (left) { @@ -2115,7 +2473,11 @@ void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred) //above const PredictionUnit *neibAbovePU = NULL; neibAbovePU = pu.cs->getPURestricted(posRT.offset(0, -1), pu, pu.cs->chType); +#if JVET_M0483_IBC + above = (neibAbovePU) ? CU::isIBC(*neibAbovePU->cu) : 0; +#else above = (neibAbovePU) ? neibAbovePU->cu->ibc : 0; +#endif if (above) { @@ -2127,7 +2489,11 @@ void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred) // Below Left predictor search const PredictionUnit *neibBelowLeftPU = NULL; neibBelowLeftPU = pu.cs->getPURestricted(posLB.offset(-1, 1), pu, pu.cs->chType); +#if JVET_M0483_IBC + unsigned int belowLeft = (neibBelowLeftPU) ? CU::isIBC(*neibBelowLeftPU->cu) : 0; +#else unsigned int belowLeft = (neibBelowLeftPU) ? neibBelowLeftPU->cu->ibc : 0; +#endif if (belowLeft) { @@ -2140,7 +2506,11 @@ void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred) // Above Right predictor search const PredictionUnit *neibAboveRightPU = NULL; neibAboveRightPU = pu.cs->getPURestricted(posRT.offset(1, -1), pu, pu.cs->chType); +#if JVET_M0483_IBC + unsigned int aboveRight = (neibAboveRightPU) ? CU::isIBC(*neibAboveRightPU->cu) : 0; +#else unsigned int aboveRight = (neibAboveRightPU) ? neibAboveRightPU->cu->ibc : 0; +#endif if (aboveRight) { @@ -2153,7 +2523,11 @@ void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred) // Above Left predictor search const PredictionUnit *neibAboveLeftPU = NULL; neibAboveLeftPU = pu.cs->getPURestricted(posLT.offset(-1, -1), pu, pu.cs->chType); +#if JVET_M0483_IBC + unsigned int aboveLeft = (neibAboveLeftPU) ? CU::isIBC(*neibAboveLeftPU->cu) : 0; +#else unsigned int aboveLeft = (neibAboveLeftPU) ? neibAboveLeftPU->cu->ibc : 0; +#endif if (aboveLeft) { @@ -2181,7 +2555,11 @@ bool PU::getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv) const PredictionUnit *neibRefPU = NULL; neibRefPU = pu.cs->getPURestricted(pu.lumaPos().offset(offsetX, offsetY), pu, pu.cs->chType); +#if JVET_M0483_IBC + bool isIBC = (neibRefPU) ? CU::isIBC(*neibRefPU->cu) : 0; +#else bool isIBC = (neibRefPU) ? neibRefPU->cu->ibc : 0; +#endif if (isIBC) { derivedMv = neibRefPU->bv; @@ -2189,6 +2567,102 @@ bool PU::getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv) } return isIBC; } + +#if JVET_M0483_IBC +/** + * Constructs a list of candidates for IBC AMVP (See specification, section "Derivation process for motion vector predictor candidates") + */ +void PU::fillIBCMvpCand(PredictionUnit &pu, AMVPInfo &amvpInfo) +{ + CodingStructure &cs = *pu.cs; + + AMVPInfo *pInfo = &amvpInfo; + + pInfo->numCand = 0; + + //-- Get Spatial MV + Position posLT = pu.Y().topLeft(); + Position posRT = pu.Y().topRight(); + Position posLB = pu.Y().bottomLeft(); + + bool isScaledFlagLX = false; /// variable name from specification; true when the PUs below left or left are available (availableA0 || availableA1). + { + const PredictionUnit* tmpPU = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType); // getPUBelowLeft(idx, partIdxLB); + isScaledFlagLX = tmpPU != NULL && CU::isIBC(*tmpPU->cu); + if (!isScaledFlagLX) + { + tmpPU = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType); + isScaledFlagLX = tmpPU != NULL && CU::isIBC(*tmpPU->cu); + } + } + + // Left predictor search + if (isScaledFlagLX) + { + bool isAdded = addIBCMVPCand(pu, posLB, MD_BELOW_LEFT, *pInfo); + + if (!isAdded) + { + isAdded = addIBCMVPCand(pu, posLB, MD_LEFT, *pInfo); + } + } + + // Above predictor search + { + bool isAdded = addIBCMVPCand(pu, posRT, MD_ABOVE_RIGHT, *pInfo); + + if (!isAdded) + { + isAdded = addIBCMVPCand(pu, posRT, MD_ABOVE, *pInfo); + + if (!isAdded) + { + addIBCMVPCand(pu, posLT, MD_ABOVE_LEFT, *pInfo); + } + } + } + + if (pu.cu->imv != 0) + { + for (int i = 0; i < pInfo->numCand; i++) + { + pInfo->mvCand[i].roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv); + } + } + + if (pInfo->numCand == 2) + { + if (pInfo->mvCand[0] == pInfo->mvCand[1]) + { + pInfo->numCand = 1; + } + } + + if (pInfo->numCand < AMVP_MAX_NUM_CANDS) + { + addAMVPHMVPCand(pu, REF_PIC_LIST_0, REF_PIC_LIST_1, cs.slice->getPOC(), *pInfo, pu.cu->imv); + } + + if (pInfo->numCand > AMVP_MAX_NUM_CANDS) + { + pInfo->numCand = AMVP_MAX_NUM_CANDS; + } + + while (pInfo->numCand < AMVP_MAX_NUM_CANDS) + { + pInfo->mvCand[pInfo->numCand] = Mv(0, 0); + pInfo->numCand++; + } + + for (Mv &mv : pInfo->mvCand) + { + mv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER); + mv.roundToAmvrSignalPrecision(MV_PRECISION_QUARTER, pu.cu->imv); + } +} + +#endif + /** Constructs a list of candidates for AMVP (See specification, section "Derivation process for motion vector predictor candidates") * \param uiPartIdx * \param uiPartAddr @@ -2821,6 +3295,47 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co } +#if JVET_M0483_IBC +bool PU::addIBCMVPCand(const PredictionUnit &pu, const Position &pos, const MvpDir &eDir, AMVPInfo &info) +{ + CodingStructure &cs = *pu.cs; + const PredictionUnit *neibPU = NULL; + Position neibPos; + + switch (eDir) + { + case MD_LEFT: + neibPos = pos.offset(-1, 0); + break; + case MD_ABOVE: + neibPos = pos.offset(0, -1); + break; + case MD_ABOVE_RIGHT: + neibPos = pos.offset(1, -1); + break; + case MD_BELOW_LEFT: + neibPos = pos.offset(-1, 1); + break; + case MD_ABOVE_LEFT: + neibPos = pos.offset(-1, -1); + break; + default: + break; + } + + neibPU = cs.getPURestricted(neibPos, pu, pu.chType); + + if (neibPU == NULL || CU::isIBC(*neibPU->cu)==false) + { + return false; + } + + const MotionInfo& neibMi = neibPU->getMotionInfo(neibPos); + info.mvCand[info.numCand++] = neibMi.mv[REF_PIC_LIST_0]; + return true; +} +#endif + bool PU::addMVPCandUnscaled( const PredictionUnit &pu, const RefPicList &eRefPicList, const int &iRefIdx, const Position &pos, const MvpDir &eDir, AMVPInfo &info ) { CodingStructure &cs = *pu.cs; @@ -2913,7 +3428,11 @@ bool PU::addMVPCandWithScaling( const PredictionUnit &pu, const RefPicList &eRef neibPU = cs.getPURestricted( neibPos, pu, pu.chType ); +#if JVET_M0483_IBC + if (neibPU == NULL || !CU::isInter(*neibPU->cu) || !CU::isInter(*pu.cu)) +#else if( neibPU == NULL || !CU::isInter( *neibPU->cu ) ) +#endif { return false; } @@ -2967,7 +3486,12 @@ void PU::addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList, #if !JVET_M0117_AMVP_LIST_GEN int i = 0; #endif +#if JVET_M0483_IBC + int offset = CU::isIBC(*pu.cu) ? MAX_NUM_HMVP_CANDS : 0; + int num_avai_candInLUT = CU::isIBC(*pu.cu) ? slice.getAvailableLUTIBCMrgNum() : slice.getAvailableLUTMrgNum(); +#else int num_avai_candInLUT = slice.getAvailableLUTMrgNum(); +#endif int num_allowedCand = std::min(MAX_NUM_HMVP_AVMPCANDS, num_avai_candInLUT); for (int mrgIdx = 1; mrgIdx <= num_allowedCand; mrgIdx++) @@ -2977,9 +3501,17 @@ void PU::addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList, return; } #if JVET_M0117_AMVP_LIST_GEN +#if JVET_M0483_IBC + neibMi = slice.getMotionInfoFromLUTs(mrgIdx - 1 + offset) ; +#else neibMi = slice.getMotionInfoFromLUTs(mrgIdx - 1); +#endif +#else +#if JVET_M0483_IBC + neibMi = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx + offset); #else neibMi = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx); +#endif #endif for (int predictorSource = 0; predictorSource < 2; predictorSource++) @@ -2987,7 +3519,11 @@ void PU::addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList, const RefPicList eRefPicListIndex = (predictorSource == 0) ? eRefPicList : eRefPicList2nd; const int neibRefIdx = neibMi.refIdx[eRefPicListIndex]; +#if JVET_M0483_IBC + if (neibRefIdx >= 0 && (CU::isIBC(*pu.cu) || (currRefPOC == slice.getRefPOC(eRefPicListIndex, neibRefIdx)))) +#else if (neibRefIdx >= 0 && currRefPOC == slice.getRefPOC(eRefPicListIndex, neibRefIdx)) +#endif { Mv pmv = neibMi.mv[eRefPicListIndex]; #if JVET_M0281_AMVP_ROUNDING || JVET_M0117_AMVP_LIST_GEN @@ -3266,7 +3802,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx bool isAvailableSubPu = false; if ( enableSubPuMvp && slice.getEnableTMVPFlag() ) { -#if !JVET_M0409_ATMVP_FIX +#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0 int cntIBC = 0; #endif MergeCtx mrgCtx = *affMrgCtx.mrgCtx; @@ -3296,7 +3832,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx mrgCtx.interDirNeighbours[pos] = miLeft.interDir; // get Mv from Left -#if !JVET_M0409_ATMVP_FIX +#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0 if (puLeft->cu->ibc) { cntIBC++; @@ -3324,7 +3860,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx // get Inter Dir mrgCtx.interDirNeighbours[pos] = miAbove.interDir; // get Mv from Left -#if !JVET_M0409_ATMVP_FIX +#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0 if (puAbove->cu->ibc) { cntIBC++; @@ -3357,7 +3893,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx // get Inter Dir mrgCtx.interDirNeighbours[pos] = miAboveRight.interDir; // get Mv from Left -#if !JVET_M0409_ATMVP_FIX +#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0 if (puAboveRight->cu->ibc) { cntIBC++; @@ -3390,7 +3926,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx // get Inter Dir mrgCtx.interDirNeighbours[pos] = miBelowLeft.interDir; // get Mv from Bottom-Left -#if !JVET_M0409_ATMVP_FIX +#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0 if (puLeftBottom->cu->ibc) { cntIBC++; @@ -3410,7 +3946,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx isAvailableSubPu = getInterMergeSubPuMvpCand( pu, mrgCtx, tmpLICFlag, pos , 0 -#if !JVET_M0409_ATMVP_FIX +#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0 , cntIBC #endif ); @@ -3500,7 +4036,9 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx const PredictionUnit* puNeigh = cs.getPURestricted( pos, pu, pu.chType ); if ( puNeigh && CU::isInter( *puNeigh->cu ) +#if JVET_M0483_IBC==0 && !puNeigh->cu->ibc +#endif ) { isAvailable[0] = true; @@ -3518,7 +4056,9 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx if ( puNeigh && CU::isInter( *puNeigh->cu ) +#if JVET_M0483_IBC==0 && !puNeigh->cu->ibc +#endif ) { isAvailable[1] = true; @@ -3536,7 +4076,9 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx if ( puNeigh && CU::isInter( *puNeigh->cu ) +#if JVET_M0483_IBC==0 && !puNeigh->cu->ibc +#endif ) { isAvailable[2] = true; @@ -3847,12 +4389,12 @@ void clipColPos(int& posX, int& posY, const PredictionUnit& pu) bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, bool& LICFlag, const int count , int mmvdList -#if !JVET_M0409_ATMVP_FIX +#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0 , const int countIBC #endif ) { -#if !JVET_M0409_ATMVP_FIX +#if !JVET_M0409_ATMVP_FIX && JVET_M0483_IBC==0 if (count == countIBC && pu.cs->slice->getSPS()->getSpsNext().getIBCMode()) return false; #endif @@ -3918,7 +4460,11 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b // derivation of center motion parameters from the collocated CU const MotionInfo &mi = pColPic->cs->getMotionInfo(centerPos); +#if JVET_M0483_IBC + if (mi.isInter && mi.isIBCmot == false) +#else if (mi.isInter) +#endif { for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++) { @@ -3970,7 +4516,12 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b mi.isInter = true; mi.sliceIdx = slice.getIndependentSliceIdx(); +#if JVET_M0483_IBC + mi.isIBCmot = false; + if (colMi.isInter && colMi.isIBCmot == false) +#else if (colMi.isInter && !((colMi.interDir == 1 || colMi.interDir == 3) && (pColPic->cs->slice->getRefPOC(REF_PIC_LIST_0, colMi.refIdx[0]) == pColPic->cs->slice->getPOC()) && pu.cs->sps->getSpsNext().getIBCMode())) +#endif { for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++) { @@ -4017,7 +4568,12 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx ) { MotionInfo mi; +#if JVET_M0483_IBC + mi.isInter = !CU::isIntra(*pu.cu); + mi.isIBCmot = CU::isIBC(*pu.cu); +#else mi.isInter = CU::isInter( *pu.cu ); +#endif mi.sliceIdx = pu.cu->slice->getIndependentSliceIdx(); if( mi.isInter ) @@ -4029,7 +4585,11 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx ) mi.mv[i] = pu.mv[i]; mi.refIdx[i] = pu.refIdx[i]; } +#if JVET_M0483_IBC + if (mi.isIBCmot) +#else if (pu.interDir == 1 && pu.cu->slice->getRefPOC(REF_PIC_LIST_0, pu.refIdx[0]) == pu.cu->slice->getPOC()) +#endif { mi.bv = pu.bv; } @@ -4043,6 +4603,9 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx ) { MotionInfo &dest = mb.at( x, y ); dest.isInter = mi.isInter; +#if JVET_M0483_IBC + dest.isIBCmot = false; +#endif dest.interDir = mi.interDir; dest.sliceIdx = mi.sliceIdx; for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ ) @@ -4097,15 +4660,24 @@ void PU::applyImv( PredictionUnit& pu, MergeCtx &mrgCtx, InterPrediction *interP pu.mvd[0].changePrecisionAmvr( pu.cu->imv, MV_PRECISION_QUARTER); unsigned mvp_idx = pu.mvpIdx[0]; AMVPInfo amvpInfo; +#if JVET_M0483_IBC + if (CU::isIBC(*pu.cu)) + { + PU::fillIBCMvpCand(pu, amvpInfo); + } + else +#endif PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[0], amvpInfo); pu.mvpNum[0] = amvpInfo.numCand; pu.mvpIdx[0] = mvp_idx; pu.mv [0] = amvpInfo.mvCand[mvp_idx] + pu.mvd[0]; pu.mv[0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); +#if JVET_M0483_IBC==0 if (pu.interDir == 1 && pu.cs->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[REF_PIC_LIST_0])->getPOC() == pu.cs->slice->getPOC()) { pu.cu->ibc = true; } +#endif } if (pu.interDir != 1 /* PRED_L0 */) @@ -4235,7 +4807,9 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl //left const PredictionUnit* puLeft = cs.getPURestricted( posLB.offset( -1, 0 ), pu, pu.chType ); const bool isAvailableA1 = puLeft && isDiffMER( pu, *puLeft ) && pu.cu != puLeft->cu && CU::isInter( *puLeft->cu ) +#if JVET_M0483_IBC==0 && !puLeft->cu->ibc +#endif ; if( isAvailableA1 ) { @@ -4252,7 +4826,9 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl // above const PredictionUnit *puAbove = cs.getPURestricted( posRT.offset( 0, -1 ), pu, pu.chType ); bool isAvailableB1 = puAbove && isDiffMER( pu, *puAbove ) && pu.cu != puAbove->cu && CU::isInter( *puAbove->cu ) +#if JVET_M0483_IBC==0 && !puAbove->cu->ibc +#endif ; if( isAvailableB1 ) { @@ -4273,7 +4849,9 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl // above right const PredictionUnit *puAboveRight = cs.getPURestricted( posRT.offset( 1, -1 ), pu, pu.chType ); bool isAvailableB0 = puAboveRight && isDiffMER( pu, *puAboveRight ) && CU::isInter( *puAboveRight->cu ) +#if JVET_M0483_IBC==0 && !puAboveRight->cu->ibc +#endif ; if( isAvailableB0 ) @@ -4295,7 +4873,9 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl //left bottom const PredictionUnit *puLeftBottom = cs.getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType ); bool isAvailableA0 = puLeftBottom && isDiffMER( pu, *puLeftBottom ) && CU::isInter( *puLeftBottom->cu ) +#if JVET_M0483_IBC==0 && !puLeftBottom->cu->ibc +#endif ; if( isAvailableA0 ) { @@ -4316,7 +4896,9 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl // above left const PredictionUnit *puAboveLeft = cs.getPURestricted( posLT.offset( -1, -1 ), pu, pu.chType ); bool isAvailableB2 = puAboveLeft && isDiffMER( pu, *puAboveLeft ) && CU::isInter( *puAboveLeft->cu ) +#if JVET_M0483_IBC==0 && !puAboveLeft->cu->ibc +#endif ; if( isAvailableB2 ) @@ -4746,6 +5328,11 @@ void CU::resetMVDandMV2Int( CodingUnit& cu, InterPrediction *interPred ) Mv mv = pu.mv[0]; Mv mvPred; AMVPInfo amvpInfo; +#if JVET_M0483_IBC + if (CU::isIBC(*pu.cu)) + PU::fillIBCMvpCand(pu, amvpInfo); + else +#endif PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[0], amvpInfo); pu.mvpNum[0] = amvpInfo.numCand; @@ -4896,6 +5483,13 @@ bool CU::isGBiIdxCoded( const CodingUnit &cu ) return false; } +#if JVET_M0483_IBC + if (cu.predMode == MODE_IBC) + { + return false; + } +#endif + if( cu.predMode == MODE_INTRA || cu.cs->slice->isInterP() ) { return false; @@ -5141,8 +5735,13 @@ uint32_t TU::getCoefScanIdx(const TransformUnit &tu, const ComponentID &compID) #endif bool TU::hasCrossCompPredInfo( const TransformUnit &tu, const ComponentID &compID ) { +#if JVET_M0483_IBC + return (isChroma(compID) && tu.cs->pps->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && TU::getCbf(tu, COMPONENT_Y) && + (!CU::isIntra(*tu.cu) || PU::isChromaIntraModeCrossCheckMode(*tu.cs->getPU(tu.blocks[compID].pos(), toChannelType(compID))))); +#else return ( isChroma(compID) && tu.cs->pps->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && TU::getCbf( tu, COMPONENT_Y ) && ( CU::isInter(*tu.cu) || PU::isChromaIntraModeCrossCheckMode( *tu.cs->getPU( tu.blocks[compID].pos(), toChannelType( compID ) ) ) ) ); +#endif } uint32_t TU::getNumNonZeroCoeffsNonTS( const TransformUnit& tu, const bool bLuma, const bool bChroma ) diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 27d400023d3feef96d3357a5f7b686e1276602a9..5cdb1fb6f7f9f9b227382a39dab373a00ecbd759 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -60,6 +60,9 @@ namespace CU { bool isIntra (const CodingUnit &cu); bool isInter (const CodingUnit &cu); +#if JVET_M0483_IBC + bool isIBC (const CodingUnit &cu); +#endif bool isRDPCMEnabled (const CodingUnit &cu); bool isLosslessCoded (const CodingUnit &cu); uint32_t getIntraSizeIdx (const CodingUnit &cu); @@ -124,11 +127,18 @@ namespace PU void getInterMergeCandidates (const PredictionUnit &pu, MergeCtx& mrgCtx, int mmvdList, const int& mrgCandIdx = -1 ); +#if JVET_M0483_IBC + void getIBCMergeCandidates (const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx = -1); +#endif void getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx = -1); int getDistScaleFactor(const int &currPOC, const int &currRefPOC, const int &colPOC, const int &colRefPOC); bool isDiffMER (const PredictionUnit &pu, const PredictionUnit &pu2); bool getColocatedMVP (const PredictionUnit &pu, const RefPicList &eRefPicList, const Position &pos, Mv& rcMv, const int &refIdx); void fillMvpCand ( PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AMVPInfo &amvpInfo ); +#if JVET_M0483_IBC + void fillIBCMvpCand (PredictionUnit &pu, AMVPInfo &amvpInfo); + bool addIBCMVPCand (const PredictionUnit &pu, const Position &pos, const MvpDir &eDir, AMVPInfo &amvpInfo); +#endif void fillAffineMvpCand ( PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AffineAMVPInfo &affiAMVPInfo); bool addMVPCandUnscaled (const PredictionUnit &pu, const RefPicList &eRefPicList, const int &iRefIdx, const Position &pos, const MvpDir &eDir, AMVPInfo &amvpInfo); bool addMVPCandWithScaling (const PredictionUnit &pu, const RefPicList &eRefPicList, const int &iRefIdx, const Position &pos, const MvpDir &eDir, AMVPInfo &amvpInfo); @@ -136,14 +146,21 @@ namespace PU bool xCheckSimilarMotion(const int mergeCandIndex, const int prevCnt, const MergeCtx mergeCandList, bool hasPruned[MRG_MAX_NUM_CANDS]); #if JVET_L0090_PAIR_AVG bool addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool canFastExit, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const int prevCnt, bool isAvailableSubPu, unsigned subPuMvpPos +#if JVET_M0483_IBC==0 , int mmvdList +#endif +#if JVET_M0483_IBC + , bool ibcFlag +#endif #if JVET_M0170_MRG_SHARELIST , bool isShared #endif ); #else bool addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter[MRG_MAX_NUM_CANDS], bool canFastExit, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const int prevCnt, bool isAvailableSubPu, unsigned subPuMvpPos +#if JVET_M0483_IBC==0 , int mmvdList +#endif ); #endif void addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList, const RefPicList eRefPicList2nd, const int currRefPOC, AMVPInfo &info, uint8_t imv); @@ -160,7 +177,9 @@ namespace PU bool getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx &mrgCtx, bool& LICFlag, const int count , int mmvdList #if !JVET_M0409_ATMVP_FIX +#if JVET_M0483_IBC==0 , const int countIBC +#endif #endif ); bool getInterMergeSubPuRecurCand(const PredictionUnit &pu, MergeCtx &mrgCtx, const int count); diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 0ab7f1eb51e09cdfc47e0c35c764f5c8eb99ee01..3ff8a9a798246a5dac50c56d1faa2795063c08fc 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -885,7 +885,11 @@ bool CABACReader::coding_unit( CodingUnit &cu, Partitioner &partitioner, CUCtx& } // skip flag +#if JVET_M0483_IBC + if ((!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag()) && cu.Y().valid()) +#else if (!cs.slice->isIntra() && cu.Y().valid()) +#endif { cu_skip_flag( cu ); } @@ -951,12 +955,54 @@ void CABACReader::cu_skip_flag( CodingUnit& cu ) { RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__SKIP_FLAG ); +#if JVET_M0483_IBC + if (cu.slice->isIntra() && cu.cs->slice->getSPS()->getIBCFlag()) + { + cu.skip = false; + cu.rootCbf = false; + cu.predMode = MODE_INTRA; + cu.mmvdSkip = false; + unsigned ctxId = DeriveCtx::CtxSkipFlag(cu); + unsigned skip = m_BinDecoder.decodeBin(Ctx::SkipFlag(ctxId)); + if (skip) + { + cu.skip = true; + cu.rootCbf = false; + cu.predMode = MODE_IBC; + cu.mmvdSkip = false; + } + + return; + } +#endif + unsigned ctxId = DeriveCtx::CtxSkipFlag(cu); unsigned skip = m_BinDecoder.decodeBin( Ctx::SkipFlag(ctxId) ); DTRACE( g_trace_ctx, D_SYNTAX, "cu_skip_flag() ctx=%d skip=%d\n", ctxId, skip ? 1 : 0 ); +#if JVET_M0483_IBC + if (skip && cu.cs->slice->getSPS()->getIBCFlag()) + { + unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu); + if (m_BinDecoder.decodeBin(Ctx::IBCFlag(ctxidx))) + { + cu.skip = true; + cu.rootCbf = false; + cu.predMode = MODE_IBC; + cu.mmvdSkip = false; + } + else + { + cu.predMode = MODE_INTER; + } + DTRACE(g_trace_ctx, D_SYNTAX, "ibc() ctx=%d cu.predMode=%d\n", ctxidx, cu.predMode); + } + if ((skip && CU::isInter(cu) && cu.cs->slice->getSPS()->getIBCFlag()) || + (skip && !cu.cs->slice->getSPS()->getIBCFlag())) +#else if( skip ) +#endif { unsigned mmvdSkip = m_BinDecoder.decodeBin(Ctx::MmvdFlag(0)); cu.mmvdSkip = mmvdSkip; @@ -993,7 +1039,11 @@ void CABACReader::imv_mode( CodingUnit& cu, MergeCtx& mrgCtx ) unsigned value = 0; unsigned ctxId = DeriveCtx::CtxIMVFlag( cu ); +#if JVET_M0483_IBC + if (CU::isIBC(cu)) +#else if (cu.firstPU->interDir == 1 && cu.cs->slice->getRefPic(REF_PIC_LIST_0, cu.firstPU->refIdx[REF_PIC_LIST_0])->getPOC() == cu.cs->slice->getPOC()) // the first bin of IMV flag does need to be signaled in IBC block +#endif value = 1; else value = m_BinDecoder.decodeBin( Ctx::ImvFlag( ctxId ) ); @@ -1047,6 +1097,55 @@ void CABACReader::pred_mode( CodingUnit& cu ) { RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__PRED_MODE ); +#if JVET_M0483_IBC + if (cu.cs->slice->getSPS()->getIBCFlag()) + { + if (cu.cs->slice->isIntra()) + { + cu.predMode = MODE_INTRA; + unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu); + if (m_BinDecoder.decodeBin(Ctx::IBCFlag(ctxidx))) + { + cu.predMode = MODE_IBC; + } + } + else + { +#if JVET_M0502_PRED_MODE_CTX + if (m_BinDecoder.decodeBin(Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu)))) +#else + if (m_BinDecoder.decodeBin(Ctx::PredMode())) +#endif + { + cu.predMode = MODE_INTRA; + } + else + { + cu.predMode = MODE_INTER; + unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu); + if (m_BinDecoder.decodeBin(Ctx::IBCFlag(ctxidx))) + { + cu.predMode = MODE_IBC; + } + } + } + } + else + { +#if JVET_M0502_PRED_MODE_CTX + if (cu.cs->slice->isIntra() || m_BinDecoder.decodeBin(Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu)))) +#else + if (cu.cs->slice->isIntra() || m_BinDecoder.decodeBin(Ctx::PredMode())) +#endif + { + cu.predMode = MODE_INTRA; + } + else + { + cu.predMode = MODE_INTER; + } + } +#else #if JVET_M0502_PRED_MODE_CTX if( cu.cs->slice->isIntra() || m_BinDecoder.decodeBin( Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu)) ) ) #else @@ -1059,6 +1158,7 @@ void CABACReader::pred_mode( CodingUnit& cu ) { cu.predMode = MODE_INTER; } +#endif } void CABACReader::pcm_flag( CodingUnit& cu, Partitioner &partitioner ) @@ -1084,8 +1184,12 @@ void CABACReader::cu_pred_data( CodingUnit &cu ) } if (!cu.Y().valid()) // dual tree chroma CU { +#if JVET_M0483_IBC + cu.predMode = MODE_IBC; +#else cu.predMode = MODE_INTER; cu.ibc = true; +#endif return; } MergeCtx mrgCtx; @@ -1369,7 +1473,11 @@ void CABACReader::intra_chroma_pred_mode( PredictionUnit& pu ) void CABACReader::cu_residual( CodingUnit& cu, Partitioner &partitioner, CUCtx& cuCtx ) { +#if JVET_M0483_IBC + if (!CU::isIntra(cu)) +#else if( CU::isInter( cu ) ) +#endif { PredictionUnit& pu = *cu.firstPU; if( !pu.mergeFlag ) @@ -1465,6 +1573,14 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx ) } if( pu.mergeFlag ) { +#if JVET_M0483_IBC + if (CU::isIBC(*pu.cu)) + { + merge_idx(pu); + } + else + { +#endif subblock_merge_flag( *pu.cu ); MHIntra_flag(pu); if (pu.mhIntraFlag) @@ -1478,8 +1594,21 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx ) mmvd_merge_idx(pu); } else - merge_data ( pu ); + merge_data ( pu ); +#if JVET_M0483_IBC + } +#endif } +#if JVET_M0483_IBC + else if (CU::isIBC(*pu.cu)) + { + pu.interDir = 1; + pu.cu->affine = false; + pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; + mvd_coding(pu.mvd[REF_PIC_LIST_0]); + mvp_flag(pu, REF_PIC_LIST_0); + } +#endif else { inter_pred_idc( pu ); @@ -1629,6 +1758,15 @@ void CABACReader::merge_flag( PredictionUnit& pu ) pu.mergeFlag = ( m_BinDecoder.decodeBin( Ctx::MergeFlag() ) ); DTRACE( g_trace_ctx, D_SYNTAX, "merge_flag() merge=%d pos=(%d,%d) size=%dx%d\n", pu.mergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height ); + +#if JVET_M0483_IBC + if (pu.mergeFlag && CU::isIBC(*pu.cu)) + { + pu.mmvdMergeFlag = false; + return; + } +#endif + if (pu.mergeFlag) { pu.mmvdMergeFlag = (m_BinDecoder.decodeBin(Ctx::MmvdFlag(0))); @@ -1875,6 +2013,7 @@ void CABACReader::ref_idx( PredictionUnit &pu, RefPicList eRefList ) #endif int numRef = pu.cs->slice->getNumRefIdx(eRefList); + if( numRef <= 1 || !m_BinDecoder.decodeBin( Ctx::RefPic() ) ) { if( numRef > 1 ) @@ -2715,7 +2854,11 @@ void CABACReader::emt_cu_flag( CodingUnit& cu ) #endif const CodingStructure &cs = *cu.cs; +#if JVET_M0483_IBC + if (!((cs.sps->getSpsNext().getUseIntraEMT() && CU::isIntra(cu)) || (cs.sps->getSpsNext().getUseInterEMT() && !CU::isIntra(cu))) || isChroma(cu.chType)) +#else if( !( ( cs.sps->getSpsNext().getUseIntraEMT() && CU::isIntra( cu ) ) || ( cs.sps->getSpsNext().getUseInterEMT() && CU::isInter( cu ) ) ) || isChroma( cu.chType ) ) +#endif { return; } diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index baaf5739a88746a282c8c18a17933a2f49d49630..8b3740b345015e261bacc287e875a2919acad882 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -149,6 +149,9 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) switch( currCU.predMode ) { case MODE_INTER: +#if JVET_M0483_IBC + case MODE_IBC: +#endif xReconInter( currCU ); break; case MODE_INTRA: @@ -458,10 +461,17 @@ void DecCu::xReconInter(CodingUnit &cu) m_pcIntraPred->geneIntrainterPred(cu); // inter prediction +#if JVET_M0483_IBC + CHECK(CU::isIBC(cu) && cu.firstPU->mhIntraFlag, "IBC and MHIntra cannot be used together"); + CHECK(CU::isIBC(cu) && cu.affine, "IBC and Affine cannot be used together"); + CHECK(CU::isIBC(cu) && cu.triangle, "IBC and triangle cannot be used together"); + CHECK(CU::isIBC(cu) && cu.firstPU->mmvdMergeFlag, "IBC and MMVD cannot be used together"); +#else CHECK(cu.ibc && cu.firstPU->mhIntraFlag, "IBC and MHIntra cannot be used together"); CHECK(cu.ibc && cu.affine, "IBC and Affine cannot be used together"); CHECK(cu.ibc && cu.triangle, "IBC and triangle cannot be used together"); CHECK(cu.ibc && cu.firstPU->mmvdMergeFlag, "IBC and MMVD cannot be used together"); +#endif const bool luma = cu.Y().valid(); const bool chroma = cu.Cb().valid(); if (luma && chroma) @@ -515,7 +525,11 @@ void DecCu::xReconInter(CodingUnit &cu) tmpPred.copyFrom(cs.getPredBuf(cu).get(COMPONENT_Y)); } #endif +#if JVET_M0483_IBC + if (!cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#else if (!cu.firstPU->mhIntraFlag && !cu.ibc ) +#endif cs.getPredBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT()); } #endif @@ -541,7 +555,11 @@ void DecCu::xReconInter(CodingUnit &cu) { cs.getRecoBuf(cu).copyClip(cs.getPredBuf(cu), cs.slice->clpRngs()); #if JVET_M0427_INLOOP_RESHAPER +#if JVET_M0483_IBC + if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#else if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !cu.ibc) +#endif { cs.getRecoBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT()); } @@ -615,7 +633,11 @@ void DecCu::xDecodeInterTexture(CodingUnit &cu) CompArea tmpArea(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size()); PelBuf tmpPred = m_tmpStorageLCU->getBuf(tmpArea); tmpPred.copyFrom(predY); - if (!cu.firstPU->mhIntraFlag && !cu.ibc) +#if JVET_M0483_IBC + if (!cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#else + if (!cu.firstPU->mhIntraFlag && !cu.ibc) +#endif tmpPred.rspSignal(m_pcReshape->getFwdLUT()); const Pel avgLuma = tmpPred.computeAvg(); int adj = m_pcReshape->calculateChromaAdj(avgLuma); @@ -717,6 +739,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) #if JVET_M0170_MRG_SHARELIST pu.shareParentPos = cu.shareParentPos; pu.shareParentSize = cu.shareParentSize; +#endif +#if JVET_M0483_IBC + if (CU::isIBC(*pu.cu)) + PU::getIBCMergeCandidates(pu, mrgCtx, pu.mergeIdx); + else #endif PU::getInterMergeCandidates(pu, mrgCtx, 0, pu.mergeIdx); #if !JVET_M0068_M0171_MMVD_CLEANUP @@ -809,16 +836,36 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) } } } +#if JVET_M0483_IBC + else if (CU::isIBC(*pu.cu) && pu.interDir == 1) + { + AMVPInfo amvpInfo; + PU::fillIBCMvpCand(pu, amvpInfo); + pu.mvpNum[REF_PIC_LIST_0] = amvpInfo.numCand; + Mv mvd = pu.mvd[REF_PIC_LIST_0]; +#if REUSE_CU_RESULTS + if (!cu.cs->pcv->isEncoder) +#endif + mvd <<= 2; + pu.mv[REF_PIC_LIST_0] = amvpInfo.mvCand[pu.mvpIdx[REF_PIC_LIST_0]] + mvd; + pu.mv[REF_PIC_LIST_0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); + } +#endif else { for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ) { RefPicList eRefList = RefPicList( uiRefListIdx ); +#if JVET_M0483_IBC + if ((pu.cs->slice->getNumRefIdx(eRefList) > 0 || (eRefList == REF_PIC_LIST_0 && CU::isIBC(*pu.cu))) && (pu.interDir & (1 << uiRefListIdx))) +#else if ( pu.cs->slice->getNumRefIdx( eRefList ) > 0 && ( pu.interDir & ( 1 << uiRefListIdx ) ) ) +#endif { AMVPInfo amvpInfo; PU::fillMvpCand(pu, eRefList, pu.refIdx[eRefList], amvpInfo); pu.mvpNum [eRefList] = amvpInfo.numCand; +#if JVET_M0483_IBC==0 Mv mvd = pu.mvd[eRefList]; if (eRefList == REF_PIC_LIST_0 && pu.cs->slice->getRefPic(eRefList, pu.refIdx[eRefList])->getPOC() == pu.cs->slice->getPOC()) { @@ -829,6 +876,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) mvd.changePrecision(MV_PRECISION_INT, MV_PRECISION_QUARTER); } pu.mv [eRefList] = amvpInfo.mvCand[pu.mvpIdx[eRefList]] + mvd; +#else + pu.mv[eRefList] = amvpInfo.mvCand[pu.mvpIdx[eRefList]] + pu.mvd[eRefList]; +#endif pu.mv[eRefList].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); } } diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 6bfbc6672e837f7d4a2c5b3cc886794a9e81296a..a936ef43438a08a7137c452bce15681ca6cef6fc 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -1256,7 +1256,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl } #endif +#if JVET_M0483_IBC + if (pcSlice->getSPS()->getIBCFlag() && pcSlice->getEnableTMVPFlag()) +#else if (pcSlice->getSPS()->getSpsNext().getIBCMode() && pcSlice->getEnableTMVPFlag()) +#endif { CHECK(pcSlice->getRefPic(RefPicList(pcSlice->isInterB() ? 1 - pcSlice->getColFromL0Flag() : 0), pcSlice->getColRefIdx())->getPOC() == pcSlice->getPOC(), "curr ref picture cannot be collocated picture"); } @@ -1303,10 +1307,12 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl m_cSliceDecoder.decompressSlice( pcSlice, &(nalu.getBitstream()) ); m_bFirstSliceInPicture = false; +#if JVET_M0483_IBC==0 if (pcSlice->getSPS()->getSpsNext().getIBCMode()) { pcSlice->getPic()->longTerm = false; } +#endif m_uiSliceSegmentIdx++; return false; diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index da6544a9fea0c271e6a2a38d6f965f786db15417..742391b504a127a88f964f863a22cd36f7fe5657 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -821,7 +821,9 @@ void HLSyntaxReader::parseSPSNext( SPSNext& spsNext, const bool usePCM ) READ_FLAG( symbol, "affine_type_flag" ); spsNext.setUseAffineType ( symbol != 0 ); } READ_FLAG( symbol, "gbi_flag" ); spsNext.setUseGBi ( symbol != 0 ); +#if JVET_M0483_IBC==0 READ_FLAG( symbol, "ibc_flag"); spsNext.setIBCMode ( symbol != 0 ); +#endif for( int k = 0; k < SPSNext::NumReservedFlags; k++ ) { READ_FLAG( symbol, "reserved_flag" ); if( symbol != 0 ) EXIT("Incompatible version: SPSNext reserved flag not equal to zero (bitstream was probably created with newer software version)" ); @@ -925,6 +927,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_FLAG(uiCode, "no_ladf_constraint_flag"); pcSPS->setNoLadfConstraintFlag(uiCode > 0 ? true : false); READ_FLAG(uiCode, "no_dep_quant_constraint_flag"); pcSPS->setNoDepQuantConstraintFlag(uiCode > 0 ? true : false); READ_FLAG(uiCode, "no_sign_data_hiding_constraint_flag"); pcSPS->setNoSignDataHidingConstraintFlag(uiCode > 0 ? true : false); +#if JVET_M0483_IBC + READ_FLAG(uiCode, "ibc_flag"); pcSPS->setIBCFlag(uiCode); +#endif #if HEVC_VPS READ_CODE( 4, uiCode, "sps_video_parameter_set_id"); pcSPS->setVPSId ( uiCode ); #endif @@ -1806,10 +1811,21 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para } } } + +#if JVET_M0483_IBC + if (!pcSlice->isIntra() || sps->getIBCFlag()) + { + READ_UVLC(uiCode, "six_minus_max_num_merge_cand"); + pcSlice->setMaxNumMergeCand(MRG_MAX_NUM_CANDS - uiCode); + } +#endif + if (!pcSlice->isIntra()) { +#if JVET_M0483_IBC==0 READ_UVLC(uiCode, "six_minus_max_num_merge_cand"); pcSlice->setMaxNumMergeCand(MRG_MAX_NUM_CANDS - uiCode); +#endif if ( sps->getSBTMVPEnabledFlag() && !sps->getSpsNext().getUseAffine() ) // ATMVP only { diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 4323228d3b5cad6969d0f40fd5283e516b206a87..85f257b789db7f4f4a633f9b270623627202681a 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -713,7 +713,11 @@ void CABACWriter::coding_unit( const CodingUnit& cu, Partitioner& partitioner, C } // skip flag +#if JVET_M0483_IBC + if ((!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag()) && cu.Y().valid()) +#else if (!cs.slice->isIntra() && cu.Y().valid()) +#endif { cu_skip_flag( cu ); } @@ -769,19 +773,86 @@ void CABACWriter::cu_transquant_bypass_flag( const CodingUnit& cu ) void CABACWriter::cu_skip_flag( const CodingUnit& cu ) { unsigned ctxId = DeriveCtx::CtxSkipFlag( cu ); + +#if JVET_M0483_IBC + if (cu.slice->isIntra() && cu.cs->slice->getSPS()->getIBCFlag()) + { + m_BinEncoder.encodeBin((cu.skip), Ctx::SkipFlag(ctxId)); + DTRACE(g_trace_ctx, D_SYNTAX, "cu_skip_flag() ctx=%d skip=%d\n", ctxId, cu.skip ? 1 : 0); + return; + } +#endif + m_BinEncoder.encodeBin( ( cu.skip ), Ctx::SkipFlag( ctxId ) ); DTRACE( g_trace_ctx, D_SYNTAX, "cu_skip_flag() ctx=%d skip=%d\n", ctxId, cu.skip ? 1 : 0 ); +#if JVET_M0483_IBC + if (cu.skip && cu.cs->slice->getSPS()->getIBCFlag()) + { + unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu); + m_BinEncoder.encodeBin(CU::isIBC(cu) ? 1 : 0, Ctx::IBCFlag(ctxidx)); + DTRACE(g_trace_ctx, D_SYNTAX, "ibc() ctx=%d cu.predMode=%d\n", ctxidx, cu.predMode); + + if (CU::isInter(cu)) + { + m_BinEncoder.encodeBin(cu.mmvdSkip, Ctx::MmvdFlag(0)); + DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, cu.mmvdSkip ? 1 : 0); + } + } + if (cu.skip && !cu.cs->slice->getSPS()->getIBCFlag()) + { + m_BinEncoder.encodeBin(cu.mmvdSkip, Ctx::MmvdFlag(0)); + DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, cu.mmvdSkip ? 1 : 0); + } +#else if (cu.skip) { m_BinEncoder.encodeBin(cu.mmvdSkip, Ctx::MmvdFlag(0)); DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_cu_skip_flag() ctx=%d mmvd_skip=%d\n", 0, cu.mmvdSkip ? 1 : 0); } +#endif } void CABACWriter::pred_mode( const CodingUnit& cu ) { +#if JVET_M0483_IBC + if (cu.cs->slice->getSPS()->getIBCFlag()) + { +#endif +#if JVET_M0483_IBC + if (cu.cs->slice->isIntra()) + { + unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu); + m_BinEncoder.encodeBin(CU::isIBC(cu), Ctx::IBCFlag(ctxidx)); + } + else + { +#if JVET_M0502_PRED_MODE_CTX + m_BinEncoder.encodeBin((CU::isIntra(cu)), Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu))); +#else + m_BinEncoder.encodeBin((CU::isIntra(cu)), Ctx::PredMode()); +#endif + if (!CU::isIntra(cu)) + { + unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu); + m_BinEncoder.encodeBin(CU::isIBC(cu), Ctx::IBCFlag(ctxidx)); + } + } + } + else + { + if (cu.cs->slice->isIntra()) + { + return; + } +#if JVET_M0502_PRED_MODE_CTX + m_BinEncoder.encodeBin((CU::isIntra(cu)), Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu))); +#else + m_BinEncoder.encodeBin((CU::isIntra(cu)), Ctx::PredMode()); +#endif + } +#else if( cu.cs->slice->isIntra() ) { return; @@ -791,6 +862,7 @@ void CABACWriter::pred_mode( const CodingUnit& cu ) #else m_BinEncoder.encodeBin( ( CU::isIntra( cu ) ), Ctx::PredMode() ); #endif +#endif } void CABACWriter::pcm_data( const CodingUnit& cu, Partitioner& partitioner ) @@ -1235,7 +1307,11 @@ void CABACWriter::intra_chroma_pred_mode( const PredictionUnit& pu ) void CABACWriter::cu_residual( const CodingUnit& cu, Partitioner& partitioner, CUCtx& cuCtx ) { +#if JVET_M0483_IBC + if (!CU::isIntra(cu)) +#else if( CU::isInter( cu ) ) +#endif { PredictionUnit& pu = *cu.firstPU; if( !pu.mergeFlag ) @@ -1336,6 +1412,13 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu ) } if( pu.mergeFlag ) { +#if JVET_M0483_IBC + if (CU::isIBC(*pu.cu)) + { + merge_idx(pu); + return; + } +#endif subblock_merge_flag( *pu.cu ); MHIntra_flag( pu ); if ( pu.mhIntraFlag ) @@ -1350,6 +1433,14 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu ) else merge_idx ( pu ); } +#if JVET_M0483_IBC + else if (CU::isIBC(*pu.cu)) + { + ref_idx(pu, REF_PIC_LIST_0); + mvd_coding(pu.mvd[REF_PIC_LIST_0], pu.cu->imv); + mvp_flag(pu, REF_PIC_LIST_0); + } +#endif else { #if JVET_M0246_AFFINE_AMVR @@ -1483,6 +1574,14 @@ void CABACWriter::merge_flag( const PredictionUnit& pu ) m_BinEncoder.encodeBin( pu.mergeFlag, Ctx::MergeFlag() ); DTRACE( g_trace_ctx, D_SYNTAX, "merge_flag() merge=%d pos=(%d,%d) size=%dx%d\n", pu.mergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height ); + +#if JVET_M0483_IBC + if (pu.mergeFlag && CU::isIBC(*pu.cu)) + { + return; + } +#endif + if (pu.mergeFlag) { m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(0)); @@ -1512,7 +1611,11 @@ void CABACWriter::imv_mode( const CodingUnit& cu ) } unsigned ctxId = DeriveCtx::CtxIMVFlag( cu ); +#if JVET_M0483_IBC + if (CU::isIBC(cu) == false) +#else if (!(cu.firstPU->interDir == 1 && cu.cs->slice->getRefPic(REF_PIC_LIST_0, cu.firstPU->refIdx[REF_PIC_LIST_0])->getPOC() == cu.cs->slice->getPOC())) // the first bin of IMV flag does need to be signaled in IBC block +#endif m_BinEncoder.encodeBin( ( cu.imv > 0 ), Ctx::ImvFlag( ctxId ) ); DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", (cu.imv > 0), ctxId ); @@ -1764,6 +1867,15 @@ void CABACWriter::ref_idx( const PredictionUnit& pu, RefPicList eRefList ) #endif int numRef = pu.cs->slice->getNumRefIdx(eRefList); + +#if JVET_M0483_IBC + if (eRefList == REF_PIC_LIST_0 && pu.cs->sps->getIBCFlag()) + { + if (CU::isIBC(*pu.cu)) + return; + } +#endif + if( numRef <= 1 ) { return; @@ -2554,7 +2666,11 @@ void CABACWriter::emt_cu_flag( const CodingUnit& cu ) #endif const CodingStructure& cs = *cu.cs; +#if JVET_M0483_IBC + if (!((cs.sps->getSpsNext().getUseIntraEMT() && CU::isIntra(cu)) || (cs.sps->getSpsNext().getUseInterEMT() && !CU::isIntra(cu))) || isChroma(cu.chType)) +#else if( !( ( cs.sps->getSpsNext().getUseIntraEMT() && CU::isIntra( cu ) ) || ( cs.sps->getSpsNext().getUseInterEMT() && CU::isInter( cu ) ) ) || isChroma( cu.chType ) ) +#endif { return; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index d91e00e72fe74d49738980306ee455b0e859d531..6f6d16822c359eda71c161ce7b5e59166de345e9 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -116,6 +116,22 @@ void EncCu::create( EncCfg* encCfg ) m_pTempMotLUTs[w][h] = new LutMotionCand ; m_pBestMotLUTs[w][h] = new LutMotionCand ; m_pSplitTempMotLUTs[w][h] = new LutMotionCand; +#if JVET_M0483_IBC + m_pSplitTempMotLUTs[w][h]->currCnt = 0; + m_pSplitTempMotLUTs[w][h]->currCntIBC = 0; + m_pSplitTempMotLUTs[w][h]->motionCand = nullptr; + m_pSplitTempMotLUTs[w][h]->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS * 2]; + + m_pTempMotLUTs[w][h]->currCnt = 0; + m_pTempMotLUTs[w][h]->currCntIBC = 0; + m_pTempMotLUTs[w][h]->motionCand = nullptr; + m_pTempMotLUTs[w][h]->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS * 2]; + + m_pBestMotLUTs[w][h]->currCnt = 0; + m_pBestMotLUTs[w][h]->currCntIBC = 0; + m_pBestMotLUTs[w][h]->motionCand = nullptr; + m_pBestMotLUTs[w][h]->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS * 2]; +#else m_pSplitTempMotLUTs[w][h]->currCnt = 0; m_pSplitTempMotLUTs[w][h]->motionCand = nullptr; m_pSplitTempMotLUTs[w][h]->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS]; @@ -127,6 +143,7 @@ void EncCu::create( EncCfg* encCfg ) m_pBestMotLUTs[w][h]->currCnt = 0; m_pBestMotLUTs[w][h]->motionCand = nullptr; m_pBestMotLUTs[w][h]->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS]; +#endif } else { @@ -395,7 +412,11 @@ void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsign m_ctuIbcSearchRangeX >>= 1; m_ctuIbcSearchRangeY >>= 1; } +#if JVET_M0483_IBC + if (cs.slice->getNumRefIdx(REF_PIC_LIST_0) > 0) +#else if (cs.slice->getNumRefIdx(REF_PIC_LIST_0) > 1) +#endif { m_ctuIbcSearchRangeX >>= 1; m_ctuIbcSearchRangeY >>= 1; @@ -680,7 +701,11 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par const unsigned wIdx = gp_sizeIdxInfo->idxFrom( partitioner.currArea().lwidth() ); const UnitArea currCsArea = clipArea( CS::getArea( *bestCS, bestCS->area, partitioner.chType ), *tempCS->picture ); +#if JVET_M0483_IBC + if (m_pImvTempCS && (!slice.isIntra() || slice.getSPS()->getIBCFlag())) +#else if( m_pImvTempCS && !slice.isIntra() ) +#endif { tempCS->initSubStructure( *m_pImvTempCS[wIdx], partitioner.chType, partitioner.currArea(), false ); } @@ -705,7 +730,11 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par m_modeCtrl->finishCULevel( partitioner ); return; } +#if JVET_M0483_IBC + if ((!slice.isIntra() || slice.getSPS()->getIBCFlag()) +#else if (!slice.isIntra() +#endif && tempCS->chType == CHANNEL_TYPE_LUMA ) { @@ -866,9 +895,17 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par // QP from last processed CU for further processing bestCS->prevQP[partitioner.chType] = bestCS->cus.back()->qp; +#if JVET_M0483_IBC + if ((!slice.isIntra() || slice.getSPS()->getIBCFlag()) +#else if (!slice.isIntra() +#endif && bestCS->chType == CHANNEL_TYPE_LUMA +#if JVET_M0483_IBC + && bestCS->cus.size() == 1 && (bestCS->cus.back()->predMode == MODE_INTER || bestCS->cus.back()->predMode == MODE_IBC) +#else && bestCS->cus.size() == 1 && bestCS->cus.back()->predMode == MODE_INTER +#endif && bestCS->area.Y() == (*bestCS->cus.back()).Y() ) { @@ -1435,7 +1472,11 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, if (isAffMVInfoSaved) m_pcInterSearch->addAffMVInfo(tmpMVInfo); +#if JVET_M0483_IBC + if ((!slice.isIntra() || slice.getSPS()->getIBCFlag()) +#else if (!slice.isIntra() +#endif && tempCS->chType == CHANNEL_TYPE_LUMA ) { @@ -1599,7 +1640,11 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC m_CABACEstimator->cu_transquant_bypass_flag( cu ); } +#if JVET_M0483_IBC + if ((!cu.cs->slice->isIntra() || cu.cs->slice->getSPS()->getIBCFlag()) +#else if( !cu.cs->slice->isIntra() +#endif && cu.Y().valid() ) { @@ -1716,7 +1761,11 @@ void EncCu::xCheckIntraPCM(CodingStructure *&tempCS, CodingStructure *&bestCS, P m_CABACEstimator->cu_transquant_bypass_flag( cu ); } +#if JVET_M0483_IBC + if ((!cu.cs->slice->isIntra() || cu.cs->slice->getSPS()->getIBCFlag()) +#else if( !cu.cs->slice->isIntra() +#endif && cu.Y().valid() ) { @@ -1853,7 +1902,9 @@ void EncCu::xCheckRDCostHashInter( CodingStructure *&tempCS, CodingStructure *&b cu.transQuantBypass = encTestMode.lossless; cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1; cu.qp = encTestMode.qp; +#if !JVET_M0483_IBC cu.ibc = false; +#endif CU::addPUs(cu); cu.mmvdSkip = false; cu.firstPU->mmvdMergeFlag = false; @@ -1994,7 +2045,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& if( auto blkCache = dynamic_cast< CacheBlkInfoCtrl* >( m_modeCtrl ) ) { +#if JVET_M0483_IBC + if (slice.getSPS()->getIBCFlag()) +#else if (slice.getSPS()->getSpsNext().getIBCMode()) +#endif { ComprCUCtx cuECtx = m_modeCtrl->getComprCUCtx(); bestIsSkip = blkCache->isSkip(tempCS->area) && cuECtx.bestCU; @@ -2044,16 +2099,20 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& m_pcRdCost->setDistParam (distParam, tempCS->getOrgBuf().Y(), m_acMergeBuffer[0].Y(), sps.getBitDepth (CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard); const UnitArea localUnitArea( tempCS->area.chromaFormat, Area( 0, 0, tempCS->area.Y().width, tempCS->area.Y().height) ); +#if JVET_M0483_IBC==0 uint32_t ibcCand = 0; uint32_t numValidMv = mergeCtx.numValidMergeCand; +#endif for( uint32_t uiMergeCand = 0; uiMergeCand < mergeCtx.numValidMergeCand; uiMergeCand++ ) { +#if JVET_M0483_IBC==0 if ((mergeCtx.interDirNeighbours[uiMergeCand] == 1 || mergeCtx.interDirNeighbours[uiMergeCand] == 3) && tempCS->slice->getRefPic(REF_PIC_LIST_0, mergeCtx.mvFieldNeighbours[uiMergeCand << 1].refIdx)->getPOC() == tempCS->slice->getPOC()) { ibcCand++; numValidMv--; continue; } +#endif mergeCtx.setMergeInfo( pu, uiMergeCand ); PU::spanMotionInfo( pu, mergeCtx ); @@ -2116,13 +2175,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]); } } +#if JVET_M0483_IBC==0 CHECK(std::min(uiMergeCand + 1 - ibcCand, uiNumMrgSATDCand) != RdModeList.size(), ""); +#else + CHECK(std::min(uiMergeCand + 1, uiNumMrgSATDCand) != RdModeList.size(), ""); +#endif } +#if JVET_M0483_IBC==0 if (numValidMv < uiNumMrgSATDCand) uiNumMrgSATDCand = numValidMv; if (numValidMv == 0) return; - +#endif if (isIntrainterEnabled) { @@ -2139,11 +2203,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& // save the to-be-tested merge candidates uint32_t MHIntraMergeCand[NUM_MRG_SATD_CAND]; +#if JVET_M0483_IBC==0 for (uint32_t mergeCnt = 0; mergeCnt < std::min(NUM_MRG_SATD_CAND, (const int) uiNumMrgSATDCand); mergeCnt++) +#else + for (uint32_t mergeCnt = 0; mergeCnt < NUM_MRG_SATD_CAND; mergeCnt++) +#endif { MHIntraMergeCand[mergeCnt] = RdModeList[mergeCnt]; } +#if JVET_M0483_IBC==0 for (uint32_t mergeCnt = 0; mergeCnt < std::min( std::min(NUM_MRG_SATD_CAND, (const int)uiNumMrgSATDCand), 4); mergeCnt++) +#else + for (uint32_t mergeCnt = 0; mergeCnt < std::min(NUM_MRG_SATD_CAND, 4); mergeCnt++) +#endif { uint32_t mergeCand = MHIntraMergeCand[mergeCnt]; acMergeBuffer[mergeCand] = m_acRealMergeBuffer[mergeCand].getBuf(localUnitArea); @@ -2387,12 +2459,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& { uint32_t uiMergeCand = RdModeList[uiMrgHADIdx]; - +#if JVET_M0483_IBC==0 if(uiMergeCand < mergeCtx.numValidMergeCand) if ((mergeCtx.interDirNeighbours[uiMergeCand] == 1 || mergeCtx.interDirNeighbours[uiMergeCand] == 3) && tempCS->slice->getRefPic(REF_PIC_LIST_0, mergeCtx.mvFieldNeighbours[uiMergeCand << 1].refIdx)->getPOC() == tempCS->slice->getPOC()) { continue; } +#endif if (uiNoResidualPass != 0 && uiMergeCand >= (MRG_MAX_NUM_CANDS + MMVD_ADD_NUM)) // intrainter does not support skip mode { @@ -3196,8 +3269,12 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct // first get merge candidates CodingUnit cu(tempCS->area); cu.cs = tempCS; +#if JVET_M0483_IBC + cu.predMode = MODE_IBC; +#else cu.predMode = MODE_INTER; cu.ibc = true; +#endif cu.slice = tempCS->slice; #if HEVC_TILES_WPP cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos()); @@ -3212,9 +3289,13 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct pu.shareParentPos = tempCS->sharedBndPos; pu.shareParentSize = tempCS->sharedBndSize; #endif +#if JVET_M0483_IBC + PU::getIBCMergeCandidates(pu, mergeCtx); +#else PU::getInterMergeCandidates(pu, mergeCtx , 0 ); +#endif } int candHasNoResidual[MRG_MAX_NUM_CANDS]; @@ -3245,8 +3326,12 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos()); #endif cu.skip = false; +#if JVET_M0483_IBC + cu.predMode = MODE_IBC; +#else cu.predMode = MODE_INTER; cu.ibc = true; +#endif cu.transQuantBypass = encTestMode.lossless; cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1; cu.qp = encTestMode.qp; @@ -3277,6 +3362,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct int numValidBv = mergeCtx.numValidMergeCand; for (unsigned int mergeCand = 0; mergeCand < mergeCtx.numValidMergeCand; mergeCand++) { +#if JVET_M0483_IBC==0 if (mergeCtx.interDirNeighbours[mergeCand] != 1) { numValidBv--; @@ -3287,6 +3373,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct numValidBv--; continue; } +#endif mergeCtx.setMergeInfo(pu, mergeCand); // set bv info in merge mode const int cuPelX = pu.Y().x; const int cuPelY = pu.Y().y; @@ -3356,6 +3443,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct for (unsigned int mrgHADIdx = 0; mrgHADIdx < numMrgSATDCand; mrgHADIdx++) { unsigned int mergeCand = RdModeList[mrgHADIdx]; +#if JVET_M0483_IBC==0 if (mergeCtx.interDirNeighbours[mergeCand] != 1) { continue; @@ -3364,6 +3452,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct { continue; } +#endif if (!(numResidualPass == 1 && candHasNoResidual[mergeCand] == 1)) { if (!(bestIsSkip && (numResidualPass == 0))) @@ -3394,8 +3483,12 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos()); #endif cu.skip = false; +#if JVET_M0483_IBC + cu.predMode = MODE_IBC; +#else cu.predMode = MODE_INTER; cu.ibc = true; +#endif cu.transQuantBypass = encTestMode.lossless; cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1; cu.qp = encTestMode.qp; @@ -3462,6 +3555,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode) { + if (tempCS->area.lwidth() > IBC_MAX_CAND_SIZE || tempCS->area.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip + { + return; + } + tempCS->initStructData(encTestMode.qp, encTestMode.lossless); CodingUnit &cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, partitioner.chType), partitioner.chType); @@ -3472,11 +3570,17 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos()); #endif cu.skip = false; +#if JVET_M0483_IBC + cu.predMode = MODE_IBC; +#else cu.predMode = MODE_INTER; +#endif cu.transQuantBypass = encTestMode.lossless; cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1; cu.qp = encTestMode.qp; +#if JVET_M0483_IBC==0 cu.ibc = true; +#endif cu.imv = 0; CU::addPUs(cu); @@ -3489,8 +3593,11 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best pu.intraDir[1] = PLANAR_IDX; // set intra pred for ibc block pu.interDir = 1; // use list 0 for IBC mode +#if JVET_M0483_IBC + pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; // last idx in the list +#else pu.refIdx[REF_PIC_LIST_0] = pu.cs->slice->getNumRefIdx(REF_PIC_LIST_0) - 1; // last idx in the list - +#endif if (partitioner.chType == CHANNEL_TYPE_LUMA) { diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index 2811474aab32fd50ccb610a4c0b4ae01ff4f2b4d..b7c2fa6f8ba27af4547f066dddb00b1bddbdc83a 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -1478,10 +1478,12 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, { pcSlice->setSliceType(I_SLICE); } +#if JVET_M0483_IBC ==0 if (pcSlice->getSliceType() == I_SLICE && pcSlice->getSPS()->getSpsNext().getIBCMode()) { pcSlice->setSliceType(P_SLICE); } +#endif // Set the nal unit type pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField)); if(pcSlice->getTemporalLayerNonReferenceFlag()) @@ -1652,6 +1654,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, if (pcPic->cs->sps->getSpsNext().getUseCompositeRef() && getPrepareLTRef()) { arrangeCompositeReference(pcSlice, rcListPic, pocCurr); } +#if JVET_M0483_IBC==0 if (pcSlice->getSPS()->getSpsNext().getIBCMode()) { if (m_pcCfg->getIntraPeriod() > 0 && pcSlice->getPOC() % m_pcCfg->getIntraPeriod() == 0) @@ -1662,6 +1665,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, pcSlice->setNumRefIdx(REF_PIC_LIST_0, pcSlice->getNumRefIdx(REF_PIC_LIST_0) + 1); } +#endif // Set reference list pcSlice->setRefPicList ( rcListPic ); @@ -1786,10 +1790,12 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, { pcSlice->setSliceType ( P_SLICE ); } +#if JVET_M0483_IBC==0 if (pcSlice->getSPS()->getSpsNext().getIBCMode() && pcSlice->getNumRefIdx(REF_PIC_LIST_0) == 1) { m_pcSliceEncoder->setEncCABACTableIdx(P_SLICE); } +#endif xUpdateRasInit( pcSlice ); // Do decoding refresh marking if any @@ -1876,7 +1882,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, } // disable TMVP when current picture is the only ref picture +#if JVET_M0483_IBC + if (pcSlice->isIRAP() && pcSlice->getSPS()->getIBCFlag()) +#else if (pcSlice->isIRAP() && pcSlice->getSPS()->getSpsNext().getIBCMode()) +#endif { pcSlice->setEnableTMVPFlag(0); } @@ -1890,6 +1900,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, bool bGPBcheck=false; if ( pcSlice->getSliceType() == B_SLICE) { +#if JVET_M0483_IBC==0 if (pcSlice->getSPS()->getSpsNext().getIBCMode()) { if (pcSlice->getNumRefIdx(RefPicList(0)) - 1 == pcSlice->getNumRefIdx(RefPicList(1))) @@ -1906,6 +1917,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, } } else +#endif if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) ) { bGPBcheck=true; @@ -2692,7 +2704,9 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "final", 0 ) ) ); pcPic->reconstructed = true; +#if JVET_M0483_IBC ==0 pcPic->longTerm = false; +#endif m_bFirst = false; m_iNumPicCoded++; if (!(pcPic->cs->sps->getSpsNext().getUseCompositeRef() && isEncodeLtRef)) diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 5139abba74cb7b065dd995d819235e1736e63703..2deda4f064adbf1df0d5e64e3452f0b86d613135 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -937,8 +937,12 @@ void EncLib::xInitSPS(SPS &sps) #if JVET_M0147_DMVR sps.setUseDMVR ( m_DMVR ); #endif - sps.getSpsNext().setIBCMode ( m_IBCMode ); +#if JVET_M0483_IBC + sps.setIBCFlag ( m_IBCMode); +#else + sps.getSpsNext().setIBCMode (m_IBCMode); +#endif sps.setWrapAroundEnabledFlag ( m_wrapAround ); sps.setWrapAroundOffset ( m_wrapAroundOffset ); // ADD_NEW_TOOL : (encoder lib) set tool enabling flags and associated parameters here @@ -1442,11 +1446,13 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps) } } CHECK(!(bestPos <= 15), "Unspecified error"); +#if JVET_M0483_IBC==0 if (sps.getSpsNext().getIBCMode()) { pps.setNumRefIdxL0DefaultActive(bestPos + 1); } else +#endif pps.setNumRefIdxL0DefaultActive(bestPos); pps.setNumRefIdxL1DefaultActive(bestPos); pps.setTransquantBypassEnabledFlag(getTransquantBypassEnabledFlag()); diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp index 6e175ebeff5ed0d4452611186602876b1304de14..dd4b2282e974f1b728279275d411cf224d5b115b 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -854,7 +854,11 @@ bool BestEncInfoCache::isValid( const CodingStructure& cs, const Partitioner& pa , encInfo.pu, (cs.picture->Y().width), (cs.picture->Y().height) #endif ) +#if JVET_M0483_IBC + || CU::isIBC(encInfo.cu) +#else || encInfo.cu.ibc +#endif ) { return false; @@ -1192,7 +1196,11 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru m_ComprCUCtxList.back().testModes.push_back( { ETM_IPCM, ETO_STANDARD, qp, lossless } ); m_ComprCUCtxList.back().testModes.push_back( { ETM_INTRA, ETO_STANDARD, qp, lossless } ); // add ibc mode to intra path +#if JVET_M0483_IBC + if (cs.sps->getIBCFlag() && checkIbc) +#else if (cs.sps->getSpsNext().getIBCMode() && checkIbc ) +#endif { m_ComprCUCtxList.back().testModes.push_back({ ETM_IBC, ETO_STANDARD, qp, lossless }); if (cs.chType == CHANNEL_TYPE_LUMA) @@ -1372,18 +1380,30 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt return false; } +#if JVET_M0483_IBC + if (m_pcEncCfg->getUsePbIntraFast() && (!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag()) && !interHadActive(cuECtx) && cuECtx.bestCU && !CU::isIntra(*cuECtx.bestCU)) +#else if( m_pcEncCfg->getUsePbIntraFast() && !cs.slice->isIntra() && !interHadActive( cuECtx ) && cuECtx.bestCU && CU::isInter( *cuECtx.bestCU ) ) +#endif { return false; } // INTRA MODES +#if JVET_M0483_IBC + if (cs.sps->getIBCFlag() && !cuECtx.bestTU) +#else if (cs.sps->getSpsNext().getIBCMode() && !cuECtx.bestTU) +#endif return true; CHECK( !slice.isIntra() && !cuECtx.bestTU, "No possible non-intra encoding for a P- or B-slice found" ); if( !( slice.isIRAP() || bestMode.type == ETM_INTRA || - ( ( !m_pcEncCfg->getDisableIntraPUsInInterSlices() ) && !relatedCU.isInter && ( +#if JVET_M0483_IBC + ((!m_pcEncCfg->getDisableIntraPUsInInterSlices()) && (!relatedCU.isInter || !relatedCU.isIBC) && ( +#else + ( ( !m_pcEncCfg->getDisableIntraPUsInInterSlices() ) && !relatedCU.isInter && ( +#endif ( cuECtx.bestTU->cbf[0] != 0 ) || ( ( numComp > COMPONENT_Cb ) && cuECtx.bestTU->cbf[1] != 0 ) || ( ( numComp > COMPONENT_Cr ) && cuECtx.bestTU->cbf[2] != 0 ) // avoid very complex intra if it is unlikely @@ -1405,7 +1425,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt if( !cs.slice->isIRAP() && m_pcEncCfg->getUsePbIntraFast() ) { CodingUnit* bestCU = cuECtx.bestCU; +#if JVET_M0483_IBC + if (bestCU && !CU::isIntra(*bestCU)) +#else if( bestCU && CU::isInter( *bestCU ) ) +#endif { DistParam distParam; const bool useHad = !bestCU->transQuantBypass; @@ -1436,7 +1460,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt else if (encTestmode.type == ETM_IBC || encTestmode.type == ETM_IBC_MERGE) { // IBC MODES +#if JVET_M0483_IBC + return sps.getIBCFlag() && width <= IBC_MAX_CAND_SIZE && partitioner.currArea().lumaSize().height <= IBC_MAX_CAND_SIZE; +#else return sps.getSpsNext().getIBCMode() && width <= IBC_MAX_CAND_SIZE && partitioner.currArea().lumaSize().height <= IBC_MAX_CAND_SIZE; +#endif } else if( isModeInter( encTestmode ) ) { @@ -1502,7 +1530,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt ////////////////////////////////////////////////////////////////////////// int skipScore = 0; +#if JVET_M0483_IBC + if ((!slice.isIntra() || slice.getSPS()->getIBCFlag()) && cuECtx.get<bool>(IS_BEST_NOSPLIT_SKIP)) +#else if( !slice.isIntra() && cuECtx.get<bool>( IS_BEST_NOSPLIT_SKIP ) ) +#endif { for( int i = 2; i < m_ComprCUCtxList.size(); i++ ) { @@ -1597,6 +1629,15 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt const CodingUnit *cuBR = bestCS->cus.back(); unsigned height = partitioner.currArea().lumaSize().height; +#if JVET_M0483_IBC + if (bestCU && ((bestCU->btDepth == 0 && maxBTD >= ((slice.isIntra() && !slice.getSPS()->getIBCFlag()) ? 3 : 2)) + || (bestCU->btDepth == 1 && cuBR && cuBR->btDepth == 1 && maxBTD >= ((slice.isIntra() && !slice.getSPS()->getIBCFlag()) ? 4 : 3))) + && (width <= MAX_TU_SIZE_FOR_PROFILE && height <= MAX_TU_SIZE_FOR_PROFILE) + && cuECtx.get<bool>(DID_HORZ_SPLIT) && cuECtx.get<bool>(DID_VERT_SPLIT)) + { + return false; + } +#else if( bestCU && ( ( bestCU->btDepth == 0 && maxBTD >= ( slice.isIntra() ? 3 : 2 ) ) || ( bestCU->btDepth == 1 && cuBR && cuBR->btDepth == 1 && maxBTD >= ( slice.isIntra() ? 4 : 3 ) ) ) && ( width <= MAX_TU_SIZE_FOR_PROFILE && height <= MAX_TU_SIZE_FOR_PROFILE ) @@ -1604,6 +1645,7 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt { return false; } +#endif } if( m_pcEncCfg->getUseEarlyCU() && bestCS->cost != MAX_DOUBLE && bestCU && bestCU->skip ) { @@ -1708,6 +1750,15 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt #endif relatedCU.GBiIdx = bestCU->GBiIdx; } +#if JVET_M0483_IBC + else if (CU::isIBC(*bestCU)) + { + relatedCU.isIBC = true; +#if HM_CODED_CU_INFO + relatedCU.isSkip |= bestCU->skip; +#endif + } +#endif else if( CU::isIntra( *bestCU ) ) { relatedCU.isIntra = true; diff --git a/source/Lib/EncoderLib/EncModeCtrl.h b/source/Lib/EncoderLib/EncModeCtrl.h index fb3e9864a90a461a426ab5dad0b7738826a030cb..145d0c4b96e5875e0c112e04617276ce2aad7993 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.h +++ b/source/Lib/EncoderLib/EncModeCtrl.h @@ -364,6 +364,9 @@ struct CodedCUInfo bool isIntra; bool isSkip; bool isMMVDSkip; +#if JVET_M0483_IBC + bool isIBC; +#endif bool validMv[NUM_REF_PIC_LIST_01][MAX_STORED_CU_INFO_REFS]; Mv saveMv [NUM_REF_PIC_LIST_01][MAX_STORED_CU_INFO_REFS]; diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index 64a1fe894b3be8f037415c00140820475309c4b0..86dba88c48318a3743865d11df00ada1a245f8aa 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -536,7 +536,11 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr #endif if(rpcSlice->getPPS()->getSliceChromaQpFlag()) { +#if JVET_M0483_IBC + const bool bUseIntraOrPeriodicOffset = (rpcSlice->isIntra() && !rpcSlice->getSPS()->getIBCFlag()) || (m_pcCfg->getSliceChromaOffsetQpPeriodicity() > 0 && (rpcSlice->getPOC() % m_pcCfg->getSliceChromaOffsetQpPeriodicity()) == 0); +#else const bool bUseIntraOrPeriodicOffset = rpcSlice->isIntra() || (m_pcCfg->getSliceChromaOffsetQpPeriodicity() > 0 && (rpcSlice->getPOC() % m_pcCfg->getSliceChromaOffsetQpPeriodicity()) == 0); +#endif int cbQP = bUseIntraOrPeriodicOffset ? m_pcCfg->getSliceChromaOffsetQpIntraOrPeriodic(false) : m_pcCfg->getGOPEntry(iGOPid).m_CbQPoffset; int crQP = bUseIntraOrPeriodicOffset ? m_pcCfg->getSliceChromaOffsetQpIntraOrPeriodic(true) : m_pcCfg->getGOPEntry(iGOPid).m_CrQPoffset; @@ -1481,7 +1485,11 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons #endif #if JVET_M0255_FRACMMVD_SWITCH if ( pcSlice->getSPS()->getDisFracMmvdEnabledFlag() || +#if JVET_M0483_IBC + (pcSlice->getSPS()->getIBCFlag() && m_pcCuEncoder->getEncCfg()->getIBCHashSearch())) +#else ( pcSlice->getSPS()->getSpsNext().getIBCMode() && m_pcCuEncoder->getEncCfg()->getIBCHashSearch() ) ) +#endif { #if JVET_M0427_INLOOP_RESHAPER if (pcSlice->getSPS()->getUseReshaper() && m_pcLib->getReshaper()->getCTUFlag() && pcSlice->getSPS()->getSpsNext().getIBCMode()) diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 48ad42e09d703812ab1ec111173fdb3a2c4befdd..cd19a77f979ae2ae17a601d2c6fe16b7ed72c068 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -829,7 +829,11 @@ int InterSearch::xIBCSearchMVChromaRefine(PredictionUnit& pu, pu.mv[0] = cMVCand[cand]; pu.mv[0].changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL); pu.interDir = 1; +#if JVET_M0483_IBC + pu.refIdx[0] = pu.cs->slice->getNumRefIdx(REF_PIC_LIST_0); // last idx in the list +#else pu.refIdx[0] = pu.cs->slice->getNumRefIdx(REF_PIC_LIST_0) - 1; // last idx in the list +#endif PelUnitBuf predBufTmp = m_tmpPredStorage[REF_PIC_LIST_0].getBuf(UnitAreaRelative(*pu.cu, pu)); motionCompensation(pu, predBufTmp, REF_PIC_LIST_0); @@ -1361,9 +1365,11 @@ void InterSearch::xSetIntraSearchRange(PredictionUnit& pu, int iRoiWidth, int iR bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const int localSearchRangeX, const int localSearchRangeY, IbcHashMap& ibcHashMap) { +#if JVET_M0483_IBC==0 // check only no greater than IBC_MAX_CAND_SIZE if (cu.Y().width > IBC_MAX_CAND_SIZE || cu.Y().height > IBC_MAX_CAND_SIZE) return false; +#endif Mv cMvSrchRngLT; Mv cMvSrchRngRB; @@ -1379,13 +1385,20 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const /// ibc search pu.cu->imv = 2; AMVPInfo amvpInfo4Pel; +#if JVET_M0483_IBC + PU::fillIBCMvpCand(pu, amvpInfo4Pel); +#else PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[REF_PIC_LIST_0], amvpInfo4Pel); - +#endif pu.cu->imv = 0;// (Int)cu.cs->sps->getSpsNext().getUseIMV(); // set as IMV=0 initially Mv cMv, cMvPred[2]; AMVPInfo amvpInfo; +#if JVET_M0483_IBC + PU::fillIBCMvpCand(pu, amvpInfo); +#else PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[REF_PIC_LIST_0], amvpInfo); +#endif cMvPred[0].set(amvpInfo.mvCand[0].getHor() >> (2), amvpInfo.mvCand[0].getVer() >> (2)); // store in full pel accuracy, shift before use in search cMvPred[1].set(amvpInfo.mvCand[1].getHor() >> (2), amvpInfo.mvCand[1].getVer() >> (2)); @@ -1482,7 +1495,11 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const if (!cu.cs->sps->getSpsNext().getUseIMV()) pu.mvd[REF_PIC_LIST_0] >>= (2); +#if JVET_M0483_IBC + pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; +#else pu.refIdx[REF_PIC_LIST_0] = pu.cs->slice->getNumRefIdx(REF_PIC_LIST_0) - 1; +#endif pu.mv[REF_PIC_LIST_0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); m_ctuRecord[cu.lumaPos()][cu.lumaSize()].bvRecord[pu.bv] = cost; @@ -1995,12 +2012,16 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) for ( int iRefList = 0; iRefList < iNumPredDir; iRefList++ ) { RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); +#if JVET_M0483_IBC==0 int refPicNumber = cs.slice->getNumRefIdx(eRefPicList); if (cs.slice->getSPS()->getSpsNext().getIBCMode() && eRefPicList == REF_PIC_LIST_0) { refPicNumber--; } for (int iRefIdxTemp = 0; iRefIdxTemp < refPicNumber; iRefIdxTemp++) +#else + for (int iRefIdxTemp = 0; iRefIdxTemp < cs.slice->getNumRefIdx(eRefPicList); iRefIdxTemp++) +#endif { uiBitsTemp = uiMbBits[iRefList]; if ( cs.slice->getNumRefIdx(eRefPicList) > 1 ) @@ -2206,10 +2227,12 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) iRefStart = 0; iRefEnd = cs.slice->getNumRefIdx(eRefPicList)-1; +#if JVET_M0483_IBC==0 if (cs.slice->getSPS()->getSpsNext().getIBCMode() && eRefPicList == REF_PIC_LIST_0) { iRefEnd--; } +#endif for (int iRefIdxTemp = iRefStart; iRefIdxTemp <= iRefEnd; iRefIdxTemp++) { if( m_pcEncCfg->getUseGBiFast() && (gbiIdx != GBI_DEFAULT) @@ -4048,12 +4071,16 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, for ( int iRefList = 0; iRefList < iNumPredDir; iRefList++ ) { RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); +#if JVET_M0483_IBC==0 int refPicNumber = slice.getNumRefIdx(eRefPicList); if (slice.getSPS()->getSpsNext().getIBCMode() && eRefPicList == REF_PIC_LIST_0) { refPicNumber--; } for (int iRefIdxTemp = 0; iRefIdxTemp < refPicNumber; iRefIdxTemp++) +#else + for (int iRefIdxTemp = 0; iRefIdxTemp < slice.getNumRefIdx(eRefPicList); iRefIdxTemp++) +#endif { // Get RefIdx bits uiBitsTemp = uiMbBits[iRefList]; @@ -4571,10 +4598,12 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, iRefStart = 0; iRefEnd = slice.getNumRefIdx(eRefPicList) - 1; +#if JVET_M0483_IBC==0 if (slice.getSPS()->getSpsNext().getIBCMode() && eRefPicList == REF_PIC_LIST_0) { iRefEnd--; } +#endif for ( int iRefIdxTemp = iRefStart; iRefIdxTemp <= iRefEnd; iRefIdxTemp++ ) { if ( pu.cu->affineType == AFFINEMODEL_6PARAM && refIdx4Para[iRefList] != iRefIdxTemp ) @@ -6022,7 +6051,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par CompArea tmpArea(COMPONENT_Y, areaY.chromaFormat, Position(0, 0), areaY.size()); PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea); tmpPred.copyFrom(piPredY); +#if JVET_M0483_IBC + if (!cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#else if (!cu.firstPU->mhIntraFlag && !cu.ibc) +#endif tmpPred.rspSignal(m_pcReshape->getFwdLUT()); const Pel avgLuma = tmpPred.computeAvg(); int adj = m_pcReshape->calculateChromaAdj(avgLuma); @@ -6545,7 +6578,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa { cs.getRecoBuf().copyFrom(cs.getPredBuf() ); #if JVET_M0427_INLOOP_RESHAPER +#if JVET_M0483_IBC + if (m_pcEncCfg->getReshaper() && (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag()) && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#else if (m_pcEncCfg->getReshaper() && (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag()) && !cu.firstPU->mhIntraFlag && !cu.ibc) +#endif { cs.getRecoBuf().Y().rspSignal(m_pcReshape->getFwdLUT()); } @@ -6604,6 +6641,14 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa PredictionUnit &pu = *cs.getPU( partitioner.chType ); m_CABACEstimator->cu_skip_flag ( cu ); +#if JVET_M0483_IBC + if (CU::isIBC(cu)) + { + m_CABACEstimator->merge_idx(pu); + } + else + { +#endif m_CABACEstimator->subblock_merge_flag( cu ); m_CABACEstimator->triangle_mode ( cu ); if (cu.mmvdSkip) @@ -6612,7 +6657,9 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa } else m_CABACEstimator->merge_idx ( pu ); - +#if JVET_M0483_IBC + } +#endif cs.dist = distortion; cs.fracBits = m_CABACEstimator->getEstFracBits(); @@ -6633,7 +6680,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea); tmpPred.copyFrom(cs.getPredBuf(COMPONENT_Y)); +#if JVET_M0483_IBC + if (!cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#else if (!cu.firstPU->mhIntraFlag && !cu.ibc) +#endif tmpPred.rspSignal(m_pcReshape->getFwdLUT()); cs.getResiBuf(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT()); cs.getResiBuf(COMPONENT_Y).subtract(tmpPred); @@ -6736,7 +6787,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea); tmpPred.copyFrom(cs.getPredBuf(COMPONENT_Y)); +#if JVET_M0483_IBC + if (!cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#else if (!cu.firstPU->mhIntraFlag && !cu.ibc) +#endif tmpPred.rspSignal(m_pcReshape->getFwdLUT()); cs.getRecoBuf(COMPONENT_Y).reconstruct(tmpPred, cs.getResiBuf(COMPONENT_Y), cs.slice->clpRng(COMPONENT_Y)); @@ -6746,7 +6801,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa #endif cs.getRecoBuf().bufs[0].reconstruct(cs.getPredBuf().bufs[0], cs.getResiBuf().bufs[0], cs.slice->clpRngs().comp[0]); #if JVET_M0427_INLOOP_RESHAPER +#if JVET_M0483_IBC + if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !CU::isIBC(cu)) +#else if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() && !cu.firstPU->mhIntraFlag && !cu.ibc) +#endif { cs.getRecoBuf().bufs[0].rspSignal(m_pcReshape->getFwdLUT()); } diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index d7279af9ba3e7080967cff8c90a29065ceec1230..6c82913cd89e7cab4d6ca706e3fb066d6ccc1b29 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -1378,7 +1378,11 @@ void IntraSearch::xEncIntraHeader(CodingStructure &cs, Partitioner &partitioner, // CU header if( isFirst ) { +#if JVET_M0483_IBC + if ((!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag()) +#else if( !cs.slice->isIntra() +#endif && cu.Y().valid() ) { diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 743c3b4e7ff6e27d1fb5457507ea6cba78311a32..248ee6db4253939623ff5f674a122e333e233592 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -561,7 +561,9 @@ void HLSWriter::codeSPSNext( const SPSNext& spsNext, const bool usePCM ) WRITE_FLAG( spsNext.getUseAffineType() ? 1 : 0, "affine_type_flag" ); } WRITE_FLAG( spsNext.getUseGBi() ? 1 : 0, "gbi_flag" ); +#if JVET_M0483_IBC==0 WRITE_FLAG(spsNext.getIBCMode() ? 1 : 0, "ibc_flag" ); +#endif for( int k = 0; k < SPSNext::NumReservedFlags; k++ ) { WRITE_FLAG( 0, "reserved_flag" ); @@ -659,6 +661,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_FLAG(pcSPS->getNoLadfConstraintFlag() ? 1 : 0, "no_ladf_constraint_flag"); WRITE_FLAG(pcSPS->getNoDepQuantConstraintFlag() ? 1 : 0, "no_dep_quant_constraint_flag"); WRITE_FLAG(pcSPS->getNoSignDataHidingConstraintFlag() ? 1 : 0, "no_sign_data_hiding_constraint_flag"); +#if JVET_M0483_IBC + WRITE_FLAG(pcSPS->getIBCFlag() ? 1 : 0, "ibc_flag"); +#endif #if ENABLE_TRACING xTraceSPSHeader (); #endif @@ -1320,10 +1325,19 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) } } } +#if JVET_M0483_IBC + if (!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag()) + { + CHECK(pcSlice->getMaxNumMergeCand() > MRG_MAX_NUM_CANDS, "More merge candidates signalled than supported"); + WRITE_UVLC(MRG_MAX_NUM_CANDS - pcSlice->getMaxNumMergeCand(), "six_minus_max_num_merge_cand"); + } +#endif if( !pcSlice->isIntra() ) { +#if JVET_M0483_IBC==0 CHECK( pcSlice->getMaxNumMergeCand() > MRG_MAX_NUM_CANDS, "More merge candidates signalled than supported" ); WRITE_UVLC( MRG_MAX_NUM_CANDS - pcSlice->getMaxNumMergeCand(), "six_minus_max_num_merge_cand" ); +#endif if ( pcSlice->getSPS()->getSBTMVPEnabledFlag() && !pcSlice->getSPS()->getSpsNext().getUseAffine() ) // ATMVP only {