diff --git a/source/Lib/CommonLib/Contexts_ecm14.0.inl b/source/Lib/CommonLib/Contexts_ecm14.0.inl index 0c9a685720de8ef4af16c0f829785856103b95ba..2498b51efd573e8a3c68a035e757c5074fa78082 100644 --- a/source/Lib/CommonLib/Contexts_ecm14.0.inl +++ b/source/Lib/CommonLib/Contexts_ecm14.0.inl @@ -376,6 +376,32 @@ const CtxSet ContextSetCfg::GeoBlendFlag = ContextSetCfg::addCtxSet #endif #if JVET_AG0135_AFFINE_CIIP +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION +const CtxSet ContextSetCfg::CiipAffineFlag = ContextSetCfg::addCtxSet +({ +// ctx 57 59 + { 12, 6, 15, 15, 15, 15 }, + { 19, 5, 6, 6, 6, 6 }, + { 35, 35, 35, 35, 35, 35 }, + { 12, 14, 15, 15, 15, 15 }, + { 5, 1, 1, 1, 1, 1 }, + { 6, 3, 5, 5, 5, 5 }, + { 8, 8, 8, 8, 8, 8 }, + { 5, 1, 1, 1, 1, 1 }, + { 4, 4, 11, 11, 11, 11 }, + { 4, 4, 11, 11, 11, 11 }, + { 18, 18, 18, 18, 18, 18 }, + { 4, 4, 4, 4, 4, 4 }, + { 105, 118, 116, 116, 116, 116 }, + { 211, 118, 116, 116, 116, 116 }, + { 107, 119, 103, 103, 103, 103 }, + { 107, 122, 148, 148, 148, 148 }, + { 119, 119, 119, 119, 119, 119 }, + { 119, 119, 119, 119, 119, 119 }, + { 107, 118, 116, 116, 116, 116 }, + { 116, 119, 118, 118, 118, 118 }, +}); +#else const CtxSet ContextSetCfg::CiipAffineFlag = ContextSetCfg::addCtxSet ({ // ctx 57 59 @@ -401,6 +427,7 @@ const CtxSet ContextSetCfg::CiipAffineFlag = ContextSetCfg::addCtxSet { 116, 119, 118 }, }); #endif +#endif const CtxSet ContextSetCfg::MergeIdx = ContextSetCfg::addCtxSet({ // ctx 60 69 @@ -1556,7 +1583,31 @@ const CtxSet ContextSetCfg::RefPicLC = ContextSetCfg::addCtxSet({ { 117, 117, 234 }, { 148, 117, 251 }, }); - +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION +const CtxSet ContextSetCfg::SubblockMergeFlag = ContextSetCfg::addCtxSet({ +// ctx 202 204 + { 25, 34, 21, 21, 21, 21 }, + { 40, 34, 36, 36, 36, 36 }, + { 35, 35, 35, 35, 35, 35 }, + { 25, 20, 37, 37, 37, 37 }, + { 6, 5, 4, 4, 4, 4 }, + { 6, 5, 5, 5, 5, 5 }, + { 8, 8, 8, 8, 8, 8 }, + { 6, 5, 5, 5, 5, 5 }, + { 4, 4, 18, 18, 18, 18 }, + { 11, 4, 18, 18, 18, 18 }, + { 18, 18, 18, 18, 18, 18 }, + { 4, 4, 18, 18, 18, 18 }, + { 131, 116, 117, 117, 117, 117 }, + { 131, 132, 118, 118, 118, 118 }, + { 117, 117, 119, 119, 119, 119 }, + { 117, 132, 117, 117, 117, 117 }, + { 119, 119, 119, 119, 119, 119 }, + { 119, 119, 119, 119, 119, 119 }, + { 131, 117, 118, 118, 118, 118 }, + { 131, 117, 118, 118, 118, 118 }, +}); +#else const CtxSet ContextSetCfg::SubblockMergeFlag = ContextSetCfg::addCtxSet({ // ctx 202 204 { 25, 34, 21 }, @@ -1580,6 +1631,7 @@ const CtxSet ContextSetCfg::SubblockMergeFlag = ContextSetCfg::addCtxSet({ { 131, 117, 118 }, { 131, 117, 118 }, }); +#endif const CtxSet ContextSetCfg::BMMergeFlag = ContextSetCfg::addCtxSet({ // ctx 205 208 diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index faff01c4cc0ceafd7057e3cb3374f714f55c5311..4d91910052ed3696f5e7125dc03d84f9aa476205 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -4978,8 +4978,10 @@ void InterPrediction::xPredAffineBlk(const ComponentID &compID, const Prediction int blockWidth = AFFINE_MIN_BLOCK_SIZE; int blockHeight = AFFINE_MIN_BLOCK_SIZE; +#if !JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION CHECK(blockWidth > (width >> iScaleX ), "Sub Block width > Block width"); CHECK(blockHeight > (height >> iScaleY), "Sub Block height > Block height"); +#endif #if !AFFINE_RM_CONSTRAINTS_AND_OPT const int MVBUFFER_SIZE = MAX_CU_SIZE / MIN_PU_SIZE; #endif diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index c80541219d4fe44b7991e67242a347761c3a36af..3d4fabef4e11ceafea4ed3a66644e1428af45ae4 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -374,6 +374,7 @@ #define JVET_AI0094_SHARP_MC_FILTER_FOR_BIPRED 1 // JVET-AI0094: Sharp motion compensation filter for bi-prediction #define JVET_AI0185_ADAPTIVE_COST_IN_MERGE_MODE 1 // JVET-AI0185 adaptive cost function selection in merge mode #define JVET_AI0183_MVP_EXTENSION 1 // JVET-AI0183 MVP extension +#define JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION 1 // JVET-AJ0085 subblock merge mode extension #define JVET_AJ0097_BDOF_LDB 1 // JVET-AJ0097 BDOF for low-delay pictures #define JVET_AJ0126_INTER_AMVP_ENHANCEMENT 1 // JVET-AJ0126: Enhanced inter AMVP (inter TM part is controlled by EnableTMTools) #define JVET_AJ0107_GPM_SHAPE_ADAPT 1 // JVET-AJ0107: Test 3.4d, GPM with shape adaptation only applied to regular GPM. diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index e5fa9eefa83e54ea76295529c79c4b688deedc9b..64f18539c302bcb4d5201a5cebf66123562e2113 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -35620,4 +35620,81 @@ void getTemporalBv(const PredictionUnit &pu, std::vector<MotionInfo>& temporalMi addOneTypeTempCandidates(pu, temporalMiCandList, temporalPos); } #endif +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION +bool CU::hasAffineNb(const CodingUnit& cu) +{ + int affineNb = 0; + Position pos[7] = { + cu.lumaPos().offset(-1, 0), + cu.lumaPos().offset(0, -1), + cu.lumaPos().offset(-1, -1), + cu.lumaPos().offset(cu.lwidth() - 1, -1), + cu.lumaPos().offset(cu.lwidth(), -1), + cu.lumaPos().offset(-1, cu.lheight() - 1), + cu.lumaPos().offset(-1, cu.lheight()) + }; + for (int i = 0; i < 7; i++) + { + const CodingUnit* cuNb = cu.cs->getCURestricted(pos[i], cu, CH_L); + affineNb += (cuNb && (cuNb->affine || (cuNb->geoFlag && (cuNb->firstPU->affineGPM[0] || cuNb->firstPU->affineGPM[1]) && !cu.slice->getCheckLDB()))) ? 1 : 0; + if (affineNb) + { + return true; + } + } + int offsetX = 0; + int offsetY = 0; + int offsetX0 = 0; int offsetX1 = 0; int offsetX2 = cu.lwidth() >> 1; + int offsetY0 = 0; int offsetY1 = 0; int offsetY2 = cu.lheight() >> 1; + + const int numNACandidate = 5; + const int idxMap[5] = { 0, 1, 2, 3, 4 }; + int iDistanceIndex = 0; + const int iNADistanceHor = cu.lwidth() * (iDistanceIndex + 1); + const int iNADistanceVer = cu.lheight() * (iDistanceIndex + 1); + + for (int iNASPIdx = 0; iNASPIdx < numNACandidate; iNASPIdx++) + { + switch (idxMap[iNASPIdx]) + { + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY0 = cu.lheight() + iNADistanceVer - 1; break; + case 1:offsetX = offsetX1 = cu.lwidth() + iNADistanceHor - 1; offsetY = offsetY1 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX2; offsetY = offsetY1; break; + case 3:offsetX = offsetX0; offsetY = offsetY2; break; + case 4:offsetX = offsetX0; offsetY = offsetY1; break; + case 5:offsetX = -1; offsetY = offsetY0; break; + case 6:offsetX = offsetX1; offsetY = -1; break; + case 7:offsetX = offsetX0 >> 1; offsetY = offsetY0; break; + case 8:offsetX = offsetX1; offsetY = offsetY1 >> 1; break; + default: printf("error!"); exit(0); break; + } + const CodingUnit* cuNb = cu.cs->getCURestricted(cu.lumaPos().offset(offsetX, offsetY), cu, CH_L); + affineNb += (cuNb && (cuNb->affine || (cuNb->geoFlag && (cuNb->firstPU->affineGPM[0] || cuNb->firstPU->affineGPM[1]) && !cu.slice->getCheckLDB()))) ? 1 : 0; + if (affineNb) + { + return true; + } + } + + return false; +} +bool CU::isAffineAllowed(const CodingUnit& cu) +{ + if ((cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 && (cu.lumaSize().width * cu.lumaSize().height >= 128)) || + (cu.lumaSize().width * cu.lumaSize().height >= 32 && CU::hasAffineNb(cu))) + { + return true; + } + return false; +} + +bool CU::affineCtxInc(const CodingUnit& cu) +{ + if (!(cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 && (cu.lumaSize().width * cu.lumaSize().height >= 128)) && !cu.slice->getCheckLDB()) + { + return true; + } + return false; +} +#endif diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 8fd5f59dc11e4fe92a2bc86066fb99d014eaf255..afbbdd79112e693e3e175cd138f23893dd59b8d1 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -64,6 +64,12 @@ namespace CS // CU tools namespace CU { +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION + bool hasAffineNb(const CodingUnit& cu); + bool isAffineAllowed(const CodingUnit& cu); + bool affineCtxInc(const CodingUnit& cu); +#endif + #if JVET_AG0276_NLIC bool isSecLicParaNeeded (const CodingUnit &cu); bool isPredRefined (const CodingUnit &cu); diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 077b3d7584568fa7bdb1936185adac8dcf2c1a3d..03972d32e8be1ce7f60ebc60be3597ee339528ac 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -4834,11 +4834,24 @@ void CABACReader::subblock_merge_flag( CodingUnit& cu ) { cu.affine = false; - if ( !cu.cs->slice->isIntra() && (cu.slice->getPicHeader()->getMaxNumAffineMergeCand() > 0) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 ) + if ( !cu.cs->slice->isIntra() && (cu.slice->getPicHeader()->getMaxNumAffineMergeCand() > 0) && +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION + CU::isAffineAllowed(cu) +#else + cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 +#endif + ) { RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE( STATS__CABAC_BITS__AFFINE_FLAG, cu.lumaSize()); unsigned ctxId = DeriveCtx::CtxAffineFlag( cu ); +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION + if(CU::affineCtxInc(cu)) + { + ctxId += 3; + } +#endif + cu.affine = m_BinDecoder.decodeBin( Ctx::SubblockMergeFlag( ctxId ) ); DTRACE( g_trace_ctx, D_SYNTAX, "subblock_merge_flag() subblock_merge_flag=%d ctx=%d pos=(%d,%d)\n", cu.affine ? 1 : 0, ctxId, cu.Y().x, cu.Y().y ); } @@ -7357,9 +7370,21 @@ void CABACReader::mvp_flag( PredictionUnit& pu, RefPicList eRefList ) #if JVET_AG0135_AFFINE_CIIP void CABACReader::ciipAffineFlag(PredictionUnit& pu) { - if (!pu.cu->slice->isIntra() && pu.cs->sps->getUseCiipAffine() && (pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand() > 0) && pu.cu->lumaSize().width >= 8 && pu.cu->lumaSize().height >= 8) + if (!pu.cu->slice->isIntra() && pu.cs->sps->getUseCiipAffine() && (pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand() > 0) && +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION + CU::isAffineAllowed(*pu.cu) +#else + pu.cu->lumaSize().width >= 8 && pu.cu->lumaSize().height >= 8 +#endif + ) { unsigned ctxId = DeriveCtx::CtxCiipAffineFlag(*pu.cu); +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION + if (CU::affineCtxInc(*pu.cu)) + { + ctxId += 3; + } +#endif pu.ciipAffine = m_BinDecoder.decodeBin(Ctx::CiipAffineFlag(ctxId)); } else diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 33c963de683c79f63e70ca33385087b8b1772dfe..137ebf1a86657512d0d78f647119c0fd343b4672 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -4430,9 +4430,21 @@ void CABACWriter::amvpSbTmvpMvdCoding(const PredictionUnit &pu) void CABACWriter::subblock_merge_flag( const CodingUnit& cu ) { - if ( !cu.cs->slice->isIntra() && (cu.slice->getPicHeader()->getMaxNumAffineMergeCand() > 0) && cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 ) + if ( !cu.cs->slice->isIntra() && (cu.slice->getPicHeader()->getMaxNumAffineMergeCand() > 0) && +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION + CU::isAffineAllowed(cu) +#else + cu.lumaSize().width >= 8 && cu.lumaSize().height >= 8 +#endif + ) { unsigned ctxId = DeriveCtx::CtxAffineFlag( cu ); +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION + if (CU::affineCtxInc(cu)) + { + ctxId += 3; + } +#endif m_BinEncoder.encodeBin( cu.affine, Ctx::SubblockMergeFlag( ctxId ) ); DTRACE( g_trace_ctx, D_SYNTAX, "subblock_merge_flag() subblock_merge_flag=%d ctx=%d pos=(%d,%d)\n", cu.affine ? 1 : 0, ctxId, cu.Y().x, cu.Y().y ); } @@ -7364,9 +7376,21 @@ void CABACWriter::mvp_flag( const PredictionUnit& pu, RefPicList eRefList ) #if JVET_AG0135_AFFINE_CIIP void CABACWriter::ciipAffineFlag(const PredictionUnit& pu) { - if (!pu.cu->slice->isIntra() && pu.cs->sps->getUseCiipAffine() && (pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand() > 0) && pu.cu->lumaSize().width >= 8 && pu.cu->lumaSize().height >= 8) + if (!pu.cu->slice->isIntra() && pu.cs->sps->getUseCiipAffine() && (pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand() > 0) && +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION + CU::isAffineAllowed(*pu.cu) +#else + pu.cu->lumaSize().width >= 8 && pu.cu->lumaSize().height >= 8 +#endif + ) { unsigned ctxId = DeriveCtx::CtxCiipAffineFlag(*pu.cu); +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION + if (CU::affineCtxInc(*pu.cu)) + { + ctxId += 3; + } +#endif m_BinEncoder.encodeBin(pu.ciipAffine, Ctx::CiipAffineFlag(ctxId)); } } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 10376a65b18d53492f651f3674717cf7a02c22c8..6e855806252e62bc396e503bc6ff6dc35b70725e 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -5176,10 +5176,20 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& uint32_t affMmvdLUT[AF_MMVD_NUM]; #endif const SPS &sps = *tempCS->sps; - +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION + CodingUnit tempCu(tempCS->area); + tempCu.cs = tempCS; + tempCu.slice = tempCS->slice; + tempCu.tileIdx = tempCS->pps->getTileIdx(tempCS->area.lumaPos()); + bool affineMrgAvailSize = CU::isAffineAllowed(tempCu); +#endif #if MERGE_ENC_OPT const bool affineMrgAvail = (sps.getUseAffine() || sps.getSbTMVPEnabledFlag()) && slice.getPicHeader()->getMaxNumAffineMergeCand() +#if JVET_AJ0085_SUBBLOCK_MERGE_MODE_EXTENSION + && affineMrgAvailSize; +#else && !(bestCS->area.lumaSize().width < 8 || bestCS->area.lumaSize().height < 8); +#endif AffineMergeCtx affineMergeCtx; #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS