From cf0eff9f2703021554da39d264c591b12d563c37 Mon Sep 17 00:00:00 2001 From: Yu Han <yuhan@qti.qualcomm.com> Date: Tue, 29 Jan 2019 17:30:53 -0800 Subject: [PATCH] Add IBC from VTM3.0 to master --- source/Lib/CommonLib/CodingStructure.cpp | 12 + source/Lib/CommonLib/ContextModelling.cpp | 22 + source/Lib/CommonLib/ContextModelling.h | 3 + source/Lib/CommonLib/Contexts.cpp | 15 + source/Lib/CommonLib/Contexts.h | 3 + source/Lib/CommonLib/InterPrediction.cpp | 27 +- source/Lib/CommonLib/MotionInfo.h | 15 + source/Lib/CommonLib/Slice.cpp | 82 ++- source/Lib/CommonLib/Slice.h | 8 +- source/Lib/CommonLib/TypeDef.h | 20 + source/Lib/CommonLib/Unit.cpp | 4 + source/Lib/CommonLib/Unit.h | 2 + source/Lib/CommonLib/UnitTools.cpp | 730 +++++++++++++++++++++- source/Lib/CommonLib/UnitTools.h | 18 + source/Lib/DecoderLib/CABACReader.cpp | 203 ++++++ source/Lib/DecoderLib/DecCu.cpp | 64 ++ source/Lib/DecoderLib/DecLib.cpp | 2 + source/Lib/DecoderLib/VLCReader.cpp | 11 + source/Lib/EncoderLib/CABACWriter.cpp | 156 +++++ source/Lib/EncoderLib/EncCu.cpp | 102 ++- source/Lib/EncoderLib/EncGOP.cpp | 10 + source/Lib/EncoderLib/EncLib.cpp | 2 + source/Lib/EncoderLib/EncModeCtrl.cpp | 41 +- source/Lib/EncoderLib/EncModeCtrl.h | 3 + source/Lib/EncoderLib/EncSlice.cpp | 4 + source/Lib/EncoderLib/InterSearch.cpp | 46 +- source/Lib/EncoderLib/IntraSearch.cpp | 4 + source/Lib/EncoderLib/VLCWriter.cpp | 9 + 28 files changed, 1600 insertions(+), 18 deletions(-) diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp index 8d5013fcc1..dfbc5b4cb0 100644 --- a/source/Lib/CommonLib/CodingStructure.cpp +++ b/source/Lib/CommonLib/CodingStructure.cpp @@ -746,7 +746,11 @@ void CodingStructure::useSubStructure( const CodingStructure& subStruct, const C if( cpyResi ) picture->getResiBuf( clippedArea ).copyFrom( subResiBuf ); if( cpyReco ) picture->getRecoBuf( clippedArea ).copyFrom( subRecoBuf ); +#if IBC_SEPERATE_MODE + if (!subStruct.m_isTuEnc && ((!slice->isIntra() || slice->getSPS()->getSpsNext().getIBCMode()) && 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 ); @@ -926,7 +930,11 @@ void CodingStructure::copyStructure( const CodingStructure& other, const Channel pu = *ppu; } +#if IBC_SEPERATE_MODE + if (!other.slice->isIntra() || other.slice->getSPS()->getSpsNext().getIBCMode()) +#else if( !other.slice->isIntra() ) +#endif { // copy motion buffer MotionBuf ownMB = getMotionBuf(); @@ -981,7 +989,11 @@ void CodingStructure::initStructData( const int &QP, const bool &_isLosses, cons isLossless = _isLosses; } +#if IBC_SEPERATE_MODE + if (!skipMotBuf && (!parent || ((!slice->isIntra() || slice->getSPS()->getSpsNext().getIBCMode()) && !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 d52ea51e00..134d430ff5 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -451,6 +451,20 @@ unsigned DeriveCtx::CtxPredModeFlag( const CodingUnit& cu ) } #endif +#if IBC_SEPERATE_MODE +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" ); @@ -470,12 +484,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 IBC_SEPERATE_MODE // remove macro VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE + if (CU::isIBC(*pu.cu)) + { + pu.bv = pu.mv[REF_PIC_LIST_0]; + pu.bv >>= (2 + MV_FRACTIONAL_BITS_DIFF); // 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 4f2c0d9032..d726c25888 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -317,6 +317,9 @@ unsigned CtxTriangleFlag( const CodingUnit& cu ); #if JVET_M0502_PRED_MODE_CTX unsigned CtxPredModeFlag( const CodingUnit& cu ); #endif +#if IBC_SEPERATE_MODE +unsigned CtxIBCFlag(const CodingUnit& cu); +#endif } #endif // __CONTEXTMODELLING__ diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp index 5dd621fe0a..db264e715a 100644 --- a/source/Lib/CommonLib/Contexts.cpp +++ b/source/Lib/CommonLib/Contexts.cpp @@ -1326,6 +1326,21 @@ const CtxSet ContextSetCfg::TriangleIdx = ContextSetCfg::addCtxSet }); // clang-format on +#if IBC_SEPERATE_MODE +const CtxSet ContextSetCfg::IBCFlag = ContextSetCfg::addCtxSet +({ +#if TRAINED_CABAC_INIT_TABLES + { 165, 137, 153, }, + { 106, 122, 138, }, + { CNU, CNU, CNU, }, +#else + { 151, 137, 154, }, + { 151, 137, 154, }, + { 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 fcc59f0152..261f6c4186 100644 --- a/source/Lib/CommonLib/Contexts.h +++ b/source/Lib/CommonLib/Contexts.h @@ -306,6 +306,9 @@ public: static const CtxSet TriangleIdx; #if JVET_M0444_SMVD static const CtxSet SmvdFlag; +#endif +#if IBC_SEPERATE_MODE + static const CtxSet IBCFlag; #endif static const unsigned NumberOfContexts; diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 629426aa7c..ff6634136d 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -375,7 +375,11 @@ void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList& int iRefIdx = pu.refIdx[eRefPicList]; Mv mv[3]; bool isIBC = false; +#if IBC_SEPERATE_MODE + if (CU::isIBC(*pu.cu)) +#else if (pu.cs->slice->getRefPic(eRefPicList, iRefIdx)->getPOC() == pu.cs->slice->getPOC()) +#endif { isIBC = true; } @@ -411,11 +415,27 @@ void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList& } else { +#if IBC_SEPERATE_MODE + 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 } } } @@ -468,7 +488,12 @@ void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred) RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); +#if IBC_SEPERATE_MODE + CHECK(pu.refIdx[refList] > slice.getNumRefIdx(eRefPicList), "Invalid reference index"); + 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/MotionInfo.h b/source/Lib/CommonLib/MotionInfo.h index 2078892974..4093475c21 100644 --- a/source/Lib/CommonLib/MotionInfo.h +++ b/source/Lib/CommonLib/MotionInfo.h @@ -101,19 +101,31 @@ struct MvField struct MotionInfo { bool isInter; +#if IBC_SEPERATE_MODE + 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 IBC_SEPERATE_MODE + MotionInfo() : isInter(false), isIBCmot(false), interDir(0), sliceIdx(0), refIdx{ NOT_VALID, NOT_VALID } { } + // ensure that MotionInfo(0) produces '\x000....' bit pattern - needed to work with AreaBuf - don't use this constructor for anything 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'"); } +#else MotionInfo() : isInter( false ), interDir( 0 ), sliceIdx( 0 ), refIdx{ NOT_VALID, NOT_VALID } { } // ensure that MotionInfo(0) produces '\x000....' bit pattern - needed to work with AreaBuf - don't use this constructor for anything 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 bool operator==( const MotionInfo& mi ) const { if( isInter != mi.isInter ) return false; +#if IBC_SEPERATE_MODE + if (isIBCmot != mi.isIBCmot) return false; +#endif if( isInter ) { if( sliceIdx != mi.sliceIdx ) return false; @@ -211,5 +223,8 @@ struct LutMotionCand { MotionInfo* motionCand; int currCnt; +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + int currCntIBC; +#endif }; #endif // __MOTIONINFO__ diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 00f16676bc..61ae73d43b 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -435,6 +435,7 @@ void Slice::setRefPicList( PicList& rcListPic, bool checkNumPocTotalCurr, bool b pcRefPic = xGetLongTermRefPic(rcListPic, m_pRPS->getPOC(i), m_pRPS->getCheckLTMSBPresent(i)); } } +#if IBC_SEPERATE_MODE==0 if (getSPS()->getSpsNext().getIBCMode()) { RefPicSetLtCurr[NumPicLtCurr] = getPic(); @@ -442,6 +443,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]; @@ -454,11 +456,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 IBC_SEPERATE_MODE==0 if (getSPS()->getSpsNext().getIBCMode()) { CHECK(numPicTotalCurr != 1, "Invalid state"); } else +#endif CHECK(numPicTotalCurr != 0, "Invalid state"); } @@ -529,11 +533,13 @@ void Slice::setRefPicList( PicList& rcListPic, bool checkNumPocTotalCurr, bool b m_bIsUsedAsLongTerm[REF_PIC_LIST_1][rIdx] = ( cIdx >= NumPicStCurr0 + NumPicStCurr1 ); } } +#if IBC_SEPERATE_MODE==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) @@ -1612,14 +1618,28 @@ void Slice::initMotionLUTs() { m_MotionCandLut = new LutMotionCand; m_MotionCandLut->currCnt = 0; +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + m_MotionCandLut->currCntIBC = 0; +#endif m_MotionCandLut->motionCand = nullptr; +#if IBC_SEPERATE_MODE + 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 IBC_SEPERATE_MODE_AND_MER && IBC_SEPERATE_MODE_REDUCTION==0 + m_MotionCandLuTsBkup->currCntIBC = 0; +#endif m_MotionCandLuTsBkup->motionCand = nullptr; +#if IBC_SEPERATE_MODE_AND_MER + 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() { @@ -1637,8 +1657,14 @@ void Slice::destroyMotionLUTs() void Slice::resetMotionLUTs() { m_MotionCandLut->currCnt = 0; +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + m_MotionCandLut->currCntIBC = 0; +#endif #if JVET_M0170_MRG_SHARELIST m_MotionCandLuTsBkup->currCnt = 0; +#if IBC_SEPERATE_MODE_AND_MER && IBC_SEPERATE_MODE_REDUCTION==0 + m_MotionCandLuTsBkup->currCntIBC = 0; +#endif #endif } @@ -1653,8 +1679,46 @@ MotionInfo Slice::getMotionInfoFromLUTBkup(int MotCandIdx) const } #endif +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 +void Slice::addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi, bool ibcflag) +#else void Slice::addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi) +#endif { +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + 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; @@ -1678,6 +1742,7 @@ void Slice::addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi) { memcpy(&lutMC->motionCand[lutMC->currCnt++], &newMi, sizeof(MotionInfo)); } +#endif } void Slice::updateMotionLUTs(LutMotionCand* lutMC, CodingUnit & cu) @@ -1686,19 +1751,34 @@ void Slice::updateMotionLUTs(LutMotionCand* lutMC, CodingUnit & cu) if (cu.affine) { return; } if (cu.triangle) { return; } - MotionInfo newMi = selectedPU->getMotionInfo(); + MotionInfo newMi = selectedPU->getMotionInfo(); +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + 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 IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + 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 IBC_SEPERATE_MODE + if (getSPS()->getSpsNext().getIBCMode()) + { + minPicDist = 0; + } + else +#endif if( ! isIntra() ) { const int currPOC = getPOC(); diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 05b8ea8f04..84e2cb998c 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1949,6 +1949,9 @@ public: void initMotionLUTs (); void destroyMotionLUTs (); void resetMotionLUTs(); +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + 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; } @@ -1957,8 +1960,11 @@ public: MotionInfo getMotionInfoFromLUTs(int MotCandIdx) const; LutMotionCand* getMotionLUTs() { return m_MotionCandLut; } - +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + 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 0add5d415e..6db76d61dd 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,21 @@ #include <assert.h> #include <cassert> +#define JVET_M0483_IBC 1 // +#if JVET_M0483_IBC +#define IBC_SEPERATE_MODE 1 //JVET-M0483_method3 +#define IBC_SEPERATE_MODE_FIX 1 //JVET-M0483_method3 bug fix ticket 129 and 140 +#define IBC_SEPERATE_MODE_REDUCTION 0 +#define IBC_SIZE_CONSTRAINT 0 +#define IBC_SEPERATE_FUNCTION 1 + +#define CLEAN_getInterMergeCandidates 1 +#define CLEAN_fillMvpCand 1 +#define MODIFY_for_vtm4 1 +#define IBC_SEPERATE_MODE_AND_MER 1 +#define DEBUG_M0483 1 +#endif + #define JVET_M0145_AFFINE_MV_CLIP 1 // Missing clipping for MV storage in affine #define JVET_M0381_ONE_CTX_FOR_SUBBLOCK_MRG_IDX 1 // CE2.2.2 a: one context for subblock Merge index @@ -443,7 +458,12 @@ enum PredMode { MODE_INTER = 0, ///< inter-prediction mode MODE_INTRA = 1, ///< intra-prediction mode +#if IBC_SEPERATE_MODE + 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 ecaf89ca16..7d586a2283 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -277,7 +277,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other ) shareParentPos = other.shareParentPos; shareParentSize = other.shareParentSize; #endif +#if IBC_SEPERATE_MODE==0 ibc = other.ibc; +#endif #if JVET_M0444_SMVD smvdMode = other.smvdMode; #endif @@ -319,7 +321,9 @@ void CodingUnit::initData() shareParentSize.width = -1; shareParentSize.height = -1; #endif +#if IBC_SEPERATE_MODE==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 4eb057dde4..fae1f4f6d0 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -316,7 +316,9 @@ struct CodingUnit : public UnitArea Position shareParentPos; Size shareParentSize; #endif +#if IBC_SEPERATE_MODE ==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 0559434c4c..a093910d45 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -78,6 +78,13 @@ bool CU::isInter(const CodingUnit &cu) return cu.predMode == MODE_INTER; } +#if IBC_SEPERATE_MODE +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); @@ -711,7 +718,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 IBC_SEPERATE_MODE==0 , int mmvdList +#endif +#if IBC_SEPERATE_MODE&& IBC_SEPERATE_MODE_REDUCTION==0 + , bool ibc_flag +#endif #if JVET_M0170_MRG_SHARELIST , bool isShared #endif @@ -723,7 +735,9 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter ) #endif { +#if IBC_SEPERATE_MODE==0 int mrgCandIdxIBC = mrgCandIdx; +#endif MotionInfo miNeighbor; bool hasPruned[MRG_MAX_NUM_CANDS]; memset(hasPruned, 0, MRG_MAX_NUM_CANDS * sizeof(bool)); @@ -732,17 +746,35 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter hasPruned[subPuMvpPos] = true; } #if JVET_M0170_MRG_SHARELIST +#if IBC_SEPERATE_MODE_AND_MER && IBC_SEPERATE_MODE_REDUCTION==0 // Todo: remove int num_avai_candInLUT = (isShared ? slice.getAvailableLUTBkupMrgNum() : slice.getAvailableLUTMrgNum()); + int offset = ibc_flag ? MAX_NUM_HMVP_CANDS : 0; +#else + int num_avai_candInLUT = (isShared ? slice.getAvailableLUTBkupMrgNum() : slice.getAvailableLUTMrgNum()); +#endif +#else +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + int num_avai_candInLUT = ibc_flag ? slice.getAvailableLUTIBCMrgNum() : slice.getAvailableLUTMrgNum(); + int offset = ibc_flag ? 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 IBC_SEPERATE_MODE_AND_MER && IBC_SEPERATE_MODE_REDUCTION==0//Todo: remove miNeighbor = 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 IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + miNeighbor = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx + offset); #else miNeighbor = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx); +#endif #endif mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); @@ -755,6 +787,7 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter #if !JVET_L0090_PAIR_AVG isCandInter[cnt] = true; #endif +#if IBC_SEPERATE_MODE==0 if (miNeighbor.interDir == 1 && slice.getRefPic(REF_PIC_LIST_0, miNeighbor.refIdx[0])->getPOC() == slice.getPOC()) { mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC; @@ -762,6 +795,9 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter mrgCandIdxIBC++; } if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return true; } @@ -775,6 +811,293 @@ bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter return false; } +#if IBC_SEPERATE_FUNCTION +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 << 1)].refIdx = NOT_VALID; + mrgCtx.mvFieldNeighbours[(ui << 1) + 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 IBC_SEPERATE_MODE_REDUCTION + if (cnt != maxNumMergeCandMin1 && pu.cu->predMode == MODE_INTER) +#else + if (cnt != maxNumMergeCandMin1) +#endif + { + bool isAvailableSubPu = false; + unsigned subPuMvpPos = 0; + +#if JVET_L0090_PAIR_AVG +#if MODIFY_for_vtm4 +#if JVET_M0170_MRG_SHARELIST + bool isShared = ((pu.Y().lumaSize().width != pu.shareParentSize.width) || (pu.Y().lumaSize().height != pu.shareParentSize.height)); +#endif +#endif + bool bFound = addMergeHMVPCand(slice, mrgCtx, canFastExit + , mrgCandIdx + , maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + , true +#endif +#if MODIFY_for_vtm4 +#if JVET_M0170_MRG_SHARELIST + , isShared +#endif +#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 IBC_SEPERATE_MODE_REDUCTION + if (pu.cu->predMode == MODE_INTER) +#endif + { + 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]; + + mrgCtx.mvFieldNeighbours[cnt * 2].setMvField(Mv(0, 0), NOT_VALID); + mrgCtx.mvFieldNeighbours[cnt * 2 + 1].setMvField(Mv(0, 0), NOT_VALID); + // calculate average MV for L0 and L1 seperately + unsigned char interDir = 0; + + for (int refListId = 0; refListId < 1; refListId++) + { + const short refIdxI = mrgCtx.mvFieldNeighbours[i * 2 + refListId].refIdx; + const short refIdxJ = mrgCtx.mvFieldNeighbours[j * 2 + refListId].refIdx; + + // both MVs are invalid, skip + if ((refIdxI == NOT_VALID) && (refIdxJ == NOT_VALID)) + { + continue; + } + + interDir += 1 << refListId; + // both MVs are valid, average these two MVs + if ((refIdxI != NOT_VALID) && (refIdxJ != NOT_VALID)) + { + const Mv& MvI = mrgCtx.mvFieldNeighbours[i * 2 + refListId].mv; + const Mv& MvJ = mrgCtx.mvFieldNeighbours[j * 2 + refListId].mv; + + // average two MVs + Mv avgMv = MvI; + + avgMv += MvJ; + mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_IBC; + avgMv.setHor(avgMv.getHor() / 2); + avgMv.setVer(avgMv.getVer() / 2); + avgMv.setHor((avgMv.getHor() / 16) << 4); + avgMv.setVer((avgMv.getVer() / 16) << 4); + mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField(avgMv, refIdxI); + } + } + mrgCtx.interDirNeighbours[cnt] = interDir; + if (interDir > 0) + { + 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 ) @@ -796,7 +1119,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, #endif mrgCtx.GBiIdx[ui] = GBI_DEFAULT; mrgCtx.interDirNeighbours[ui] = 0; +#if IBC_SEPERATE_MODE && CLEAN_getInterMergeCandidates==0 + mrgCtx.mrgTypeNeighbours[ui] = CU::isIBC(*pu.cu) ? MRG_TYPE_IBC : MRG_TYPE_DEFAULT_N; +#else mrgCtx.mrgTypeNeighbours [ui] = MRG_TYPE_DEFAULT_N; +#endif mrgCtx.mvFieldNeighbours[(ui << 1) ].refIdx = NOT_VALID; mrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; } @@ -806,8 +1133,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, int cnt = 0; - +#if IBC_SEPERATE_MODE==0 int mrgCandIdxIBC = mrgCandIdx; +#endif #if JVET_M0170_MRG_SHARELIST const Position posLT = pu.shareParentPos; @@ -823,7 +1151,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, //left const PredictionUnit* puLeft = cs.getPURestricted( posLB.offset( -1, 0 ), pu, pu.chType ); +#if IBC_SEPERATE_MODE + const bool isAvailableA1 = puLeft && isDiffMER(pu, *puLeft) && pu.cu != puLeft->cu && (puLeft->cu->predMode == pu.cu->predMode); +#else const bool isAvailableA1 = puLeft && isDiffMER( pu, *puLeft ) && pu.cu != puLeft->cu && CU::isInter( *puLeft->cu ); +#endif if( isAvailableA1 ) { @@ -837,19 +1169,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 IBC_SEPERATE_MODE==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 IBC_SEPERATE_MODE==0 if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return; } @@ -867,7 +1205,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, // above const PredictionUnit *puAbove = cs.getPURestricted( posRT.offset( 0, -1 ), pu, pu.chType ); +#if IBC_SEPERATE_MODE + bool isAvailableB1 = puAbove && isDiffMER(pu, *puAbove) && pu.cu != puAbove->cu && puAbove->cu->predMode == pu.cu->predMode; +#else bool isAvailableB1 = puAbove && isDiffMER( pu, *puAbove ) && pu.cu != puAbove->cu && CU::isInter( *puAbove->cu ); +#endif if( isAvailableB1 ) { @@ -883,19 +1225,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 IBC_SEPERATE_MODE==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 IBC_SEPERATE_MODE==0 if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return; } @@ -913,7 +1261,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, // above right const PredictionUnit *puAboveRight = cs.getPURestricted( posRT.offset( 1, -1 ), pu, pu.chType ); +#if IBC_SEPERATE_MODE + bool isAvailableB0 = puAboveRight && isDiffMER(pu, *puAboveRight) && (puAboveRight->cu->predMode == pu.cu->predMode); +#else bool isAvailableB0 = puAboveRight && isDiffMER( pu, *puAboveRight ) && CU::isInter( *puAboveRight->cu ); +#endif if( isAvailableB0 ) { @@ -933,12 +1285,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 IBC_SEPERATE_MODE==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() ) @@ -946,7 +1300,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAboveRight.mv[1], miAboveRight.refIdx[1] ); } +#if IBC_SEPERATE_MODE==0 if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return; } @@ -963,7 +1321,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, //left bottom const PredictionUnit *puLeftBottom = cs.getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType ); +#if IBC_SEPERATE_MODE + bool isAvailableA0 = puLeftBottom && isDiffMER(pu, *puLeftBottom) && (puLeftBottom->cu->predMode == pu.cu->predMode); +#else bool isAvailableA0 = puLeftBottom && isDiffMER( pu, *puLeftBottom ) && CU::isInter( *puLeftBottom->cu ); +#endif if( isAvailableA0 ) { @@ -983,12 +1345,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 IBC_SEPERATE_MODE==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() ) @@ -996,7 +1360,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miBelowLeft.mv[1], miBelowLeft.refIdx[1] ); } +#if IBC_SEPERATE_MODE==0 if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return; } @@ -1016,7 +1384,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, { const PredictionUnit *puAboveLeft = cs.getPURestricted( posLT.offset( -1, -1 ), pu, pu.chType ); +#if IBC_SEPERATE_MODE + bool isAvailableB2 = puAboveLeft && isDiffMER(pu, *puAboveLeft) && (puAboveLeft->cu->predMode == pu.cu->predMode); +#else bool isAvailableB2 = puAboveLeft && isDiffMER( pu, *puAboveLeft ) && CU::isInter( *puAboveLeft->cu ); +#endif if( isAvailableB2 ) { @@ -1036,12 +1408,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 IBC_SEPERATE_MODE==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() ) @@ -1049,7 +1423,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAboveLeft.mv[1], miAboveLeft.refIdx[1] ); } +#if IBC_SEPERATE_MODE==0 if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return; } @@ -1064,7 +1442,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, return; } +#if IBC_SEPERATE_MODE_REDUCTION && CLEAN_getInterMergeCandidates==0 + if (slice.getEnableTMVPFlag() && pu.cu->predMode == MODE_INTER) +#else if (slice.getEnableTMVPFlag()) +#endif { //>> MTK colocated-RightBottom // offset the pos to be sure to "point" to the same position the uiAbsPartIdx would've pointed to @@ -1150,7 +1532,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, if( dir != 0 ) { +#if IBC_SEPERATE_MODE + bool addTMvp = !CU::isIBC(*pu.cu); +#else bool addTMvp = true; +#endif #if HM_JEM_MERGE_CANDS int iSpanCand = cnt; for( int i = 0; i < iSpanCand; i++ ) @@ -1170,7 +1556,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, isCandInter [uiArrayAddr] = true; #endif mrgCtx.GBiIdx[uiArrayAddr] = GBI_DEFAULT; +#if IBC_SEPERATE_MODE==0 if (mrgCandIdxIBC == cnt && canFastExit) +#else + if (mrgCandIdx == cnt && canFastExit) +#endif { return; } @@ -1187,7 +1577,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, } int maxNumMergeCandMin1 = maxNumMergeCand - 1; +#if IBC_SEPERATE_MODE_REDUCTION && CLEAN_getInterMergeCandidates==0 + if (cnt != maxNumMergeCandMin1 && pu.cu->predMode == MODE_INTER) +#else if (cnt != maxNumMergeCandMin1) +#endif { bool isAvailableSubPu = false; unsigned subPuMvpPos = 0; @@ -1196,9 +1590,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 IBC_SEPERATE_MODE==0 , (mmvdList != 0 && mrgCandIdx != -1) ? (const int) mrgCandIdxIBC : mrgCandIdx +#else + , mrgCandIdx +#endif , maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos +#if IBC_SEPERATE_MODE==0 , mmvdList +#endif +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + , CU::isIBC(*pu.cu) +#endif #if JVET_M0170_MRG_SHARELIST , isShared #endif @@ -1218,6 +1621,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, #if JVET_L0090_PAIR_AVG // pairwise-average candidates +#if IBC_SEPERATE_MODE_REDUCTION && CLEAN_getInterMergeCandidates==0 + if (pu.cu->predMode == MODE_INTER) +#endif { const int cutoff = std::min( cnt, 4 ); const int end = cutoff * (cutoff - 1) / 2; @@ -1353,7 +1759,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, int r = 0; int refcnt = 0; +#if IBC_SEPERATE_MODE && CLEAN_getInterMergeCandidates==0 + while (uiArrayAddr < maxNumMergeCand && CU::isIBC(*pu.cu) == false) +#else while (uiArrayAddr < maxNumMergeCand) +#endif { #if !JVET_L0090_PAIR_AVG isCandInter [uiArrayAddr ] = true; @@ -1584,7 +1994,17 @@ bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList { return false; } +#if IBC_SEPERATE_MODE//Todo: really need? + if (mi.isIBCmot) + { + return false; + } +#endif +#if IBC_SEPERATE_MODE + 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; } @@ -1687,7 +2107,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 IBC_SEPERATE_MODE + left = (neibLeftPU) ? CU::isIBC(*neibLeftPU->cu) : 0; +#else left = (neibLeftPU) ? neibLeftPU->cu->ibc : 0; +#endif if (left) { @@ -1699,7 +2123,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 IBC_SEPERATE_MODE + above = (neibAbovePU) ? CU::isIBC(*neibAbovePU->cu) : 0; +#else above = (neibAbovePU) ? neibAbovePU->cu->ibc : 0; +#endif if (above) { @@ -1711,7 +2139,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 IBC_SEPERATE_MODE + unsigned int belowLeft = (neibBelowLeftPU) ? CU::isIBC(*neibBelowLeftPU->cu) : 0; +#else unsigned int belowLeft = (neibBelowLeftPU) ? neibBelowLeftPU->cu->ibc : 0; +#endif if (belowLeft) { @@ -1724,7 +2156,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 IBC_SEPERATE_MODE + unsigned int aboveRight = (neibAboveRightPU) ? CU::isIBC(*neibAboveRightPU->cu) : 0; +#else unsigned int aboveRight = (neibAboveRightPU) ? neibAboveRightPU->cu->ibc : 0; +#endif if (aboveRight) { @@ -1737,7 +2173,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 IBC_SEPERATE_MODE + unsigned int aboveLeft = (neibAboveLeftPU) ? CU::isIBC(*neibAboveLeftPU->cu) : 0; +#else unsigned int aboveLeft = (neibAboveLeftPU) ? neibAboveLeftPU->cu->ibc : 0; +#endif if (aboveLeft) { @@ -1765,7 +2205,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 IBC_SEPERATE_MODE + bool isIBC = (neibRefPU) ? CU::isIBC(*neibRefPU->cu) : 0; +#else bool isIBC = (neibRefPU) ? neibRefPU->cu->ibc : 0; +#endif if (isIBC) { derivedMv = neibRefPU->bv; @@ -1773,6 +2217,168 @@ bool PU::getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv) } return isIBC; } + +#if IBC_SEPERATE_FUNCTION +/** Constructs a list of candidates for IBC AMVP (See specification, section "Derivation process for motion vector predictor candidates") +* \param uiPartIdx +* \param uiPartAddr +* \param eRefPicList +* \param iRefIdx +* \param pInfo +*/ +void PU::fillIBCMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AMVPInfo &amvpInfo) +{ + CodingStructure &cs = *pu.cs; + + AMVPInfo *pInfo = &amvpInfo; + + pInfo->numCand = 0; + + if (refIdx < 0) + { + return; + } + + //-- 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 bAdded = addMVPCandUnscaled(pu, eRefPicList, refIdx, posLB, MD_BELOW_LEFT, *pInfo); + + if (!bAdded) + { + bAdded = addMVPCandUnscaled(pu, eRefPicList, refIdx, posLB, MD_LEFT, *pInfo); + } + } + + // Above predictor search + { + bool bAdded = addMVPCandUnscaled(pu, eRefPicList, refIdx, posRT, MD_ABOVE_RIGHT, *pInfo); + + if (!bAdded) + { + bAdded = addMVPCandUnscaled(pu, eRefPicList, refIdx, posRT, MD_ABOVE, *pInfo); + + if (!bAdded) + { + addMVPCandUnscaled(pu, eRefPicList, refIdx, posLT, MD_ABOVE_LEFT, *pInfo); + } + } + } + + if (pu.cu->imv != 0) + { +#if MODIFY_for_vtm4==0 + unsigned imvShift = pu.cu->imv << 1; +#if REMOVE_MV_ADAPT_PREC + imvShift += VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE; +#endif +#endif + for (int i = 0; i < pInfo->numCand; i++) + { +#if MODIFY_for_vtm4 + pInfo->mvCand[i].roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv); +#else + roundMV(pInfo->mvCand[i], imvShift); +#endif + } + } + + if (pInfo->numCand == 2) + { + if (pInfo->mvCand[0] == pInfo->mvCand[1]) + { + pInfo->numCand = 1; + } + } + + if (pInfo->numCand < AMVP_MAX_NUM_CANDS) + { +#if IBC_SEPERATE_MODE + const int currRefPOC = CU::isIBC(*pu.cu) ? cs.slice->getPOC() : cs.slice->getRefPic(eRefPicList, refIdx)->getPOC(); +#else + const int currRefPOC = cs.slice->getRefPic(eRefPicList, refIdx)->getPOC(); +#endif + const RefPicList eRefPicList2nd = (eRefPicList == REF_PIC_LIST_0) ? REF_PIC_LIST_1 : REF_PIC_LIST_0; + addAMVPHMVPCand(pu, eRefPicList, eRefPicList2nd, currRefPOC, *pInfo, pu.cu->imv); + } + + if (pInfo->numCand > AMVP_MAX_NUM_CANDS) + { + pInfo->numCand = AMVP_MAX_NUM_CANDS; + } + + while (pInfo->numCand < AMVP_MAX_NUM_CANDS) + { +#if !REMOVE_MV_ADAPT_PREC && MODIFY_for_vtm4==0 + const bool prec = pInfo->mvCand[pInfo->numCand].highPrec; + pInfo->mvCand[pInfo->numCand] = Mv(0, 0, prec); +#else + pInfo->mvCand[pInfo->numCand] = Mv(0, 0); +#endif + pInfo->numCand++; + } +#if !REMOVE_MV_ADAPT_PREC && MODIFY_for_vtm4==0 + if (pu.cs->sps->getSpsNext().getUseHighPrecMv()) + { +#endif + for (Mv &mv : pInfo->mvCand) + { +#if MODIFY_for_vtm4//Todo : check + mv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER); + mv.roundToAmvrSignalPrecision(MV_PRECISION_QUARTER, pu.cu->imv); +#else +#if REMOVE_MV_ADAPT_PREC + const int nShift = VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE; + const int nOffset = 1 << (nShift - 1); + mv.hor = mv.hor >= 0 ? (mv.hor + nOffset) >> nShift : -((-mv.hor + nOffset) >> nShift); + mv.ver = mv.ver >= 0 ? (mv.ver + nOffset) >> nShift : -((-mv.ver + nOffset) >> nShift); +#else + if (mv.highPrec) mv.setLowPrec(); +#endif +#endif + } +#if !REMOVE_MV_ADAPT_PREC && MODIFY_for_vtm4==0 + } +#endif +#if MODIFY_for_vtm4==0//Todo : check + if (pu.cu->imv != 0) + { + unsigned imvShift = pu.cu->imv << 1; + for (int i = 0; i < pInfo->numCand; i++) + { + roundMV(pInfo->mvCand[i], imvShift); + } + } +#endif +#if !REMOVE_MV_ADAPT_PREC && MODIFY_for_vtm4==0 + if (pu.cs->sps->getSpsNext().getUseHighPrecMv()) + { + for (Mv &mv : pInfo->mvCand) + { + if (mv.highPrec) mv.setLowPrec(); + } + } +#endif +} + +#endif + /** Constructs a list of candidates for AMVP (See specification, section "Derivation process for motion vector predictor candidates") * \param uiPartIdx * \param uiPartAddr @@ -1802,12 +2408,20 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in { const PredictionUnit* tmpPU = cs.getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType ); // getPUBelowLeft(idx, partIdxLB); +#if IBC_SEPERATE_MODE + isScaledFlagLX = tmpPU != NULL && !CU::isIntra(*tmpPU->cu); +#else isScaledFlagLX = tmpPU != NULL && CU::isInter( *tmpPU->cu ); +#endif if( !isScaledFlagLX ) { tmpPU = cs.getPURestricted( posLB.offset( -1, 0 ), pu, pu.chType ); +#if IBC_SEPERATE_MODE + isScaledFlagLX = tmpPU != NULL && !CU::isIntra(*tmpPU->cu); +#else isScaledFlagLX = tmpPU != NULL && CU::isInter( *tmpPU->cu ); +#endif } } @@ -1878,7 +2492,11 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in } } +#if IBC_SEPERATE_MODE && CLEAN_fillMvpCand==0 + if (cs.slice->getEnableTMVPFlag() && CU::isInter(*pu.cu)) +#else if( cs.slice->getEnableTMVPFlag() ) +#endif { // Get Temporal Motion Predictor const int refIdx_Col = refIdx; @@ -1949,7 +2567,11 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in } if (pInfo->numCand < AMVP_MAX_NUM_CANDS) { +#if IBC_SEPERATE_MODE && CLEAN_fillMvpCand==0 + const int currRefPOC = CU::isIBC(*pu.cu) ? cs.slice->getPOC() : cs.slice->getRefPic(eRefPicList, refIdx)->getPOC(); +#else const int currRefPOC = cs.slice->getRefPic(eRefPicList, refIdx)->getPOC(); +#endif const RefPicList eRefPicList2nd = (eRefPicList == REF_PIC_LIST_0) ? REF_PIC_LIST_1 : REF_PIC_LIST_0; addAMVPHMVPCand(pu, eRefPicList, eRefPicList2nd, currRefPOC, *pInfo, pu.cu->imv); } @@ -2351,14 +2973,22 @@ bool PU::addMVPCandUnscaled( const PredictionUnit &pu, const RefPicList &eRefPic neibPU = cs.getPURestricted( neibPos, pu, pu.chType ); +#if IBC_SEPERATE_MODE + if (neibPU == NULL || neibPU->cu->predMode != pu.cu->predMode) +#else if( neibPU == NULL || !CU::isInter( *neibPU->cu ) ) +#endif { return false; } const MotionInfo& neibMi = neibPU->getMotionInfo( neibPos ); +#if IBC_SEPERATE_MODE + const int currRefPOC = CU::isIBC(*pu.cu) ? cs.slice->getPOC() : cs.slice->getRefPic(eRefPicList, iRefIdx)->getPOC(); +#else const int currRefPOC = cs.slice->getRefPic( eRefPicList, iRefIdx )->getPOC(); +#endif const RefPicList eRefPicList2nd = ( eRefPicList == REF_PIC_LIST_0 ) ? REF_PIC_LIST_1 : REF_PIC_LIST_0; for( int predictorSource = 0; predictorSource < 2; predictorSource++ ) // examine the indicated reference picture list, then if not available, examine the other list. @@ -2366,7 +2996,11 @@ bool PU::addMVPCandUnscaled( const PredictionUnit &pu, const RefPicList &eRefPic const RefPicList eRefPicListIndex = ( predictorSource == 0 ) ? eRefPicList : eRefPicList2nd; const int neibRefIdx = neibMi.refIdx[eRefPicListIndex]; +#if IBC_SEPERATE_MODE + if (neibRefIdx >= 0 && currRefPOC == (CU::isIBC(*neibPU->cu) ? cs.slice->getPOC() : cs.slice->getRefPOC(eRefPicListIndex, neibRefIdx))) +#else if( neibRefIdx >= 0 && currRefPOC == cs.slice->getRefPOC( eRefPicListIndex, neibRefIdx ) ) +#endif { info.mvCand[info.numCand++] = neibMi.mv[eRefPicListIndex]; return true; @@ -2414,7 +3048,11 @@ bool PU::addMVPCandWithScaling( const PredictionUnit &pu, const RefPicList &eRef neibPU = cs.getPURestricted( neibPos, pu, pu.chType ); +#if IBC_SEPERATE_MODE + if (neibPU == NULL || !CU::isInter(*neibPU->cu) || !CU::isInter(*pu.cu)) +#else if( neibPU == NULL || !CU::isInter( *neibPU->cu ) ) +#endif { return false; } @@ -2466,7 +3104,12 @@ void PU::addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList, MotionInfo neibMi; int i = 0; +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + 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++) @@ -2475,14 +3118,22 @@ void PU::addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList, { return; } +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + neibMi = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx + offset); +#else neibMi = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx); +#endif for (int predictorSource = 0; predictorSource < 2; predictorSource++) { const RefPicList eRefPicListIndex = (predictorSource == 0) ? eRefPicList : eRefPicList2nd; const int neibRefIdx = neibMi.refIdx[eRefPicListIndex]; +#if IBC_SEPERATE_MODE + if (neibRefIdx >= 0 && (CU::isIBC(*pu.cu) || (CU::isIBC(*pu.cu) == false && currRefPOC == slice.getRefPOC(eRefPicListIndex, neibRefIdx)))) +#else if (neibRefIdx >= 0 && currRefPOC == slice.getRefPOC(eRefPicListIndex, neibRefIdx)) +#endif { Mv pmv = neibMi.mv[eRefPicListIndex]; if (imv != 0) @@ -2739,7 +3390,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 && IBC_SEPERATE_MODE==0 int cntIBC = 0; #endif MergeCtx mrgCtx = *affMrgCtx.mrgCtx; @@ -2764,7 +3415,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 && IBC_SEPERATE_MODE==0 if (puLeft->cu->ibc) { cntIBC++; @@ -2791,7 +3442,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 && IBC_SEPERATE_MODE==0 if (puAbove->cu->ibc) { cntIBC++; @@ -2824,7 +3475,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 && IBC_SEPERATE_MODE==0 if (puAboveRight->cu->ibc) { cntIBC++; @@ -2857,7 +3508,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 && IBC_SEPERATE_MODE==0 if (puLeftBottom->cu->ibc) { cntIBC++; @@ -2876,7 +3527,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 && IBC_SEPERATE_MODE==0 , cntIBC #endif ); @@ -2966,7 +3617,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 IBC_SEPERATE_MODE==0 && !puNeigh->cu->ibc +#endif ) { isAvailable[0] = true; @@ -2984,7 +3637,9 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx if ( puNeigh && CU::isInter( *puNeigh->cu ) +#if IBC_SEPERATE_MODE==0 && !puNeigh->cu->ibc +#endif ) { isAvailable[1] = true; @@ -3002,7 +3657,9 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx if ( puNeigh && CU::isInter( *puNeigh->cu ) +#if IBC_SEPERATE_MODE==0 && !puNeigh->cu->ibc +#endif ) { isAvailable[2] = true; @@ -3309,12 +3966,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 && IBC_SEPERATE_MODE==0 , const int countIBC #endif ) { -#if !JVET_M0409_ATMVP_FIX +#if !JVET_M0409_ATMVP_FIX && IBC_SEPERATE_MODE==0 if (count == countIBC && pu.cs->slice->getSPS()->getSpsNext().getIBCMode()) return false; #endif @@ -3380,7 +4037,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 IBC_SEPERATE_MODE + if (mi.isInter && mi.isIBCmot == false) +#else if (mi.isInter) +#endif { for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++) { @@ -3432,7 +4093,12 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b mi.isInter = true; mi.sliceIdx = slice.getIndependentSliceIdx(); +#if IBC_SEPERATE_MODE + 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++) { @@ -3479,7 +4145,12 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx ) { MotionInfo mi; +#if IBC_SEPERATE_MODE + 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 ) @@ -3491,7 +4162,11 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx ) mi.mv[i] = pu.mv[i]; mi.refIdx[i] = pu.refIdx[i]; } +#if IBC_SEPERATE_MODE + 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; } @@ -3505,6 +4180,9 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx ) { MotionInfo &dest = mb.at( x, y ); dest.isInter = mi.isInter; +#if IBC_SEPERATE_MODE + dest.isIBCmot = false; +#endif dest.interDir = mi.interDir; dest.sliceIdx = mi.sliceIdx; for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ ) @@ -3559,15 +4237,22 @@ 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 IBC_SEPERATE_FUNCTION + if (CU::isIBC(*pu.cu)) + PU::fillIBCMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[0], 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 IBC_SEPERATE_MODE==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 */) @@ -3679,7 +4364,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 IBC_SEPERATE_MODE==0 && !puLeft->cu->ibc +#endif ; if( isAvailableA1 ) { @@ -3696,7 +4383,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 IBC_SEPERATE_MODE==0 && !puAbove->cu->ibc +#endif ; if( isAvailableB1 ) { @@ -3717,7 +4406,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 IBC_SEPERATE_MODE==0 && !puAboveRight->cu->ibc +#endif ; if( isAvailableB0 ) @@ -3739,7 +4430,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 IBC_SEPERATE_MODE==0 && !puLeftBottom->cu->ibc +#endif ; if( isAvailableA0 ) { @@ -3760,7 +4453,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 IBC_SEPERATE_MODE==0 && !puAboveLeft->cu->ibc +#endif ; if( isAvailableB2 ) @@ -4175,6 +4870,11 @@ void CU::resetMVDandMV2Int( CodingUnit& cu, InterPrediction *interPred ) Mv mv = pu.mv[0]; Mv mvPred; AMVPInfo amvpInfo; +#if IBC_SEPERATE_FUNCTION + if (CU::isIBC(*pu.cu)) + PU::fillIBCMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[0], amvpInfo); + else +#endif PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[0], amvpInfo); pu.mvpNum[0] = amvpInfo.numCand; @@ -4284,6 +4984,13 @@ bool CU::isGBiIdxCoded( const CodingUnit &cu ) return false; } +#if IBC_SEPERATE_MODE + if (cu.predMode == MODE_IBC) + { + return false; + } +#endif + if( cu.predMode == MODE_INTRA || cu.cs->slice->isInterP() ) { return false; @@ -4523,8 +5230,13 @@ uint32_t TU::getCoefScanIdx(const TransformUnit &tu, const ComponentID &compID) #endif bool TU::hasCrossCompPredInfo( const TransformUnit &tu, const ComponentID &compID ) { +#if IBC_SEPERATE_MODE + 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 0b7c97f00b..50a40f28c6 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -57,6 +57,9 @@ namespace CU { bool isIntra (const CodingUnit &cu); bool isInter (const CodingUnit &cu); +#if IBC_SEPERATE_MODE + bool isIBC (const CodingUnit &cu); +#endif bool isRDPCMEnabled (const CodingUnit &cu); bool isLosslessCoded (const CodingUnit &cu); uint32_t getIntraSizeIdx (const CodingUnit &cu); @@ -107,11 +110,17 @@ namespace PU void getInterMergeCandidates (const PredictionUnit &pu, MergeCtx& mrgCtx, int mmvdList, const int& mrgCandIdx = -1 ); +#if IBC_SEPERATE_FUNCTION + 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 IBC_SEPERATE_FUNCTION + void fillIBCMvpCand (PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, 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); @@ -119,14 +128,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 IBC_SEPERATE_MODE==0 , int mmvdList +#endif +#if IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + , bool ibc_flag +#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 IBC_SEPERATE_MODE==0 , int mmvdList +#endif ); #endif void addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList, const RefPicList eRefPicList2nd, const int currRefPOC, AMVPInfo &info, uint8_t imv); @@ -143,7 +159,9 @@ namespace PU bool getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx &mrgCtx, bool& LICFlag, const int count , int mmvdList #if !JVET_M0409_ATMVP_FIX +#if IBC_SEPERATE_MODE==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 7f57b25d50..eac3b1e0c2 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 IBC_SEPERATE_MODE + if ((!cs.slice->isIntra() || cs.slice->getSPS()->getSpsNext().getIBCMode()) && cu.Y().valid()) +#else if (!cs.slice->isIntra() && cu.Y().valid()) +#endif { cu_skip_flag( cu ); } @@ -948,12 +952,83 @@ void CABACReader::cu_skip_flag( CodingUnit& cu ) { RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__SKIP_FLAG ); +#if IBC_SEPERATE_MODE +#if IBC_SEPERATE_MODE_FIX + if (cu.slice->isIntra() && cu.cs->slice->getSPS()->getSpsNext().getIBCMode()) +#else + if (cu.slice->isIntra()) +#endif + { + cu.skip = false; + cu.rootCbf = false; + cu.predMode = MODE_INTRA; + //cu.partSize = SIZE_2Nx2N; //Todo + cu.mmvdSkip = false; + + if (cu.lwidth() > IBC_MAX_CAND_SIZE || cu.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip + { + + } + else + { + 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.partSize = SIZE_2Nx2N;//Todo + 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 IBC_SEPERATE_MODE +#if IBC_SEPERATE_MODE_FIX + if (skip && cu.cs->slice->getSPS()->getSpsNext().getIBCMode()) +#else + if (skip) +#endif + { + if (cu.lwidth() > IBC_MAX_CAND_SIZE || cu.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip + { + cu.predMode = MODE_INTER; + } + else + { + unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu); + if (m_BinDecoder.decodeBin(Ctx::IBCFlag(ctxidx))) + { + cu.skip = true; + cu.rootCbf = false; + cu.predMode = MODE_IBC; + //cu.partSize = SIZE_2Nx2N;//Todo + 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 IBC_SEPERATE_MODE_FIX + if ((skip && CU::isInter(cu) && cu.cs->slice->getSPS()->getSpsNext().getIBCMode()) || + (skip && !cu.cs->slice->getSPS()->getSpsNext().getIBCMode())) +#else + if (skip && CU::isInter(cu)) +#endif +#else if( skip ) +#endif { unsigned mmvdSkip = m_BinDecoder.decodeBin(Ctx::MmvdFlag(0)); cu.mmvdSkip = mmvdSkip; @@ -983,7 +1058,11 @@ void CABACReader::imv_mode( CodingUnit& cu, MergeCtx& mrgCtx ) unsigned value = 0; unsigned ctxId = DeriveCtx::CtxIMVFlag( cu ); +#if IBC_SEPERATE_MODE + 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 ) ); @@ -1004,6 +1083,72 @@ void CABACReader::pred_mode( CodingUnit& cu ) { RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__PRED_MODE ); +#if IBC_SEPERATE_MODE//Todo : predmode ctx +#if IBC_SEPERATE_MODE_FIX + if (cu.cs->slice->getSPS()->getSpsNext().getIBCMode()) + { +#endif + if (cu.cs->slice->isIntra()) + { + cu.predMode = MODE_INTRA; + if (cu.lwidth() > IBC_MAX_CAND_SIZE || cu.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip + { + + } + else + { + 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; + if (cu.lwidth() > IBC_MAX_CAND_SIZE || cu.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip + { + } + else + { + unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu); + if (m_BinDecoder.decodeBin(Ctx::IBCFlag(ctxidx))) + { + cu.predMode = MODE_IBC; + } + } + } + } +#if IBC_SEPERATE_MODE_FIX + } + 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; + } + } +#endif +#else #if JVET_M0502_PRED_MODE_CTX if( cu.cs->slice->isIntra() || m_BinDecoder.decodeBin( Ctx::PredMode(DeriveCtx::CtxPredModeFlag(cu)) ) ) #else @@ -1016,6 +1161,7 @@ void CABACReader::pred_mode( CodingUnit& cu ) { cu.predMode = MODE_INTER; } +#endif } void CABACReader::pcm_flag( CodingUnit& cu, Partitioner &partitioner ) @@ -1041,8 +1187,12 @@ void CABACReader::cu_pred_data( CodingUnit &cu ) } if (!cu.Y().valid()) // dual tree chroma CU { +#if IBC_SEPERATE_MODE + cu.predMode = MODE_IBC; +#else cu.predMode = MODE_INTER; cu.ibc = true; +#endif return; } MergeCtx mrgCtx; @@ -1320,7 +1470,11 @@ void CABACReader::intra_chroma_pred_mode( PredictionUnit& pu ) void CABACReader::cu_residual( CodingUnit& cu, Partitioner &partitioner, CUCtx& cuCtx ) { +#if IBC_SEPERATE_MODE + if (!CU::isIntra(cu)) +#else if( CU::isInter( cu ) ) +#endif { PredictionUnit& pu = *cu.firstPU; if( !pu.mergeFlag ) @@ -1404,6 +1558,14 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx ) } if( pu.mergeFlag ) { +#if IBC_SEPERATE_MODE + if (CU::isIBC(*pu.cu)) + { + merge_idx(pu); + } + else + { +#endif subblock_merge_flag( *pu.cu ); MHIntra_flag(pu); if (pu.mhIntraFlag) @@ -1418,7 +1580,20 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx ) } else merge_data ( pu ); +#if IBC_SEPERATE_MODE + } +#endif } +#if IBC_SEPERATE_MODE + else if (CU::isIBC(*pu.cu)) + { + pu.interDir = 1; + pu.cu->affine = false; + ref_idx(pu, REF_PIC_LIST_0); + mvd_coding(pu.mvd[REF_PIC_LIST_0]); + mvp_flag(pu, REF_PIC_LIST_0); + } +#endif else { inter_pred_idc( pu ); @@ -1568,6 +1743,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 IBC_SEPERATE_MODE + if (pu.mergeFlag && CU::isIBC(*pu.cu)) + { + pu.mmvdMergeFlag = false; + return; + } +#endif + if (pu.mergeFlag) { pu.mmvdMergeFlag = (m_BinDecoder.decodeBin(Ctx::MmvdFlag(0))); @@ -1781,6 +1965,18 @@ void CABACReader::ref_idx( PredictionUnit &pu, RefPicList eRefList ) #endif int numRef = pu.cs->slice->getNumRefIdx(eRefList); + +#if IBC_SEPERATE_MODE //Todo : check + if (eRefList == REF_PIC_LIST_0 && pu.cs->sps->getSpsNext().getIBCMode()) + { + if (CU::isIBC(*pu.cu)) + { + pu.refIdx[eRefList] = numRef; + return; + } + } +#endif + if( numRef <= 1 || !m_BinDecoder.decodeBin( Ctx::RefPic() ) ) { if( numRef > 1 ) @@ -2426,6 +2622,9 @@ void CABACReader::mts_coding( TransformUnit& tu, ComponentID compID ) const bool tsAllowed = TU::isTSAllowed ( tu, compID ); const bool mtsAllowed = TU::isMTSAllowed( tu, compID ); +#if IBC_SEPERATE_MODE//Todo +#endif + if( !mtsAllowed && !tsAllowed ) return; int symbol = 0; @@ -2514,7 +2713,11 @@ void CABACReader::emt_cu_flag( CodingUnit& cu ) { const CodingStructure &cs = *cu.cs; +#if IBC_SEPERATE_MODE + 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 6913f67f69..5571db00a8 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -102,6 +102,8 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) for( auto &currCU : cs.traverseCUs( CS::getArea( cs, ctuArea, chType ), chType ) ) { #if JVET_M0170_MRG_SHARELIST +#if IBC_SEPERATE_MODE//Todo : check +#endif if(sharePrepareCondition) { if ((currCU.shareParentPos.x >= 0) && (!(currCU.shareParentPos.x == prevTmpPos.x && currCU.shareParentPos.y == prevTmpPos.y))) @@ -125,6 +127,9 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) switch( currCU.predMode ) { case MODE_INTER: +#if IBC_SEPERATE_MODE + case MODE_IBC: +#endif xReconInter( currCU ); break; case MODE_INTRA: @@ -364,10 +369,17 @@ void DecCu::xReconInter(CodingUnit &cu) m_pcIntraPred->geneIntrainterPred(cu); // inter prediction +#if IBC_SEPERATE_MODE + 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) @@ -557,6 +569,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) #if JVET_M0170_MRG_SHARELIST pu.shareParentPos = cu.shareParentPos; pu.shareParentSize = cu.shareParentSize; +#endif +#if IBC_SEPERATE_FUNCTION//Todo : check + 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 @@ -616,17 +633,60 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) } } } +#if IBC_SEPERATE_FUNCTION//Todo : check mv precision and partsize + else if (CU::isIBC(*pu.cu) && pu.interDir == 1) + { + AMVPInfo amvpInfo; + PU::fillIBCMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[REF_PIC_LIST_0], 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; + +#if MODIFY_for_vtm4 + pu.mv[REF_PIC_LIST_0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); +#else +#if REMOVE_MV_ADAPT_PREC + pu.mv[REF_PIC_LIST_0].hor = pu.mv[REF_PIC_LIST_0].hor << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE; + pu.mv[REF_PIC_LIST_0].ver = pu.mv[REF_PIC_LIST_0].ver << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE; +#else + if (pu.cs->sps->getSpsNext().getUseAffine()) + { + pu.mv[REF_PIC_LIST_0].setHighPrec(); + } +#endif +#endif + } +#endif else { for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ) { RefPicList eRefList = RefPicList( uiRefListIdx ); +#if IBC_SEPERATE_MODE + 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 IBC_SEPERATE_FUNCTION==0//Todo : check Mv mvd = pu.mvd[eRefList]; +#if IBC_SEPERATE_MODE + if (CU::isIBC(cu)) + { +#if REUSE_CU_RESULTS + if (!cu.cs->pcv->isEncoder) +#endif + mvd <<= 2; + } +#else if (eRefList == REF_PIC_LIST_0 && pu.cs->slice->getRefPic(eRefList, pu.refIdx[eRefList])->getPOC() == pu.cs->slice->getPOC()) { pu.cu->ibc = true; @@ -635,7 +695,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) #endif mvd.changePrecision(MV_PRECISION_INT, MV_PRECISION_QUARTER); } +#endif 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 09b493dd5c..1e5d151c2e 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -1238,10 +1238,12 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl m_cSliceDecoder.decompressSlice( pcSlice, &(nalu.getBitstream()) ); m_bFirstSliceInPicture = false; +#if IBC_SEPERATE_MODE==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 8e1725797c..fd44a0cda5 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -1748,10 +1748,21 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para } } } + +#if IBC_SEPERATE_MODE + if (!pcSlice->isIntra() || sps->getSpsNext().getIBCMode()) + { + READ_UVLC(uiCode, "six_minus_max_num_merge_cand"); + pcSlice->setMaxNumMergeCand(MRG_MAX_NUM_CANDS - uiCode); + } +#endif + if (!pcSlice->isIntra()) { +#if IBC_SEPERATE_MODE==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 862ed98359..7f37a079a5 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 IBC_SEPERATE_MODE + if ((!cs.slice->isIntra() || cs.slice->getSPS()->getSpsNext().getIBCMode()) && cu.Y().valid()) +#else if (!cs.slice->isIntra() && cu.Y().valid()) +#endif { cu_skip_flag( cu ); } @@ -766,19 +770,123 @@ void CABACWriter::cu_transquant_bypass_flag( const CodingUnit& cu ) void CABACWriter::cu_skip_flag( const CodingUnit& cu ) { unsigned ctxId = DeriveCtx::CtxSkipFlag( cu ); + +#if IBC_SEPERATE_MODE +#if IBC_SEPERATE_MODE_FIX + if (cu.slice->isIntra() && cu.cs->slice->getSPS()->getSpsNext().getIBCMode()) +#else + if (cu.slice->isIntra()) +#endif + { + if (cu.lwidth() > IBC_MAX_CAND_SIZE || cu.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip + { + } + else + { + 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 IBC_SEPERATE_MODE +#if IBC_SEPERATE_MODE_FIX + if (cu.skip && cu.cs->slice->getSPS()->getSpsNext().getIBCMode()) +#else + if (cu.skip) +#endif + { + if (cu.lwidth() > IBC_MAX_CAND_SIZE || cu.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip + { + + } + else + { + 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 IBC_SEPERATE_MODE_FIX + if (cu.skip && !cu.cs->slice->getSPS()->getSpsNext().getIBCMode()) + { + 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 +#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 IBC_SEPERATE_MODE_FIX + if (cu.cs->slice->getSPS()->getSpsNext().getIBCMode()) + { +#endif +#if IBC_SEPERATE_MODE//Todo : check ctx + if (cu.cs->slice->isIntra()) + { + if (cu.lwidth() > IBC_MAX_CAND_SIZE || cu.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip + { + } + else + { + 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)) + { + if (cu.lwidth() > IBC_MAX_CAND_SIZE || cu.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip + { + } + else + { + unsigned ctxidx = DeriveCtx::CtxIBCFlag(cu); + m_BinEncoder.encodeBin(CU::isIBC(cu), Ctx::IBCFlag(ctxidx)); + } + } + } +#if IBC_SEPERATE_MODE_FIX + } + 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 + } +#endif +#else if( cu.cs->slice->isIntra() ) { return; @@ -788,6 +896,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 ) @@ -1221,7 +1330,11 @@ void CABACWriter::intra_chroma_pred_mode( const PredictionUnit& pu ) void CABACWriter::cu_residual( const CodingUnit& cu, Partitioner& partitioner, CUCtx& cuCtx ) { +#if IBC_SEPERATE_MODE + if (!CU::isIntra(cu)) +#else if( CU::isInter( cu ) ) +#endif { PredictionUnit& pu = *cu.firstPU; if( !pu.mergeFlag ) @@ -1310,6 +1423,13 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu ) } if( pu.mergeFlag ) { +#if IBC_SEPERATE_MODE + if (CU::isIBC(*pu.cu)) + { + merge_idx(pu); + return; + } +#endif subblock_merge_flag( *pu.cu ); MHIntra_flag( pu ); if ( pu.mhIntraFlag ) @@ -1324,6 +1444,14 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu ) else merge_idx ( pu ); } +#if IBC_SEPERATE_MODE + 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 { inter_pred_idc( pu ); @@ -1436,6 +1564,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 IBC_SEPERATE_MODE + if (pu.mergeFlag && CU::isIBC(*pu.cu)) + { + return; + } +#endif + if (pu.mergeFlag) { m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(0)); @@ -1459,7 +1595,11 @@ void CABACWriter::imv_mode( const CodingUnit& cu ) } unsigned ctxId = DeriveCtx::CtxIMVFlag( cu ); +#if IBC_SEPERATE_MODE + 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 ); @@ -1651,6 +1791,15 @@ void CABACWriter::ref_idx( const PredictionUnit& pu, RefPicList eRefList ) #endif int numRef = pu.cs->slice->getNumRefIdx(eRefList); + +#if IBC_SEPERATE_MODE + if (eRefList == REF_PIC_LIST_0 && pu.cs->sps->getSpsNext().getIBCMode()) + { + if (CU::isIBC(*pu.cu)) + return; + } +#endif + if( numRef <= 1 ) { return; @@ -2248,6 +2397,9 @@ void CABACWriter::mts_coding( const TransformUnit& tu, ComponentID compID ) const bool tsAllowed = TU::isTSAllowed ( tu, compID ); const bool mtsAllowed = TU::isMTSAllowed( tu, compID ); +#if IBC_SEPERATE_MODE//Todo : check +#endif + if( !mtsAllowed && !tsAllowed ) return; int symbol = 0; @@ -2325,7 +2477,11 @@ void CABACWriter::emt_cu_flag( const CodingUnit& cu ) { const CodingStructure& cs = *cu.cs; +#if IBC_SEPERATE_MODE + 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 363af63c23..b21bcecc28 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -103,6 +103,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 IBC_SEPERATE_MODE && IBC_SEPERATE_MODE_REDUCTION==0 + 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]; @@ -114,6 +130,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 { @@ -343,7 +360,11 @@ void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsign m_ctuIbcSearchRangeX >>= 1; m_ctuIbcSearchRangeY >>= 1; } +#if IBC_SEPERATE_MODE + 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; @@ -620,7 +641,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 IBC_SEPERATE_MODE + if (m_pImvTempCS && (!slice.isIntra() || slice.getSPS()->getSpsNext().getIBCMode())) +#else if( m_pImvTempCS && !slice.isIntra() ) +#endif { tempCS->initSubStructure( *m_pImvTempCS[wIdx], partitioner.chType, partitioner.currArea(), false ); } @@ -645,7 +670,11 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par m_modeCtrl->finishCULevel( partitioner ); return; } +#if IBC_SEPERATE_MODE + if ((!slice.isIntra() || slice.getSPS()->getSpsNext().getIBCMode()) +#else if (!slice.isIntra() +#endif && tempCS->chType == CHANNEL_TYPE_LUMA ) { @@ -785,9 +814,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 IBC_SEPERATE_MODE + if ((!slice.isIntra() || slice.getSPS()->getSpsNext().getIBCMode()) +#else if (!slice.isIntra() +#endif && bestCS->chType == CHANNEL_TYPE_LUMA +#if IBC_SEPERATE_MODE + && 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() ) { @@ -1347,7 +1384,11 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, if (isAffMVInfoSaved) m_pcInterSearch->addAffMVInfo(tmpMVInfo); +#if IBC_SEPERATE_MODE + if ((!slice.isIntra() || slice.getSPS()->getSpsNext().getIBCMode()) +#else if (!slice.isIntra() +#endif && tempCS->chType == CHANNEL_TYPE_LUMA ) { @@ -1467,7 +1508,11 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC m_CABACEstimator->cu_transquant_bypass_flag( cu ); } +#if IBC_SEPERATE_MODE + if ((!cu.cs->slice->isIntra() || cu.cs->slice->getSPS()->getSpsNext().getIBCMode()) +#else if( !cu.cs->slice->isIntra() +#endif && cu.Y().valid() ) { @@ -1553,7 +1598,11 @@ void EncCu::xCheckIntraPCM(CodingStructure *&tempCS, CodingStructure *&bestCS, P m_CABACEstimator->cu_transquant_bypass_flag( cu ); } +#if IBC_SEPERATE_MODE + if ((!cu.cs->slice->isIntra() || cu.cs->slice->getSPS()->getSpsNext().getIBCMode()) +#else if( !cu.cs->slice->isIntra() +#endif && cu.Y().valid() ) { @@ -1829,16 +1878,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 IBC_SEPERATE_MODE==0 uint32_t ibcCand = 0; uint32_t numValidMv = mergeCtx.numValidMergeCand; +#endif for( uint32_t uiMergeCand = 0; uiMergeCand < mergeCtx.numValidMergeCand; uiMergeCand++ ) { +#if IBC_SEPERATE_MODE==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 ); @@ -1877,13 +1930,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]); } } +#if IBC_SEPERATE_MODE==0 CHECK(std::min(uiMergeCand + 1 - ibcCand, uiNumMrgSATDCand) != RdModeList.size(), ""); +#else + CHECK(std::min(uiMergeCand + 1, uiNumMrgSATDCand) != RdModeList.size(), ""); +#endif } +#if IBC_SEPERATE_MODE==0 if (numValidMv < uiNumMrgSATDCand) uiNumMrgSATDCand = numValidMv; if (numValidMv == 0) return; - +#endif if (isIntrainterEnabled) { @@ -1900,11 +1958,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& // save the to-be-tested merge candidates uint32_t MHIntraMergeCand[NUM_MRG_SATD_CAND]; +#if IBC_SEPERATE_MODE==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 IBC_SEPERATE_MODE==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); @@ -2096,12 +2162,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& { uint32_t uiMergeCand = RdModeList[uiMrgHADIdx]; - +#if IBC_SEPERATE_MODE==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 { @@ -2784,8 +2851,12 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct // first get merge candidates CodingUnit cu(tempCS->area); cu.cs = tempCS; +#if IBC_SEPERATE_MODE + 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()); @@ -2800,9 +2871,13 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct pu.shareParentPos = tempCS->sharedBndPos; pu.shareParentSize = tempCS->sharedBndSize; #endif +#if IBC_SEPERATE_FUNCTION//Todo : check sharelist + PU::getIBCMergeCandidates(pu, mergeCtx); +#else PU::getInterMergeCandidates(pu, mergeCtx , 0 ); +#endif } int candHasNoResidual[MRG_MAX_NUM_CANDS]; @@ -2833,8 +2908,12 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos()); #endif cu.skip = false; +#if IBC_SEPERATE_MODE + 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; @@ -2853,6 +2932,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct int numValidBv = mergeCtx.numValidMergeCand; for (unsigned int mergeCand = 0; mergeCand < mergeCtx.numValidMergeCand; mergeCand++) { +#if IBC_SEPERATE_MODE==0 if (mergeCtx.interDirNeighbours[mergeCand] != 1) { numValidBv--; @@ -2863,6 +2943,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; @@ -2932,6 +3013,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct for (unsigned int mrgHADIdx = 0; mrgHADIdx < numMrgSATDCand; mrgHADIdx++) { unsigned int mergeCand = RdModeList[mrgHADIdx]; +#if IBC_SEPERATE_MODE==0 if (mergeCtx.interDirNeighbours[mergeCand] != 1) { continue; @@ -2940,6 +3022,7 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct { continue; } +#endif if (!(numResidualPass == 1 && candHasNoResidual[mergeCand] == 1)) { if (!(bestIsSkip && (numResidualPass == 0))) @@ -2970,8 +3053,12 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos()); #endif cu.skip = false; +#if IBC_SEPERATE_MODE + 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; @@ -3048,11 +3135,17 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos()); #endif cu.skip = false; +#if IBC_SEPERATE_MODE + 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 IBC_SEPERATE_MODE==0 cu.ibc = true; +#endif cu.imv = 0; CU::addPUs(cu); @@ -3065,8 +3158,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 IBC_SEPERATE_MODE + pu.refIdx[REF_PIC_LIST_0] = pu.cs->slice->getNumRefIdx(REF_PIC_LIST_0); // 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 bc863bb6c7..d99bd39b2f 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -1456,10 +1456,12 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, { pcSlice->setSliceType(I_SLICE); } +#if IBC_SEPERATE_MODE ==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()) @@ -1630,6 +1632,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, if (pcPic->cs->sps->getSpsNext().getUseCompositeRef() && getPrepareLTRef()) { arrangeCompositeReference(pcSlice, rcListPic, pocCurr); } +#if IBC_SEPERATE_MODE==0 if (pcSlice->getSPS()->getSpsNext().getIBCMode()) { if (m_pcCfg->getIntraPeriod() > 0 && pcSlice->getPOC() % m_pcCfg->getIntraPeriod() == 0) @@ -1640,6 +1643,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 ); @@ -1696,10 +1700,12 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, { pcSlice->setSliceType ( P_SLICE ); } +#if IBC_SEPERATE_MODE==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 @@ -1800,6 +1806,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, bool bGPBcheck=false; if ( pcSlice->getSliceType() == B_SLICE) { +#if IBC_SEPERATE_MODE==0 if (pcSlice->getSPS()->getSpsNext().getIBCMode()) { if (pcSlice->getNumRefIdx(RefPicList(0)) - 1 == pcSlice->getNumRefIdx(RefPicList(1))) @@ -1816,6 +1823,7 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, } } else +#endif if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) ) { bGPBcheck=true; @@ -2498,7 +2506,9 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "final", 0 ) ) ); pcPic->reconstructed = true; +#if IBC_SEPERATE_MODE ==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 56f49fc862..28fe9244e6 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1395,11 +1395,13 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps) } } CHECK(!(bestPos <= 15), "Unspecified error"); +#if IBC_SEPERATE_MODE==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 5c9aeb9b77..7aa24eb395 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -801,7 +801,11 @@ bool BestEncInfoCache::isValid( const CodingStructure& cs, const Partitioner& pa , encInfo.pu, (cs.picture->Y().width), (cs.picture->Y().height) #endif ) +#if IBC_SEPERATE_MODE + || CU::isIBC(encInfo.cu) +#else || encInfo.cu.ibc +#endif ) { return false; @@ -1280,7 +1284,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt return false; } +#if IBC_SEPERATE_MODE + if (m_pcEncCfg->getUsePbIntraFast() && (!cs.slice->isIntra() || cs.slice->getSPS()->getSpsNext().getIBCMode()) && !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; } @@ -1291,7 +1299,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt 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 IBC_SEPERATE_MODE + ((!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 @@ -1313,7 +1325,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt if( !cs.slice->isIRAP() && m_pcEncCfg->getUsePbIntraFast() ) { CodingUnit* bestCU = cuECtx.bestCU; +#if IBC_SEPERATE_MODE + if (bestCU && !CU::isIntra(*bestCU)) +#else if( bestCU && CU::isInter( *bestCU ) ) +#endif { DistParam distParam; const bool useHad = !bestCU->transQuantBypass; @@ -1407,7 +1423,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt ////////////////////////////////////////////////////////////////////////// int skipScore = 0; +#if IBC_SEPERATE_MODE + if ((!slice.isIntra() || slice.getSPS()->getSpsNext().getIBCMode()) && 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++ ) { @@ -1502,6 +1522,15 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt const CodingUnit *cuBR = bestCS->cus.back(); unsigned height = partitioner.currArea().lumaSize().height; +#if IBC_SEPERATE_MODE + if (bestCU && ((bestCU->btDepth == 0 && maxBTD >= ((slice.isIntra() && !slice.getSPS()->getSpsNext().getIBCMode()) ? 3 : 2)) + || (bestCU->btDepth == 1 && cuBR && cuBR->btDepth == 1 && maxBTD >= ((slice.isIntra() && !slice.getSPS()->getSpsNext().getIBCMode()) ? 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 ) @@ -1509,6 +1538,7 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt { return false; } +#endif } if( m_pcEncCfg->getUseEarlyCU() && bestCS->cost != MAX_DOUBLE && bestCU && bestCU->skip ) { @@ -1613,6 +1643,15 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt #endif relatedCU.GBiIdx = bestCU->GBiIdx; } +#if IBC_SEPERATE_MODE//Todo : macro hm_code_cu_info + 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 422e4c8084..faf84491ff 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.h +++ b/source/Lib/EncoderLib/EncModeCtrl.h @@ -327,6 +327,9 @@ struct CodedCUInfo bool isIntra; bool isSkip; bool isMMVDSkip; +#if IBC_SEPERATE_MODE + 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 73b9cc08af..1c73d78b05 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 IBC_SEPERATE_MODE + const bool bUseIntraOrPeriodicOffset = (rpcSlice->isIntra() && !rpcSlice->getSPS()->getSpsNext().getIBCMode()) || (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; diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 81ac4b3378..7d7d6717d6 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -762,7 +762,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 IBC_SEPERATE_MODE + 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); @@ -1300,13 +1304,20 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const /// ibc search pu.cu->imv = 2; AMVPInfo amvpInfo4Pel; +#if IBC_SEPERATE_FUNCTION + PU::fillIBCMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[REF_PIC_LIST_0], 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 IBC_SEPERATE_FUNCTION + PU::fillIBCMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[REF_PIC_LIST_0], 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)); @@ -1403,7 +1414,11 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const if (!cu.cs->sps->getSpsNext().getUseIMV()) pu.mvd[REF_PIC_LIST_0] >>= (2); +#if IBC_SEPERATE_MODE + pu.refIdx[REF_PIC_LIST_0] = pu.cs->slice->getNumRefIdx(REF_PIC_LIST_0); +#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; @@ -1587,12 +1602,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 IBC_SEPERATE_MODE==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 ) @@ -1794,10 +1813,12 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) iRefStart = 0; iRefEnd = cs.slice->getNumRefIdx(eRefPicList)-1; +#if IBC_SEPERATE_MODE==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) @@ -2055,6 +2076,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) cu.GBiIdx = GBI_DEFAULT; // Reset to default for the Non-NormalMC modes. } +#if IBC_SEPERATE_MODE//Todo : no cu.partsize + //no mergeestimation + //xMergeEstimation(pu, origBuf, puIdx, uiMRGIndex, uiMRGCost, mergeCtx); +#endif + uiHevcCost = ( uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1] ) ? uiCostBi : ( ( uiCost[0] <= uiCost[1] ) ? uiCost[0] : uiCost[1] ); if (cu.Y().width > 8 && cu.Y().height > 8 && cu.slice->getSPS()->getSpsNext().getUseAffine() && cu.imv == 0 && (gbiIdx == GBI_DEFAULT || m_affineModeSelected || !m_pcEncCfg->getUseGBiFast()) @@ -3493,12 +3519,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 IBC_SEPERATE_MODE==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]; @@ -3876,10 +3906,12 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, iRefStart = 0; iRefEnd = slice.getNumRefIdx(eRefPicList) - 1; +#if IBC_SEPERATE_MODE==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 ) @@ -5584,6 +5616,14 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa PredictionUnit &pu = *cs.getPU( partitioner.chType ); m_CABACEstimator->cu_skip_flag ( cu ); +#if IBC_SEPERATE_MODE + 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) @@ -5592,7 +5632,9 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa } else m_CABACEstimator->merge_idx ( pu ); - +#if IBC_SEPERATE_MODE + } +#endif cs.dist = distortion; cs.fracBits = m_CABACEstimator->getEstFracBits(); diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index ac23b0a313..cddf799dce 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -1012,7 +1012,11 @@ void IntraSearch::xEncIntraHeader(CodingStructure &cs, Partitioner &partitioner, // CU header if( isFirst ) { +#if IBC_SEPERATE_MODE + if ((!cs.slice->isIntra() || cs.slice->getSPS()->getSpsNext().getIBCMode()) +#else if( !cs.slice->isIntra() +#endif && cu.Y().valid() ) { diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 34a8b308db..22fddc7411 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -1265,10 +1265,19 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) } } } +#if IBC_SEPERATE_MODE + if (!cs.slice->isIntra() || cs.slice->getSPS()->getSpsNext().getIBCMode()) + { + 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 IBC_SEPERATE_MODE==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 { -- GitLab