diff --git a/cfg/encoder_lowdelay_vtm.cfg b/cfg/encoder_lowdelay_vtm.cfg index 2b449a99efbcb37256ed42fe5b7420dbf146e14a..40e34457346c0b031007d8705f8d51e8fac8ef9f 100644 --- a/cfg/encoder_lowdelay_vtm.cfg +++ b/cfg/encoder_lowdelay_vtm.cfg @@ -116,7 +116,7 @@ ALF : 1 BCW : 1 BcwFast : 1 CIIP : 1 -Triangle : 1 +Geo : 1 IBC : 0 # turned off in CTC AllowDisFracMMVD : 1 AffineAmvr : 0 diff --git a/cfg/encoder_randomaccess_vtm.cfg b/cfg/encoder_randomaccess_vtm.cfg index 47f57f957765ea9bc213667a1bd188cad7134c0d..87ea48f866da85363356a38eb262dd52af49f04d 100644 --- a/cfg/encoder_randomaccess_vtm.cfg +++ b/cfg/encoder_randomaccess_vtm.cfg @@ -129,7 +129,7 @@ BCW : 1 BcwFast : 1 BIO : 1 CIIP : 1 -Triangle : 1 +Geo : 1 IBC : 0 # turned off in CTC AllowDisFracMMVD : 1 AffineAmvr : 1 diff --git a/doc/software-manual.tex b/doc/software-manual.tex index 3b71317ac238fe468bfca2a594682e1bae4d997f..e0df3c4d0c478131d1862dea79cbc1b4945c0549 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -1295,10 +1295,10 @@ Defines the SPS-derived Log2ParallelMergeLevel variable. Specifies the maximum number of merge candidates to use. \\ -\Option{MaxNumTriangleCand} & +\Option{MaxNumGeoCand} & %\ShortOption{\None} & \Default{5} & -Specifies the maximum number of triangle merge candidates to use. +Specifies the maximum number of geometric partitioning mode candidates to use. \\ \Option{MaxNumIBCMergeCand} & @@ -2170,7 +2170,7 @@ Enables signaling the below parameters either in PPS or for each slice according collocated_from_l0_flag & s & s & p & s \\ six_minus_max_num_merge_cand & s & p & p & p \\ five_minus_max_num_subblock_merge_cand & s & p & p & p \\ - max_num_merge_cand_minus_max_num_triangle_cand & s & p & p & s \\ + max_num_merge_cand_minus_max_num_geo_cand & s & p & p & s \\ \end{tabular} \\ @@ -2263,6 +2263,12 @@ QP threshold above which the encoder reduces cross-component ALF usage. Enables or disables symmetric MVD mode. \\ +\Option{Geo} & +%\ShortOption{\None} & +\Default{false} & +Enables or disables geometric partitioning mode. +\\ + \Option{PLT} & %\ShortOption{\None} & \Default{false} & diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 542b3ba7e9905682ce8597745d5a9a28a1741337..2996e44372583a8ad51fc7469c2aea9d4c007bec 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -236,7 +236,11 @@ void EncApp::xInitLibCfg() m_cEncLib.setNoIbcConstraintFlag ( m_IBCMode ? false : true ); m_cEncLib.setNoCiipConstraintFlag ( !m_ciip ); m_cEncLib.setNoFPelMmvdConstraintFlag ( !(m_MMVD && m_allowDisFracMMVD) ); +#if !JVET_Q0806 m_cEncLib.setNoTriangleConstraintFlag ( !m_Triangle ); +#else + m_cEncLib.setNoGeoConstraintFlag ( !m_Geo ); +#endif m_cEncLib.setNoLadfConstraintFlag ( !m_LadfEnabed ); m_cEncLib.setNoTransformSkipConstraintFlag ( !m_useTransformSkip ); m_cEncLib.setNoBDPCMConstraintFlag ( m_useBDPCM == 0 ); @@ -429,7 +433,11 @@ void EncApp::xInitLibCfg() } #endif m_cEncLib.setUseCiip ( m_ciip ); +#if !JVET_Q0806 m_cEncLib.setUseTriangle ( m_Triangle ); +#else + m_cEncLib.setUseGeo ( m_Geo ); +#endif m_cEncLib.setUseHashME ( m_HashME ); m_cEncLib.setAllowDisFracMMVD ( m_allowDisFracMMVD ); @@ -523,7 +531,11 @@ void EncApp::xInitLibCfg() m_cEncLib.setMaxNumMergeCand ( m_maxNumMergeCand ); m_cEncLib.setMaxNumAffineMergeCand ( m_maxNumAffineMergeCand ); +#if !JVET_Q0806 m_cEncLib.setMaxNumTriangleCand ( m_maxNumTriangleCand ); +#else + m_cEncLib.setMaxNumGeoCand ( m_maxNumGeoCand ); +#endif m_cEncLib.setMaxNumIBCMergeCand ( m_maxNumIBCMergeCand ); //====== Weighted Prediction ======== @@ -712,7 +724,11 @@ void EncApp::xInitLibCfg() m_cEncLib.setPPSMvdL1ZeroIdc ( m_PPSMvdL1ZeroIdc ); m_cEncLib.setPPSCollocatedFromL0Idc ( m_PPSCollocatedFromL0Idc ); m_cEncLib.setPPSSixMinusMaxNumMergeCandPlus1 ( m_PPSSixMinusMaxNumMergeCandPlus1 ); +#if !JVET_Q0806 m_cEncLib.setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 ( m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 ); +#else + m_cEncLib.setPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 ( m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 ); +#endif m_cEncLib.setUseScalingListId ( m_useScalingListId ); m_cEncLib.setScalingListFileName ( m_scalingListFileName ); m_cEncLib.setDisableScalingMatrixForLfnstBlks ( m_disableScalingMatrixForLfnstBlks); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 44cfdba40c9883e77cdcac874b7d36ba4ea3d8f3..e21caa1c7b2656647f70e3f18cc908441507512e 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -104,7 +104,11 @@ EncAppCfg::EncAppCfg() , m_noIbcConstraintFlag(false) , m_bNoCiipConstraintFlag(false) , m_noFPelMmvdConstraintFlag(false) +#if !JVET_Q0806 , m_bNoTriangleConstraintFlag(false) +#else +, m_noGeoConstraintFlag(false) +#endif , m_bNoLadfConstraintFlag(false) , m_noTransformSkipConstraintFlag(false) , m_noBDPCMConstraintFlag(false) @@ -925,7 +929,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("LadfIntervalLowerBound", cfg_LadfIntervalLowerBound, cfg_LadfIntervalLowerBound, "LADF lower bound for 2nd lowest interval") #endif ("CIIP", m_ciip, false, "Enable CIIP mode") +#if !JVET_Q0806 ("Triangle", m_Triangle, false, "Enable triangular shape motion vector prediction (0:off, 1:on)") +#else + ("Geo", m_Geo, false, "Enable geometric partitioning mode (0:off, 1:on)") +#endif ("HashME", m_HashME, false, "Enable hash motion estimation (0:off, 1:on)") ("AllowDisFracMMVD", m_allowDisFracMMVD, false, "Disable fractional MVD in MMVD mode adaptively") @@ -1147,7 +1155,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("SignHideFlag,-SBH", m_signDataHidingEnabledFlag, false, "Enable sign hiding" ) ("MaxNumMergeCand", m_maxNumMergeCand, 5u, "Maximum number of merge candidates") ("MaxNumAffineMergeCand", m_maxNumAffineMergeCand, 5u, "Maximum number of affine merge candidates") +#if !JVET_Q0806 ("MaxNumTriangleCand", m_maxNumTriangleCand, 5u, "Maximum number of triangle candidates") +#else + ("MaxNumGeoCand", m_maxNumGeoCand, 5u, "Maximum number of geometric partitioning mode candidates") +#endif ("MaxNumIBCMergeCand", m_maxNumIBCMergeCand, 6u, "Maximum number of IBC merge candidates") /* Misc. */ ("SEIDecodedPictureHash,-dph", tmpDecodedPictureHashSEIMappedType, 0, "Control generation of decode picture hash SEI messages\n" @@ -2523,9 +2535,15 @@ bool EncAppCfg::xCheckParameter() xConfirmPara( m_log2MaxTbSize < 5, "Log2MaxTbSize must be 5 or greater." ); xConfirmPara( m_maxNumMergeCand < 1, "MaxNumMergeCand must be 1 or greater."); xConfirmPara( m_maxNumMergeCand > MRG_MAX_NUM_CANDS, "MaxNumMergeCand must be no more than MRG_MAX_NUM_CANDS." ); +#if !JVET_Q0806 xConfirmPara( m_maxNumTriangleCand > TRIANGLE_MAX_NUM_UNI_CANDS, "MaxNumTriangleCand must be no more than TRIANGLE_MAX_NUM_UNI_CANDS." ); xConfirmPara( m_maxNumTriangleCand > m_maxNumMergeCand, "MaxNumTriangleCand must be no more than MaxNumMergeCand." ); xConfirmPara( 0 < m_maxNumTriangleCand && m_maxNumTriangleCand < 2, "MaxNumTriangleCand must be no less than 2 unless MaxNumTriangleCand is 0." ); +#else + xConfirmPara( m_maxNumGeoCand > GEO_MAX_NUM_UNI_CANDS, "MaxNumGeoCand must be no more than GEO_MAX_NUM_UNI_CANDS." ); + xConfirmPara( m_maxNumGeoCand > m_maxNumMergeCand, "MaxNumGeoCand must be no more than MaxNumMergeCand." ); + xConfirmPara( 0 < m_maxNumGeoCand && m_maxNumGeoCand < 2, "MaxNumGeoCand must be no less than 2 unless MaxNumGeoCand is 0." ); +#endif xConfirmPara( m_maxNumIBCMergeCand < 1, "MaxNumIBCMergeCand must be 1 or greater." ); xConfirmPara( m_maxNumIBCMergeCand > IBC_MRG_MAX_NUM_CANDS, "MaxNumIBCMergeCand must be no more than IBC_MRG_MAX_NUM_CANDS." ); xConfirmPara( m_maxNumAffineMergeCand < 1, "MaxNumAffineMergeCand must be 1 or greater." ); @@ -3273,7 +3291,11 @@ bool EncAppCfg::xCheckParameter() m_PPSMvdL1ZeroIdc = 0; m_PPSCollocatedFromL0Idc = 0; m_PPSSixMinusMaxNumMergeCandPlus1 = 0; +#if !JVET_Q0806 m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = 0; +#else + m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 = 0; +#endif break; case 1: // RA setting m_constantSliceHeaderParamsEnabledFlag = 1; @@ -3283,7 +3305,11 @@ bool EncAppCfg::xCheckParameter() m_PPSMvdL1ZeroIdc = 0; m_PPSCollocatedFromL0Idc = 0; m_PPSSixMinusMaxNumMergeCandPlus1 = 6 - m_maxNumMergeCand + 1; +#if !JVET_Q0806 m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = m_maxNumMergeCand - m_maxNumTriangleCand + 1; +#else + m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 = m_maxNumMergeCand - m_maxNumGeoCand + 1; +#endif break; case 2: // LDB setting m_constantSliceHeaderParamsEnabledFlag = 1; @@ -3293,7 +3319,11 @@ bool EncAppCfg::xCheckParameter() m_PPSMvdL1ZeroIdc = 2; m_PPSCollocatedFromL0Idc = 1; m_PPSSixMinusMaxNumMergeCandPlus1 = 6 - m_maxNumMergeCand + 1; +#if !JVET_Q0806 m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = m_maxNumMergeCand - m_maxNumTriangleCand + 1; +#else + m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 = m_maxNumMergeCand - m_maxNumGeoCand + 1; +#endif break; case 3: // LDP setting m_constantSliceHeaderParamsEnabledFlag = 1; @@ -3303,7 +3333,11 @@ bool EncAppCfg::xCheckParameter() m_PPSMvdL1ZeroIdc = 0; m_PPSCollocatedFromL0Idc = 0; m_PPSSixMinusMaxNumMergeCandPlus1 = 6 - m_maxNumMergeCand + 1; +#if !JVET_Q0806 m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = 0; +#else + m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 = 0; +#endif break; default: THROW("Invalid value for PPSorSliceMode"); @@ -3598,7 +3632,11 @@ void EncAppCfg::xPrintParameter() msg( DETAILS, "Max Num Merge Candidates : %d\n", m_maxNumMergeCand ); msg( DETAILS, "Max Num Affine Merge Candidates : %d\n", m_maxNumAffineMergeCand ); +#if !JVET_Q0806 msg( DETAILS, "Max Num Triangle Merge Candidates : %d\n", m_maxNumTriangleCand ); +#else + msg( DETAILS, "Max Num Geo Merge Candidates : %d\n", m_maxNumGeoCand ); +#endif msg( DETAILS, "Max Num IBC Merge Candidates : %d\n", m_maxNumIBCMergeCand ); msg( DETAILS, "\n"); @@ -3675,7 +3713,11 @@ void EncAppCfg::xPrintParameter() msg( VERBOSE, "LADF:%d ", m_LadfEnabed ); #endif msg(VERBOSE, "CIIP:%d ", m_ciip); +#if !JVET_Q0806 msg( VERBOSE, "Triangle:%d ", m_Triangle ); +#else + msg( VERBOSE, "Geo:%d ", m_Geo ); +#endif m_allowDisFracMMVD = m_MMVD ? m_allowDisFracMMVD : false; if ( m_MMVD ) msg(VERBOSE, "AllowDisFracMMVD:%d ", m_allowDisFracMMVD); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 73559591cc37743aef0c2b9e523b944e3dbe5696..247379852806b35742d1f769e4d178602c867c9d 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -157,7 +157,11 @@ protected: bool m_noIbcConstraintFlag; bool m_bNoCiipConstraintFlag; bool m_noFPelMmvdConstraintFlag; +#if !JVET_Q0806 bool m_bNoTriangleConstraintFlag; +#else + bool m_noGeoConstraintFlag; +#endif bool m_bNoLadfConstraintFlag; bool m_noTransformSkipConstraintFlag; bool m_noBDPCMConstraintFlag; @@ -311,7 +315,11 @@ protected: #endif bool m_ciip; +#if !JVET_Q0806 bool m_Triangle; +#else + bool m_Geo; +#endif bool m_HashME; bool m_allowDisFracMMVD; bool m_AffineAmvr; @@ -592,7 +600,11 @@ protected: #endif uint32_t m_maxNumMergeCand; ///< Max number of merge candidates uint32_t m_maxNumAffineMergeCand; ///< Max number of affine merge candidates +#if !JVET_Q0806 uint32_t m_maxNumTriangleCand; +#else + uint32_t m_maxNumGeoCand; +#endif uint32_t m_maxNumIBCMergeCand; ///< Max number of IBC merge candidates bool m_sliceLevelRpl; ///< code reference picture lists in slice headers rather than picture header @@ -608,7 +620,11 @@ protected: int m_PPSMvdL1ZeroIdc; int m_PPSCollocatedFromL0Idc; uint32_t m_PPSSixMinusMaxNumMergeCandPlus1; +#if !JVET_Q0806 uint32_t m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1; +#else + uint32_t m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1; +#endif bool m_depQuantEnabledFlag; bool m_signDataHidingEnabledFlag; bool m_RCEnableRateControl; ///< enable rate control or not diff --git a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp index b1ef4b056c62ed8c62b353fd8829ad0cf7703eeb..4d862ff95008c1b7543b0f1d53f480f329e066ea 100644 --- a/source/Lib/CommonLib/AdaptiveLoopFilter.cpp +++ b/source/Lib/CommonLib/AdaptiveLoopFilter.cpp @@ -294,20 +294,16 @@ void AdaptiveLoopFilter::applyCcAlfFilter(CodingStructure &cs, ComponentID compI const short filterSet[MAX_NUM_CC_ALF_FILTERS][MAX_NUM_CC_ALF_CHROMA_COEFF], const int selectedFilterIdx) { + bool clipTop = false, clipBottom = false, clipLeft = false, clipRight = false; + int numHorVirBndry = 0, numVerVirBndry = 0; + int horVirBndryPos[] = { 0, 0, 0 }; + int verVirBndryPos[] = { 0, 0, 0 }; + int ctuIdx = 0; for( int yPos = 0; yPos < m_picHeight; yPos += m_maxCUHeight ) { for( int xPos = 0; xPos < m_picWidth; xPos += m_maxCUWidth ) { - const int width = ( xPos + m_maxCUWidth > m_picWidth ) ? ( m_picWidth - xPos ) : m_maxCUWidth; - const int height = ( yPos + m_maxCUHeight > m_picHeight ) ? ( m_picHeight - yPos ) : m_maxCUHeight; - const UnitArea area( m_chromaFormat, Area( xPos, yPos, width, height ) ); - const int chromaScaleX = getComponentScaleX( compID, m_chromaFormat ); - const int chromaScaleY = getComponentScaleY( compID, m_chromaFormat ); - - Area blkDst(xPos >> chromaScaleX, yPos >> chromaScaleY, width >> chromaScaleX, height >> chromaScaleY); - Area blkSrc(xPos, yPos, width, height); - int filterIdx = (filterControl == nullptr) ? selectedFilterIdx @@ -320,8 +316,73 @@ void AdaptiveLoopFilter::applyCcAlfFilter(CodingStructure &cs, ComponentID compI const int16_t *filterCoeff = filterSet[filterIdx]; - m_filterCcAlf(dstBuf, recYuvExt, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_alfVBLumaCTUHeight, - m_alfVBLumaPos); + const int width = (xPos + m_maxCUWidth > m_picWidth) ? (m_picWidth - xPos) : m_maxCUWidth; + const int height = (yPos + m_maxCUHeight > m_picHeight) ? (m_picHeight - yPos) : m_maxCUHeight; + const int chromaScaleX = getComponentScaleX(compID, m_chromaFormat); + const int chromaScaleY = getComponentScaleY(compID, m_chromaFormat); + + int rasterSliceAlfPad = 0; + if (isCrossedByVirtualBoundaries(cs, xPos, yPos, width, height, clipTop, clipBottom, clipLeft, clipRight, + numHorVirBndry, numVerVirBndry, horVirBndryPos, verVirBndryPos, + rasterSliceAlfPad)) + { + int yStart = yPos; + for (int i = 0; i <= numHorVirBndry; i++) + { + const int yEnd = i == numHorVirBndry ? yPos + height : horVirBndryPos[i]; + const int h = yEnd - yStart; + const bool clipT = (i == 0 && clipTop) || (i > 0) || (yStart == 0); + const bool clipB = (i == numHorVirBndry && clipBottom) || (i < numHorVirBndry) || (yEnd == m_picHeight); + int xStart = xPos; + for (int j = 0; j <= numVerVirBndry; j++) + { + const int xEnd = j == numVerVirBndry ? xPos + width : verVirBndryPos[j]; + const int w = xEnd - xStart; + const bool clipL = (j == 0 && clipLeft) || (j > 0) || (xStart == 0); + const bool clipR = (j == numVerVirBndry && clipRight) || (j < numVerVirBndry) || (xEnd == m_picWidth); + const int wBuf = w + (clipL ? 0 : MAX_ALF_PADDING_SIZE) + (clipR ? 0 : MAX_ALF_PADDING_SIZE); + const int hBuf = h + (clipT ? 0 : MAX_ALF_PADDING_SIZE) + (clipB ? 0 : MAX_ALF_PADDING_SIZE); + PelUnitBuf buf = m_tempBuf2.subBuf(UnitArea(cs.area.chromaFormat, Area(0, 0, wBuf, hBuf))); + buf.copyFrom(recYuvExt.subBuf( + UnitArea(cs.area.chromaFormat, Area(xStart - (clipL ? 0 : MAX_ALF_PADDING_SIZE), + yStart - (clipT ? 0 : MAX_ALF_PADDING_SIZE), wBuf, hBuf)))); + // pad top-left unavailable samples for raster slice + if (xStart == xPos && yStart == yPos && (rasterSliceAlfPad & 1)) + { + buf.padBorderPel(MAX_ALF_PADDING_SIZE, 1); + } + + // pad bottom-right unavailable samples for raster slice + if (xEnd == xPos + width && yEnd == yPos + height && (rasterSliceAlfPad & 2)) + { + buf.padBorderPel(MAX_ALF_PADDING_SIZE, 2); + } + buf.extendBorderPel(MAX_ALF_PADDING_SIZE); + buf = buf.subBuf(UnitArea( + cs.area.chromaFormat, Area(clipL ? 0 : MAX_ALF_PADDING_SIZE, clipT ? 0 : MAX_ALF_PADDING_SIZE, w, h))); + + const Area blkSrc(0, 0, w, h); + + const Area blkDst(xStart >> chromaScaleX, yStart >> chromaScaleY, w >> chromaScaleX, h >> chromaScaleY); + m_filterCcAlf(dstBuf, buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_alfVBLumaCTUHeight, + m_alfVBLumaPos); + + xStart = xEnd; + } + + yStart = yEnd; + } + } + else + { + const UnitArea area(m_chromaFormat, Area(xPos, yPos, width, height)); + + Area blkDst(xPos >> chromaScaleX, yPos >> chromaScaleY, width >> chromaScaleX, height >> chromaScaleY); + Area blkSrc(xPos, yPos, width, height); + + m_filterCcAlf(dstBuf, recYuvExt, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_alfVBLumaCTUHeight, + m_alfVBLumaPos); + } } ctuIdx++; } @@ -474,13 +535,12 @@ void AdaptiveLoopFilter::ALFProcess(CodingStructure& cs) if (filterIdx != 0) { - const Area blkSrc(0, 0, w >> chromaScaleX, h >> chromaScaleY); - Area blkDst(xPos >> chromaScaleX, yPos >> chromaScaleY, width >> chromaScaleX, - height >> chromaScaleY); + const Area blkSrc(0, 0, w, h); + Area blkDst(xStart >> chromaScaleX, yStart >> chromaScaleY, w >> chromaScaleX, h >> chromaScaleY); const int16_t *filterCoeff = m_ccAlfFilterParam.ccAlfCoeff[compIdx - 1][filterIdx - 1]; - m_filterCcAlf(recYuv.get(compID), tmpYuv, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, + m_filterCcAlf(recYuv.get(compID), buf, blkDst, blkSrc, compID, filterCoeff, m_clpRngs, cs, m_alfVBLumaCTUHeight, m_alfVBLumaPos); } } diff --git a/source/Lib/CommonLib/Buffer.cpp b/source/Lib/CommonLib/Buffer.cpp index 8320dbe7c8ae76e93689d0b7b581b5681bd9696d..7b59a40e88aaed51824cbecb6fa4f7aae3a9e1b4 100644 --- a/source/Lib/CommonLib/Buffer.cpp +++ b/source/Lib/CommonLib/Buffer.cpp @@ -553,6 +553,38 @@ void AreaBuf<Pel>::copyClip( const AreaBuf<const Pel> &src, const ClpRng& clpRng } } +#if JVET_Q0806 +template<> +void AreaBuf<Pel>::roundToOutputBitdepth( const AreaBuf<const Pel> &src, const ClpRng& clpRng ) +{ + const Pel* srcp = src.buf; + Pel* dest = buf; + const unsigned srcStride = src.stride; + const unsigned destStride = stride; + + const int32_t clipbd = clpRng.bd; + const int32_t shiftDefault = std::max<int>(2, (IF_INTERNAL_PREC - clipbd)); + const int32_t offsetDefault = (1<<(shiftDefault-1)) + IF_INTERNAL_OFFS; + + if( width == 1 ) + { + THROW( "Blocks of width = 1 not supported" ); + } + else + { +#define RND_OP( ADDR ) dest[ADDR] = ClipPel( rightShift( srcp[ADDR] + offsetDefault, shiftDefault), clpRng ) +#define RND_INC \ + srcp += srcStride; \ + dest += destStride; \ + + SIZE_AWARE_PER_EL_OP( RND_OP, RND_INC ); + +#undef RND_OP +#undef RND_INC + } +} +#endif + template<> void AreaBuf<Pel>::reconstruct( const AreaBuf<const Pel> &pred, const AreaBuf<const Pel> &resi, const ClpRng& clpRng ) diff --git a/source/Lib/CommonLib/Buffer.h b/source/Lib/CommonLib/Buffer.h index 0fbd97a5edcceb94333a08174c9ad91a48e0a555..fa72565ba5dcf5e4ebeac4fd2bfaca4d7593accc 100644 --- a/source/Lib/CommonLib/Buffer.h +++ b/source/Lib/CommonLib/Buffer.h @@ -110,6 +110,9 @@ struct AreaBuf : public Size void memset ( const int val ); void copyFrom ( const AreaBuf<const T> &other ); +#if JVET_Q0806 + void roundToOutputBitdepth(const AreaBuf<const T> &src, const ClpRng& clpRng); +#endif void reconstruct ( const AreaBuf<const T> &pred, const AreaBuf<const T> &resi, const ClpRng& clpRng); void copyClip ( const AreaBuf<const T> &src, const ClpRng& clpRng); @@ -764,6 +767,9 @@ struct UnitBuf void fill ( const T &val ); void copyFrom ( const UnitBuf<const T> &other, const bool lumaOnly = false, const bool chromaOnly = false ); +#if JVET_Q0806 + void roundToOutputBitdepth(const UnitBuf<const T> &src, const ClpRngs& clpRngs); +#endif void reconstruct ( const UnitBuf<const T> &pred, const UnitBuf<const T> &resi, const ClpRngs& clpRngs ); void copyClip ( const UnitBuf<const T> &src, const ClpRngs& clpRngs, const bool lumaOnly = false, const bool chromaOnly = false ); void subtract ( const UnitBuf<const T> &other ); @@ -843,6 +849,19 @@ void UnitBuf<T>::copyClip(const UnitBuf<const T> &src, const ClpRngs &clpRngs, c } +#if JVET_Q0806 +template<typename T> +void UnitBuf<T>::roundToOutputBitdepth(const UnitBuf<const T> &src, const ClpRngs& clpRngs) +{ + CHECK(chromaFormat != src.chromaFormat, "Incompatible formats"); + + for (unsigned i = 0; i < bufs.size(); i++) + { + bufs[i].roundToOutputBitdepth(src.bufs[i], clpRngs.comp[i]); + } +} +#endif + template<typename T> void UnitBuf<T>::reconstruct(const UnitBuf<const T> &pred, const UnitBuf<const T> &resi, const ClpRngs& clpRngs) { diff --git a/source/Lib/CommonLib/CodingStatistics.h b/source/Lib/CommonLib/CodingStatistics.h index 59b610717e1fd61074fa6cb2c88217775b98f38b..7c0ad7af7ecca5b2bb650e9045a49bdbe4acd933 100644 --- a/source/Lib/CommonLib/CodingStatistics.h +++ b/source/Lib/CommonLib/CodingStatistics.h @@ -112,8 +112,13 @@ enum CodingStatisticsType STATS__CABAC_BITS__BCW_IDX, STATS__CABAC_BITS__SBT_MODE, STATS__CABAC_BITS__MH_INTRA_FLAG, +#if !JVET_Q0806 STATS__CABAC_BITS__TRIANGLE_FLAG, STATS__CABAC_BITS__TRIANGLE_INDEX, +#else + STATS__CABAC_BITS__GEO_FLAG, + STATS__CABAC_BITS__GEO_INDEX, +#endif STATS__CABAC_BITS__MULTI_REF_LINE, STATS__CABAC_BITS__SYMMVD_FLAG, STATS__CABAC_BITS__BDPCM_MODE, @@ -207,8 +212,13 @@ static inline const char* getName(CodingStatisticsType name) "CABAC_BITS__BCW_IDX", "CABAC_BITS__SBT_MODE", "CABAC_BITS__MH_INTRA_FLAG", +#if !JVET_Q0806 "CABAC_BITS__TRIANGLE_FLAG", "CABAC_BITS__TRIANGLE_INDEX", +#else + "CABAC_BITS__GEO_FLAG", + "CABAC_BITS__GEO_INDEX", +#endif "CABAC_BITS__MULTI_REF_LINE", "CABAC_BITS__SYMMVD_FLAG", "CABAC_BITS__BDPCM_MODE", diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index fb83cf5b8b4b13bc96acbccc099206c2aa30b324..4f1864b5f21ee9cd9fb760c1feed4ece53561611 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -427,11 +427,29 @@ static const int MAX_LADF_INTERVALS = 5; /// max n static const int NTAPS_BILINEAR = 2; ///< Number of taps for bilinear filter static const int ATMVP_SUB_BLOCK_SIZE = 3; ///< sub-block size for ATMVP +#if !JVET_Q0806 static const int TRIANGLE_MAX_NUM_UNI_CANDS = 6; static const int TRIANGLE_MAX_NUM_CANDS_MEM = 7; static const int TRIANGLE_MAX_NUM_CANDS = TRIANGLE_MAX_NUM_UNI_CANDS * (TRIANGLE_MAX_NUM_UNI_CANDS - 1) * 2; static const int TRIANGLE_MAX_NUM_SATD_CANDS = 3; static const int TRIANGLE_MIN_SIZE = 8 * 8; +#else +static const int GEO_MAX_NUM_UNI_CANDS = 6; +static const int GEO_MAX_NUM_CANDS = GEO_MAX_NUM_UNI_CANDS * (GEO_MAX_NUM_UNI_CANDS - 1); +static const int GEO_MIN_CU_LOG2 = 3; +static const int GEO_MAX_CU_LOG2 = 6; +static const int GEO_MIN_CU_SIZE = 1 << GEO_MIN_CU_LOG2; +static const int GEO_MAX_CU_SIZE = 1 << GEO_MAX_CU_LOG2; +static const int GEO_NUM_CU_SIZE = ( GEO_MAX_CU_LOG2 - GEO_MIN_CU_LOG2 ) + 1; +static const int GEO_NUM_PARTITION_MODE = 64; +static const int GEO_NUM_ANGLES = 32; +static const int GEO_NUM_DISTANCES = 4; +static const int GEO_NUM_PRESTORED_MASK = 6; +static const int GEO_WEIGHT_MASK_SIZE = 3 * (GEO_MAX_CU_SIZE >> 3) * 2 + GEO_MAX_CU_SIZE; +static const int GEO_MV_MASK_SIZE = GEO_WEIGHT_MASK_SIZE >> 2; +static const int GEO_MAX_TRY_WEIGHTED_SAD = 60; +static const int GEO_MAX_TRY_WEIGHTED_SATD = 8; +#endif static const int SBT_MAX_SIZE = 64; ///< maximum CU size for using SBT static const int SBT_NUM_SL = 10; ///< maximum number of historical PU decision saved for a CU diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index a8cd73368084658fcad816d2629de404833d639a..6913c4d54f3075d930bc7a96a4922abc5a106e12 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -320,11 +320,19 @@ unsigned DeriveCtx::CtxIBCFlag(const CodingUnit& cu) void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) { CHECK( candIdx >= numValidMergeCand, "Merge candidate does not exist" ); +#if !JVET_Q0806 pu.regularMergeFlag = !(pu.ciipFlag || pu.cu->triangle); +#else + pu.regularMergeFlag = !(pu.ciipFlag || pu.cu->geoFlag); +#endif pu.mergeFlag = true; pu.mmvdMergeFlag = false; pu.interDir = interDirNeighbours[candIdx]; +#if !JVET_Q0806 pu.cu->imv = (!pu.cu->triangle && useAltHpelIf[candIdx]) ? IMV_HPEL : 0; +#else + pu.cu->imv = (!pu.cu->geoFlag && useAltHpelIf[candIdx]) ? IMV_HPEL : 0; +#endif pu.mergeIdx = candIdx; pu.mergeType = mrgTypeNeighbours[candIdx]; pu.mv [REF_PIC_LIST_0] = mvFieldNeighbours[(candIdx << 1) + 0].mv; diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index d749d78e90b73f8a2d74bff6661b3d1e2faf79da..ab4a35f8d3ab128b876e3de87312cc35b567260c 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -126,7 +126,12 @@ void InterPrediction::destroy() } } +#if !JVET_Q0806 m_triangleBuf.destroy(); +#else + m_geoPartBuf[0].destroy(); + m_geoPartBuf[1].destroy(); +#endif m_colorTransResiBuf[0].destroy(); m_colorTransResiBuf[1].destroy(); m_colorTransResiBuf[2].destroy(); @@ -192,7 +197,12 @@ void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC, cons } } +#if !JVET_Q0806 m_triangleBuf.create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); +#else + m_geoPartBuf[0].create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); + m_geoPartBuf[1].create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); +#endif m_colorTransResiBuf[0].create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); m_colorTransResiBuf[1].create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); m_colorTransResiBuf[2].create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); @@ -629,7 +639,11 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co } else { +#if !JVET_Q0806 xPredInterUni( pu, eRefPicList, pcMbBuf, pu.cu->triangle +#else + xPredInterUni(pu, eRefPicList, pcMbBuf, pu.cu->geoFlag +#endif , bioApplied , luma, chroma ); @@ -644,13 +658,21 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[1][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[1][2], pcYuvPred.Cr())) ); const bool lumaOnly = luma && !chroma; const bool chromaOnly = !luma && chroma; +#if !JVET_Q0806 if( !pu.cu->triangle && (!dmvrApplied) && (!bioApplied) && pps.getWPBiPred() && slice.getSliceType() == B_SLICE && pu.cu->BcwIdx==BCW_DEFAULT) +#else + if( !pu.cu->geoFlag && (!dmvrApplied) && (!bioApplied) && pps.getWPBiPred() && slice.getSliceType() == B_SLICE && pu.cu->BcwIdx == BCW_DEFAULT) +#endif { xWeightedPredictionBi( pu, srcPred0, srcPred1, pcYuvPred, m_maxCompIDToPred, lumaOnly, chromaOnly ); if (yuvPredTmp) yuvPredTmp->copyFrom(pcYuvPred); } +#if !JVET_Q0806 else if( !pu.cu->triangle && pps.getUseWP() && slice.getSliceType() == P_SLICE ) +#else + else if( !pu.cu->geoFlag && pps.getUseWP() && slice.getSliceType() == P_SLICE ) +#endif { xWeightedPredictionUni( pu, srcPred0, REF_PIC_LIST_0, pcYuvPred, -1, m_maxCompIDToPred, lumaOnly, chromaOnly ); if (yuvPredTmp) @@ -1453,22 +1475,38 @@ void InterPrediction::xWeightedAverage(const PredictionUnit& pu, const CPelUnitB } else if( iRefIdx0 >= 0 && iRefIdx1 < 0 ) { +#if !JVET_Q0806 if( pu.cu->triangle ) { pcYuvDst.copyFrom( pcYuvSrc0 ); } else +#else + if( pu.cu->geoFlag ) + { + pcYuvDst.copyFrom( pcYuvSrc0 ); + } + else +#endif pcYuvDst.copyClip( pcYuvSrc0, clpRngs, lumaOnly, chromaOnly ); if (yuvDstTmp) yuvDstTmp->copyFrom( pcYuvDst, lumaOnly, chromaOnly ); } else if( iRefIdx0 < 0 && iRefIdx1 >= 0 ) { +#if !JVET_Q0806 if( pu.cu->triangle ) { pcYuvDst.copyFrom( pcYuvSrc1 ); } else +#else + if( pu.cu->geoFlag ) + { + pcYuvDst.copyFrom( pcYuvSrc1 ); + } + else +#endif pcYuvDst.copyClip( pcYuvSrc1, clpRngs, lumaOnly, chromaOnly ); if (yuvDstTmp) yuvDstTmp->copyFrom(pcYuvDst, lumaOnly, chromaOnly); @@ -1655,6 +1693,7 @@ int InterPrediction::rightShiftMSB(int numer, int denom) return numer >> floorLog2(denom); } +#if !JVET_Q0806 void InterPrediction::motionCompensation4Triangle( CodingUnit &cu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 ) { for( auto &pu : CU::traversePUs( cu ) ) @@ -1706,7 +1745,57 @@ void InterPrediction::weightedTriangleBlk( PredictionUnit &pu, const bool splitD m_if.weightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 ); } } +#else +void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx ) +{ + const uint8_t splitDir = cu.firstPU->geoSplitDir; + const uint8_t candIdx0 = cu.firstPU->geoMergeIdx0; + const uint8_t candIdx1 = cu.firstPU->geoMergeIdx1; + for( auto &pu : CU::traversePUs( cu ) ) + { + const UnitArea localUnitArea( cu.cs->area.chromaFormat, Area( 0, 0, pu.lwidth(), pu.lheight() ) ); + PelUnitBuf tmpGeoBuf0 = m_geoPartBuf[0].getBuf( localUnitArea ); + PelUnitBuf tmpGeoBuf1 = m_geoPartBuf[1].getBuf( localUnitArea ); + PelUnitBuf predBuf = cu.cs->getPredBuf( pu ); + + geoMrgCtx.setMergeInfo( pu, candIdx0 ); + PU::spanMotionInfo( pu ); + motionCompensation(pu, tmpGeoBuf0, REF_PIC_LIST_X, true, isChromaEnabled(pu.chromaFormat)); + if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) ) + { + printf( "DECODER_GEO_PU: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() ); + } + + geoMrgCtx.setMergeInfo( pu, candIdx1 ); + PU::spanMotionInfo( pu ); + motionCompensation(pu, tmpGeoBuf1, REF_PIC_LIST_X, true, isChromaEnabled(pu.chromaFormat)); + if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) ) + { + printf( "DECODER_GEO_PU: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() ); + } + weightedGeoBlk(pu, splitDir, isChromaEnabled(pu.chromaFormat)? MAX_NUM_CHANNEL_TYPE : CHANNEL_TYPE_LUMA, predBuf, tmpGeoBuf0, tmpGeoBuf1); + } +} +void InterPrediction::weightedGeoBlk( PredictionUnit &pu, const uint8_t splitDir, int32_t channel, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1) +{ + if( channel == CHANNEL_TYPE_LUMA ) + { + m_if.weightedGeoBlk( pu, pu.lumaSize().width, pu.lumaSize().height, COMPONENT_Y, splitDir, predDst, predSrc0, predSrc1 ); + } + else if( channel == CHANNEL_TYPE_CHROMA ) + { + m_if.weightedGeoBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, predDst, predSrc0, predSrc1 ); + m_if.weightedGeoBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 ); + } + else + { + m_if.weightedGeoBlk( pu, pu.lumaSize().width, pu.lumaSize().height, COMPONENT_Y, splitDir, predDst, predSrc0, predSrc1 ); + m_if.weightedGeoBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, predDst, predSrc0, predSrc1 ); + m_if.weightedGeoBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 ); + } +} +#endif void InterPrediction::xPrefetch(PredictionUnit& pu, PelUnitBuf &pcPad, RefPicList refId, bool forLuma) { diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index 1bc16ff8d7b567029f5eaff532713e6f850cb822..a7455d46186a691fddb8ec20d96a67a12b29a729 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -81,7 +81,11 @@ protected: RdCost* m_pcRdCost; int m_iRefListIdx; +#if !JVET_Q0806 PelStorage m_triangleBuf; +#else + PelStorage m_geoPartBuf[2]; +#endif Mv* m_storedMv; /*buffers for bilinear Filter data for DMVR refinement*/ Pel* m_cYuvPredTempDMVRL0; @@ -138,7 +142,9 @@ protected: void xCalcBlkGradient (int sx, int sy, int *arraysGx2, int *arraysGxGy, int *arraysGxdI, int *arraysGy2, int *arraysGydI, int &sGx2, int &sGy2, int &sGxGy, int &sGxdI, int &sGydI, int width, int height, int unitSize); void xWeightedAverage ( const PredictionUnit& pu, const CPelUnitBuf& pcYuvSrc0, const CPelUnitBuf& pcYuvSrc1, PelUnitBuf& pcYuvDst, const BitDepths& clipBitDepths, const ClpRngs& clpRngs, const bool& bioApplied, const bool lumaOnly = false, const bool chromaOnly = false, PelUnitBuf* yuvDstTmp = NULL ); void xPredAffineBlk ( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv* _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng, const bool genChromaMv = false, const std::pair<int, int> scalingRatio = SCALE_1X ); +#if !JVET_Q0806 void xWeightedTriangleBlk ( const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 ); +#endif static bool xCheckIdenticalMotion( const PredictionUnit& pu ); @@ -171,8 +177,13 @@ public: , const bool luma = true, const bool chroma = true ); +#if !JVET_Q0806 void motionCompensation4Triangle( CodingUnit &cu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 ); void weightedTriangleBlk ( PredictionUnit &pu, const bool splitDir, int32_t channel, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 ); +#else + void motionCompensationGeo(CodingUnit &cu, MergeCtx &GeoMrgCtx); + void weightedGeoBlk(PredictionUnit &pu, const uint8_t splitDir, int32_t channel, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); +#endif void xPrefetch(PredictionUnit& pu, PelUnitBuf &pcPad, RefPicList refId, bool forLuma); void xPad(PredictionUnit& pu, PelUnitBuf &pcPad, RefPicList refId); void xFinalPaddedMCForDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvSrc0, PelUnitBuf &pcYuvSrc1, PelUnitBuf &pcPad0, PelUnitBuf &pcPad1, const bool bioApplied diff --git a/source/Lib/CommonLib/InterpolationFilter.cpp b/source/Lib/CommonLib/InterpolationFilter.cpp index 77f46edcaef115d526d647209de596b041790405..5fb66c384000e6eb3a174233326180ed17e118c3 100644 --- a/source/Lib/CommonLib/InterpolationFilter.cpp +++ b/source/Lib/CommonLib/InterpolationFilter.cpp @@ -371,7 +371,11 @@ InterpolationFilter::InterpolationFilter() m_filterCopy[1][0] = filterCopy<true, false>; m_filterCopy[1][1] = filterCopy<true, true>; +#if !JVET_Q0806 m_weightedTriangleBlk = xWeightedTriangleBlk; +#else + m_weightedGeoBlk = xWeightedGeoBlk; +#endif } @@ -888,6 +892,7 @@ void InterpolationFilter::filterVer(const ComponentID compID, Pel const *src, in } } +#if !JVET_Q0806 void InterpolationFilter::xWeightedTriangleBlk( const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 ) { Pel* dst = predDst .get(compIdx).buf; @@ -983,6 +988,65 @@ void InterpolationFilter::weightedTriangleBlk(const PredictionUnit &pu, const ui { m_weightedTriangleBlk(pu, width, height, compIdx, splitDir, predDst, predSrc0, predSrc1); } +#else +void InterpolationFilter::weightedGeoBlk(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const uint8_t splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1) +{ + m_weightedGeoBlk(pu, width, height, compIdx, splitDir, predDst, predSrc0, predSrc1); +} + +void InterpolationFilter::xWeightedGeoBlk(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const uint8_t splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1) +{ + Pel* dst = predDst.get(compIdx).buf; + Pel* src0 = predSrc0.get(compIdx).buf; + Pel* src1 = predSrc1.get(compIdx).buf; + int32_t strideDst = predDst.get(compIdx).stride - width; + int32_t strideSrc0 = predSrc0.get(compIdx).stride - width; + int32_t strideSrc1 = predSrc1.get(compIdx).stride - width; + + const char log2WeightBase = 3; + const ClpRng clipRng = pu.cu->slice->clpRngs().comp[compIdx]; + const int32_t clipbd = clipRng.bd; + const int32_t shiftWeighted = std::max<int>(2, (IF_INTERNAL_PREC - clipbd)) + log2WeightBase; + const int32_t offsetWeighted = (1 << (shiftWeighted - 1)) + (IF_INTERNAL_OFFS << log2WeightBase); + const uint32_t scaleX = getComponentScaleX(compIdx, pu.chromaFormat); + const uint32_t scaleY = getComponentScaleY(compIdx, pu.chromaFormat); + + int16_t angle = g_GeoParams[splitDir][0]; + int16_t wIdx = floorLog2(pu.lwidth()) - GEO_MIN_CU_LOG2; + int16_t hIdx = floorLog2(pu.lheight()) - GEO_MIN_CU_LOG2; + int16_t stepX = 1 << scaleX; + int16_t stepY = 0; + int16_t* weight = nullptr; + if (g_angle2mirror[angle] == 2) + { + stepY = -(int)((GEO_WEIGHT_MASK_SIZE << scaleY) + pu.lwidth()); + weight = &g_globalGeoWeights[g_angle2mask[angle]][(GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[splitDir][hIdx][wIdx][1]) * GEO_WEIGHT_MASK_SIZE + g_weightOffset[splitDir][hIdx][wIdx][0]]; + } + else if (g_angle2mirror[angle] == 1) + { + stepX = -1 << scaleX; + stepY = (GEO_WEIGHT_MASK_SIZE << scaleY) + pu.lwidth(); + weight = &g_globalGeoWeights[g_angle2mask[angle]][g_weightOffset[splitDir][hIdx][wIdx][1] * GEO_WEIGHT_MASK_SIZE + (GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[splitDir][hIdx][wIdx][0])]; + } + else + { + stepY = (GEO_WEIGHT_MASK_SIZE << scaleY) - pu.lwidth(); + weight = &g_globalGeoWeights[g_angle2mask[angle]][g_weightOffset[splitDir][hIdx][wIdx][1] * GEO_WEIGHT_MASK_SIZE + g_weightOffset[splitDir][hIdx][wIdx][0]]; + } + for( int y = 0; y < height; y++ ) + { + for( int x = 0; x < width; x++ ) + { + *dst++ = ClipPel(rightShift((*weight*(*src0++) + ((8 - *weight) * (*src1++)) + offsetWeighted), shiftWeighted), clipRng); + weight += stepX; + } + dst += strideDst; + src0 += strideSrc0; + src1 += strideSrc1; + weight += stepY; + } +} +#endif /** * \brief turn on SIMD fuc diff --git a/source/Lib/CommonLib/InterpolationFilter.h b/source/Lib/CommonLib/InterpolationFilter.h index db2a0846381e46ac152241b9a7357f64cca8640a..c166395af7ec59bb1e37dad27a2c3436d81e0a96 100644 --- a/source/Lib/CommonLib/InterpolationFilter.h +++ b/source/Lib/CommonLib/InterpolationFilter.h @@ -83,8 +83,13 @@ public: template<int N> void filterVer(const ClpRng& clpRng, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, bool isFirst, bool isLast, TFilterCoeff const *coeff, bool biMCForDMVR); +#if !JVET_Q0806 static void xWeightedTriangleBlk(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); void weightedTriangleBlk(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); +#else + static void xWeightedGeoBlk(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const uint8_t splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); + void weightedGeoBlk(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const uint8_t splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); +#endif protected: #if JVET_J0090_MEMORY_BANDWITH_MEASURE static CacheModel* m_cacheModel; @@ -95,7 +100,11 @@ public: void( *m_filterHor[3][2][2] )( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff, bool biMCForDMVR); void( *m_filterVer[3][2][2] )( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, TFilterCoeff const *coeff, bool biMCForDMVR); void( *m_filterCopy[2][2] ) ( const ClpRng& clpRng, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, bool biMCForDMVR); +#if !JVET_Q0806 void( *m_weightedTriangleBlk )(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); +#else + void( *m_weightedGeoBlk )(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const uint8_t splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1); +#endif void initInterpolationFilter( bool enable ); #ifdef TARGET_SIMD_X86 diff --git a/source/Lib/CommonLib/MatrixIntraPrediction.cpp b/source/Lib/CommonLib/MatrixIntraPrediction.cpp index f3376aa25da490108aa96b72541b597bebead49c..af6adae25633456c844c2b326f7b96c4badb8d7d 100644 --- a/source/Lib/CommonLib/MatrixIntraPrediction.cpp +++ b/source/Lib/CommonLib/MatrixIntraPrediction.cpp @@ -105,8 +105,13 @@ void MatrixIntraPrediction::prepareInputForPred(const CPelBuf &pSrc, const Area& m_inputOffsetTransp = m_reducedBoundaryTransposed[0]; const bool hasFirstCol = (m_sizeId < 2); +#if JVET_Q0446_MIP_CONST_SHIFT_OFFSET + m_reducedBoundary [0] = hasFirstCol ? ((1 << (bitDepth - 1)) - m_inputOffset ) : 0; // first column of matrix not needed for large blocks + m_reducedBoundaryTransposed[0] = hasFirstCol ? ((1 << (bitDepth - 1)) - m_inputOffsetTransp) : 0; +#else m_reducedBoundary [0] = hasFirstCol ? (m_inputOffset - (1 << (bitDepth - 1))) : 0; // first column of matrix not needed for large blocks m_reducedBoundaryTransposed[0] = hasFirstCol ? (m_inputOffsetTransp - (1 << (bitDepth - 1))) : 0; +#endif for (int i = 1; i < inputSize; i++) { m_reducedBoundary [i] -= m_inputOffset; @@ -118,14 +123,22 @@ void MatrixIntraPrediction::predBlock(int* const result, const int modeIdx, cons { const bool needUpsampling = ( m_upsmpFactorHor > 1 ) || ( m_upsmpFactorVer > 1 ); +#if JVET_Q0446_MIP_CONST_SHIFT_OFFSET + const uint8_t* matrix = getMatrixData(modeIdx); +#else const uint8_t* matrix; int shiftMatrix = 0, offsetMatrix = 0; getMatrixData(matrix, shiftMatrix, offsetMatrix, modeIdx); +#endif static_vector<int, MIP_MAX_REDUCED_OUTPUT_SAMPLES> bufReducedPred( m_reducedPredSize * m_reducedPredSize ); int* const reducedPred = needUpsampling ? bufReducedPred.data() : result; const int* const reducedBoundary = transpose ? m_reducedBoundaryTransposed.data() : m_reducedBoundary.data(); +#if JVET_Q0446_MIP_CONST_SHIFT_OFFSET + computeReducedPred(reducedPred, reducedBoundary, matrix, transpose, bitDepth); +#else computeReducedPred( reducedPred, reducedBoundary, matrix, shiftMatrix, offsetMatrix, transpose, bitDepth ); +#endif if( needUpsampling ) { predictionUpsampling( result, reducedPred ); @@ -262,10 +275,21 @@ void MatrixIntraPrediction::predictionUpsampling( int* const dst, const int* con } } +#if JVET_Q0446_MIP_CONST_SHIFT_OFFSET +const uint8_t* MatrixIntraPrediction::getMatrixData(const int modeIdx) const +#else void MatrixIntraPrediction::getMatrixData(const uint8_t*& matrix, int &shiftMatrix, int &offsetMatrix, const int modeIdx) const +#endif { switch( m_sizeId ) { +#if JVET_Q0446_MIP_CONST_SHIFT_OFFSET + case 0: return &mipMatrix4x4[modeIdx][0][0]; + + case 1: return &mipMatrix8x8[modeIdx][0][0]; + + case 2: return &mipMatrix16x16[modeIdx][0][0]; +#else case 0: matrix = &mipMatrix4x4 [modeIdx][0][0]; shiftMatrix = mipShiftMatrix4x4 [modeIdx]; offsetMatrix = mipOffsetMatrix4x4[modeIdx]; @@ -280,13 +304,18 @@ void MatrixIntraPrediction::getMatrixData(const uint8_t*& matrix, int &shiftMatr shiftMatrix = mipShiftMatrix16x16 [modeIdx]; offsetMatrix = mipOffsetMatrix16x16[modeIdx]; break; +#endif default: THROW( "Invalid mipSizeId" ); } } void MatrixIntraPrediction::computeReducedPred( int*const result, const int* const input, +#if JVET_Q0446_MIP_CONST_SHIFT_OFFSET + const uint8_t* matrix, +#else const uint8_t*matrix, const int shiftMatrix, const int offsetMatrix, +#endif const bool transpose, const int bitDepth ) { const int inputSize = 2 * m_reducedBdrySize; @@ -297,7 +326,11 @@ void MatrixIntraPrediction::computeReducedPred( int*const result, const int* con int sum = 0; for( int i = 0; i < inputSize; i++ ) { sum += input[i]; } +#if JVET_Q0446_MIP_CONST_SHIFT_OFFSET + const int offset = (1 << (MIP_SHIFT_MATRIX - 1)) - MIP_OFFSET_MATRIX * sum; +#else const int offset = (1 << (shiftMatrix - 1)) - offsetMatrix * sum; +#endif CHECK( inputSize != 4 * (inputSize >> 2), "Error, input size not divisible by four" ); const uint8_t *weight = matrix; @@ -321,7 +354,11 @@ void MatrixIntraPrediction::computeReducedPred( int*const result, const int* con tmp2 += input[i + 2] * weight[i + 2]; tmp3 += input[i + 3] * weight[i + 3]; } +#if JVET_Q0446_MIP_CONST_SHIFT_OFFSET + resPtr[posRes++] = ClipBD<int>(((tmp0 + tmp1 + tmp2 + tmp3 + offset) >> MIP_SHIFT_MATRIX) + inputOffset, bitDepth); +#else resPtr[posRes++] = ClipBD<int>( ((tmp0 + tmp1 + tmp2 + tmp3 + offset) >> shiftMatrix) + inputOffset, bitDepth ); +#endif weight += inputSize; } diff --git a/source/Lib/CommonLib/MatrixIntraPrediction.h b/source/Lib/CommonLib/MatrixIntraPrediction.h index bf90ae11d4ea414386fe60c855787d8d8f11ae86..2452150d3f6fa46c020f2fd704e64554292cbf1c 100644 --- a/source/Lib/CommonLib/MatrixIntraPrediction.h +++ b/source/Lib/CommonLib/MatrixIntraPrediction.h @@ -80,11 +80,19 @@ public: const SizeType bndryStep, const unsigned int upsmpFactor ); +#if JVET_Q0446_MIP_CONST_SHIFT_OFFSET + const uint8_t* getMatrixData(const int modeIdx) const; +#else void getMatrixData(const uint8_t*& matrix, int &shiftMatrix, int &offsetMatrix, const int modeIdx) const; +#endif void computeReducedPred( int*const result, const int* const input, +#if JVET_Q0446_MIP_CONST_SHIFT_OFFSET + const uint8_t* matrix, +#else const uint8_t*matrix, const int shiftMatrix, const int offsetMatrix, +#endif const bool transpose, const int bitDepth ); }; diff --git a/source/Lib/CommonLib/MipData.h b/source/Lib/CommonLib/MipData.h index 487565eb11e846bbc5f4e9e279f855e54f786d11..7200a9f85234c563ecd95bdb1de60e1d6d203656 100644 --- a/source/Lib/CommonLib/MipData.h +++ b/source/Lib/CommonLib/MipData.h @@ -35,6 +35,850 @@ \brief weight and bias data for matrix-based intra prediction (MIP) */ +#if JVET_Q0446_MIP_CONST_SHIFT_OFFSET +static const uint8_t MIP_SHIFT_MATRIX = 6; +static const uint8_t MIP_OFFSET_MATRIX = 32; + +ALIGN_DATA(MEMORY_ALIGN_DEF_SIZE, const uint8_t mipMatrix4x4[16][16][4]) = +{ + { + { 32, 30, 90, 28}, + { 32, 32, 72, 28}, + { 34, 77, 53, 30}, + { 51, 124, 36, 37}, + { 31, 31, 95, 37}, + { 33, 31, 70, 50}, + { 52, 80, 25, 60}, + { 78, 107, 1, 65}, + { 31, 29, 37, 95}, + { 38, 34, 19, 101}, + { 73, 85, 0, 81}, + { 92, 99, 0, 65}, + { 34, 29, 14, 111}, + { 48, 48, 7, 100}, + { 80, 91, 0, 74}, + { 89, 97, 0, 64} + }, + { + { 31, 23, 34, 29}, + { 31, 43, 34, 31}, + { 30, 95, 34, 32}, + { 29, 100, 35, 33}, + { 31, 23, 34, 29}, + { 31, 43, 34, 31}, + { 30, 95, 34, 32}, + { 29, 99, 35, 33}, + { 31, 24, 35, 29}, + { 31, 44, 34, 31}, + { 30, 95, 35, 32}, + { 29, 99, 35, 33}, + { 31, 24, 35, 30}, + { 31, 44, 35, 31}, + { 30, 95, 35, 32}, + { 29, 99, 35, 33} + }, + { + { 32, 32, 36, 58}, + { 32, 29, 26, 66}, + { 36, 37, 23, 61}, + { 79, 84, 3, 37}, + { 32, 32, 30, 69}, + { 33, 29, 24, 71}, + { 44, 16, 21, 70}, + { 96, 18, 0, 57}, + { 32, 31, 24, 74}, + { 33, 30, 23, 71}, + { 36, 24, 24, 71}, + { 59, 9, 16, 68}, + { 32, 32, 23, 75}, + { 33, 30, 24, 70}, + { 32, 30, 25, 71}, + { 36, 26, 25, 70} + }, + { + { 32, 33, 34, 32}, + { 32, 30, 22, 38}, + { 29, 46, 25, 38}, + { 53, 123, 28, 22}, + { 32, 33, 30, 37}, + { 32, 30, 21, 38}, + { 32, 40, 24, 38}, + { 64, 116, 26, 17}, + { 32, 32, 23, 49}, + { 32, 30, 21, 39}, + { 34, 39, 24, 37}, + { 72, 109, 23, 16}, + { 33, 31, 17, 60}, + { 32, 31, 21, 39}, + { 35, 41, 24, 37}, + { 72, 106, 22, 18} + }, + { + { 34, 25, 89, 20}, + { 38, 32, 47, 24}, + { 40, 86, 29, 27}, + { 38, 98, 32, 29}, + { 34, 31, 94, 40}, + { 44, 25, 83, 27}, + { 54, 72, 43, 16}, + { 47, 94, 33, 22}, + { 33, 31, 36, 94}, + { 43, 23, 51, 76}, + { 62, 55, 64, 25}, + { 57, 89, 38, 15}, + { 32, 32, 28, 101}, + { 38, 26, 33, 94}, + { 55, 38, 68, 47}, + { 59, 80, 52, 16} + }, + { + { 28, 30, 68, 29}, + { 23, 48, 23, 48}, + { 39, 98, 16, 42}, + { 84, 86, 20, 17}, + { 25, 31, 52, 74}, + { 38, 68, 5, 70}, + { 95, 78, 7, 21}, + { 127, 54, 12, 0}, + { 30, 47, 14, 107}, + { 79, 76, 0, 53}, + { 127, 59, 7, 1}, + { 127, 51, 9, 0}, + { 50, 71, 1, 96}, + { 109, 69, 7, 25}, + { 127, 56, 9, 0}, + { 123, 53, 13, 0} + }, + { + { 40, 20, 72, 18}, + { 48, 29, 44, 18}, + { 53, 81, 35, 18}, + { 48, 96, 33, 22}, + { 45, 23, 79, 49}, + { 61, 21, 56, 49}, + { 72, 52, 32, 48}, + { 65, 69, 20, 50}, + { 41, 27, 29, 96}, + { 49, 22, 28, 94}, + { 52, 22, 28, 93}, + { 49, 27, 27, 92}, + { 37, 29, 26, 98}, + { 39, 28, 28, 97}, + { 38, 28, 30, 97}, + { 38, 29, 30, 95} + }, + { + { 33, 27, 43, 27}, + { 32, 29, 31, 31}, + { 31, 73, 33, 31}, + { 35, 104, 34, 28}, + { 32, 30, 63, 22}, + { 33, 26, 33, 29}, + { 33, 57, 33, 30}, + { 37, 100, 35, 27}, + { 32, 31, 85, 25}, + { 34, 25, 39, 25}, + { 35, 39, 32, 28}, + { 40, 91, 35, 25}, + { 32, 30, 77, 50}, + { 34, 26, 54, 22}, + { 37, 31, 34, 27}, + { 45, 75, 34, 23} + }, + { + { 34, 25, 77, 19}, + { 36, 34, 56, 24}, + { 41, 83, 39, 30}, + { 47, 96, 28, 35}, + { 34, 31, 70, 65}, + { 38, 29, 53, 77}, + { 43, 36, 37, 83}, + { 48, 39, 28, 83}, + { 33, 31, 31, 98}, + { 33, 31, 30, 99}, + { 34, 30, 31, 98}, + { 36, 29, 31, 96}, + { 32, 32, 30, 97}, + { 32, 32, 31, 96}, + { 31, 33, 33, 96}, + { 32, 33, 34, 94} + }, + { + { 30, 30, 93, 19}, + { 31, 59, 67, 34}, + { 31, 79, 36, 59}, + { 30, 67, 17, 79}, + { 30, 38, 68, 69}, + { 29, 40, 43, 91}, + { 26, 35, 32, 101}, + { 23, 32, 30, 101}, + { 26, 34, 30, 101}, + { 23, 33, 30, 102}, + { 20, 32, 31, 102}, + { 18, 33, 32, 102}, + { 23, 33, 31, 100}, + { 20, 34, 32, 100}, + { 18, 35, 33, 100}, + { 18, 35, 33, 100} + }, + { + { 31, 54, 90, 26}, + { 32, 60, 53, 61}, + { 34, 49, 37, 84}, + { 34, 39, 35, 89}, + { 35, 38, 41, 88}, + { 35, 35, 32, 96}, + { 35, 31, 33, 96}, + { 35, 32, 35, 94}, + { 34, 34, 30, 97}, + { 35, 32, 33, 95}, + { 35, 32, 34, 94}, + { 35, 34, 34, 93}, + { 34, 34, 34, 93}, + { 35, 34, 34, 93}, + { 35, 34, 34, 92}, + { 36, 34, 35, 91} + }, + { + { 32, 29, 54, 24}, + { 31, 32, 34, 29}, + { 31, 43, 34, 29}, + { 32, 67, 36, 28}, + { 31, 34, 69, 37}, + { 31, 35, 46, 33}, + { 30, 35, 39, 33}, + { 30, 42, 39, 36}, + { 31, 35, 39, 88}, + { 30, 38, 41, 84}, + { 30, 39, 40, 81}, + { 39, 46, 38, 78}, + { 31, 36, 34, 96}, + { 34, 38, 37, 93}, + { 55, 42, 38, 82}, + { 89, 53, 38, 65} + }, + { + { 32, 33, 43, 29}, + { 32, 30, 29, 33}, + { 31, 47, 31, 33}, + { 33, 100, 31, 31}, + { 32, 33, 74, 25}, + { 32, 32, 34, 31}, + { 32, 33, 30, 33}, + { 32, 68, 30, 32}, + { 32, 31, 91, 40}, + { 32, 32, 58, 26}, + { 31, 31, 30, 32}, + { 31, 42, 30, 33}, + { 32, 31, 49, 85}, + { 32, 31, 83, 35}, + { 31, 33, 48, 29}, + { 31, 36, 32, 33} + }, + { + { 31, 29, 81, 35}, + { 32, 28, 34, 50}, + { 31, 75, 16, 43}, + { 34, 103, 29, 32}, + { 32, 32, 53, 78}, + { 31, 28, 36, 88}, + { 30, 52, 18, 73}, + { 52, 88, 17, 35}, + { 32, 32, 35, 94}, + { 30, 31, 35, 95}, + { 36, 29, 31, 92}, + { 100, 43, 16, 40}, + { 32, 32, 35, 93}, + { 30, 32, 38, 93}, + { 55, 18, 37, 83}, + { 127, 0, 30, 40} + }, + { + { 31, 22, 47, 30}, + { 31, 48, 25, 34}, + { 30, 95, 31, 32}, + { 32, 103, 33, 32}, + { 30, 24, 57, 31}, + { 30, 47, 26, 34}, + { 31, 95, 31, 32}, + { 43, 97, 35, 25}, + { 29, 26, 44, 63}, + { 37, 38, 24, 47}, + { 74, 63, 28, 20}, + { 110, 58, 34, 3}, + { 46, 22, 5, 108}, + { 93, 5, 9, 77}, + { 127, 0, 17, 52}, + { 127, 0, 15, 50} + }, + { + { 32, 27, 68, 24}, + { 35, 23, 35, 28}, + { 35, 64, 29, 29}, + { 37, 104, 33, 28}, + { 32, 32, 91, 40}, + { 36, 23, 67, 36}, + { 49, 23, 39, 28}, + { 60, 67, 30, 20}, + { 32, 32, 36, 95}, + { 35, 29, 38, 93}, + { 50, 16, 30, 84}, + { 72, 16, 15, 65}, + { 32, 32, 27, 100}, + { 33, 32, 29, 100}, + { 37, 29, 30, 98}, + { 48, 21, 29, 90} + } +}; + +ALIGN_DATA(MEMORY_ALIGN_DEF_SIZE, const uint8_t mipMatrix8x8[8][16][8]) = +{ + { + { 30, 63, 46, 37, 25, 33, 33, 34}, + { 30, 60, 66, 38, 32, 31, 32, 33}, + { 29, 45, 74, 42, 32, 32, 32, 33}, + { 30, 39, 62, 58, 32, 33, 32, 33}, + { 30, 66, 55, 39, 32, 30, 30, 36}, + { 29, 54, 69, 40, 33, 31, 31, 33}, + { 28, 48, 71, 43, 32, 33, 32, 33}, + { 28, 41, 72, 46, 32, 34, 32, 33}, + { 30, 66, 56, 40, 32, 33, 28, 33}, + { 29, 55, 69, 39, 33, 33, 30, 32}, + { 27, 46, 72, 43, 33, 33, 32, 33}, + { 27, 42, 69, 48, 32, 34, 32, 33}, + { 30, 63, 55, 40, 32, 33, 35, 30}, + { 29, 56, 66, 40, 33, 33, 33, 30}, + { 27, 47, 69, 44, 33, 33, 33, 32}, + { 27, 42, 65, 50, 32, 34, 32, 33} + }, + { + { 32, 33, 30, 31, 74, 30, 31, 32}, + { 33, 56, 28, 30, 41, 29, 32, 32}, + { 33, 77, 52, 26, 29, 34, 30, 32}, + { 33, 37, 80, 41, 31, 34, 30, 32}, + { 32, 32, 33, 31, 59, 76, 28, 31}, + { 33, 31, 31, 30, 78, 40, 28, 32}, + { 33, 47, 28, 29, 53, 27, 31, 31}, + { 33, 61, 44, 28, 34, 32, 31, 31}, + { 32, 31, 34, 30, 26, 64, 76, 27}, + { 32, 31, 34, 29, 45, 86, 36, 29}, + { 33, 27, 34, 29, 73, 55, 25, 32}, + { 33, 33, 34, 30, 62, 33, 30, 31}, + { 32, 31, 34, 30, 30, 29, 58, 74}, + { 32, 31, 35, 29, 27, 53, 77, 35}, + { 32, 30, 36, 29, 40, 80, 44, 31}, + { 33, 28, 37, 30, 58, 60, 31, 33} + }, + { + { 32, 51, 27, 32, 27, 50, 29, 32}, + { 32, 95, 42, 29, 29, 42, 30, 32}, + { 32, 27, 99, 34, 31, 41, 29, 32}, + { 32, 34, 21, 104, 31, 42, 30, 32}, + { 32, 45, 30, 32, 9, 88, 40, 30}, + { 32, 77, 38, 30, 9, 76, 38, 30}, + { 32, 38, 78, 33, 14, 67, 37, 30}, + { 32, 30, 30, 87, 20, 59, 38, 31}, + { 33, 37, 32, 32, 27, 18, 106, 34}, + { 34, 44, 34, 31, 25, 17, 108, 31}, + { 36, 39, 45, 31, 24, 15, 108, 30}, + { 37, 31, 31, 54, 25, 14, 101, 32}, + { 36, 33, 32, 30, 29, 37, 13, 110}, + { 39, 32, 32, 29, 27, 37, 15, 108}, + { 44, 33, 31, 27, 25, 37, 16, 106}, + { 47, 30, 31, 32, 25, 34, 19, 102} + }, + { + { 32, 48, 35, 35, 47, 68, 31, 31}, + { 32, 33, 59, 40, 27, 71, 33, 30}, + { 32, 29, 47, 65, 24, 62, 37, 30}, + { 33, 33, 31, 81, 26, 50, 42, 32}, + { 32, 30, 40, 38, 30, 70, 55, 31}, + { 32, 20, 46, 50, 26, 55, 64, 31}, + { 33, 30, 29, 66, 25, 41, 72, 33}, + { 36, 34, 27, 69, 26, 31, 67, 39}, + { 33, 28, 36, 40, 30, 26, 85, 47}, + { 36, 27, 33, 50, 31, 20, 79, 53}, + { 43, 30, 26, 57, 28, 17, 67, 62}, + { 51, 27, 28, 55, 22, 23, 49, 70}, + { 38, 29, 32, 39, 28, 30, 22, 104}, + { 51, 31, 28, 43, 24, 31, 17, 102}, + { 69, 23, 30, 40, 15, 38, 10, 95}, + { 77, 13, 35, 38, 8, 43, 8, 90} + }, + { + { 32, 38, 32, 33, 101, 40, 29, 32}, + { 32, 40, 37, 32, 100, 36, 30, 32}, + { 32, 37, 46, 35, 94, 33, 30, 31}, + { 33, 34, 30, 62, 81, 35, 30, 31}, + { 32, 32, 33, 32, 22, 102, 39, 29}, + { 32, 31, 33, 33, 26, 104, 34, 28}, + { 33, 33, 33, 33, 31, 103, 32, 28}, + { 33, 32, 34, 36, 37, 94, 33, 28}, + { 32, 33, 32, 32, 34, 24, 99, 36}, + { 32, 34, 33, 33, 33, 30, 98, 32}, + { 33, 33, 34, 33, 31, 37, 95, 29}, + { 33, 33, 33, 36, 30, 46, 85, 31}, + { 32, 33, 32, 33, 30, 34, 23, 104}, + { 32, 34, 33, 33, 31, 32, 30, 98}, + { 32, 33, 34, 34, 31, 29, 39, 91}, + { 33, 33, 32, 37, 32, 30, 47, 82} + }, + { + { 32, 52, 48, 31, 38, 76, 26, 32}, + { 33, 19, 62, 50, 25, 50, 51, 31}, + { 33, 30, 20, 74, 29, 29, 54, 51}, + { 34, 35, 23, 56, 31, 25, 41, 76}, + { 33, 25, 38, 39, 28, 39, 83, 35}, + { 35, 28, 25, 47, 31, 23, 57, 74}, + { 37, 35, 22, 38, 31, 27, 30, 101}, + { 38, 32, 33, 29, 30, 31, 27, 103}, + { 34, 32, 27, 37, 32, 25, 41, 92}, + { 38, 33, 28, 32, 30, 31, 18, 111}, + { 40, 32, 33, 27, 29, 33, 18, 111}, + { 40, 32, 34, 27, 28, 33, 23, 105}, + { 35, 32, 30, 33, 31, 33, 20, 107}, + { 38, 31, 33, 30, 29, 33, 21, 106}, + { 40, 32, 33, 29, 29, 34, 22, 105}, + { 40, 32, 33, 30, 29, 34, 24, 101} + }, + { + { 32, 28, 31, 33, 92, 33, 30, 31}, + { 33, 30, 28, 33, 71, 26, 32, 30}, + { 33, 60, 26, 33, 47, 28, 33, 30}, + { 33, 63, 44, 36, 37, 31, 33, 30}, + { 33, 30, 31, 33, 43, 90, 33, 29}, + { 33, 28, 29, 34, 71, 71, 26, 30}, + { 33, 30, 26, 33, 86, 45, 28, 30}, + { 33, 38, 29, 32, 74, 32, 33, 29}, + { 33, 32, 30, 32, 29, 41, 95, 27}, + { 34, 31, 29, 33, 26, 71, 73, 22}, + { 34, 31, 29, 33, 37, 88, 46, 25}, + { 33, 32, 28, 34, 55, 75, 36, 28}, + { 34, 31, 30, 32, 33, 27, 43, 89}, + { 35, 32, 28, 33, 33, 23, 77, 59}, + { 34, 33, 28, 33, 30, 35, 91, 37}, + { 34, 34, 28, 34, 33, 53, 74, 31} + }, + { + { 33, 49, 26, 32, 26, 52, 28, 31}, + { 33, 71, 72, 24, 30, 32, 34, 31}, + { 32, 23, 70, 68, 32, 32, 32, 32}, + { 31, 33, 21, 106, 33, 32, 32, 33}, + { 34, 47, 32, 29, 5, 86, 44, 26}, + { 34, 44, 89, 28, 28, 37, 33, 30}, + { 32, 27, 46, 89, 33, 31, 31, 32}, + { 30, 33, 20, 107, 33, 33, 32, 33}, + { 35, 39, 42, 27, 26, 24, 92, 35}, + { 34, 27, 87, 43, 30, 34, 38, 31}, + { 31, 31, 32, 100, 32, 33, 30, 32}, + { 29, 32, 22, 106, 33, 33, 32, 33}, + { 35, 29, 47, 32, 32, 32, 17, 100}, + { 34, 24, 69, 60, 34, 33, 28, 44}, + { 31, 33, 31, 99, 32, 33, 32, 31}, + { 29, 33, 25, 103, 33, 33, 32, 35} + } +}; + +ALIGN_DATA(MEMORY_ALIGN_DEF_SIZE, const uint8_t mipMatrix16x16[6][64][7]) = +{ + { + { 42, 37, 33, 27, 44, 33, 35}, + { 71, 39, 34, 24, 36, 35, 36}, + { 77, 46, 35, 33, 30, 34, 36}, + { 64, 60, 35, 33, 31, 32, 36}, + { 49, 71, 38, 32, 32, 31, 36}, + { 42, 66, 50, 33, 31, 32, 36}, + { 40, 52, 67, 33, 31, 32, 35}, + { 38, 43, 75, 33, 32, 32, 35}, + { 56, 40, 33, 26, 43, 38, 36}, + { 70, 49, 34, 30, 28, 38, 38}, + { 65, 57, 36, 34, 28, 33, 39}, + { 59, 60, 39, 33, 30, 31, 38}, + { 55, 60, 43, 33, 30, 31, 38}, + { 51, 61, 47, 33, 30, 32, 37}, + { 46, 62, 51, 34, 30, 32, 37}, + { 42, 60, 55, 33, 31, 32, 37}, + { 60, 42, 34, 30, 37, 43, 38}, + { 68, 52, 35, 35, 22, 37, 40}, + { 62, 58, 37, 34, 28, 31, 40}, + { 58, 59, 41, 33, 30, 30, 39}, + { 56, 59, 44, 34, 30, 31, 38}, + { 53, 60, 45, 33, 30, 31, 38}, + { 49, 65, 45, 33, 30, 31, 38}, + { 45, 64, 47, 33, 31, 32, 38}, + { 59, 44, 35, 31, 34, 43, 41}, + { 66, 53, 36, 35, 25, 31, 43}, + { 61, 58, 38, 34, 29, 30, 40}, + { 59, 57, 41, 33, 30, 31, 39}, + { 57, 58, 43, 33, 30, 31, 39}, + { 54, 61, 43, 33, 31, 31, 39}, + { 51, 64, 43, 33, 31, 31, 39}, + { 48, 64, 45, 33, 32, 31, 39}, + { 57, 45, 35, 30, 35, 40, 44}, + { 65, 54, 37, 33, 33, 24, 44}, + { 63, 56, 38, 34, 30, 29, 39}, + { 61, 56, 41, 34, 30, 32, 39}, + { 58, 58, 42, 33, 31, 31, 39}, + { 54, 62, 41, 33, 31, 31, 39}, + { 51, 65, 42, 33, 31, 31, 39}, + { 48, 63, 43, 33, 32, 31, 39}, + { 55, 46, 35, 30, 36, 38, 47}, + { 65, 53, 37, 32, 36, 26, 40}, + { 65, 54, 38, 33, 31, 30, 38}, + { 63, 55, 39, 33, 30, 32, 38}, + { 59, 58, 40, 33, 31, 31, 39}, + { 54, 64, 40, 33, 31, 30, 40}, + { 49, 66, 40, 32, 32, 30, 41}, + { 48, 64, 42, 32, 32, 30, 41}, + { 54, 46, 35, 30, 34, 39, 49}, + { 64, 52, 36, 32, 34, 34, 35}, + { 65, 53, 37, 33, 32, 32, 37}, + { 63, 55, 38, 33, 31, 31, 39}, + { 59, 60, 38, 33, 31, 31, 40}, + { 54, 64, 38, 33, 32, 30, 40}, + { 49, 66, 39, 33, 32, 29, 41}, + { 47, 64, 42, 32, 33, 29, 42}, + { 51, 46, 35, 31, 33, 37, 54}, + { 61, 51, 36, 32, 33, 38, 36}, + { 63, 53, 37, 32, 32, 34, 37}, + { 62, 55, 37, 33, 32, 32, 39}, + { 58, 59, 37, 33, 32, 31, 40}, + { 53, 63, 38, 33, 32, 31, 40}, + { 49, 64, 40, 33, 33, 30, 41}, + { 46, 62, 42, 33, 33, 30, 42} + }, + { + { 39, 34, 33, 58, 44, 31, 32}, + { 60, 38, 32, 40, 51, 30, 31}, + { 73, 49, 31, 39, 48, 32, 31}, + { 60, 73, 30, 39, 46, 33, 32}, + { 43, 87, 35, 38, 45, 33, 32}, + { 35, 78, 54, 36, 45, 33, 32}, + { 33, 47, 86, 35, 44, 33, 32}, + { 31, 17, 114, 34, 44, 34, 33}, + { 43, 37, 32, 53, 70, 30, 31}, + { 53, 50, 30, 42, 72, 31, 30}, + { 52, 66, 30, 39, 70, 32, 30}, + { 46, 78, 35, 37, 68, 34, 30}, + { 43, 75, 48, 37, 66, 34, 30}, + { 40, 62, 68, 35, 65, 35, 30}, + { 33, 37, 97, 33, 62, 37, 31}, + { 26, 14, 122, 32, 59, 38, 33}, + { 40, 39, 33, 34, 87, 37, 30}, + { 45, 54, 32, 34, 84, 41, 29}, + { 41, 70, 35, 33, 83, 40, 29}, + { 37, 73, 44, 32, 82, 40, 30}, + { 37, 65, 60, 31, 81, 41, 29}, + { 35, 48, 82, 30, 79, 43, 29}, + { 28, 27, 108, 28, 76, 45, 30}, + { 19, 11, 127, 27, 70, 46, 32}, + { 38, 40, 34, 27, 73, 62, 28}, + { 39, 54, 35, 30, 73, 62, 28}, + { 33, 65, 41, 29, 75, 59, 28}, + { 30, 65, 53, 27, 76, 58, 29}, + { 29, 53, 72, 26, 77, 58, 29}, + { 27, 35, 95, 24, 77, 60, 28}, + { 19, 19, 117, 23, 74, 61, 30}, + { 9, 16, 127, 23, 68, 60, 34}, + { 35, 40, 35, 29, 44, 89, 30}, + { 33, 51, 39, 29, 49, 86, 30}, + { 28, 57, 49, 28, 53, 83, 30}, + { 24, 52, 65, 26, 56, 82, 30}, + { 22, 39, 86, 24, 58, 82, 30}, + { 18, 22, 108, 23, 59, 82, 31}, + { 10, 13, 125, 22, 58, 80, 33}, + { 0, 19, 127, 22, 56, 74, 40}, + { 33, 40, 36, 31, 28, 90, 45}, + { 29, 46, 44, 29, 31, 92, 43}, + { 24, 45, 58, 28, 34, 91, 43}, + { 19, 37, 78, 26, 37, 91, 43}, + { 15, 22, 99, 25, 38, 91, 42}, + { 11, 11, 118, 24, 39, 90, 44}, + { 2, 11, 127, 23, 41, 85, 48}, + { 0, 17, 127, 23, 43, 75, 55}, + { 31, 37, 39, 30, 28, 54, 82}, + { 27, 37, 52, 28, 30, 58, 79}, + { 22, 30, 70, 27, 32, 58, 79}, + { 15, 19, 91, 26, 33, 58, 79}, + { 10, 8, 111, 25, 34, 58, 79}, + { 5, 2, 125, 25, 35, 57, 80}, + { 0, 9, 127, 25, 36, 53, 84}, + { 0, 13, 127, 25, 39, 47, 88}, + { 28, 29, 46, 28, 39, 2, 123}, + { 24, 24, 62, 27, 41, 1, 125}, + { 19, 14, 81, 25, 43, 0, 126}, + { 13, 4, 101, 24, 44, 0, 127}, + { 6, 0, 116, 23, 45, 0, 127}, + { 0, 0, 126, 23, 45, 1, 127}, + { 0, 4, 127, 25, 44, 2, 127}, + { 0, 9, 127, 25, 44, 3, 127} + }, + { + { 30, 32, 32, 42, 34, 32, 32}, + { 63, 26, 34, 16, 38, 32, 32}, + { 98, 26, 34, 25, 34, 33, 32}, + { 75, 61, 30, 31, 32, 33, 32}, + { 36, 94, 32, 30, 33, 32, 32}, + { 26, 76, 58, 30, 33, 32, 32}, + { 30, 39, 91, 31, 32, 33, 31}, + { 32, 23, 105, 32, 32, 32, 32}, + { 34, 30, 33, 31, 52, 29, 32}, + { 66, 24, 34, 11, 41, 33, 32}, + { 97, 28, 34, 24, 34, 33, 32}, + { 71, 65, 30, 30, 32, 33, 32}, + { 34, 92, 35, 30, 33, 32, 32}, + { 26, 70, 64, 29, 34, 32, 32}, + { 30, 37, 94, 30, 33, 32, 31}, + { 32, 23, 105, 31, 33, 33, 31}, + { 37, 29, 33, 8, 79, 27, 32}, + { 71, 22, 35, 5, 50, 32, 32}, + { 98, 29, 34, 23, 34, 34, 32}, + { 66, 70, 30, 31, 31, 33, 32}, + { 31, 92, 38, 30, 33, 32, 32}, + { 26, 66, 68, 29, 34, 32, 31}, + { 30, 34, 97, 30, 34, 33, 31}, + { 31, 22, 106, 30, 34, 33, 31}, + { 40, 28, 34, 0, 76, 46, 28}, + { 76, 21, 35, 0, 55, 35, 32}, + { 97, 32, 34, 21, 37, 33, 33}, + { 61, 75, 29, 30, 32, 32, 32}, + { 29, 92, 40, 29, 33, 32, 32}, + { 26, 62, 73, 29, 34, 32, 31}, + { 29, 32, 99, 30, 34, 33, 30}, + { 31, 22, 107, 30, 34, 33, 31}, + { 42, 27, 34, 1, 48, 79, 25}, + { 80, 20, 35, 0, 48, 47, 31}, + { 94, 36, 32, 17, 40, 33, 33}, + { 55, 80, 29, 27, 35, 31, 32}, + { 27, 90, 43, 28, 34, 32, 31}, + { 26, 58, 76, 29, 33, 33, 30}, + { 29, 30, 101, 29, 34, 34, 30}, + { 31, 21, 108, 29, 35, 34, 30}, + { 44, 26, 34, 6, 30, 80, 40}, + { 81, 21, 35, 0, 41, 52, 35}, + { 90, 41, 31, 14, 41, 35, 33}, + { 51, 82, 29, 24, 37, 32, 32}, + { 27, 87, 47, 27, 35, 32, 31}, + { 26, 54, 79, 29, 34, 33, 30}, + { 29, 29, 102, 28, 34, 33, 30}, + { 31, 21, 108, 28, 35, 33, 31}, + { 47, 26, 34, 7, 34, 44, 75}, + { 80, 24, 34, 0, 41, 41, 50}, + { 84, 45, 31, 12, 40, 36, 36}, + { 49, 81, 31, 22, 37, 33, 32}, + { 28, 81, 51, 26, 35, 33, 31}, + { 28, 51, 81, 28, 34, 33, 30}, + { 29, 30, 101, 28, 35, 33, 31}, + { 31, 22, 107, 28, 35, 33, 32}, + { 48, 27, 34, 10, 40, 16, 97}, + { 75, 27, 34, 3, 42, 26, 66}, + { 77, 47, 33, 12, 40, 32, 43}, + { 49, 75, 36, 21, 37, 33, 35}, + { 32, 72, 55, 25, 36, 33, 32}, + { 30, 49, 81, 27, 35, 33, 31}, + { 30, 32, 98, 28, 35, 32, 32}, + { 31, 24, 104, 28, 35, 32, 33} + }, + { + { 36, 29, 33, 43, 47, 29, 31}, + { 74, 20, 35, 19, 47, 34, 32}, + { 92, 35, 32, 29, 31, 40, 34}, + { 53, 80, 26, 33, 28, 36, 37}, + { 24, 91, 41, 31, 31, 31, 38}, + { 25, 57, 74, 31, 32, 30, 37}, + { 32, 28, 99, 32, 32, 29, 36}, + { 34, 20, 105, 33, 32, 30, 35}, + { 50, 26, 34, 33, 74, 30, 31}, + { 75, 28, 33, 23, 46, 47, 33}, + { 64, 58, 29, 30, 26, 46, 40}, + { 31, 85, 37, 31, 27, 33, 44}, + { 22, 67, 64, 30, 31, 28, 42}, + { 29, 35, 93, 31, 32, 27, 40}, + { 33, 20, 105, 32, 33, 27, 37}, + { 34, 19, 106, 33, 32, 29, 36}, + { 51, 29, 33, 25, 72, 51, 30}, + { 61, 42, 31, 30, 31, 60, 39}, + { 40, 70, 34, 32, 24, 41, 50}, + { 22, 72, 54, 30, 31, 27, 50}, + { 25, 44, 83, 30, 33, 25, 44}, + { 32, 23, 102, 32, 33, 26, 40}, + { 34, 18, 107, 32, 33, 28, 37}, + { 34, 19, 105, 33, 32, 30, 35}, + { 45, 35, 32, 30, 39, 79, 33}, + { 43, 53, 33, 35, 24, 53, 55}, + { 27, 67, 45, 32, 29, 27, 61}, + { 22, 53, 72, 30, 33, 22, 52}, + { 28, 31, 95, 31, 33, 25, 43}, + { 32, 20, 105, 32, 33, 27, 38}, + { 34, 18, 107, 32, 32, 29, 36}, + { 34, 20, 105, 33, 31, 31, 35}, + { 38, 40, 32, 35, 23, 72, 54}, + { 31, 55, 39, 34, 29, 32, 73}, + { 22, 57, 60, 31, 35, 18, 64}, + { 25, 39, 86, 31, 35, 22, 49}, + { 30, 24, 101, 32, 33, 27, 40}, + { 33, 19, 106, 32, 32, 30, 36}, + { 34, 18, 107, 33, 31, 31, 35}, + { 34, 20, 104, 33, 31, 32, 34}, + { 33, 42, 35, 34, 28, 39, 82}, + { 26, 51, 50, 33, 34, 18, 80}, + { 23, 46, 74, 31, 35, 20, 59}, + { 27, 32, 93, 32, 34, 26, 44}, + { 31, 22, 103, 32, 32, 30, 37}, + { 33, 19, 106, 33, 31, 31, 35}, + { 34, 19, 106, 33, 31, 32, 34}, + { 35, 21, 103, 34, 31, 32, 34}, + { 29, 41, 41, 33, 34, 20, 92}, + { 24, 44, 62, 34, 35, 18, 73}, + { 24, 37, 83, 34, 33, 25, 52}, + { 28, 28, 97, 33, 32, 30, 40}, + { 32, 23, 103, 33, 31, 32, 36}, + { 34, 20, 105, 34, 30, 33, 34}, + { 35, 20, 104, 34, 30, 33, 33}, + { 35, 22, 102, 34, 30, 33, 34}, + { 27, 38, 51, 34, 34, 20, 86}, + { 26, 37, 71, 35, 34, 24, 64}, + { 27, 33, 87, 35, 32, 30, 47}, + { 30, 28, 96, 34, 31, 32, 39}, + { 32, 24, 100, 35, 30, 32, 36}, + { 34, 23, 101, 34, 30, 33, 34}, + { 35, 23, 101, 34, 30, 32, 34}, + { 34, 24, 99, 35, 30, 33, 34} + }, + { + { 39, 30, 31, 67, 33, 34, 31}, + { 72, 21, 32, 43, 39, 33, 31}, + { 100, 23, 32, 35, 39, 34, 31}, + { 75, 63, 24, 32, 38, 34, 32}, + { 32, 98, 26, 29, 37, 35, 32}, + { 22, 77, 55, 29, 36, 35, 31}, + { 31, 37, 90, 31, 35, 35, 32}, + { 35, 22, 100, 33, 33, 36, 33}, + { 47, 29, 32, 74, 54, 32, 31}, + { 71, 24, 32, 60, 50, 36, 30}, + { 86, 31, 30, 46, 48, 37, 30}, + { 65, 63, 25, 34, 46, 39, 30}, + { 33, 85, 32, 28, 43, 40, 30}, + { 26, 64, 60, 27, 39, 41, 30}, + { 33, 33, 87, 29, 35, 41, 31}, + { 37, 23, 93, 32, 33, 41, 32}, + { 41, 32, 32, 45, 84, 32, 32}, + { 55, 31, 32, 50, 70, 40, 30}, + { 62, 37, 31, 45, 61, 45, 29}, + { 53, 55, 31, 36, 55, 48, 29}, + { 38, 63, 40, 29, 48, 50, 28}, + { 34, 49, 60, 27, 43, 51, 29}, + { 38, 30, 78, 28, 38, 50, 31}, + { 40, 24, 83, 30, 36, 48, 33}, + { 35, 33, 33, 29, 75, 58, 29}, + { 39, 35, 33, 34, 68, 59, 29}, + { 41, 39, 34, 36, 61, 62, 29}, + { 41, 43, 37, 33, 54, 64, 28}, + { 41, 43, 45, 30, 48, 65, 29}, + { 42, 36, 56, 27, 44, 63, 30}, + { 42, 30, 65, 27, 41, 60, 33}, + { 42, 28, 68, 28, 37, 56, 36}, + { 33, 34, 33, 31, 42, 88, 30}, + { 31, 36, 34, 31, 44, 84, 31}, + { 31, 37, 35, 32, 43, 83, 31}, + { 35, 35, 39, 32, 40, 82, 31}, + { 40, 32, 44, 31, 38, 81, 31}, + { 44, 30, 48, 30, 37, 78, 33}, + { 44, 30, 52, 28, 37, 72, 36}, + { 43, 30, 55, 29, 35, 66, 40}, + { 32, 33, 33, 34, 25, 85, 48}, + { 30, 34, 34, 33, 25, 88, 44}, + { 30, 34, 36, 34, 25, 90, 41}, + { 33, 32, 38, 34, 25, 90, 40}, + { 38, 29, 41, 34, 26, 88, 40}, + { 42, 29, 41, 33, 27, 85, 41}, + { 43, 30, 42, 31, 28, 80, 43}, + { 42, 31, 45, 31, 30, 72, 47}, + { 32, 33, 33, 33, 26, 54, 79}, + { 31, 32, 34, 35, 20, 68, 68}, + { 32, 32, 35, 36, 17, 76, 62}, + { 34, 31, 36, 36, 17, 79, 59}, + { 37, 29, 37, 36, 18, 78, 58}, + { 39, 29, 37, 35, 20, 77, 58}, + { 41, 30, 37, 34, 22, 74, 58}, + { 40, 31, 40, 32, 26, 68, 59}, + { 33, 31, 34, 33, 29, 31, 98}, + { 34, 30, 34, 35, 23, 45, 88}, + { 34, 31, 34, 36, 20, 54, 82}, + { 35, 31, 34, 36, 18, 59, 78}, + { 36, 31, 34, 37, 19, 60, 76}, + { 38, 30, 34, 36, 20, 61, 74}, + { 39, 31, 35, 35, 22, 60, 73}, + { 39, 31, 37, 34, 24, 59, 71} + }, + { + { 30, 33, 32, 55, 32, 32, 32}, + { 47, 30, 31, 29, 36, 32, 32}, + { 81, 28, 32, 28, 34, 32, 32}, + { 85, 46, 29, 32, 32, 33, 32}, + { 54, 82, 26, 32, 32, 33, 32}, + { 30, 90, 38, 31, 32, 33, 32}, + { 30, 56, 73, 31, 33, 32, 32}, + { 37, 21, 102, 32, 32, 32, 32}, + { 33, 32, 31, 68, 39, 31, 31}, + { 38, 32, 31, 43, 34, 33, 31}, + { 63, 30, 31, 29, 34, 32, 32}, + { 82, 37, 30, 29, 33, 32, 32}, + { 71, 63, 27, 31, 32, 33, 32}, + { 44, 86, 30, 30, 33, 33, 32}, + { 33, 72, 55, 30, 32, 32, 31}, + { 37, 37, 86, 31, 32, 33, 31}, + { 34, 33, 32, 60, 61, 29, 32}, + { 36, 33, 31, 56, 38, 32, 31}, + { 51, 30, 31, 38, 33, 33, 32}, + { 75, 31, 31, 30, 33, 33, 32}, + { 80, 47, 29, 30, 32, 33, 31}, + { 60, 73, 27, 30, 33, 33, 31}, + { 41, 78, 41, 30, 33, 32, 31}, + { 38, 53, 68, 30, 32, 33, 31}, + { 33, 33, 32, 43, 77, 35, 30}, + { 35, 33, 31, 55, 54, 29, 32}, + { 43, 32, 31, 46, 39, 31, 32}, + { 64, 30, 31, 35, 34, 33, 32}, + { 79, 37, 30, 31, 32, 33, 31}, + { 73, 57, 28, 30, 32, 33, 31}, + { 54, 73, 33, 30, 32, 33, 31}, + { 43, 64, 52, 30, 32, 33, 31}, + { 33, 33, 32, 34, 68, 58, 28}, + { 34, 33, 31, 45, 70, 33, 31}, + { 38, 33, 31, 48, 52, 29, 32}, + { 54, 31, 31, 40, 39, 31, 32}, + { 73, 32, 31, 34, 34, 33, 31}, + { 77, 45, 29, 31, 32, 32, 32}, + { 65, 63, 30, 31, 31, 33, 31}, + { 51, 66, 42, 30, 32, 33, 31}, + { 33, 32, 32, 34, 44, 81, 31}, + { 34, 33, 31, 38, 66, 52, 28}, + { 36, 33, 30, 44, 62, 34, 31}, + { 47, 31, 31, 43, 48, 30, 32}, + { 64, 31, 31, 38, 38, 32, 32}, + { 75, 38, 30, 33, 34, 32, 32}, + { 71, 53, 30, 31, 32, 33, 32}, + { 59, 61, 37, 30, 32, 33, 32}, + { 33, 32, 31, 35, 31, 71, 54}, + { 34, 33, 31, 37, 49, 70, 33}, + { 36, 33, 31, 41, 60, 48, 30}, + { 43, 32, 31, 43, 54, 35, 31}, + { 56, 31, 31, 40, 44, 32, 32}, + { 68, 35, 30, 36, 37, 32, 32}, + { 70, 45, 30, 33, 34, 33, 32}, + { 63, 55, 35, 31, 33, 33, 32}, + { 33, 32, 31, 33, 34, 36, 87}, + { 34, 32, 31, 36, 38, 62, 52}, + { 36, 33, 31, 39, 50, 57, 36}, + { 41, 33, 31, 41, 53, 43, 33}, + { 50, 33, 31, 41, 48, 36, 32}, + { 59, 35, 31, 37, 41, 34, 32}, + { 65, 42, 31, 35, 36, 33, 32}, + { 62, 49, 35, 33, 34, 34, 33} + } +}; +#else ALIGN_DATA(MEMORY_ALIGN_DEF_SIZE, const uint8_t mipMatrix4x4[16][16][4]) = { { @@ -892,3 +1736,4 @@ ALIGN_DATA(MEMORY_ALIGN_DEF_SIZE, const uint8_t mipOffsetMatrix16x16[6]) = ALIGN_DATA(MEMORY_ALIGN_DEF_SIZE, const uint8_t mipShiftMatrix16x16[6]) = { 6, 7, 5, 6, 6, 6}; +#endif \ No newline at end of file diff --git a/source/Lib/CommonLib/RdCost.cpp b/source/Lib/CommonLib/RdCost.cpp index 7c0960cb71eade8f2df88a1b26038d034d460c63..5a68bee8aee8913ad2830b7874efbbb97c8db157 100644 --- a/source/Lib/CommonLib/RdCost.cpp +++ b/source/Lib/CommonLib/RdCost.cpp @@ -205,6 +205,10 @@ void RdCost::init() m_afpDistortFunc[DF_SAD_INTERMEDIATE_BITDEPTH] = RdCost::xGetSAD; +#if JVET_Q0806 + m_afpDistortFunc[DF_SAD_WITH_MASK] = RdCost::xGetSADwMask; +#endif + #if ENABLE_SIMD_OPT_DIST #ifdef TARGET_SIMD_X86 initRdCostX86(); @@ -318,6 +322,15 @@ void RdCost::setDistParam( DistParam &rcDP, const CPelBuf &org, const Pel* piRef rcDP.subShift = 1; } } +#if JVET_Q0806 + else if( subShiftMode == 3 ) + { + if (rcDP.org.height > 8 ) + { + rcDP.subShift = 1; + } + } +#endif } void RdCost::setDistParam( DistParam &rcDP, const CPelBuf &org, const CPelBuf &cur, int bitDepth, ComponentID compID, bool useHadamard ) @@ -3452,4 +3465,69 @@ Distortion RdCost::xGetMRHADs( const DistParam &rcDtParam ) return m_afpDistortFunc[DF_HAD]( modDistParam ); } + +#if JVET_Q0806 +void RdCost::setDistParam( DistParam &rcDP, const CPelBuf &org, const Pel* piRefY, int iRefStride, const Pel* mask, int iMaskStride, int stepX, int iMaskStride2, int bitDepth, ComponentID compID) +{ + rcDP.bitDepth = bitDepth; + rcDP.compID = compID; + + // set Original & Curr Pointer / Stride + rcDP.org = org; + rcDP.cur.buf = piRefY; + rcDP.cur.stride = iRefStride; + + // set Mask + rcDP.mask = mask; + rcDP.maskStride = iMaskStride; + rcDP.stepX = stepX; + rcDP.maskStride2 = iMaskStride2; + + // set Block Width / Height + rcDP.cur.width = org.width; + rcDP.cur.height = org.height; + rcDP.maximumDistortionForEarlyExit = std::numeric_limits<Distortion>::max(); + + // set Cost function for motion estimation with Mask + rcDP.distFunc = m_afpDistortFunc[ DF_SAD_WITH_MASK ]; +} + +Distortion RdCost::xGetSADwMask( const DistParam& rcDtParam ) +{ + if ( rcDtParam.applyWeight ) + { + return RdCostWeightPrediction::xGetSADw( rcDtParam ); + } + + const Pel* org = rcDtParam.org.buf; + const Pel* cur = rcDtParam.cur.buf; + const Pel* mask = rcDtParam.mask; + const int cols = rcDtParam.org.width; + int rows = rcDtParam.org.height; + const int subShift = rcDtParam.subShift; + const int subStep = ( 1 << subShift); + const int strideCur = rcDtParam.cur.stride * subStep; + const int strideOrg = rcDtParam.org.stride * subStep; + const int strideMask = rcDtParam.maskStride * subStep; + const int stepX = rcDtParam.stepX; + const int strideMask2 = rcDtParam.maskStride2; + const uint32_t distortionShift = DISTORTION_PRECISION_ADJUSTMENT(rcDtParam.bitDepth); + + Distortion sum = 0; + for (; rows != 0; rows -= subStep) + { + for (int n = 0; n < cols; n++) + { + sum += abs(org[n] - cur[n]) * *mask; + mask += stepX; + } + org += strideOrg; + cur += strideCur; + mask += strideMask; + mask += strideMask2; + } + sum <<= subShift; + return (sum >> distortionShift ); +} +#endif //! \} diff --git a/source/Lib/CommonLib/RdCost.h b/source/Lib/CommonLib/RdCost.h index a7aef6fa7700fbe9cac8236d0317687c167ff53a..7d10e131abeee507b6dd52fb589a2d843f2c060b 100644 --- a/source/Lib/CommonLib/RdCost.h +++ b/source/Lib/CommonLib/RdCost.h @@ -71,6 +71,12 @@ public: CPelBuf cur; #if WCG_EXT CPelBuf orgLuma; +#endif +#if JVET_Q0806 + const Pel* mask; + int maskStride; + int stepX; + int maskStride2; #endif int step; FpDistFunc distFunc; @@ -90,7 +96,14 @@ public: int cShiftX; int cShiftY; DistParam() : - org(), cur(), step( 1 ), bitDepth( 0 ), useMR( false ), applyWeight( false ), isBiPred( false ), wpCur( nullptr ), compID( MAX_NUM_COMPONENT ), maximumDistortionForEarlyExit( std::numeric_limits<Distortion>::max() ), subShift( 0 ) + org(), cur(), +#if JVET_Q0806 + mask( nullptr ), + maskStride( 0 ), + stepX(0), + maskStride2(0), +#endif + step( 1 ), bitDepth( 0 ), useMR( false ), applyWeight( false ), isBiPred( false ), wpCur( nullptr ), compID( MAX_NUM_COMPONENT ), maximumDistortionForEarlyExit( std::numeric_limits<Distortion>::max() ), subShift( 0 ) , cShiftX(-1), cShiftY(-1) { } }; @@ -167,6 +180,9 @@ public: void setDistParam( DistParam &rcDP, const CPelBuf &org, const Pel* piRefY , int iRefStride, int bitDepth, ComponentID compID, int subShiftMode = 0, int step = 1, bool useHadamard = false ); void setDistParam( DistParam &rcDP, const CPelBuf &org, const CPelBuf &cur, int bitDepth, ComponentID compID, bool useHadamard = false ); void setDistParam( DistParam &rcDP, const Pel* pOrg, const Pel* piRefY, int iOrgStride, int iRefStride, int bitDepth, ComponentID compID, int width, int height, int subShiftMode = 0, int step = 1, bool useHadamard = false, bool bioApplied = false ); +#if JVET_Q0806 + void setDistParam( DistParam &rcDP, const CPelBuf &org, const Pel* piRefY, int iRefStride, const Pel* mask, int iMaskStride, int stepX, int iMaskStride2, int bitDepth, ComponentID compID); +#endif double getMotionLambda ( ) { return m_dLambdaMotionSAD; } void selectMotionLambda ( ) { m_motionLambda = getMotionLambda( ); } @@ -351,6 +367,9 @@ private: static Distortion xGetSAD48 ( const DistParam& pcDtParam ); static Distortion xGetSAD_full ( const DistParam& pcDtParam ); +#if JVET_Q0806 + static Distortion xGetSADwMask ( const DistParam& pcDtParam ); +#endif static Distortion xGetMRSAD ( const DistParam& pcDtParam ); static Distortion xGetMRSAD4 ( const DistParam& pcDtParam ); @@ -389,6 +408,11 @@ private: template<X86_VEXT vext> static Distortion xGetHADs_SIMD ( const DistParam& pcDtParam ); + +#if JVET_Q0806 + template< X86_VEXT vext > + static Distortion xGetSADwMask_SIMD( const DistParam& pcDtParam ); +#endif #endif public: @@ -399,6 +423,9 @@ public: Distortion getDistPart( const CPelBuf &org, const CPelBuf &cur, int bitDepth, const ComponentID compID, DFunc eDFunc ); #endif +#if JVET_Q0806 + Distortion getDistPart(const CPelBuf &org, const CPelBuf &cur, const Pel* mask, int bitDepth, const ComponentID compID, DFunc eDFunc); +#endif };// END CLASS DEFINITION RdCost //! \} diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp index 5bc2f227a26e924598f0185c9169e8450619e685..7bd1333159a6690ae84778fda2ff9d2832488fe0 100644 --- a/source/Lib/CommonLib/Rom.cpp +++ b/source/Lib/CommonLib/Rom.cpp @@ -403,6 +403,7 @@ void initROM() } } +#if !JVET_Q0806 for( int idxH = MAX_CU_DEPTH - MIN_CU_LOG2; idxH >= 0; --idxH ) { for( int idxW = MAX_CU_DEPTH - MIN_CU_LOG2; idxW >= 0; --idxW ) @@ -446,8 +447,23 @@ void initROM() } } } +#else + initGeoTemplate(); +#endif ::memset(g_isReusedUniMVsFilled, 0, sizeof(g_isReusedUniMVsFilled)); + +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + for (int qp = 0; qp < 57; qp++) + { + int qpRem = (qp + 12) % 6; + int qpPer = (qp + 12) / 6; + int quantiserScale = g_quantScales[0][qpRem]; + int quantiserRightShift = QUANT_SHIFT + qpPer; + double threshQP = ((double)(1 << quantiserRightShift)) / quantiserScale; + g_paletteQuant[qp] = (int)(threshQP*0.16 + 0.5); + } +#endif } void destroyROM() @@ -473,6 +489,7 @@ void destroyROM() delete gp_sizeIdxInfo; gp_sizeIdxInfo = nullptr; +#if !JVET_Q0806 for (int idxH = 0; idxH < MAX_CU_DEPTH - MIN_CU_LOG2 + 2; ++idxH) { for (int idxW = 0; idxW < MAX_CU_DEPTH - MIN_CU_LOG2 + 2; ++idxW) @@ -483,6 +500,21 @@ void destroyROM() g_triangleWeights[1][idxH][idxW] = nullptr; } } +#else + for( int modeIdx = 0; modeIdx < GEO_NUM_PARTITION_MODE; modeIdx++ ) + { + delete[] g_GeoParams[modeIdx]; + g_GeoParams[modeIdx] = nullptr; + } + delete[] g_GeoParams; + for( int i = 0; i < GEO_NUM_PRESTORED_MASK; i++ ) + { + delete[] g_globalGeoWeights [i]; + delete[] g_globalGeoEncSADmask[i]; + g_globalGeoWeights [i] = nullptr; + g_globalGeoEncSADmask[i] = nullptr; + } +#endif } // ==================================================================================================================== @@ -708,12 +740,102 @@ const uint32_t g_scalingListSize [SCALING_LIST_SIZE_NUM] = { 1, 4, 16, 64, 256, const uint32_t g_scalingListSizeX[SCALING_LIST_SIZE_NUM] = { 1, 2, 4, 8, 16, 32, 64, 128 }; +#if !JVET_Q0806 uint8_t g_triangleMvStorage[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2]; int16_t *g_triangleWeights[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 2][MAX_CU_DEPTH - MIN_CU_LOG2 + 2]; +#endif + Mv g_reusedUniMVs[32][32][8][8][2][33]; bool g_isReusedUniMVsFilled[32][32][8][8]; +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX +uint16_t g_paletteQuant[57]; +#else const uint8_t g_paletteQuant[52] = { 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 22, 24, 23, 25, 26, 28, 29, 31, 32, 34, 36, 37, 39, 41, 42, 45 }; +#endif uint8_t g_paletteRunTopLut [5] = { 0, 1, 1, 2, 2 }; uint8_t g_paletteRunLeftLut[5] = { 0, 1, 2, 3, 4 }; + +#if JVET_Q0806 +void initGeoTemplate() +{ + g_GeoParams = new int16_t*[GEO_NUM_PARTITION_MODE]; + int modeIdx = 0; + for( int angleIdx = 0; angleIdx < GEO_NUM_ANGLES; angleIdx++ ) + { + for( int distanceIdx = 0; distanceIdx < GEO_NUM_DISTANCES; distanceIdx++ ) + { + if( (distanceIdx == 0 && angleIdx >= 16) + || ((distanceIdx == 2 || distanceIdx == 0) && (g_angle2mask[angleIdx] == 0 || g_angle2mask[angleIdx] == 5)) + || g_angle2mask[angleIdx] == -1 ) + continue; + g_GeoParams[modeIdx] = new int16_t[2]; + g_GeoParams[modeIdx][0] = (int16_t)angleIdx; + g_GeoParams[modeIdx][1] = (int16_t)distanceIdx; + modeIdx++; + } + } + for (int angleIdx = 0; angleIdx < (GEO_NUM_ANGLES >> 2) + 1; angleIdx++) + { + if (g_angle2mask[angleIdx] == -1) + continue; + g_globalGeoWeights[g_angle2mask[angleIdx]] = new int16_t[GEO_WEIGHT_MASK_SIZE * GEO_WEIGHT_MASK_SIZE]; + g_globalGeoEncSADmask[g_angle2mask[angleIdx]] = new int16_t[GEO_WEIGHT_MASK_SIZE * GEO_WEIGHT_MASK_SIZE]; + + int distanceX = angleIdx; + int distanceY = (distanceX + (GEO_NUM_ANGLES >> 2)) % GEO_NUM_ANGLES; + int16_t rho = (g_Dis[distanceX] << (GEO_MAX_CU_LOG2+1)) + (g_Dis[distanceY] << (GEO_MAX_CU_LOG2 + 1)); + static const int16_t maskOffset = (2*GEO_MAX_CU_SIZE - GEO_WEIGHT_MASK_SIZE) >> 1; + int index = 0; + for( int y = 0; y < GEO_WEIGHT_MASK_SIZE; y++ ) + { + int16_t lookUpY = (((y + maskOffset) << 1) + 1) * g_Dis[distanceY]; + for( int x = 0; x < GEO_WEIGHT_MASK_SIZE; x++, index++ ) + { + int16_t sx_i = ((x + maskOffset) << 1) + 1; + int16_t weightIdx = sx_i * g_Dis[distanceX] + lookUpY - rho; + int weightLinearIdx = 32 + weightIdx; + g_globalGeoWeights[g_angle2mask[angleIdx]][index] = Clip3(0, 8, (weightLinearIdx + 4) >> 3); + g_globalGeoEncSADmask[g_angle2mask[angleIdx]][index] = weightIdx > 0 ? 1 : 0; + } + } + } + + for( int hIdx = 0; hIdx < GEO_NUM_CU_SIZE; hIdx++ ) + { + int16_t height = 1 << ( hIdx + GEO_MIN_CU_LOG2); + for( int wIdx = 0; wIdx < GEO_NUM_CU_SIZE; wIdx++ ) + { + int16_t width = 1 << (wIdx + GEO_MIN_CU_LOG2); + for( int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++ ) + { + int16_t angle = g_GeoParams[splitDir][0]; + int16_t distance = g_GeoParams[splitDir][1]; + int16_t offsetX = (GEO_WEIGHT_MASK_SIZE - width) >> 1; + int16_t offsetY = (GEO_WEIGHT_MASK_SIZE - height) >> 1; + if( distance > 0 ) + { + if( angle % 16 == 8 || (angle % 16 != 0 && height >= width) ) + { + offsetY += angle < 16 ? ((distance * (int32_t)height) >> 3) : -((distance * (int32_t)height) >> 3); + } + else + { + offsetX += angle < 16 ? ((distance * (int32_t)width) >> 3) : -((distance * (int32_t)width) >> 3); + } + } + g_weightOffset[splitDir][hIdx][wIdx][0] = offsetX; + g_weightOffset[splitDir][hIdx][wIdx][1] = offsetY; + } + } + } +} +int16_t** g_GeoParams; +int16_t* g_globalGeoWeights [GEO_NUM_PRESTORED_MASK]; +int16_t* g_globalGeoEncSADmask[GEO_NUM_PRESTORED_MASK]; +int16_t g_weightOffset [GEO_NUM_PARTITION_MODE][GEO_NUM_CU_SIZE][GEO_NUM_CU_SIZE][2]; +int8_t g_angle2mask[GEO_NUM_ANGLES] = { 0, -1, 1, 2, 3, 4, -1, -1, 5, -1, -1, 4, 3, 2, 1, -1, 0, -1, 1, 2, 3, 4, -1, -1, 5, -1, -1, 4, 3, 2, 1, -1 }; +int8_t g_Dis[GEO_NUM_ANGLES] = { 8, 8, 8, 8, 4, 4, 2, 1, 0, -1, -2, -4, -4, -8, -8, -8, -8, -8, -8, -8, -4, -4, -2, -1, 0, 1, 2, 4, 4, 8, 8, 8 }; +int8_t g_angle2mirror[GEO_NUM_ANGLES] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2 }; +#endif //! \} diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h index 929a75547ef2cdafdc21e965dea0b93e8d3288e9..ecdbdd9bc79e9645352fc21264fa241d8685064a 100644 --- a/source/Lib/CommonLib/Rom.h +++ b/source/Lib/CommonLib/Rom.h @@ -205,20 +205,37 @@ constexpr uint8_t g_tbMax[257] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, //! \} +#if !JVET_Q0806 extern uint8_t g_triangleMvStorage[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MAX_CU_SIZE >> MIN_CU_LOG2][MAX_CU_SIZE >> MIN_CU_LOG2]; // 7-tap/3-tap, direction, 2/4/8/16/32/64/128 extern int16_t *g_triangleWeights[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 2][MAX_CU_DEPTH - MIN_CU_LOG2 + 2]; +#endif + extern bool g_mctsDecCheckEnabled; class Mv; extern Mv g_reusedUniMVs[32][32][8][8][2][33]; extern bool g_isReusedUniMVsFilled[32][32][8][8]; +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX +extern uint16_t g_paletteQuant[57]; +#else extern const uint8_t g_paletteQuant[52]; +#endif extern uint8_t g_paletteRunTopLut[5]; extern uint8_t g_paletteRunLeftLut[5]; const int g_IBCBufferSize = 256 * 128; +#if JVET_Q0806 +void initGeoTemplate(); +extern int16_t** g_GeoParams; +extern int16_t* g_globalGeoWeights [GEO_NUM_PRESTORED_MASK]; +extern int16_t* g_globalGeoEncSADmask[GEO_NUM_PRESTORED_MASK]; +extern int16_t g_weightOffset [GEO_NUM_PARTITION_MODE][GEO_NUM_CU_SIZE][GEO_NUM_CU_SIZE][2]; +extern int8_t g_angle2mask [GEO_NUM_ANGLES]; +extern int8_t g_Dis[GEO_NUM_ANGLES]; +extern int8_t g_angle2mirror[GEO_NUM_ANGLES]; +#endif #endif //__TCOMROM__ diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 7fec6a6f809b0bf3dbba633a3250a36fc8511516..b88b298b422c75cd951dd33b3c38207b92f5df4a 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -1785,7 +1785,11 @@ PicHeader::PicHeader() , m_disBdofFlag ( 0 ) , m_disDmvrFlag ( 0 ) , m_disProfFlag ( 0 ) +#if !JVET_Q0806 , m_maxNumTriangleCand ( 0 ) +#else +, m_maxNumGeoCand ( 0 ) +#endif , m_maxNumIBCMergeCand ( IBC_MRG_MAX_NUM_CANDS ) , m_jointCbCrSignFlag ( 0 ) , m_saoEnabledPresentFlag ( 0 ) @@ -1877,7 +1881,11 @@ void PicHeader::initPicHeader() m_disBdofFlag = 0; m_disDmvrFlag = 0; m_disProfFlag = 0; +#if !JVET_Q0806 m_maxNumTriangleCand = 0; +#else + m_maxNumGeoCand = 0; +#endif m_maxNumIBCMergeCand = IBC_MRG_MAX_NUM_CANDS; m_jointCbCrSignFlag = 0; m_saoEnabledPresentFlag = 0; @@ -2017,7 +2025,11 @@ SPS::SPS() , m_AffineType ( false ) , m_PROF ( false ) , m_ciip ( false ) +#if !JVET_Q0806 , m_Triangle ( false ) +#else +, m_Geo ( false ) +#endif #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET , m_LadfEnabled ( false ) , m_LadfNumIntervals ( 0 ) @@ -2232,7 +2244,11 @@ PPS::PPS() , m_PPSMvdL1ZeroIdc (0) , m_PPSCollocatedFromL0Idc (0) , m_PPSSixMinusMaxNumMergeCandPlus1 (0) +#if !JVET_Q0806 , m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 (0) +#else +, m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 (0) +#endif , m_cabacInitPresentFlag (false) , m_pictureHeaderExtensionPresentFlag(0) , m_sliceHeaderExtensionPresentFlag (false) diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index ed8df57a258124e71e14c2a1f71e8261607df05d..a63acb34898199c400553194de992b16a70f667e 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -267,7 +267,11 @@ class ConstraintInfo bool m_noIbcConstraintFlag; bool m_noCiipConstraintFlag; bool m_noFPelMmvdConstraintFlag; +#if !JVET_Q0806 bool m_noTriangleConstraintFlag; +#else + bool m_noGeoConstraintFlag; +#endif bool m_noLadfConstraintFlag; bool m_noTransformSkipConstraintFlag; bool m_noBDPCMConstraintFlag; @@ -314,7 +318,11 @@ public: , m_noIbcConstraintFlag (false) , m_noCiipConstraintFlag (false) , m_noFPelMmvdConstraintFlag (false) +#if !JVET_Q0806 , m_noTriangleConstraintFlag (false) +#else + , m_noGeoConstraintFlag (false) +#endif , m_noLadfConstraintFlag (false) , m_noTransformSkipConstraintFlag(false) , m_noBDPCMConstraintFlag (false) @@ -401,8 +409,13 @@ public: void setNoCiipConstraintFlag(bool bVal) { m_noCiipConstraintFlag = bVal; } bool getNoFPelMmvdConstraintFlag() const { return m_noFPelMmvdConstraintFlag; } void setNoFPelMmvdConstraintFlag(bool bVal) { m_noFPelMmvdConstraintFlag = bVal; } +#if !JVET_Q0806 bool getNoTriangleConstraintFlag() const { return m_noTriangleConstraintFlag; } void setNoTriangleConstraintFlag(bool bVal) { m_noTriangleConstraintFlag = bVal; } +#else + bool getNoGeoConstraintFlag() const { return m_noGeoConstraintFlag; } + void setNoGeoConstraintFlag(bool bVal) { m_noGeoConstraintFlag = bVal; } +#endif bool getNoLadfConstraintFlag() const { return m_noLadfConstraintFlag; } void setNoLadfConstraintFlag(bool bVal) { m_noLadfConstraintFlag = bVal; } bool getNoTransformSkipConstraintFlag() const { return m_noTransformSkipConstraintFlag; } @@ -1202,7 +1215,11 @@ private: bool m_PROF; bool m_bcw; // bool m_ciip; +#if !JVET_Q0806 bool m_Triangle; +#else + bool m_Geo; +#endif #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET bool m_LadfEnabled; int m_LadfNumIntervals; @@ -1505,8 +1522,13 @@ void setCCALFEnabledFlag( bool b ) void setUseCiip ( bool b ) { m_ciip = b; } bool getUseCiip () const { return m_ciip; } +#if !JVET_Q0806 void setUseTriangle ( bool b ) { m_Triangle = b; } bool getUseTriangle () const { return m_Triangle; } +#else + void setUseGeo ( bool b ) { m_Geo = b; } + bool getUseGeo () const { return m_Geo; } +#endif void setUseMRL ( bool b ) { m_MRL = b; } bool getUseMRL () const { return m_MRL; } void setUseMIP ( bool b ) { m_MIP = b; } @@ -1641,7 +1663,11 @@ private: int m_PPSMvdL1ZeroIdc; int m_PPSCollocatedFromL0Idc; uint32_t m_PPSSixMinusMaxNumMergeCandPlus1; +#if !JVET_Q0806 uint32_t m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1; +#else + uint32_t m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1; +#endif bool m_cabacInitPresentFlag; @@ -1849,8 +1875,13 @@ public: void setPPSCollocatedFromL0Idc(int u) { m_PPSCollocatedFromL0Idc = u; } uint32_t getPPSSixMinusMaxNumMergeCandPlus1() const { return m_PPSSixMinusMaxNumMergeCandPlus1; } void setPPSSixMinusMaxNumMergeCandPlus1(uint32_t u) { m_PPSSixMinusMaxNumMergeCandPlus1 = u; } +#if !JVET_Q0806 uint32_t getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1() const { return m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1; } void setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(uint32_t u) { m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = u; } +#else + uint32_t getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1() const { return m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1; } + void setPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1(uint32_t u) { m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 = u; } +#endif void setCabacInitPresentFlag( bool flag ) { m_cabacInitPresentFlag = flag; } bool getCabacInitPresentFlag() const { return m_cabacInitPresentFlag; } @@ -1996,7 +2027,11 @@ private: bool m_disBdofFlag; //!< picture level BDOF disable flag bool m_disDmvrFlag; //!< picture level DMVR disable flag bool m_disProfFlag; //!< picture level PROF disable flag +#if !JVET_Q0806 uint32_t m_maxNumTriangleCand; //!< max number of triangle merge candidates +#else + uint32_t m_maxNumGeoCand; //!< max number of geometric merge candidates +#endif uint32_t m_maxNumIBCMergeCand; //!< max number of IBC merge candidates bool m_jointCbCrSignFlag; //!< joint Cb/Cr residual sign flag bool m_saoEnabledPresentFlag; //!< sao enabled flags present in the picture header @@ -2116,8 +2151,13 @@ public: bool getDisDmvrFlag() const { return m_disDmvrFlag; } void setDisProfFlag( bool val ) { m_disProfFlag = val; } bool getDisProfFlag() const { return m_disProfFlag; } +#if !JVET_Q0806 void setMaxNumTriangleCand(uint32_t b) { m_maxNumTriangleCand = b; } uint32_t getMaxNumTriangleCand() const { return m_maxNumTriangleCand; } +#else + void setMaxNumGeoCand(uint32_t b) { m_maxNumGeoCand = b; } + uint32_t getMaxNumGeoCand() const { return m_maxNumGeoCand; } +#endif void setMaxNumIBCMergeCand( uint32_t b ) { m_maxNumIBCMergeCand = b; } uint32_t getMaxNumIBCMergeCand() const { return m_maxNumIBCMergeCand; } void setJointCbCrSignFlag( bool b ) { m_jointCbCrSignFlag = b; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 7ce3af5437c921ad2af97345bb829f6ddfb58621..0a264eb7c9b8bd13d6c398ee2fef2e8675bc5bb3 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,8 @@ #include <assert.h> #include <cassert> +#define JVET_Q0446_MIP_CONST_SHIFT_OFFSET 1 // JVET-Q0446: MIP with constant shift and offset + #define JVET_Q0814_DPB 1 // JVET-Q0814: DPB capacity is based on picture units regardless of the resoltuion #define JVET_Q0820_ACT 1 // JVET-Q0820: ACT bug fixes and reversible ACT transform @@ -65,6 +67,8 @@ #define JVET_Q0501_PALETTE_WPP_INIT_ABOVECTU 1 // JVET-Q0501: Initialize palette predictor from above CTU row in WPP +#define JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX 1 // JVET-Q0503/Q0712: Platte encoder improvement/bugfix + #define JVET_Q0819_PH_CHANGES 1 // JVET-Q0819: Combination of PH related syntax changes #define JVET_Q0481_PARTITION_CONSTRAINTS_ORDER 1 // JVET-Q0481: Ordering of partition constraints syntax elements in the SPS @@ -97,6 +101,9 @@ #define JVET_Q0483_CLIP_TMVP 1 // JVET-Q0483: Clip TMVP when no scaling is applied #define JVET_Q0516_MTS_SIGNALLING_DC_ONLY_COND 1 // JVET-Q0516/Q0685: disable MTS when there is only DC coefficient + +#define JVET_Q0806 1 // Geo related adoptions (JVET-Q0059, JVET-Q0077, JVET-Q0123, JVET-Q0188, JVET-Q0242_GEO, JVET-Q0309, JVET-Q0365 and JVET-Q0370) + #define JVET_Q0055_MTS_SIGNALLING 1 // JVET-Q0055: Check for transform coefficients outside the 16x16 area #define JVET_Q0480_RASTER_RECT_SLICES 1 // JVET-Q0480: Eliminate redundant slice height syntax when in raster rectangular slice mode (tile_idx_delta_present_flag == 0) @@ -106,6 +113,8 @@ #define JVET_Q0487_SCALING_WINDOW_ISSUES 1 // JVET-Q0487: Fix scaling window issues when scaling ratio is 1:1 +#define JVET_Q0787_SUBPIC 1 // JVET-Q0787: fix subpicture location signalling + #define JVET_AHG14_LOSSLESS 1 #define JVET_AHG14_LOSSLESS_ENC_QP_FIX 1 && JVET_AHG14_LOSSLESS @@ -602,7 +611,12 @@ enum DFunc DF_SAD_INTERMEDIATE_BITDEPTH = 63, +#if JVET_Q0806 + DF_SAD_WITH_MASK = 64, + DF_TOTAL_FUNCTIONS = 65 +#else DF_TOTAL_FUNCTIONS = 64 +#endif }; /// motion vector predictor direction used in AMVP @@ -880,12 +894,14 @@ enum MergeType NUM_MRG_TYPE // 5 }; +#if !JVET_Q0806 enum TriangleSplit { TRIANGLE_DIR_135 = 0, TRIANGLE_DIR_45, TRIANGLE_DIR_NUM }; +#endif ////////////////////////////////////////////////////////////////////////// // Encoder modes to try out diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 041b241b8e494577d48561d1af13d8cc07b6e6bb..8a6d7c8d6af9f7ffacf47eff65c8cbf0d2b1d45c 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -266,7 +266,11 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other ) affine = other.affine; affineType = other.affineType; colorTransform = other.colorTransform; +#if !JVET_Q0806 triangle = other.triangle; +#else + geoFlag = other.geoFlag; +#endif bdpcmMode = other.bdpcmMode; bdpcmModeChroma = other.bdpcmModeChroma; qp = other.qp; @@ -326,7 +330,11 @@ void CodingUnit::initData() affine = false; affineType = 0; colorTransform = false; +#if !JVET_Q0806 triangle = false; +#else + geoFlag = false; +#endif bdpcmMode = 0; bdpcmModeChroma = 0; qp = 0; @@ -458,10 +466,12 @@ const uint8_t CodingUnit::checkAllowedSbt() const { return 0; } +#if !JVET_Q0806 if( triangle ) { return 0; } +#endif uint8_t sbtAllowed = 0; int cuWidth = lwidth(); @@ -528,9 +538,15 @@ void PredictionUnit::initData() mergeFlag = false; regularMergeFlag = false; mergeIdx = MAX_UCHAR; +#if !JVET_Q0806 triangleSplitDir = MAX_UCHAR; triangleMergeIdx0 = MAX_UCHAR; triangleMergeIdx1 = MAX_UCHAR; +#else + geoSplitDir = MAX_UCHAR; + geoMergeIdx0 = MAX_UCHAR; + geoMergeIdx1 = MAX_UCHAR; +#endif mmvdMergeFlag = false; mmvdMergeIdx = MAX_UINT; interDir = MAX_UCHAR; @@ -579,9 +595,15 @@ PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData) mergeFlag = predData.mergeFlag; regularMergeFlag = predData.regularMergeFlag; mergeIdx = predData.mergeIdx; +#if !JVET_Q0806 triangleSplitDir = predData.triangleSplitDir ; triangleMergeIdx0 = predData.triangleMergeIdx0 ; triangleMergeIdx1 = predData.triangleMergeIdx1 ; +#else + geoSplitDir = predData.geoSplitDir; + geoMergeIdx0 = predData.geoMergeIdx0; + geoMergeIdx1 = predData.geoMergeIdx1; +#endif mmvdMergeFlag = predData.mmvdMergeFlag; mmvdMergeIdx = predData.mmvdMergeIdx; interDir = predData.interDir; @@ -625,9 +647,15 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other ) mergeFlag = other.mergeFlag; regularMergeFlag = other.regularMergeFlag; mergeIdx = other.mergeIdx; +#if !JVET_Q0806 triangleSplitDir = other.triangleSplitDir ; triangleMergeIdx0 = other.triangleMergeIdx0 ; triangleMergeIdx1 = other.triangleMergeIdx1 ; +#else + geoSplitDir = other.geoSplitDir; + geoMergeIdx0 = other.geoMergeIdx0; + geoMergeIdx1 = other.geoMergeIdx1; +#endif mmvdMergeFlag = other.mmvdMergeFlag; mmvdMergeIdx = other.mmvdMergeIdx; interDir = other.interDir; diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index 91130a7221d62eb12ddbc15dbdbfa5d5caccd706..b8c2a30c788912fc00960cb7ae0067fe364c8279 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -309,7 +309,11 @@ struct CodingUnit : public UnitArea bool affine; int affineType; bool colorTransform; +#if !JVET_Q0806 bool triangle; +#else + bool geoFlag; +#endif int bdpcmMode; int bdpcmModeChroma; uint8_t imv; @@ -383,9 +387,15 @@ struct InterPredictionData bool mergeFlag; bool regularMergeFlag; uint8_t mergeIdx; +#if !JVET_Q0806 uint8_t triangleSplitDir; uint8_t triangleMergeIdx0; uint8_t triangleMergeIdx1; +#else + uint8_t geoSplitDir; + uint8_t geoMergeIdx0; + uint8_t geoMergeIdx1; +#endif bool mmvdMergeFlag; uint32_t mmvdMergeIdx; uint8_t interDir; diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 7dae6ae23dc5e80a70fa1075dc85359a119c1ee8..ece0dcac644277fafe8574191a23578ac51bf69a 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -244,7 +244,11 @@ void CU::saveMotionInHMVP( const CodingUnit& cu, const bool isToBeDone ) { const PredictionUnit& pu = *cu.firstPU; +#if !JVET_Q0806 if (!cu.triangle && !cu.affine && !isToBeDone ) +#else + if (!cu.geoFlag && !cu.affine && !isToBeDone) +#endif { MotionInfo mi = pu.getMotionInfo(); @@ -3192,6 +3196,7 @@ void PU::restrictBiPredMergeCandsOne(PredictionUnit &pu) } } +#if !JVET_Q0806 void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangleMrgCtx ) { MergeCtx tmpMergeCtx; @@ -3348,6 +3353,167 @@ int32_t PU::mappingRefPic( const PredictionUnit &pu, int32_t refPicPoc, bool tar } return -1; } +#else +void PU::getGeoMergeCandidates( const PredictionUnit &pu, MergeCtx& geoMrgCtx ) +{ + MergeCtx tmpMergeCtx; + + const Slice &slice = *pu.cs->slice; + const uint32_t maxNumMergeCand = slice.getPicHeader()->getMaxNumMergeCand(); + + geoMrgCtx.numValidMergeCand = 0; + + for (int32_t i = 0; i < GEO_MAX_NUM_UNI_CANDS; i++) + { + geoMrgCtx.BcwIdx[i] = BCW_DEFAULT; + geoMrgCtx.interDirNeighbours[i] = 0; + geoMrgCtx.mrgTypeNeighbours[i] = MRG_TYPE_DEFAULT_N; + geoMrgCtx.mvFieldNeighbours[(i << 1)].refIdx = NOT_VALID; + geoMrgCtx.mvFieldNeighbours[(i << 1) + 1].refIdx = NOT_VALID; + geoMrgCtx.mvFieldNeighbours[(i << 1)].mv = Mv(); + geoMrgCtx.mvFieldNeighbours[(i << 1) + 1].mv = Mv(); + geoMrgCtx.useAltHpelIf[i] = false; + } + + PU::getInterMergeCandidates(pu, tmpMergeCtx, 0); + + for (int32_t i = 0; i < maxNumMergeCand; i++) + { + int parity = i & 1; + if( tmpMergeCtx.interDirNeighbours[i] & (0x01 + parity) ) + { + geoMrgCtx.interDirNeighbours[geoMrgCtx.numValidMergeCand] = 1 + parity; + geoMrgCtx.mrgTypeNeighbours[geoMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N; + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].mv = Mv(0, 0); + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].mv; + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].refIdx = -1; + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].refIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].refIdx; + geoMrgCtx.numValidMergeCand++; + if (geoMrgCtx.numValidMergeCand == GEO_MAX_NUM_UNI_CANDS) + { + return; + } + continue; + } + + if (tmpMergeCtx.interDirNeighbours[i] & (0x02 - parity)) + { + geoMrgCtx.interDirNeighbours[geoMrgCtx.numValidMergeCand] = 2 - parity; + geoMrgCtx.mrgTypeNeighbours[geoMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N; + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].mv; + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].mv = Mv(0, 0); + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].refIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].refIdx; + geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].refIdx = -1; + geoMrgCtx.numValidMergeCand++; + if (geoMrgCtx.numValidMergeCand == GEO_MAX_NUM_UNI_CANDS) + { + return; + } + } + } +} + +void PU::spanGeoMotionInfo( PredictionUnit &pu, MergeCtx &geoMrgCtx, const uint8_t splitDir, const uint8_t candIdx0, const uint8_t candIdx1) +{ + pu.geoSplitDir = splitDir; + pu.geoMergeIdx0 = candIdx0; + pu.geoMergeIdx1 = candIdx1; + MotionBuf mb = pu.getMotionBuf(); + + MotionInfo biMv; + biMv.isInter = true; + biMv.sliceIdx = pu.cs->slice->getIndependentSliceIdx(); + + if( geoMrgCtx.interDirNeighbours[candIdx0] == 1 && geoMrgCtx.interDirNeighbours[candIdx1] == 2 ) + { + biMv.interDir = 3; + biMv.mv[0] = geoMrgCtx.mvFieldNeighbours[ candIdx0 << 1 ].mv; + biMv.mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv; + biMv.refIdx[0] = geoMrgCtx.mvFieldNeighbours[ candIdx0 << 1 ].refIdx; + biMv.refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx; + } + else if( geoMrgCtx.interDirNeighbours[candIdx0] == 2 && geoMrgCtx.interDirNeighbours[candIdx1] == 1 ) + { + biMv.interDir = 3; + biMv.mv[0] = geoMrgCtx.mvFieldNeighbours[ candIdx1 << 1 ].mv; + biMv.mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv; + biMv.refIdx[0] = geoMrgCtx.mvFieldNeighbours[ candIdx1 << 1 ].refIdx; + biMv.refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx; + } + else if( geoMrgCtx.interDirNeighbours[candIdx0] == 1 && geoMrgCtx.interDirNeighbours[candIdx1] == 1 ) + { + biMv.interDir = 1; + biMv.mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv; + biMv.mv[1] = Mv(0, 0); + biMv.refIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx; + biMv.refIdx[1] = -1; + } + else if( geoMrgCtx.interDirNeighbours[candIdx0] == 2 && geoMrgCtx.interDirNeighbours[candIdx1] == 2 ) + { + biMv.interDir = 2; + biMv.mv[0] = Mv(0, 0); + biMv.mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv; + biMv.refIdx[0] = -1; + biMv.refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx; + } + + int16_t angle = g_GeoParams[splitDir][0]; + int tpmMask = 0; + int lookUpY = 0, motionIdx = 0; + bool isFlip = angle >= 13 && angle <= 27; + int distanceIdx = g_GeoParams[splitDir][1]; + int distanceX = angle; + int distanceY = (distanceX + (GEO_NUM_ANGLES >> 2)) % GEO_NUM_ANGLES; + int offsetX = (-(int)pu.lwidth()) >> 1; + int offsetY = (-(int)pu.lheight()) >> 1; + if (distanceIdx > 0) + { + if (angle % 16 == 8 || (angle % 16 != 0 && pu.lheight() >= pu.lwidth())) + offsetY += angle < 16 ? ((distanceIdx * pu.lheight()) >> 3) : -(int)((distanceIdx * pu.lheight()) >> 3); + else + offsetX += angle < 16 ? ((distanceIdx * pu.lwidth()) >> 3) : -(int)((distanceIdx * pu.lwidth()) >> 3); + } + for (int y = 0; y < mb.height; y++) + { + lookUpY = (((4 * y + offsetY) << 1) + 5) * g_Dis[distanceY]; + for (int x = 0; x < mb.width; x++) + { + motionIdx = (((4 * x + offsetX) << 1) + 5) * g_Dis[distanceX] + lookUpY; + tpmMask = abs(motionIdx) < 32 ? 2 : (motionIdx <= 0 ? (1 - isFlip) : isFlip); + if (tpmMask == 2) + { + mb.at(x, y).isInter = true; + mb.at(x, y).interDir = biMv.interDir; + mb.at(x, y).refIdx[0] = biMv.refIdx[0]; + mb.at(x, y).refIdx[1] = biMv.refIdx[1]; + mb.at(x, y).mv[0] = biMv.mv[0]; + mb.at(x, y).mv[1] = biMv.mv[1]; + mb.at(x, y).sliceIdx = biMv.sliceIdx; + } + else if (tpmMask == 0) + { + mb.at(x, y).isInter = true; + mb.at(x, y).interDir = geoMrgCtx.interDirNeighbours[candIdx0]; + mb.at(x, y).refIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx0 << 1].refIdx; + mb.at(x, y).refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx; + mb.at(x, y).mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx0 << 1].mv; + mb.at(x, y).mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv; + mb.at(x, y).sliceIdx = biMv.sliceIdx; + } + else + { + mb.at(x, y).isInter = true; + mb.at(x, y).interDir = geoMrgCtx.interDirNeighbours[candIdx1]; + mb.at(x, y).refIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx; + mb.at(x, y).refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx; + mb.at(x, y).mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv; + mb.at(x, y).mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv; + mb.at(x, y).sliceIdx = biMv.sliceIdx; + } + } + } +} +#endif bool CU::hasSubCUNonZeroMVd( const CodingUnit& cu ) { diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 8cead3c5ca37492e67158b262460de667902203f..e13475ef6c10886d9562969009bae48d6abc9ca5 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -168,9 +168,14 @@ namespace PU bool isLMCMode ( unsigned mode); bool isLMCModeEnabled (const PredictionUnit &pu, unsigned mode); bool isChromaIntraModeCrossCheckMode(const PredictionUnit &pu); +#if !JVET_Q0806 void getTriangleMergeCandidates (const PredictionUnit &pu, MergeCtx &triangleMrgCtx); void spanTriangleMotionInfo ( PredictionUnit &pu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1); int32_t mappingRefPic (const PredictionUnit &pu, int32_t refPicPoc, bool targetRefPicList); +#else + void getGeoMergeCandidates (const PredictionUnit &pu, MergeCtx &GeoMrgCtx); + void spanGeoMotionInfo ( PredictionUnit &pu, MergeCtx &GeoMrgCtx, const uint8_t splitDir, const uint8_t candIdx0, const uint8_t candIdx1); +#endif bool isAddNeighborMv (const Mv& currMv, Mv* neighborMvs, int numNeighborMv); void getIbcMVPsEncOnly(PredictionUnit &pu, Mv* mvPred, int& nbPred); bool getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv); diff --git a/source/Lib/CommonLib/dtrace_blockstatistics.cpp b/source/Lib/CommonLib/dtrace_blockstatistics.cpp index 8005a537f23095a2ca901a3d95414f68ecd3dccc..4338f027a3c0bf232b570e25cc6bc686fc532a7f 100644 --- a/source/Lib/CommonLib/dtrace_blockstatistics.cpp +++ b/source/Lib/CommonLib/dtrace_blockstatistics.cpp @@ -271,6 +271,7 @@ void CDTrace::dtrace_polygon_vector(int k, int poc, const std::vector<Position> dtrace<false>(k, "BlockStat: POC %d @[%s] %s={%4d,%4d}\n", poc, polygonDescription.c_str(), stat_type.c_str(), val_x, val_y); } +#if !JVET_Q0806 void retrieveTriangularMvInfo(const PredictionUnit& pu, MotionInfo& mi0, MotionInfo& mi1) { int triangleDir = pu.triangleSplitDir; @@ -358,6 +359,7 @@ void retrieveTrianglePolygon(const PredictionUnit& pu, std::vector<Position>& tr CHECK(triangleDir != TRIANGLE_DIR_45 && triangleDir != TRIANGLE_DIR_135, "Unknown triangle type"); } } +#endif void writeBlockStatisticsHeader(const SPS *sps) { @@ -493,7 +495,11 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea) DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, pu, GetBlockStatisticName(BlockStatistic::MVPIdxL1), pu.mvpIdx[REF_PIC_LIST_1]); DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, pu, GetBlockStatisticName(BlockStatistic::RefIdxL1), pu.refIdx[REF_PIC_LIST_1]); } +#if !JVET_Q0806 if (!pu.cu->affine && !pu.cu->triangle) +#else + if (!pu.cu->affine && !pu.cu->geoFlag) +#endif { if (pu.interDir != 2 /* PRED_L1 */) { @@ -518,6 +524,7 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea) DTRACE_BLOCK_VECTOR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, pu, GetBlockStatisticName(BlockStatistic::MVL1), mv.hor, mv.ver); } } +#if !JVET_Q0806 else if (pu.cu->triangle) { MotionInfo mi[2]; @@ -539,6 +546,7 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea) } } } +#endif else { if (pu.interDir != 2 /* PRED_L1 */) @@ -864,7 +872,11 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea) DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::MVPIdxL1), pu.mvpIdx[REF_PIC_LIST_1]); DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::RefIdxL1), pu.refIdx[REF_PIC_LIST_1]); } +#if !JVET_Q0806 if (!pu.cu->affine && !pu.cu->triangle) +#else + if (!pu.cu->affine && !pu.cu->geoFlag) +#endif { if (pu.interDir != 2 /* PRED_L1 */) { @@ -889,6 +901,7 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea) DTRACE_BLOCK_VECTOR(g_trace_ctx, D_BLOCK_STATISTICS_CODED, pu, GetBlockStatisticName(BlockStatistic::MVL1), mv.hor, mv.ver); } } +#if !JVET_Q0806 else if (pu.cu->triangle) { MotionInfo mi[2]; @@ -910,6 +923,7 @@ void writeAllCodedData(const CodingStructure & cs, const UnitArea & ctuArea) } } } +#endif else { if (pu.interDir != 2 /* PRED_L1 */) diff --git a/source/Lib/CommonLib/dtrace_blockstatistics.h b/source/Lib/CommonLib/dtrace_blockstatistics.h index 2df8b9b3af20416ee918590671b48f374c40f1d9..c692bbb3027141fa775f9675038c63f3e444a790 100644 --- a/source/Lib/CommonLib/dtrace_blockstatistics.h +++ b/source/Lib/CommonLib/dtrace_blockstatistics.h @@ -118,9 +118,15 @@ enum class BlockStatistic { MMVDMergeIdx, CiipFlag, SMVDFlag, +#if !JVET_Q0806 TrianglePartitioning, TriangleMVL0, //<< currently only uni-prediction enabled TriangleMVL1, //<< currently only uni-prediction enabled +#else + GeoPartitioning, + GeoMVL0, //<< currently only uni-prediction enabled + GeoMVL1, //<< currently only uni-prediction enabled +#endif BCWIndex, // for dual tree // general @@ -212,10 +218,16 @@ static const std::map<BlockStatistic, std::tuple<std::string, BlockStatisticType { BlockStatistic::MMVDMergeIdx, std::tuple<std::string, BlockStatisticType, std::string>{"MMVDMergeIdx", BlockStatisticType::Integer, "[0, 1]"}}, { BlockStatistic::CiipFlag, std::tuple<std::string, BlockStatisticType, std::string>{"CiipFlag", BlockStatisticType::Flag, ""}}, { BlockStatistic::SMVDFlag, std::tuple<std::string, BlockStatisticType, std::string>{"SMVDFlag", BlockStatisticType::Flag, ""}}, +#if !JVET_Q0806 { BlockStatistic::TrianglePartitioning, std::tuple<std::string, BlockStatisticType, std::string>{"TrianglePartitioning", BlockStatisticType::Line, ""}}, { BlockStatistic::TriangleMVL0, std::tuple<std::string, BlockStatisticType, std::string>{"TriangleMVL0", BlockStatisticType::VectorPolygon, "Scale: 4"}}, { BlockStatistic::TriangleMVL1, std::tuple<std::string, BlockStatisticType, std::string>{"TriangleMVL1", BlockStatisticType::VectorPolygon, "Scale: 4"}}, - { BlockStatistic::BCWIndex, std::tuple<std::string, BlockStatisticType, std::string>{"BCWIndex", BlockStatisticType::Integer, "[0, 4]"}}, +#else + { BlockStatistic::GeoPartitioning, std::tuple<std::string, BlockStatisticType, std::string>{"GeoPartitioning", BlockStatisticType::Line, ""} }, + { BlockStatistic::GeoMVL0, std::tuple<std::string, BlockStatisticType, std::string>{"GeoMVL0", BlockStatisticType::VectorPolygon, "Scale: 4"} }, + { BlockStatistic::GeoMVL1, std::tuple<std::string, BlockStatisticType, std::string>{"GeoMVL1", BlockStatisticType::VectorPolygon, "Scale: 4"} }, +#endif + { BlockStatistic::BCWIndex, std::tuple<std::string, BlockStatisticType, std::string>{"BCWIndex", BlockStatisticType::Integer, "[0, 4]"} }, // for dual tree { BlockStatistic::Depth_Chroma, std::tuple<std::string, BlockStatisticType, std::string>{"Depth_Chroma", BlockStatisticType::Integer, "[0, 10]"}}, // todo: actual limits? { BlockStatistic::QT_Depth_Chroma, std::tuple<std::string, BlockStatisticType, std::string>{"QT_Depth_Chroma", BlockStatisticType::Integer, "[0, 10]"}}, // todo: actual limits? diff --git a/source/Lib/CommonLib/x86/InterpolationFilterX86.h b/source/Lib/CommonLib/x86/InterpolationFilterX86.h index 2b5bda2df04e9ae2626a74e1696069675ad41aa8..81608d2a4da059975fd7a81eeb09170b82b0dcc5 100644 --- a/source/Lib/CommonLib/x86/InterpolationFilterX86.h +++ b/source/Lib/CommonLib/x86/InterpolationFilterX86.h @@ -1327,6 +1327,7 @@ static void simdFilter( const ClpRng& clpRng, Pel const *src, int srcStride, Pel } } +#if !JVET_Q0806 template< X86_VEXT vext > void xWeightedTriangleBlk_SSE(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const bool splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1) { @@ -1449,6 +1450,227 @@ void xWeightedTriangleBlk_SSE(const PredictionUnit &pu, const uint32_t width, co } } } +#else +template< X86_VEXT vext > +void xWeightedGeoBlk_SSE(const PredictionUnit &pu, const uint32_t width, const uint32_t height, const ComponentID compIdx, const uint8_t splitDir, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1) +{ + Pel* dst = predDst.get(compIdx).buf; + Pel* src0 = predSrc0.get(compIdx).buf; + Pel* src1 = predSrc1.get(compIdx).buf; + int32_t strideDst = predDst.get(compIdx).stride; + int32_t strideSrc0 = predSrc0.get(compIdx).stride; + int32_t strideSrc1 = predSrc1.get(compIdx).stride; + + const char log2WeightBase = 3; + const ClpRng clpRng = pu.cu->slice->clpRngs().comp[compIdx]; + const int32_t shiftWeighted = std::max<int>(2, (IF_INTERNAL_PREC - clpRng.bd)) + log2WeightBase; + const int32_t offsetWeighted = (1 << (shiftWeighted - 1)) + (IF_INTERNAL_OFFS << log2WeightBase); + + int16_t wIdx = floorLog2(pu.lwidth()) - GEO_MIN_CU_LOG2; + int16_t hIdx = floorLog2(pu.lheight()) - GEO_MIN_CU_LOG2; + int16_t angle = g_GeoParams[splitDir][0]; + int16_t stepY = 0; + int16_t* weight = nullptr; + if (g_angle2mirror[angle] == 2) + { + stepY = -GEO_WEIGHT_MASK_SIZE; + weight = &g_globalGeoWeights[g_angle2mask[angle]][(GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[splitDir][hIdx][wIdx][1]) * GEO_WEIGHT_MASK_SIZE + g_weightOffset[splitDir][hIdx][wIdx][0]]; + } + else if (g_angle2mirror[angle] == 1) + { + stepY = GEO_WEIGHT_MASK_SIZE; + weight = &g_globalGeoWeights[g_angle2mask[angle]][g_weightOffset[splitDir][hIdx][wIdx][1] * GEO_WEIGHT_MASK_SIZE + (GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[splitDir][hIdx][wIdx][0])]; + } + else + { + stepY = GEO_WEIGHT_MASK_SIZE; + weight = &g_globalGeoWeights[g_angle2mask[angle]][g_weightOffset[splitDir][hIdx][wIdx][1] * GEO_WEIGHT_MASK_SIZE + g_weightOffset[splitDir][hIdx][wIdx][0]]; + } + + const __m128i mmEight = _mm_set1_epi16(8); + const __m128i mmOffset = _mm_set1_epi32(offsetWeighted); + const __m128i mmShift = _mm_cvtsi32_si128(shiftWeighted); + const __m128i mmMin = _mm_set1_epi16(clpRng.min); + const __m128i mmMax = _mm_set1_epi16(clpRng.max); + + if (compIdx != COMPONENT_Y && pu.chromaFormat == CHROMA_420) + stepY <<= 1; + if (width == 4) + { + // it will occur to chroma only + for (int y = 0; y < height; y++) + { + __m128i s0 = _mm_loadl_epi64((__m128i *) (src0)); + __m128i s1 = _mm_loadl_epi64((__m128i *) (src1)); + __m128i w0; + if (g_angle2mirror[angle] == 1) + { + w0 = _mm_loadu_si128((__m128i *) (weight - (8 - 1))); + const __m128i shuffle_mask = _mm_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + w0 = _mm_shuffle_epi8(w0, shuffle_mask); + } + else + { + w0 = _mm_loadu_si128((__m128i *) (weight)); + } + w0 = _mm_shuffle_epi8(w0, _mm_setr_epi8(0, 1, 4, 5, 8, 9, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0)); + __m128i w1 = _mm_sub_epi16(mmEight, w0); + s0 = _mm_unpacklo_epi16(s0, s1); + w0 = _mm_unpacklo_epi16(w0, w1); + s0 = _mm_add_epi32(_mm_madd_epi16(s0, w0), mmOffset); + s0 = _mm_sra_epi32(s0, mmShift); + s0 = _mm_packs_epi32(s0, s0); + s0 = _mm_min_epi16(mmMax, _mm_max_epi16(s0, mmMin)); + _mm_storel_epi64((__m128i *) (dst), s0); + dst += strideDst; + src0 += strideSrc0; + src1 += strideSrc1; + weight += stepY; + } + } +#if USE_AVX2 + else if (width >= 16) + { + const __m256i mmEightAVX2 = _mm256_set1_epi16(8); + const __m256i mmOffsetAVX2 = _mm256_set1_epi32(offsetWeighted); + const __m256i mmMinAVX2 = _mm256_set1_epi16(clpRng.min); + const __m256i mmMaxAVX2 = _mm256_set1_epi16(clpRng.max); + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x += 16) + { + __m256i s0 = _mm256_lddqu_si256((__m256i *) (src0 + x)); // why not aligned with 128/256 bit boundaries + __m256i s1 = _mm256_lddqu_si256((__m256i *) (src1 + x)); + + __m256i w0 = _mm256_lddqu_si256((__m256i *) (weight + x)); + if (compIdx != COMPONENT_Y && pu.chromaFormat != CHROMA_444) + { + const __m256i mask = _mm256_set_epi16(0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1); + __m256i w0p0, w0p1; + if (g_angle2mirror[angle] == 1) + { + w0p0 = _mm256_lddqu_si256((__m256i *) (weight - (x << 1) - (16 - 1))); // first sub-sample the required weights. + w0p1 = _mm256_lddqu_si256((__m256i *) (weight - (x << 1) - 16 - (16 - 1))); + const __m256i shuffle_mask = _mm256_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + w0p0 = _mm256_shuffle_epi8(w0p0, shuffle_mask); + w0p0 = _mm256_permute4x64_epi64(w0p0, _MM_SHUFFLE(1, 0, 3, 2)); + w0p1 = _mm256_shuffle_epi8(w0p1, shuffle_mask); + w0p1 = _mm256_permute4x64_epi64(w0p1, _MM_SHUFFLE(1, 0, 3, 2)); + } + else + { + w0p0 = _mm256_lddqu_si256((__m256i *) (weight + (x << 1))); // first sub-sample the required weights. + w0p1 = _mm256_lddqu_si256((__m256i *) (weight + (x << 1) + 16)); + } + w0p0 = _mm256_mullo_epi16(w0p0, mask); + w0p1 = _mm256_mullo_epi16(w0p1, mask); + w0 = _mm256_packs_epi16(w0p0, w0p1); + w0 = _mm256_permute4x64_epi64(w0, _MM_SHUFFLE(3, 1, 2, 0)); + } + else + { + if (g_angle2mirror[angle] == 1) + { + w0 = _mm256_lddqu_si256((__m256i *) (weight - x - (16 - 1))); + const __m256i shuffle_mask = _mm256_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + w0 = _mm256_shuffle_epi8(w0, shuffle_mask); + w0 = _mm256_permute4x64_epi64(w0, _MM_SHUFFLE(1, 0, 3, 2)); + } + else + { + w0 = _mm256_lddqu_si256((__m256i *) (weight + x)); + } + } + __m256i w1 = _mm256_sub_epi16(mmEightAVX2, w0); + + __m256i s0tmp = _mm256_unpacklo_epi16(s0, s1); + __m256i w0tmp = _mm256_unpacklo_epi16(w0, w1); + s0tmp = _mm256_add_epi32(_mm256_madd_epi16(s0tmp, w0tmp), mmOffsetAVX2); + s0tmp = _mm256_sra_epi32(s0tmp, mmShift); + + s0 = _mm256_unpackhi_epi16(s0, s1); + w0 = _mm256_unpackhi_epi16(w0, w1); + s0 = _mm256_add_epi32(_mm256_madd_epi16(s0, w0), mmOffsetAVX2); + s0 = _mm256_sra_epi32(s0, mmShift); + + s0 = _mm256_packs_epi32(s0tmp, s0); + s0 = _mm256_min_epi16(mmMaxAVX2, _mm256_max_epi16(s0, mmMinAVX2)); + _mm256_storeu_si256((__m256i *) (dst + x), s0); + } + dst += strideDst; + src0 += strideSrc0; + src1 += strideSrc1; + weight += stepY; + } + } +#endif + else + { + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x += 8) + { + __m128i s0 = _mm_lddqu_si128((__m128i *) (src0 + x)); + __m128i s1 = _mm_lddqu_si128((__m128i *) (src1 + x)); + __m128i w0; + if (compIdx != COMPONENT_Y && pu.chromaFormat != CHROMA_444) + { + const __m128i mask = _mm_set_epi16(0, 1, 0, 1, 0, 1, 0, 1); + __m128i w0p0, w0p1; + if (g_angle2mirror[angle] == 1) + { + w0p0 = _mm_lddqu_si128((__m128i *) (weight - (x << 1) - (8 - 1))); // first sub-sample the required weights. + w0p1 = _mm_lddqu_si128((__m128i *) (weight - (x << 1) - 8 - (8 - 1))); + const __m128i shuffle_mask = _mm_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + w0p0 = _mm_shuffle_epi8(w0p0, shuffle_mask); + w0p1 = _mm_shuffle_epi8(w0p1, shuffle_mask); + } + else + { + w0p0 = _mm_lddqu_si128((__m128i *) (weight + (x << 1))); // first sub-sample the required weights. + w0p1 = _mm_lddqu_si128((__m128i *) (weight + (x << 1) + 8)); + } + w0p0 = _mm_mullo_epi16(w0p0, mask); + w0p1 = _mm_mullo_epi16(w0p1, mask); + w0 = _mm_packs_epi32(w0p0, w0p1); + } + else + { + if (g_angle2mirror[angle] == 1) + { + w0 = _mm_lddqu_si128((__m128i *) (weight - x - (8 - 1))); + const __m128i shuffle_mask = _mm_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + w0 = _mm_shuffle_epi8(w0, shuffle_mask); + } + else + { + w0 = _mm_lddqu_si128((__m128i *) (weight + x)); + } + } + __m128i w1 = _mm_sub_epi16(mmEight, w0); + + __m128i s0tmp = _mm_unpacklo_epi16(s0, s1); + __m128i w0tmp = _mm_unpacklo_epi16(w0, w1); + s0tmp = _mm_add_epi32(_mm_madd_epi16(s0tmp, w0tmp), mmOffset); + s0tmp = _mm_sra_epi32(s0tmp, mmShift); + + s0 = _mm_unpackhi_epi16(s0, s1); + w0 = _mm_unpackhi_epi16(w0, w1); + s0 = _mm_add_epi32(_mm_madd_epi16(s0, w0), mmOffset); + s0 = _mm_sra_epi32(s0, mmShift); + + s0 = _mm_packs_epi32(s0tmp, s0); + s0 = _mm_min_epi16(mmMax, _mm_max_epi16(s0, mmMin)); + _mm_storeu_si128((__m128i *) (dst + x), s0); + } + dst += strideDst; + src0 += strideSrc0; + src1 += strideSrc1; + weight += stepY; + } + } +} +#endif template <X86_VEXT vext> void InterpolationFilter::_initInterpolationFilterX86() @@ -1489,7 +1711,11 @@ void InterpolationFilter::_initInterpolationFilterX86() m_filterCopy[1][0] = simdFilterCopy<vext, true, false>; m_filterCopy[1][1] = simdFilterCopy<vext, true, true>; +#if !JVET_Q0806 m_weightedTriangleBlk = xWeightedTriangleBlk_SSE<vext>; +#else + m_weightedGeoBlk = xWeightedGeoBlk_SSE<vext>; +#endif } template void InterpolationFilter::_initInterpolationFilterX86<SIMDX86>(); diff --git a/source/Lib/CommonLib/x86/RdCostX86.h b/source/Lib/CommonLib/x86/RdCostX86.h index b5e3288be1949c3540b222b59ef011d53d84b32a..b11df9504448ceb4db9fd248851b1c38ff52736d 100644 --- a/source/Lib/CommonLib/x86/RdCostX86.h +++ b/source/Lib/CommonLib/x86/RdCostX86.h @@ -1973,6 +1973,97 @@ static uint32_t xCalcHAD8x16_AVX2( const Pel* piOrg, const Pel* piCur, const int return (sad); } +#if JVET_Q0806 +template< X86_VEXT vext > +Distortion RdCost::xGetSADwMask_SIMD( const DistParam &rcDtParam ) +{ + if (rcDtParam.org.width < 4 || rcDtParam.bitDepth > 10 || rcDtParam.applyWeight) + return RdCost::xGetSADwMask( rcDtParam ); + + const short* src1 = (const short*)rcDtParam.org.buf; + const short* src2 = (const short*)rcDtParam.cur.buf; + const short* weightMask = (const short*)rcDtParam.mask; + int rows = rcDtParam.org.height; + int cols = rcDtParam.org.width; + int subShift = rcDtParam.subShift; + int subStep = ( 1 << subShift); + const int strideSrc1 = rcDtParam.org.stride * subStep; + const int strideSrc2 = rcDtParam.cur.stride * subStep; + const int strideMask = rcDtParam.maskStride * subStep; + + Distortion sum = 0; + if( vext >= AVX2 && (cols & 15 ) == 0 ) + { +#ifdef USE_AVX2 + // Do for width that multiple of 16 + __m256i vzero = _mm256_setzero_si256(); + __m256i vsum32 = vzero; + for( int y = 0; y < rows; y+= subStep) + { + for( int x = 0; x < cols; x+=16 ) + { + __m256i vsrc1 = _mm256_lddqu_si256( ( __m256i* )( &src1[x] ) ); + __m256i vsrc2 = _mm256_lddqu_si256( ( __m256i* )( &src2[x] ) ); + __m256i vmask; + if (rcDtParam.stepX == -1) + { + vmask = _mm256_lddqu_si256((__m256i*)((&weightMask[x]) - (x << 1) - (16 - 1))); + const __m256i shuffle_mask = _mm256_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + vmask = _mm256_shuffle_epi8(vmask, shuffle_mask); + vmask = _mm256_permute4x64_epi64(vmask, _MM_SHUFFLE(1, 0, 3, 2)); + } + else + { + vmask = _mm256_lddqu_si256((__m256i*)(&weightMask[x])); + } + vsum32 = _mm256_add_epi32( vsum32, _mm256_madd_epi16( vmask, _mm256_abs_epi16( _mm256_sub_epi16( vsrc1, vsrc2 ) ) ) ); + } + src1 += strideSrc1; + src2 += strideSrc2; + weightMask += strideMask; + } + vsum32 = _mm256_hadd_epi32( vsum32, vzero ); + vsum32 = _mm256_hadd_epi32( vsum32, vzero ); + sum = _mm_cvtsi128_si32( _mm256_castsi256_si128( vsum32 ) ) + _mm_cvtsi128_si32( _mm256_castsi256_si128( _mm256_permute2x128_si256( vsum32, vsum32, 0x11 ) ) ); +#endif + } + else + { + // Do with step of 8 + __m128i vzero = _mm_setzero_si128(); + __m128i vsum32 = vzero; + for( int y = 0; y < rows; y+= subStep) + { + for( int x = 0; x < cols; x+=8 ) + { + __m128i vsrc1 = _mm_loadu_si128( ( const __m128i* )( &src1[x] ) ); + __m128i vsrc2 = _mm_lddqu_si128( ( const __m128i* )( &src2[x] ) ); + __m128i vmask; + if (rcDtParam.stepX == -1) + { + vmask = _mm_lddqu_si128((__m128i*)((&weightMask[x]) - (x << 1) - (8 - 1))); + const __m128i shuffle_mask = _mm_set_epi8(1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); + vmask = _mm_shuffle_epi8(vmask, shuffle_mask); + } + else + { + vmask = _mm_lddqu_si128((const __m128i*)(&weightMask[x])); + } + vsum32 = _mm_add_epi32( vsum32, _mm_madd_epi16( vmask, _mm_abs_epi16( _mm_sub_epi16( vsrc1, vsrc2 ) ) ) ); + } + src1 += strideSrc1; + src2 += strideSrc2; + weightMask += strideMask; + } + vsum32 = _mm_hadd_epi32( vsum32, vzero ); + vsum32 = _mm_hadd_epi32( vsum32, vzero ); + sum = _mm_cvtsi128_si32( vsum32 ); + } + sum <<= subShift; + + return sum >> DISTORTION_PRECISION_ADJUSTMENT(rcDtParam.bitDepth); +} +#endif template<X86_VEXT vext> Distortion RdCost::xGetHADs_SIMD( const DistParam &rcDtParam ) @@ -2150,6 +2241,10 @@ void RdCost::_initRdCostX86() m_afpDistortFunc[DF_HAD16N] = RdCost::xGetHADs_SIMD<vext>; m_afpDistortFunc[DF_SAD_INTERMEDIATE_BITDEPTH] = RdCost::xGetSAD_IBD_SIMD<vext>; + +#if JVET_Q0806 + m_afpDistortFunc[DF_SAD_WITH_MASK] = xGetSADwMask_SIMD<vext>; +#endif } template void RdCost::_initRdCostX86<SIMDX86>(); diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index b8f20a7dee8845906193124edffe83d6e396f1a1..08e21e18342c54ed0421f1443206e1c9bafec7d1 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -2165,10 +2165,20 @@ void CABACReader::merge_data( PredictionUnit& pu ) } RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__MERGE_FLAG ); + +#if JVET_Q0806 + const bool ciipAvailable = pu.cs->sps->getUseCiip() && !pu.cu->skip && pu.cu->lwidth() < MAX_CU_SIZE && pu.cu->lheight() < MAX_CU_SIZE && pu.cu->lwidth() * pu.cu->lheight() >= 64; + const bool geoAvailable = pu.cu->cs->slice->getSPS()->getUseGeo() && pu.cu->cs->slice->isInterB() && pu.cu->cs->picHeader->getMaxNumGeoCand() > 1 + && pu.cu->lwidth() >= GEO_MIN_CU_SIZE && pu.cu->lheight() >= GEO_MIN_CU_SIZE + && pu.cu->lwidth() <= GEO_MAX_CU_SIZE && pu.cu->lheight() <= GEO_MAX_CU_SIZE + && pu.cu->lwidth() < 8 * pu.cu->lheight() && pu.cu->lheight() < 8 * pu.cu->lwidth(); + if (geoAvailable || ciipAvailable) +#else const bool triangleAvailable = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB() && pu.cu->cs->picHeader->getMaxNumTriangleCand() > 1; const bool ciipAvailable = pu.cs->sps->getUseCiip() && !pu.cu->skip && pu.cu->lwidth() < MAX_CU_SIZE && pu.cu->lheight() < MAX_CU_SIZE; if (pu.cu->lwidth() * pu.cu->lheight() >= 64 && (triangleAvailable || ciipAvailable)) +#endif { cu.firstPU->regularMergeFlag = m_BinDecoder.decodeBin(Ctx::RegularMergeFlag(cu.skip ? 0 : 1)); } @@ -2195,6 +2205,7 @@ void CABACReader::merge_data( PredictionUnit& pu ) { pu.mmvdMergeFlag = false; pu.cu->mmvdSkip = false; +#if !JVET_Q0806 if (triangleAvailable && ciipAvailable) { Ciip_flag(pu); @@ -2216,6 +2227,29 @@ void CABACReader::merge_data( PredictionUnit& pu ) { pu.cu->triangle = true; } +#else + if (geoAvailable && ciipAvailable) + { + Ciip_flag(pu); + } + else if (ciipAvailable) + { + pu.ciipFlag = true; + } + else + { + pu.ciipFlag = false; + } + if (pu.ciipFlag) + { + pu.intraDir[0] = PLANAR_IDX; + pu.intraDir[1] = DM_CHROMA_IDX; + } + else + { + pu.cu->geoFlag = true; + } +#endif } } if (pu.mmvdMergeFlag || pu.cu->mmvdSkip) @@ -2258,6 +2292,7 @@ void CABACReader::merge_idx( PredictionUnit& pu ) int numCandminus1 = int( pu.cs->picHeader->getMaxNumMergeCand() ) - 1; pu.mergeIdx = 0; +#if !JVET_Q0806 if( pu.cu->triangle ) { RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__TRIANGLE_INDEX ); @@ -2295,6 +2330,40 @@ void CABACReader::merge_idx( PredictionUnit& pu ) pu.triangleMergeIdx1 = candIdx1; return; } +#else + if( pu.cu->geoFlag ) + { + RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__GEO_INDEX ); + uint32_t splitDir = 0; + xReadTruncBinCode(splitDir, GEO_NUM_PARTITION_MODE); + pu.geoSplitDir = splitDir; + const int maxNumGeoCand = pu.cs->picHeader->getMaxNumGeoCand(); + CHECK(maxNumGeoCand < 2, "Incorrect max number of geo candidates"); + CHECK(pu.cu->lheight() > 64 || pu.cu->lwidth() > 64, "Incorrect block size of geo flag"); + int numCandminus2 = maxNumGeoCand - 2; + pu.mergeIdx = 0; + int mergeCand0 = 0; + int mergeCand1 = 0; + if( m_BinDecoder.decodeBin( Ctx::MergeIdx() ) ) + { + mergeCand0 += unary_max_eqprob(numCandminus2) + 1; + } + if (numCandminus2 > 0) + { + if (m_BinDecoder.decodeBin(Ctx::MergeIdx())) + { + mergeCand1 += unary_max_eqprob(numCandminus2 - 1) + 1; + } + } + mergeCand1 += mergeCand1 >= mergeCand0 ? 1 : 0; + pu.geoMergeIdx0 = mergeCand0; + pu.geoMergeIdx1 = mergeCand1; + DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_split_dir=%d\n", splitDir ); + DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_idx0=%d\n", mergeCand0 ); + DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_idx1=%d\n", mergeCand1 ); + return; + } +#endif if (pu.cu->predMode == MODE_IBC) { diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 88b6a9cd3d8bbfdba72c701d9968aa716927c4d7..9298a4cb2b9b42a1ba76a63a92f0dbf92e54d191 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -644,6 +644,7 @@ void DecCu::xFillPCMBuffer(CodingUnit &cu) void DecCu::xReconInter(CodingUnit &cu) { +#if !JVET_Q0806 if( cu.triangle ) { const bool splitDir = cu.firstPU->triangleSplitDir; @@ -653,13 +654,25 @@ void DecCu::xReconInter(CodingUnit &cu) PU::spanTriangleMotionInfo( *cu.firstPU, m_triangleMrgCtx, splitDir, candIdx0, candIdx1 ); } else +#else + if( cu.geoFlag ) + { + m_pcInterPred->motionCompensationGeo( cu, m_geoMrgCtx ); + PU::spanGeoMotionInfo( *cu.firstPU, m_geoMrgCtx, cu.firstPU->geoSplitDir, cu.firstPU->geoMergeIdx0, cu.firstPU->geoMergeIdx1 ); + } + else +#endif { m_pcIntraPred->geneIntrainterPred(cu); // inter prediction CHECK(CU::isIBC(cu) && cu.firstPU->ciipFlag, "IBC and Ciip cannot be used together"); CHECK(CU::isIBC(cu) && cu.affine, "IBC and Affine cannot be used together"); +#if !JVET_Q0806 CHECK(CU::isIBC(cu) && cu.triangle, "IBC and triangle cannot be used together"); +#else + CHECK(CU::isIBC(cu) && cu.geoFlag, "IBC and geo cannot be used together"); +#endif CHECK(CU::isIBC(cu) && cu.firstPU->mmvdMergeFlag, "IBC and MMVD cannot be used together"); const bool luma = cu.Y().valid(); const bool chroma = cu.Cb().valid(); @@ -899,11 +912,19 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) else { { +#if !JVET_Q0806 if( pu.cu->triangle ) { PU::getTriangleMergeCandidates( pu, m_triangleMrgCtx ); } else +#else + if( pu.cu->geoFlag ) + { + PU::getGeoMergeCandidates( pu, m_geoMrgCtx ); + } + else +#endif { if( pu.cu->affine ) { @@ -1047,6 +1068,7 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) PU::spanMotionInfo( pu, mrgCtx ); } } +#if !JVET_Q0806 if( !cu.triangle ) { if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) ) @@ -1054,6 +1076,15 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) printf( "DECODER: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() ); } } +#else + if( !cu.geoFlag ) + { + if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) ) + { + printf( "DECODER: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() ); + } + } +#endif if (CU::isIBC(cu)) { const int cuPelX = pu.Y().x; diff --git a/source/Lib/DecoderLib/DecCu.h b/source/Lib/DecoderLib/DecCu.h index 2cbb597a9b9a48a09675b02746ef44840e9384df..c6932f3e91866433cec7aacf29e3530e6b0c01ed 100644 --- a/source/Lib/DecoderLib/DecCu.h +++ b/source/Lib/DecoderLib/DecCu.h @@ -98,7 +98,11 @@ private: MotionInfo m_SubPuMiBuf[(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)]; +#if !JVET_Q0806 MergeCtx m_triangleMrgCtx; +#else + MergeCtx m_geoMrgCtx; +#endif }; //! \} diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 0943115a94dc7020b4ef373a2bf64e0de35f6952..bb9bdd280916ecc936aa35be1ab73f4cb5ef21e2 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -698,7 +698,11 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana READ_CODE( 2, uiCode, "pps_mvd_l1_zero_idc"); pcPPS->setPPSMvdL1ZeroIdc(uiCode); READ_CODE( 2, uiCode, "pps_collocated_from_l0_idc"); pcPPS->setPPSCollocatedFromL0Idc(uiCode); READ_UVLC( uiCode, "pps_six_minus_max_num_merge_cand_plus1"); pcPPS->setPPSSixMinusMaxNumMergeCandPlus1(uiCode); +#if !JVET_Q0806 READ_UVLC( uiCode, "pps_max_num_merge_cand_minus_max_num_triangle_cand_plus1");pcPPS->setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(uiCode); +#else + READ_UVLC(uiCode, "pps_max_num_merge_cand_minus_max_num_gpm_cand_plus1"); pcPPS->setPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1(uiCode); +#endif } else { @@ -708,7 +712,11 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana pcPPS->setPPSMvdL1ZeroIdc(0); pcPPS->setPPSCollocatedFromL0Idc(0); pcPPS->setPPSSixMinusMaxNumMergeCandPlus1(0); +#if !JVET_Q0806 pcPPS->setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(0); +#else + pcPPS->setPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1(0); +#endif } @@ -1166,6 +1174,44 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_CODE(8, uiCode, "sps_num_subpics_minus1"); pcSPS->setNumSubPics(uiCode + 1); for (int picIdx = 0; picIdx < pcSPS->getNumSubPics(); picIdx++) { +#if JVET_Q0787_SUBPIC + if (pcSPS->getMaxPicWidthInLumaSamples() > pcSPS->getCTUSize()) + { + READ_CODE(ceilLog2((pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize()), uiCode, "subpic_ctu_top_left_x[ i ]"); + pcSPS->setSubPicCtuTopLeftX(picIdx, uiCode); + } + else + { + pcSPS->setSubPicCtuTopLeftX(picIdx, 0); + } + if (pcSPS->getMaxPicHeightInLumaSamples() > pcSPS->getCTUSize()) + { + READ_CODE(ceilLog2((pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize()), uiCode, "subpic_ctu_top_left_y[ i ]"); + pcSPS->setSubPicCtuTopLeftY(picIdx, uiCode); + } + else + { + pcSPS->setSubPicCtuTopLeftY(picIdx, 0); + } + if (pcSPS->getMaxPicWidthInLumaSamples() > pcSPS->getCTUSize()) + { + READ_CODE(ceilLog2((pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize()), uiCode, "subpic_width_minus1[ i ]"); + pcSPS->setSubPicWidth(picIdx, uiCode + 1); + } + else + { + pcSPS->setSubPicWidth(picIdx, 1); + } + if (pcSPS->getMaxPicHeightInLumaSamples() > pcSPS->getCTUSize()) + { + READ_CODE(ceilLog2((pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize()), uiCode, "subpic_height_minus1[ i ]"); + pcSPS->setSubPicHeight(picIdx, uiCode + 1); + } + else + { + pcSPS->setSubPicHeight(picIdx, 1); + } +#else READ_CODE(std::max(1, ceilLog2(((pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1) >> floorLog2(pcSPS->getCTUSize())))), uiCode, "subpic_ctu_top_left_x[ i ]"); pcSPS->setSubPicCtuTopLeftX(picIdx, uiCode); READ_CODE(std::max(1, ceilLog2(((pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1) >> floorLog2(pcSPS->getCTUSize())))), uiCode, "subpic_ctu_top_left_y[ i ]"); @@ -1174,6 +1220,7 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) pcSPS->setSubPicWidth(picIdx, uiCode + 1); READ_CODE(std::max(1, ceilLog2(((pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1) >> floorLog2(pcSPS->getCTUSize())))), uiCode, "subpic_height_minus1[ i ]"); pcSPS->setSubPicHeight(picIdx, uiCode + 1); +#endif READ_FLAG(uiCode, "subpic_treated_as_pic_flag[ i ]"); pcSPS->setSubPicTreatedAsPicFlag(picIdx, uiCode); READ_FLAG(uiCode, "loop_filter_across_subpic_enabled_flag[ i ]"); @@ -1549,7 +1596,11 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_FLAG( uiCode, "sps_fpel_mmvd_enabled_flag" ); pcSPS->setFpelMmvdEnabledFlag ( uiCode != 0 ); } +#if !JVET_Q0806 READ_FLAG( uiCode, "triangle_flag" ); pcSPS->setUseTriangle ( uiCode != 0 ); +#else + READ_FLAG( uiCode, "sps_gpm_enabled_flag" ); pcSPS->setUseGeo ( uiCode != 0 ); +#endif READ_FLAG(uiCode, "sps_lmcs_enable_flag"); pcSPS->setUseLmcs(uiCode == 1); READ_FLAG( uiCode, "sps_lfnst_enabled_flag" ); pcSPS->setUseLFNST( uiCode != 0 ); @@ -2328,6 +2379,7 @@ void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManag picHeader->setDisProfFlag(0); } +#if !JVET_Q0806 // triangle merge candidate list size if (sps->getUseTriangle() && picHeader->getMaxNumMergeCand() >= 2) { @@ -2346,6 +2398,26 @@ void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManag { picHeader->setMaxNumTriangleCand(0); } +#else + // geometric merge candidate list size + if (sps->getUseGeo() && picHeader->getMaxNumMergeCand() >= 2) + { + if (!pps->getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1()) + { + READ_UVLC(uiCode, "pic_max_num_merge_cand_minus_max_num_gpm_cand"); + } + else + { + uiCode = pps->getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1() - 1; + } + CHECK(picHeader->getMaxNumMergeCand() < uiCode, "Incorrrect max number of gpm candidates!"); + picHeader->setMaxNumGeoCand((uint32_t)(picHeader->getMaxNumMergeCand() - uiCode)); + } + else + { + picHeader->setMaxNumGeoCand(0); + } +#endif // ibc merge candidate list size if (sps->getIBCFlag()) @@ -3428,7 +3500,11 @@ void HLSyntaxReader::parseConstraintInfo(ConstraintInfo *cinfo) READ_FLAG(symbol, "no_ibc_constraint_flag"); cinfo->setNoIbcConstraintFlag(symbol > 0 ? true : false); READ_FLAG(symbol, "no_ciip_constraint_flag"); cinfo->setNoCiipConstraintFlag(symbol > 0 ? true : false); READ_FLAG(symbol, "no_fpel_mmvd_constraint_flag"); cinfo->setNoFPelMmvdConstraintFlag(symbol > 0 ? true : false); +#if !JVET_Q0806 READ_FLAG(symbol, "no_triangle_constraint_flag"); cinfo->setNoTriangleConstraintFlag(symbol > 0 ? true : false); +#else + READ_FLAG(symbol, "no_gpm_constraint_flag"); cinfo->setNoGeoConstraintFlag(symbol > 0 ? true : false); +#endif READ_FLAG(symbol, "no_ladf_constraint_flag"); cinfo->setNoLadfConstraintFlag(symbol > 0 ? true : false); READ_FLAG(symbol, "no_transform_skip_constraint_flag"); cinfo->setNoTransformSkipConstraintFlag(symbol > 0 ? true : false); READ_FLAG(symbol, "no_bdpcm_constraint_flag"); cinfo->setNoBDPCMConstraintFlag(symbol > 0 ? true : false); diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 4044ba80eece7c7925d054bb2c5bf9381686fc5a..441fe0465d068ff195c43326be4498f5a99fe5fb 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -1884,10 +1884,19 @@ void CABACWriter::merge_data(const PredictionUnit& pu) merge_idx(pu); return; } +#if JVET_Q0806 + const bool ciipAvailable = pu.cs->sps->getUseCiip() && !pu.cu->skip && pu.cu->lwidth() < MAX_CU_SIZE && pu.cu->lheight() < MAX_CU_SIZE && pu.cu->lwidth() * pu.cu->lheight() >= 64; + const bool geoAvailable = pu.cu->cs->slice->getSPS()->getUseGeo() && pu.cu->cs->slice->isInterB() && pu.cu->cs->picHeader->getMaxNumGeoCand() > 1 + && pu.cu->lwidth() >= GEO_MIN_CU_SIZE && pu.cu->lheight() >= GEO_MIN_CU_SIZE + && pu.cu->lwidth() <= GEO_MAX_CU_SIZE && pu.cu->lheight() <= GEO_MAX_CU_SIZE + && pu.cu->lwidth() < 8 * pu.cu->lheight() && pu.cu->lheight() < 8 * pu.cu->lwidth(); + if (geoAvailable || ciipAvailable) +#else const bool triangleAvailable = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB() && pu.cu->cs->picHeader->getMaxNumTriangleCand() > 1; const bool ciipAvailable = pu.cs->sps->getUseCiip() && !pu.cu->skip && pu.cu->lwidth() < MAX_CU_SIZE && pu.cu->lheight() < MAX_CU_SIZE; if (pu.cu->lwidth() * pu.cu->lheight() >= 64 && (triangleAvailable || ciipAvailable)) +#endif { m_BinEncoder.encodeBin(pu.regularMergeFlag, Ctx::RegularMergeFlag(pu.cu->skip ? 0 : 1)); } @@ -1909,10 +1918,17 @@ void CABACWriter::merge_data(const PredictionUnit& pu) } else { +#if !JVET_Q0806 if (triangleAvailable && ciipAvailable) { Ciip_flag(pu); } +#else + if (geoAvailable && ciipAvailable) + { + Ciip_flag(pu); + } +#endif merge_idx(pu); } } @@ -2013,6 +2029,7 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) } else { +#if !JVET_Q0806 if( pu.cu->triangle ) { bool splitDir = pu.triangleSplitDir; @@ -2056,6 +2073,38 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) encodeOneIdx(candIdx1, maxNumTriangleCand - 2); return; } +#else + if( pu.cu->geoFlag ) + { + uint8_t splitDir = pu.geoSplitDir; + uint8_t candIdx0 = pu.geoMergeIdx0; + uint8_t candIdx1 = pu.geoMergeIdx1; + DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_split_dir=%d\n", splitDir ); + DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_idx0=%d\n", candIdx0 ); + DTRACE( g_trace_ctx, D_SYNTAX, "merge_idx() geo_idx1=%d\n", candIdx1 ); + xWriteTruncBinCode(splitDir, GEO_NUM_PARTITION_MODE); + candIdx1 -= candIdx1 < candIdx0 ? 0 : 1; + const int maxNumGeoCand = pu.cs->picHeader->getMaxNumGeoCand(); + CHECK(maxNumGeoCand < 2, "Incorrect max number of geo candidates"); + CHECK(candIdx0 >= maxNumGeoCand, "Incorrect candIdx0"); + CHECK(candIdx1 >= maxNumGeoCand, "Incorrect candIdx1"); + int numCandminus2 = maxNumGeoCand - 2; + m_BinEncoder.encodeBin( candIdx0 == 0 ? 0 : 1, Ctx::MergeIdx() ); + if( candIdx0 > 0 ) + { + unary_max_eqprob(candIdx0 - 1, numCandminus2); + } + if (numCandminus2 > 0) + { + m_BinEncoder.encodeBin(candIdx1 == 0 ? 0 : 1, Ctx::MergeIdx()); + if (candIdx1 > 0) + { + unary_max_eqprob(candIdx1 - 1, numCandminus2 - 1); + } + } + return; + } +#endif int numCandminus1; if (pu.cu->predMode == MODE_IBC) numCandminus1 = int(pu.cs->picHeader->getMaxNumIBCMergeCand()) - 1; diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 7f8afbe6211b77ed354c2630b7eeee84d6ceb944..0e30d01bbb8b04bf96ba2af1777c4d45aa2537bd 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -188,7 +188,11 @@ protected: bool m_noIbcConstraintFlag; bool m_bNoCiipConstraintFlag; bool m_noFPelMmvdConstraintFlag; +#if !JVET_Q0806 bool m_bNoTriangleConstraintFlag; +#else + bool m_noGeoConstraintFlag; +#endif bool m_bNoLadfConstraintFlag; bool m_noTransformSkipConstraintFlag; bool m_noBDPCMConstraintFlag; @@ -304,7 +308,11 @@ protected: #endif bool m_ciip; +#if !JVET_Q0806 bool m_Triangle; +#else + bool m_Geo; +#endif bool m_allowDisFracMMVD; bool m_AffineAmvr; bool m_HashME; @@ -603,7 +611,11 @@ protected: #endif uint32_t m_maxNumMergeCand; ///< Maximum number of merge candidates uint32_t m_maxNumAffineMergeCand; ///< Maximum number of affine merge candidates +#if !JVET_Q0806 uint32_t m_maxNumTriangleCand; +#else + uint32_t m_maxNumGeoCand; +#endif uint32_t m_maxNumIBCMergeCand; ///< Max number of IBC merge candidates ScalingListMode m_useScalingListId; ///< Using quantization matrix i.e. 0=off, 1=default, 2=file. std::string m_scalingListFileName; ///< quantization matrix file name @@ -620,7 +632,11 @@ protected: int m_PPSMvdL1ZeroIdc; int m_PPSCollocatedFromL0Idc; uint32_t m_PPSSixMinusMaxNumMergeCandPlus1; +#if !JVET_Q0806 uint32_t m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1; +#else + uint32_t m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1; +#endif bool m_DepQuantEnabledFlag; bool m_SignDataHidingEnabledFlag; bool m_RCEnableRateControl; @@ -779,8 +795,13 @@ public: void setNoCiipConstraintFlag(bool bVal) { m_bNoCiipConstraintFlag = bVal; } bool getNoFPelMmvdConstraintFlag() const { return m_noFPelMmvdConstraintFlag; } void setNoFPelMmvdConstraintFlag(bool bVal) { m_noFPelMmvdConstraintFlag = bVal; } +#if !JVET_Q0806 bool getNoTriangleConstraintFlag() const { return m_bNoTriangleConstraintFlag; } void setNoTriangleConstraintFlag(bool bVal) { m_bNoTriangleConstraintFlag = bVal; } +#else + bool getNoGeoConstraintFlag() const { return m_noGeoConstraintFlag; } + void setNoGeoConstraintFlag(bool bVal) { m_noGeoConstraintFlag = bVal; } +#endif bool getNoLadfConstraintFlag() const { return m_bNoLadfConstraintFlag; } void setNoLadfConstraintFlag(bool bVal) { m_bNoLadfConstraintFlag = bVal; } bool getNoTransformSkipConstraintFlag() const { return m_noTransformSkipConstraintFlag; } @@ -988,8 +1009,13 @@ public: void setUseCiip ( bool b ) { m_ciip = b; } bool getUseCiip () const { return m_ciip; } +#if !JVET_Q0806 void setUseTriangle ( bool b ) { m_Triangle = b; } bool getUseTriangle () const { return m_Triangle; } +#else + void setUseGeo ( bool b ) { m_Geo = b; } + bool getUseGeo () const { return m_Geo; } +#endif void setAllowDisFracMMVD ( bool b ) { m_allowDisFracMMVD = b; } bool getAllowDisFracMMVD () const { return m_allowDisFracMMVD; } void setUseHashME ( bool b ) { m_HashME = b; } @@ -1612,8 +1638,13 @@ public: uint32_t getMaxNumMergeCand () { return m_maxNumMergeCand; } void setMaxNumAffineMergeCand ( uint32_t u ) { m_maxNumAffineMergeCand = u; } uint32_t getMaxNumAffineMergeCand () { return m_maxNumAffineMergeCand; } +#if !JVET_Q0806 void setMaxNumTriangleCand ( uint32_t u ) { m_maxNumTriangleCand = u; } uint32_t getMaxNumTriangleCand () { return m_maxNumTriangleCand; } +#else + void setMaxNumGeoCand ( uint32_t u ) { m_maxNumGeoCand = u; } + uint32_t getMaxNumGeoCand () { return m_maxNumGeoCand; } +#endif void setMaxNumIBCMergeCand ( uint32_t u ) { m_maxNumIBCMergeCand = u; } uint32_t getMaxNumIBCMergeCand () { return m_maxNumIBCMergeCand; } void setUseScalingListId ( ScalingListMode u ) { m_useScalingListId = u; } @@ -1646,8 +1677,13 @@ public: int getPPSCollocatedFromL0Idc () { return m_PPSCollocatedFromL0Idc; } void setPPSSixMinusMaxNumMergeCandPlus1 ( uint32_t u ) { m_PPSSixMinusMaxNumMergeCandPlus1 = u; } uint32_t getPPSSixMinusMaxNumMergeCandPlus1 () { return m_PPSSixMinusMaxNumMergeCandPlus1; } +#if !JVET_Q0806 void setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 ( uint32_t u ) { m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 = u; } uint32_t getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1 () { return m_PPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1; } +#else + void setPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 ( uint32_t u ) { m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 = u; } + uint32_t getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1 () { return m_PPSMaxNumMergeCandMinusMaxNumGeoCandPlus1; } +#endif WeightedPredictionMethod getWeightedPredictionMethod() const { return m_weightedPredictionMethod; } void setWeightedPredictionMethod( WeightedPredictionMethod m ) { m_weightedPredictionMethod = m; } void setDepQuantEnabledFlag( bool b ) { m_DepQuantEnabledFlag = b; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index e33e976488c070a10814dff2fac039994f5890c7..011ce09d3ac128435543ec07d31b289d850b3e90 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -59,6 +59,7 @@ //! \{ // ==================================================================================================================== +#if !JVET_Q0806 EncCu::EncCu() : m_triangleModeTest { TriangleMotionInfo( 0, 1, 0 ), TriangleMotionInfo( 1, 0, 1 ), TriangleMotionInfo( 1, 0, 2 ), TriangleMotionInfo( 0, 0, 1 ), TriangleMotionInfo( 0, 2, 0 ), @@ -71,6 +72,18 @@ EncCu::EncCu() : m_triangleModeTest TriangleMotionInfo( 0, 3, 1 ), TriangleMotionInfo( 0, 2, 4 ), TriangleMotionInfo( 1, 2, 4 ), TriangleMotionInfo( 0, 4, 2 ), TriangleMotionInfo( 0, 3, 4 ), } {} +#else +EncCu::EncCu() : m_GeoModeTest +{ + GeoMotionInfo(0, 1), GeoMotionInfo(1, 0),GeoMotionInfo(0, 2), GeoMotionInfo(1, 2), GeoMotionInfo(2, 0), + GeoMotionInfo(2, 1), GeoMotionInfo(0, 3),GeoMotionInfo(1, 3), GeoMotionInfo(2, 3), GeoMotionInfo(3, 0), + GeoMotionInfo(3, 1), GeoMotionInfo(3, 2),GeoMotionInfo(0, 4), GeoMotionInfo(1, 4), GeoMotionInfo(2, 4), + GeoMotionInfo(3, 4), GeoMotionInfo(4, 0),GeoMotionInfo(4, 1), GeoMotionInfo(4, 2), GeoMotionInfo(4, 3), + GeoMotionInfo(0, 5), GeoMotionInfo(1, 5),GeoMotionInfo(2, 5), GeoMotionInfo(3, 5), GeoMotionInfo(4, 5), + GeoMotionInfo(5, 0), GeoMotionInfo(5, 1),GeoMotionInfo(5, 2), GeoMotionInfo(5, 3), GeoMotionInfo(5, 4) +} +{} +#endif void EncCu::create( EncCfg* encCfg ) { @@ -138,6 +151,7 @@ void EncCu::create( EncCfg* encCfg ) m_acRealMergeBuffer[ui].create(chromaFormat, Area(0, 0, uiMaxWidth, uiMaxHeight)); m_acMergeTmpBuffer[ui].create(chromaFormat, Area(0, 0, uiMaxWidth, uiMaxHeight)); } +#if !JVET_Q0806 const unsigned maxNumTriangleCand = encCfg->getMaxNumTriangleCand(); for (unsigned i = 0; i < maxNumTriangleCand; i++) { @@ -174,6 +188,12 @@ void EncCu::create( EncCfg* encCfg ) { m_acTriangleWeightedBuffer[ui].create( chromaFormat, Area( 0, 0, uiMaxWidth, uiMaxHeight ) ); } +#else + for( unsigned ui = 0; ui < GEO_MAX_TRY_WEIGHTED_SAD; ui++ ) + { + m_acGeoWeightedBuffer[ui].create( chromaFormat, Area( 0, 0, uiMaxWidth, uiMaxHeight ) ); + } +#endif m_CtxBuffer.resize( maxDepth ); m_CurrCtx = 0; @@ -237,10 +257,17 @@ void EncCu::destroy() m_acRealMergeBuffer[ui].destroy(); m_acMergeTmpBuffer[ui].destroy(); } +#if !JVET_Q0806 for( unsigned ui = 0; ui < TRIANGLE_MAX_NUM_CANDS; ui++ ) { m_acTriangleWeightedBuffer[ui].destroy(); } +#else + for (unsigned ui = 0; ui < GEO_MAX_TRY_WEIGHTED_SAD; ui++) + { + m_acGeoWeightedBuffer[ui].destroy(); + } +#endif } @@ -270,6 +297,10 @@ void EncCu::init( EncLib* pcEncLib, const SPS& sps PARL_PARAM( const int tId ) ) m_dataId = tId; #endif m_pcLoopFilter = pcEncLib->getLoopFilter(); +#if JVET_Q0806 + m_GeoCostList.init(GEO_NUM_PARTITION_MODE, m_pcEncCfg->getMaxNumGeoCand()); + m_AFFBestSATDCost = MAX_DOUBLE; +#endif DecCu::init( m_pcTrQuant, m_pcIntraSearch, m_pcInterSearch ); @@ -790,10 +821,17 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par if (cu) cu->mmvdSkip = cu->skip == false ? false : cu->mmvdSkip; } +#if !JVET_Q0806 else if( currTestMode.type == ETM_MERGE_TRIANGLE ) { xCheckRDCostMergeTriangle2Nx2N( tempCS, bestCS, partitioner, currTestMode ); } +#else + else if( currTestMode.type == ETM_MERGE_GEO ) + { + xCheckRDCostMergeGeo2Nx2N( tempCS, bestCS, partitioner, currTestMode ); + } +#endif else if( currTestMode.type == ETM_INTRA ) { if (slice.getSPS()->getUseColorTrans() && !CS::isDualITree(*tempCS)) @@ -2394,7 +2432,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& cu.tileIdx = tempCS->pps->getTileIdx( tempCS->area.lumaPos() ); cu.skip = false; cu.mmvdSkip = false; +#if !JVET_Q0806 cu.triangle = false; +#else + cu.geoFlag = false; +#endif //cu.affine cu.predMode = MODE_INTER; //cu.LICFlag @@ -2653,7 +2695,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& cu.tileIdx = tempCS->pps->getTileIdx( tempCS->area.lumaPos() ); cu.skip = false; cu.mmvdSkip = false; +#if !JVET_Q0806 cu.triangle = false; +#else + cu.geoFlag = false; +#endif //cu.affine cu.predMode = MODE_INTER; //cu.LICFlag @@ -2815,6 +2861,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& } } +#if !JVET_Q0806 void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode ) { const Slice &slice = *tempCS->slice; @@ -3036,6 +3083,287 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru xCalDebCost( *bestCS, partitioner ); } } +#else +void EncCu::xCheckRDCostMergeGeo2Nx2N(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode) +{ + const Slice &slice = *tempCS->slice; + CHECK(slice.getSliceType() == I_SLICE, "Merge modes not available for I-slices"); + + tempCS->initStructData(encTestMode.qp); + + MergeCtx mergeCtx; + const SPS &sps = *tempCS->sps; + + if (sps.getSBTMVPEnabledFlag()) + { + Size bufSize = g_miScaling.scale(tempCS->area.lumaSize()); + mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); + } + + CodingUnit &cu = tempCS->addCU(tempCS->area, pm.chType); + pm.setCUData(cu); + cu.predMode = MODE_INTER; + cu.slice = tempCS->slice; + cu.tileIdx = tempCS->pps->getTileIdx(tempCS->area.lumaPos()); + cu.qp = encTestMode.qp; + cu.affine = false; + cu.mtsFlag = false; + cu.BcwIdx = BCW_DEFAULT; + cu.geoFlag = true; + cu.imv = 0; + cu.mmvdSkip = false; + cu.skip = false; + cu.mipFlag = false; + cu.bdpcmMode = 0; + + PredictionUnit &pu = tempCS->addPU(cu, pm.chType); + pu.mergeFlag = true; + pu.regularMergeFlag = false; + PU::getGeoMergeCandidates(pu, mergeCtx); + + GeoComboCostList comboList; + int bitsCandTB = floorLog2(GEO_NUM_PARTITION_MODE); + PelUnitBuf geoBuffer[MRG_MAX_NUM_CANDS]; + PelUnitBuf geoTempBuf[MRG_MAX_NUM_CANDS]; + PelUnitBuf geoCombinations[GEO_MAX_TRY_WEIGHTED_SAD]; + DistParam distParam; + + const UnitArea localUnitArea(tempCS->area.chromaFormat, Area(0, 0, tempCS->area.Y().width, tempCS->area.Y().height)); + const double sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda(); + + uint8_t maxNumMergeCandidates = cu.cs->picHeader->getMaxNumGeoCand(); + DistParam distParamWholeBlk; + m_pcRdCost->setDistParam(distParamWholeBlk, tempCS->getOrgBuf().Y(), m_acMergeBuffer[0].Y().buf, m_acMergeBuffer[0].Y().stride, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y); + Distortion bestWholeBlkSad = MAX_UINT64; + double bestWholeBlkCost = MAX_DOUBLE; + Distortion *sadWholeBlk; + sadWholeBlk = new Distortion[maxNumMergeCandidates]; + int *pocMrg; + Mv *MrgMv; + bool *isSkipThisCand; + pocMrg = new int[maxNumMergeCandidates]; + MrgMv = new Mv[maxNumMergeCandidates]; + isSkipThisCand = new bool[maxNumMergeCandidates]; + for (int i = 0; i < maxNumMergeCandidates; i++) + isSkipThisCand[i] = false; + for (uint8_t mergeCand = 0; mergeCand < maxNumMergeCandidates; mergeCand++) + { + geoBuffer[mergeCand] = m_acMergeBuffer[mergeCand].getBuf(localUnitArea); + mergeCtx.setMergeInfo(pu, mergeCand); + int MrgList = mergeCtx.mvFieldNeighbours[(mergeCand << 1) + 0].refIdx == -1 ? 1 : 0; + RefPicList MrgeRefPicList = (MrgList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); + int MrgrefIdx = mergeCtx.mvFieldNeighbours[(mergeCand << 1) + MrgList].refIdx; + pocMrg[mergeCand] = tempCS->slice->getRefPic(MrgeRefPicList, MrgrefIdx)->getPOC(); + MrgMv[mergeCand] = mergeCtx.mvFieldNeighbours[(mergeCand << 1) + MrgList].mv; + if (mergeCand) + { + for (int i = 0; i < mergeCand; i++) + { + if (pocMrg[mergeCand] == pocMrg[i] && MrgMv[mergeCand] == MrgMv[i]) + { + isSkipThisCand[mergeCand] = true; + break; + } + } + } + PU::spanMotionInfo(pu, mergeCtx); + if (m_pcEncCfg->getMCTSEncConstraint() && (!(MCTSHelper::checkMvBufferForMCTSConstraint(pu)))) + { + tempCS->initStructData(encTestMode.qp); + return; + } + m_pcInterSearch->motionCompensation(pu, geoBuffer[mergeCand]); + geoTempBuf[mergeCand] = m_acMergeTmpBuffer[mergeCand].getBuf(localUnitArea); + geoTempBuf[mergeCand].Y().copyFrom(geoBuffer[mergeCand].Y()); + geoTempBuf[mergeCand].Y().roundToOutputBitdepth(geoTempBuf[mergeCand].Y(), cu.slice->clpRng(COMPONENT_Y)); + distParamWholeBlk.cur.buf = geoTempBuf[mergeCand].Y().buf; + distParamWholeBlk.cur.stride = geoTempBuf[mergeCand].Y().stride; + sadWholeBlk[mergeCand] = distParamWholeBlk.distFunc(distParamWholeBlk); + if (sadWholeBlk[mergeCand] < bestWholeBlkSad) + { + bestWholeBlkSad = sadWholeBlk[mergeCand]; + int bitsCand = mergeCand + 1; + bestWholeBlkCost = (double)bestWholeBlkSad + (double)bitsCand * sqrtLambdaForFirstPass; + } + } + bool isGeo = true; + for (uint8_t mergeCand = 1; mergeCand < maxNumMergeCandidates; mergeCand++) + { + isGeo &= isSkipThisCand[mergeCand]; + } + if (isGeo) + { + return; + } + + int wIdx = floorLog2(cu.lwidth()) - GEO_MIN_CU_LOG2; + int hIdx = floorLog2(cu.lheight()) - GEO_MIN_CU_LOG2; + for (int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++) + { + int maskStride = 0, maskStride2 = 0; + int stepX = 1; + Pel* SADmask; + int16_t angle = g_GeoParams[splitDir][0]; + if (g_angle2mirror[angle] == 2) + { + maskStride = -GEO_WEIGHT_MASK_SIZE; + maskStride2 = -(int)cu.lwidth(); + SADmask = &g_globalGeoEncSADmask[g_angle2mask[g_GeoParams[splitDir][0]]][(GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[splitDir][hIdx][wIdx][1]) * GEO_WEIGHT_MASK_SIZE + g_weightOffset[splitDir][hIdx][wIdx][0]]; + } + else if (g_angle2mirror[angle] == 1) + { + stepX = -1; + maskStride2 = cu.lwidth(); + maskStride = GEO_WEIGHT_MASK_SIZE; + SADmask = &g_globalGeoEncSADmask[g_angle2mask[g_GeoParams[splitDir][0]]][g_weightOffset[splitDir][hIdx][wIdx][1] * GEO_WEIGHT_MASK_SIZE + (GEO_WEIGHT_MASK_SIZE - 1 - g_weightOffset[splitDir][hIdx][wIdx][0])]; + } + else + { + maskStride = GEO_WEIGHT_MASK_SIZE; + maskStride2 = -(int)cu.lwidth(); + SADmask = &g_globalGeoEncSADmask[g_angle2mask[g_GeoParams[splitDir][0]]][g_weightOffset[splitDir][hIdx][wIdx][1] * GEO_WEIGHT_MASK_SIZE + g_weightOffset[splitDir][hIdx][wIdx][0]]; + } + Distortion sadSmall = 0, sadLarge = 0; + for (uint8_t mergeCand = 0; mergeCand < maxNumMergeCandidates; mergeCand++) + { + int bitsCand = mergeCand + 1; + + m_pcRdCost->setDistParam(distParam, tempCS->getOrgBuf().Y(), geoTempBuf[mergeCand].Y().buf, geoTempBuf[mergeCand].Y().stride, SADmask, maskStride, stepX, maskStride2, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y); + sadLarge = distParam.distFunc(distParam); + m_GeoCostList.insert(splitDir, 0, mergeCand, (double)sadLarge + (double)bitsCand * sqrtLambdaForFirstPass); + sadSmall = sadWholeBlk[mergeCand] - sadLarge; + m_GeoCostList.insert(splitDir, 1, mergeCand, (double)sadSmall + (double)bitsCand * sqrtLambdaForFirstPass); + } + } + delete[] sadWholeBlk; + delete[] pocMrg; + delete[] MrgMv; + delete[] isSkipThisCand; + + for (int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++) + { + for (int GeoMotionIdx = 0; GeoMotionIdx < maxNumMergeCandidates * (maxNumMergeCandidates - 1); GeoMotionIdx++) + { + unsigned int mergeCand0 = m_GeoModeTest[GeoMotionIdx].m_candIdx0; + unsigned int mergeCand1 = m_GeoModeTest[GeoMotionIdx].m_candIdx1; + double tempCost = m_GeoCostList.singleDistList[0][splitDir][mergeCand0].cost + m_GeoCostList.singleDistList[1][splitDir][mergeCand1].cost; + if (tempCost > bestWholeBlkCost) + continue; + tempCost = tempCost + (double)bitsCandTB * sqrtLambdaForFirstPass; + comboList.list.push_back(GeoMergeCombo(splitDir, mergeCand0, mergeCand1, tempCost)); + } + } + if (comboList.list.empty()) + return; + comboList.sortByCost(); + bool geocandHasNoResidual[GEO_MAX_TRY_WEIGHTED_SAD]; + for (int mergeCand = 0; mergeCand < GEO_MAX_TRY_WEIGHTED_SAD; mergeCand++) + { + geocandHasNoResidual[mergeCand] = false; + } + bool bestIsSkip = false; + int geoNumCobo = (int)comboList.list.size(); + static_vector<uint8_t, GEO_MAX_TRY_WEIGHTED_SAD> geoRdModeList; + static_vector<double, GEO_MAX_TRY_WEIGHTED_SAD> geocandCostList; + + DistParam distParamSAD2; + const bool useHadamard = !tempCS->slice->getDisableSATDForRD(); + m_pcRdCost->setDistParam(distParamSAD2, tempCS->getOrgBuf().Y(), m_acMergeBuffer[0].Y(), sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, useHadamard); + int geoNumMrgSATDCand = min(GEO_MAX_TRY_WEIGHTED_SATD, geoNumCobo); + + for (uint8_t candidateIdx = 0; candidateIdx < min(geoNumCobo, GEO_MAX_TRY_WEIGHTED_SAD); candidateIdx++) + { + int splitDir = comboList.list[candidateIdx].splitDir; + int mergeCand0 = comboList.list[candidateIdx].mergeIdx0; + int mergeCand1 = comboList.list[candidateIdx].mergeIdx1; + + geoCombinations[candidateIdx] = m_acGeoWeightedBuffer[candidateIdx].getBuf(localUnitArea); + m_pcInterSearch->weightedGeoBlk(pu, splitDir, CHANNEL_TYPE_LUMA, geoCombinations[candidateIdx], geoBuffer[mergeCand0], geoBuffer[mergeCand1]); + distParamSAD2.cur = geoCombinations[candidateIdx].Y(); + Distortion sad = distParamSAD2.distFunc(distParamSAD2); + int mvBits = 2; + mergeCand1 -= mergeCand1 < mergeCand0 ? 0 : 1; + mvBits += mergeCand0; + mvBits += mergeCand1; + double updateCost = (double)sad + (double)(bitsCandTB + mvBits) * sqrtLambdaForFirstPass; + comboList.list[candidateIdx].cost = updateCost; + updateCandList(candidateIdx, updateCost, geoRdModeList, geocandCostList, geoNumMrgSATDCand); + } + for (uint8_t i = 0; i < geoNumMrgSATDCand; i++) + { + if (geocandCostList[i] > MRG_FAST_RATIO * geocandCostList[0] || geocandCostList[i] > getMergeBestSATDCost() || geocandCostList[i] > getAFFBestSATDCost()) + { + geoNumMrgSATDCand = i; + break; + } + } + for (uint8_t i = 0; i < geoNumMrgSATDCand && isChromaEnabled(pu.chromaFormat); i++) + { + uint8_t candidateIdx = geoRdModeList[i]; + int splitDir = comboList.list[candidateIdx].splitDir; + int mergeCand0 = comboList.list[candidateIdx].mergeIdx0; + int mergeCand1 = comboList.list[candidateIdx].mergeIdx1; + geoCombinations[candidateIdx] = m_acGeoWeightedBuffer[candidateIdx].getBuf(localUnitArea); + m_pcInterSearch->weightedGeoBlk(pu, splitDir, CHANNEL_TYPE_CHROMA, geoCombinations[candidateIdx], geoBuffer[mergeCand0], geoBuffer[mergeCand1]); + } + + m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false; + tempCS->initStructData(encTestMode.qp); + uint8_t iteration; + uint8_t iterationBegin = 0; + iteration = 2; + for (uint8_t noResidualPass = iterationBegin; noResidualPass < iteration; ++noResidualPass) + { + for (uint8_t mrgHADIdx = 0; mrgHADIdx < geoNumMrgSATDCand; mrgHADIdx++) + { + uint8_t candidateIdx = geoRdModeList[mrgHADIdx]; + if (((noResidualPass != 0) && geocandHasNoResidual[candidateIdx]) + || ((noResidualPass == 0) && bestIsSkip)) + { + continue; + } + CodingUnit &cu = tempCS->addCU(tempCS->area, pm.chType); + pm.setCUData(cu); + cu.predMode = MODE_INTER; + cu.slice = tempCS->slice; + cu.tileIdx = tempCS->pps->getTileIdx(tempCS->area.lumaPos()); + cu.qp = encTestMode.qp; + cu.affine = false; + cu.mtsFlag = false; + cu.BcwIdx = BCW_DEFAULT; + cu.geoFlag = true; + cu.imv = 0; + cu.mmvdSkip = false; + cu.skip = false; + cu.mipFlag = false; + cu.bdpcmMode = 0; + PredictionUnit &pu = tempCS->addPU(cu, pm.chType); + pu.mergeFlag = true; + pu.regularMergeFlag = false; + pu.geoSplitDir = comboList.list[candidateIdx].splitDir; + pu.geoMergeIdx0 = comboList.list[candidateIdx].mergeIdx0; + pu.geoMergeIdx1 = comboList.list[candidateIdx].mergeIdx1; + pu.mmvdMergeFlag = false; + pu.mmvdMergeIdx = MAX_UINT; + + PU::spanGeoMotionInfo(pu, mergeCtx, pu.geoSplitDir, pu.geoMergeIdx0, pu.geoMergeIdx1); + tempCS->getPredBuf().copyFrom(geoCombinations[candidateIdx]); + + xEncodeInterResidual(tempCS, bestCS, pm, encTestMode, noResidualPass, (noResidualPass == 0 ? &geocandHasNoResidual[candidateIdx] : NULL)); + + if (m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip) + { + bestIsSkip = bestCS->getCU(pm.chType)->rootCbf == 0; + } + tempCS->initStructData(encTestMode.qp); + } + } + if (m_bestModeUpdated && bestCS->cost != MAX_DOUBLE) + { + xCalDebCost(*bestCS, pm); + } +} +#endif void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode ) { @@ -3058,6 +3386,10 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct AffineMergeCtx affineMergeCtx; const SPS &sps = *tempCS->sps; +#if JVET_Q0806 + setAFFBestSATDCost(MAX_DOUBLE); +#endif + MergeCtx mrgCtx; if ( sps.getSBTMVPEnabledFlag() ) { @@ -3197,6 +3529,10 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct } tempCS->initStructData( encTestMode.qp ); +#if JVET_Q0806 + setAFFBestSATDCost(candCostList[0]); +#endif + } else { @@ -3349,7 +3685,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct cu.mmvdSkip = false; pu.mmvdMergeFlag = false; pu.regularMergeFlag = false; +#if !JVET_Q0806 cu.triangle = false; +#else + cu.geoFlag = false; +#endif PU::getIBCMergeCandidates(pu, mergeCtx); } @@ -3383,7 +3723,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1; cu.qp = encTestMode.qp; cu.mmvdSkip = false; +#if !JVET_Q0806 cu.triangle = false; +#else + cu.geoFlag = false; +#endif DistParam distParam; const bool bUseHadamard = !cu.slice->getDisableSATDForRD(); PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType); //tempCS->addPU(cu); @@ -3500,7 +3844,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct cu.mmvdSkip = false; pu.mmvdMergeFlag = false; pu.regularMergeFlag = false; +#if !JVET_Q0806 cu.triangle = false; +#else + cu.geoFlag = false; +#endif mergeCtx.setMergeInfo(pu, mergeCand); PU::spanMotionInfo(pu, mergeCtx); diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h index 18b99b00a3d84a7117131e52522a41cfe588904d..91e22c548f69522b0dbbf969aa59974df7ff86d8 100644 --- a/source/Lib/EncoderLib/EncCu.h +++ b/source/Lib/EncoderLib/EncCu.h @@ -67,6 +67,7 @@ class EncSlice; // ==================================================================================================================== /// CU encoder class +#if !JVET_Q0806 struct TriangleMotionInfo { uint8_t m_splitDir; @@ -76,6 +77,87 @@ struct TriangleMotionInfo TriangleMotionInfo ( uint8_t splitDir, uint8_t candIdx0, uint8_t candIdx1 ): m_splitDir(splitDir), m_candIdx0(candIdx0), m_candIdx1(candIdx1) { } TriangleMotionInfo() { m_splitDir = m_candIdx0 = m_candIdx1 = 0; } }; +#else +struct GeoMergeCombo +{ + int splitDir; + int mergeIdx0; + int mergeIdx1; + double cost; + GeoMergeCombo() : splitDir(), mergeIdx0(-1), mergeIdx1(-1), cost(0.0) {}; + GeoMergeCombo(int _splitDir, int _mergeIdx0, int _mergeIdx1, double _cost) : splitDir(_splitDir), mergeIdx0(_mergeIdx0), mergeIdx1(_mergeIdx1), cost(_cost) {}; +}; +struct GeoMotionInfo +{ + uint8_t m_candIdx0; + uint8_t m_candIdx1; + + GeoMotionInfo(uint8_t candIdx0, uint8_t candIdx1) : m_candIdx0(candIdx0), m_candIdx1(candIdx1) { } + GeoMotionInfo() { m_candIdx0 = m_candIdx1 = 0; } +}; +struct SmallerThanComboCost +{ + inline bool operator() (const GeoMergeCombo& first, const GeoMergeCombo& second) + { + return (first.cost < second.cost); + } +}; +class GeoComboCostList +{ +public: + GeoComboCostList() {}; + ~GeoComboCostList() {}; + std::vector<GeoMergeCombo> list; + void sortByCost() { std::sort(list.begin(), list.end(), SmallerThanComboCost()); }; +}; +struct SingleGeoMergeEntry +{ + int mergeIdx; + double cost; + SingleGeoMergeEntry() : mergeIdx(0), cost(MAX_DOUBLE) {}; + SingleGeoMergeEntry(int _mergeIdx, double _cost) : mergeIdx(_mergeIdx), cost(_cost) {}; +}; +class FastGeoCostList +{ +public: + FastGeoCostList() { numGeoTemplatesInitialized = 0; }; + ~FastGeoCostList() + { + for (int partIdx = 0; partIdx < 2; partIdx++) + { + for (int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++) + { + delete[] singleDistList[partIdx][splitDir]; + } + delete[] singleDistList[partIdx]; + singleDistList[partIdx] = nullptr; + } + }; + SingleGeoMergeEntry** singleDistList[2]; + void init(int numTemplates, int maxNumGeoCand) + { + if (numGeoTemplatesInitialized == 0 || numGeoTemplatesInitialized < numTemplates) + { + for (int partIdx = 0; partIdx < 2; partIdx++) + { + singleDistList[partIdx] = new SingleGeoMergeEntry*[numTemplates]; + for (int splitDir = 0; splitDir < numTemplates; splitDir++) + { + singleDistList[partIdx][splitDir] = new SingleGeoMergeEntry[maxNumGeoCand]; + } + } + numGeoTemplatesInitialized = numTemplates; + } + } + void insert(int geoIdx, int partIdx, int mergeIdx, double cost) + { + assert(geoIdx < numGeoTemplatesInitialized); + singleDistList[partIdx][geoIdx][mergeIdx] = SingleGeoMergeEntry(mergeIdx, cost); + } + int numGeoTemplatesInitialized; +}; +#endif + class EncCu : DecCu { @@ -121,7 +203,13 @@ private: PelStorage m_acMergeBuffer[MMVD_MRG_MAX_RD_BUF_NUM]; PelStorage m_acRealMergeBuffer[MRG_MAX_NUM_CANDS]; PelStorage m_acMergeTmpBuffer[MRG_MAX_NUM_CANDS]; +#if !JVET_Q0806 PelStorage m_acTriangleWeightedBuffer[TRIANGLE_MAX_NUM_CANDS]; // to store weighted prediction pixles +#else + PelStorage m_acGeoWeightedBuffer[GEO_MAX_TRY_WEIGHTED_SAD]; // to store weighted prediction pixles + FastGeoCostList m_GeoCostList; + double m_AFFBestSATDCost; +#endif double m_mergeBestSATDCost; MotionInfo m_SubPuMiBuf [( MAX_CU_SIZE * MAX_CU_SIZE ) >> ( MIN_CU_LOG2 << 1 )]; @@ -132,8 +220,12 @@ private: #endif int m_bestBcwIdx[2]; double m_bestBcwCost[2]; +#if !JVET_Q0806 TriangleMotionInfo m_triangleModeTest[TRIANGLE_MAX_NUM_CANDS]; uint8_t m_triangleIdxBins[2][TRIANGLE_MAX_NUM_UNI_CANDS][TRIANGLE_MAX_NUM_UNI_CANDS]; +#else + GeoMotionInfo m_GeoModeTest[GEO_MAX_NUM_CANDS]; +#endif #if SHARP_LUMA_DELTA_QP || ENABLE_QPA_SUB_CTU void updateLambda ( Slice* slice, const int dQP, #if WCG_EXT && ER_CHROMA_QP_WCG_PPS @@ -163,6 +255,10 @@ public: void setMergeBestSATDCost(double cost) { m_mergeBestSATDCost = cost; } double getMergeBestSATDCost() { return m_mergeBestSATDCost; } +#if JVET_Q0806 + void setAFFBestSATDCost(double cost) { m_AFFBestSATDCost = cost; } + double getAFFBestSATDCost() { return m_AFFBestSATDCost; } +#endif IbcHashMap& getIbcHashMap() { return m_ibcHashMap; } EncCfg* getEncCfg() const { return m_pcEncCfg; } @@ -202,7 +298,11 @@ protected: void xCheckRDCostMerge2Nx2N ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode ); +#if !JVET_Q0806 void xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode ); +#else + void xCheckRDCostMergeGeo2Nx2N(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode); +#endif void xEncodeInterResidual( CodingStructure *&tempCS , CodingStructure *&bestCS diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 27a672376fb4b57e853c98f1bf8341026835324b..fa644b5c06fd30fe11407c50e9e1a1ade448e27c 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1115,7 +1115,11 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps ) cinfo->setNoIbcConstraintFlag(m_noIbcConstraintFlag); cinfo->setNoCiipConstraintFlag(m_bNoCiipConstraintFlag); cinfo->setNoFPelMmvdConstraintFlag(m_noFPelMmvdConstraintFlag); +#if !JVET_Q0806 cinfo->setNoTriangleConstraintFlag(m_bNoTriangleConstraintFlag); +#else + cinfo->setNoGeoConstraintFlag(m_noGeoConstraintFlag); +#endif cinfo->setNoLadfConstraintFlag(m_bNoLadfConstraintFlag); cinfo->setNoTransformSkipConstraintFlag(m_noTransformSkipConstraintFlag); cinfo->setNoBDPCMConstraintFlag(m_noBDPCMConstraintFlag); @@ -1213,7 +1217,11 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps ) #endif sps.setUseCiip ( m_ciip ); +#if !JVET_Q0806 sps.setUseTriangle ( m_Triangle ); +#else + sps.setUseGeo ( m_Geo ); +#endif sps.setUseMMVD ( m_MMVD ); sps.setFpelMmvdEnabledFlag (( m_MMVD ) ? m_allowDisFracMMVD : false); sps.setBdofControlPresentFlag(m_BIO); @@ -1430,7 +1438,11 @@ void EncLib::xInitPPS(PPS &pps, const SPS &sps) pps.setPPSMvdL1ZeroIdc(getPPSMvdL1ZeroIdc()); pps.setPPSCollocatedFromL0Idc(getPPSCollocatedFromL0Idc()); pps.setPPSSixMinusMaxNumMergeCandPlus1(getPPSSixMinusMaxNumMergeCandPlus1()); +#if !JVET_Q0806 pps.setPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1()); +#else + pps.setPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1(getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1()); +#endif pps.setNumSubPics(sps.getNumSubPics()); pps.setSubPicIdSignallingPresentFlag(false); @@ -1708,7 +1720,11 @@ void EncLib::xInitPicHeader(PicHeader &picHeader, const SPS &sps, const PPS &pps // merge list sizes picHeader.setMaxNumMergeCand ( getMaxNumMergeCand() ); picHeader.setMaxNumAffineMergeCand( getMaxNumAffineMergeCand() ); +#if !JVET_Q0806 picHeader.setMaxNumTriangleCand ( getMaxNumTriangleCand() ); +#else + picHeader.setMaxNumGeoCand ( getMaxNumGeoCand() ); +#endif picHeader.setMaxNumIBCMergeCand ( getMaxNumIBCMergeCand() ); // copy partitioning constraints from SPS diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp index 833986d556bfcc41d0d55384bb98477efd857666..33d3edb25dde4ad88e91cc6c5756b82dda54e9f9 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -1364,10 +1364,17 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru // add inter modes if( m_pcEncCfg->getUseEarlySkipDetection() ) { +#if !JVET_Q0806 if( cs.sps->getUseTriangle() && cs.slice->isInterB() ) { m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_TRIANGLE, ETO_STANDARD, qp } ); } +#else + if( cs.sps->getUseGeo() && cs.slice->isInterB() ) + { + m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_GEO, ETO_STANDARD, qp } ); + } +#endif m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_SKIP, ETO_STANDARD, qp } ); if ( cs.sps->getUseAffine() || cs.sps->getSBTMVPEnabledFlag() ) { @@ -1378,10 +1385,17 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru else { m_ComprCUCtxList.back().testModes.push_back( { ETM_INTER_ME, ETO_STANDARD, qp } ); +#if !JVET_Q0806 if( cs.sps->getUseTriangle() && cs.slice->isInterB() ) { m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_TRIANGLE, ETO_STANDARD, qp } ); } +#else + if( cs.sps->getUseGeo() && cs.slice->isInterB() ) + { + m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_GEO, ETO_STANDARD, qp } ); + } +#endif m_ComprCUCtxList.back().testModes.push_back( { ETM_MERGE_SKIP, ETO_STANDARD, qp } ); if ( cs.sps->getUseAffine() || cs.sps->getSBTMVPEnabledFlag() ) { @@ -1419,7 +1433,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt ComprCUCtx& cuECtx = m_ComprCUCtxList.back(); // Fast checks, partitioning depended +#if !JVET_Q0806 if (cuECtx.isHashPerfectMatch && encTestmode.type != ETM_MERGE_SKIP && encTestmode.type != ETM_INTER_ME && encTestmode.type != ETM_AFFINE && encTestmode.type != ETM_MERGE_TRIANGLE) +#else + if (cuECtx.isHashPerfectMatch && encTestmode.type != ETM_MERGE_SKIP && encTestmode.type != ETM_INTER_ME && encTestmode.type != ETM_AFFINE && encTestmode.type != ETM_MERGE_GEO) +#endif { return false; } @@ -1640,10 +1658,20 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt { return false; } +#if !JVET_Q0806 if( encTestmode.type == ETM_MERGE_TRIANGLE && ( partitioner.currArea().lumaSize().area() < TRIANGLE_MIN_SIZE || relatedCU.isIntra ) ) { return false; } +#else + if( encTestmode.type == ETM_MERGE_GEO && ( partitioner.currArea().lwidth() < GEO_MIN_CU_SIZE || partitioner.currArea().lheight() < GEO_MIN_CU_SIZE + || partitioner.currArea().lwidth() > GEO_MAX_CU_SIZE || partitioner.currArea().lheight() > GEO_MAX_CU_SIZE + || partitioner.currArea().lwidth() >= 8 * partitioner.currArea().lheight() + || partitioner.currArea().lheight() >= 8 * partitioner.currArea().lwidth() ) ) + { + return false; + } +#endif return true; } else if( isModeSplit( encTestmode ) ) diff --git a/source/Lib/EncoderLib/EncModeCtrl.h b/source/Lib/EncoderLib/EncModeCtrl.h index 3ab1b298bafc255d2754a5eb69f176fec5b7918a..f2b75071dabfb5cdf9ebb21cc73bd6ba0ae26506 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.h +++ b/source/Lib/EncoderLib/EncModeCtrl.h @@ -59,7 +59,11 @@ enum EncTestModeType ETM_MERGE_SKIP, ETM_INTER_ME, ETM_AFFINE, +#if !JVET_Q0806 ETM_MERGE_TRIANGLE, +#else + ETM_MERGE_GEO, +#endif ETM_INTRA, ETM_PALETTE, ETM_SPLIT_QT, @@ -138,7 +142,11 @@ inline bool isModeInter( const EncTestMode& encTestmode ) // perhaps remove return ( encTestmode.type == ETM_INTER_ME || encTestmode.type == ETM_MERGE_SKIP || encTestmode.type == ETM_AFFINE +#if !JVET_Q0806 || encTestmode.type == ETM_MERGE_TRIANGLE +#else + || encTestmode.type == ETM_MERGE_GEO +#endif || encTestmode.type == ETM_HASH_INTER ); } diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index 5ee8d0ee19ec6d5b677ef1ebf56d425d22c76f58..01aefd05cfdfc5b0cafe6142340bf9e5604b67db 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -1567,13 +1567,83 @@ void IntraSearch::PLTSearch(CodingStructure &cs, Partitioner& partitioner, Compo derivePLTLossy(cs, partitioner, compBegin, numComp); reorderPLT(cs, partitioner, compBegin, numComp); +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + bool idxExist[MAXPLTSIZE + 1] = { false }; +#endif preCalcPLTIndexRD(cs, partitioner, compBegin, numComp); // Pre-calculate distortions for each pixel double rdCost = MAX_DOUBLE; +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + deriveIndexMap(cs, partitioner, compBegin, numComp, PLT_SCAN_HORTRAV, rdCost, idxExist); // Optimize palette index map (horizontal scan) +#else deriveIndexMap(cs, partitioner, compBegin, numComp, PLT_SCAN_HORTRAV, rdCost); // Optimize palette index map (horizontal scan) +#endif if ((cu.curPLTSize[compBegin] + cu.useEscape[compBegin]) > 1) { +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + deriveIndexMap(cs, partitioner, compBegin, numComp, PLT_SCAN_VERTRAV, rdCost, idxExist); // Optimize palette index map (vertical scan) +#else deriveIndexMap(cs, partitioner, compBegin, numComp, PLT_SCAN_VERTRAV, rdCost); // Optimize palette index map (vertical scan) +#endif + } +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + // Remove unused palette entries + uint8_t newPLTSize = 0; + int idxMapping[MAXPLTSIZE + 1]; + memset(idxMapping, -1, sizeof(int) * (MAXPLTSIZE + 1)); + for (int i = 0; i < cu.curPLTSize[compBegin]; i++) + { + if (idxExist[i]) + { + idxMapping[i] = newPLTSize; + newPLTSize++; + } + } + idxMapping[cu.curPLTSize[compBegin]] = cu.useEscape[compBegin]? newPLTSize: -1; + if (newPLTSize != cu.curPLTSize[compBegin]) // there exist unused palette entries + { // update palette table and reuseflag + Pel curPLTtmp[MAX_NUM_COMPONENT][MAXPLTSIZE]; + int reuseFlagIdx = 0, curPLTtmpIdx = 0, reuseEntrySize = 0; + memset(cu.reuseflag[compBegin], false, sizeof(bool) * MAXPLTPREDSIZE); + for (int curIdx = 0; curIdx < cu.curPLTSize[compBegin]; curIdx++) + { + if (idxExist[curIdx]) + { + for (int comp = compBegin; comp < (compBegin + numComp); comp++) + curPLTtmp[comp][curPLTtmpIdx] = cu.curPLT[comp][curIdx]; + + // Update reuse flags + if (curIdx < cu.reusePLTSize[compBegin]) + { + bool match = false; + for (; reuseFlagIdx < cs.prevPLT.curPLTSize[compBegin]; reuseFlagIdx++) + { + bool matchTmp = true; + for (int comp = compBegin; comp < (compBegin + numComp); comp++) + { + matchTmp = matchTmp && (curPLTtmp[comp][curPLTtmpIdx] == cs.prevPLT.curPLT[comp][reuseFlagIdx]); + } + if (matchTmp) + { + match = true; + break; + } + } + if (match) + { + cu.reuseflag[compBegin][reuseFlagIdx] = true; + reuseEntrySize++; + } + } + curPLTtmpIdx++; + } + } + cu.reusePLTSize[compBegin] = reuseEntrySize; + // update palette table + cu.curPLTSize[compBegin] = newPLTSize; + for (int comp = compBegin; comp < (compBegin + numComp); comp++) + memcpy( cu.curPLT[comp], curPLTtmp[comp], sizeof(Pel)*cu.curPLTSize[compBegin]); } +#endif cu.useRotation[compBegin] = m_bestScanRotationMode; int indexMaxSize = cu.useEscape[compBegin] ? (cu.curPLTSize[compBegin] + 1) : cu.curPLTSize[compBegin]; if (indexMaxSize <= 1) @@ -1586,6 +1656,9 @@ void IntraSearch::PLTSearch(CodingStructure &cs, Partitioner& partitioner, Compo { for (uint32_t x = 0; x < width; x++) { +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + curPLTIdx.at(x, y) = idxMapping[curPLTIdx.at(x, y)]; +#endif if (curPLTIdx.at(x, y) == cu.curPLTSize[compBegin]) { calcPixelPred(cs, partitioner, y, x, compBegin, numComp); @@ -1782,7 +1855,11 @@ void IntraSearch::preCalcPLTIndexRD(CodingStructure& cs, Partitioner& partitione } } +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX +void IntraSearch::deriveIndexMap(CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp, PLTScanMode pltScanMode, double& dMinCost, bool* idxExist) +#else void IntraSearch::deriveIndexMap(CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp, PLTScanMode pltScanMode, double& dMinCost) +#endif { CodingUnit &cu = *cs.getCU(partitioner.chType); TransformUnit &tu = *cs.getTU(partitioner.chType); @@ -1905,10 +1982,16 @@ void IntraSearch::deriveIndexMap(CodingStructure& cs, Partitioner& partitioner, { cu.useEscape[compBegin] = m_bestEscape; m_bestScanRotationMode = pltScanMode; +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + memset(idxExist, false, sizeof(bool) * (MAXPLTSIZE + 1)); +#endif for (int pos = 0; pos < (width*height); pos++) { runIndex[pos] = checkIndexTable[pos]; runType[pos] = checkRunTable[pos]; +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + idxExist[checkIndexTable[pos]] = true; +#endif } dMinCost = sumRdCost; } @@ -2072,16 +2155,32 @@ double IntraSearch::rateDistOptPLT( rdCost = MAX_DOUBLE; return rdCost; } +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + rdCost += m_pcRdCost->getLambda()*(m_truncBinBits[(runIndex > refIndex) ? runIndex - 1 : runIndex][(scanPos == 0) ? (indexMaxValue + 1) : indexMaxValue] << SCALE_BITS); +#else rdCost += m_pcRdCost->getLambda()*m_truncBinBits[(runIndex > refIndex) ? runIndex - 1 : runIndex][(scanPos == 0) ? (indexMaxValue + 1) : indexMaxValue]; +#endif } +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + rdCost += m_indexError[runIndex][m_scanOrder[scanPos].idx] * (1 << SCALE_BITS); +#else rdCost += m_indexError[runIndex][m_scanOrder[scanPos].idx]; +#endif if (scanPos > 0) { +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + rdCost += m_pcRdCost->getLambda()*( identityFlag ? (IndexfracBits[(dist < RUN_IDX_THRE) ? dist : RUN_IDX_THRE].intBits[1]) : (IndexfracBits[(dist < RUN_IDX_THRE) ? dist : RUN_IDX_THRE].intBits[0] ) ); +#else rdCost += m_pcRdCost->getLambda()*( identityFlag ? (IndexfracBits[(dist < RUN_IDX_THRE) ? dist : RUN_IDX_THRE].intBits[1] >> SCALE_BITS) : (IndexfracBits[(dist < RUN_IDX_THRE) ? dist : RUN_IDX_THRE].intBits[0] >> SCALE_BITS)); +#endif } if ( !identityFlag && scanPos >= width && prevRunType != PLT_RUN_COPY ) { +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + rdCost += m_pcRdCost->getLambda()*TypefracBits.intBits[runType]; +#else rdCost += m_pcRdCost->getLambda()*(TypefracBits.intBits[runType] >> SCALE_BITS); +#endif } if (!identityFlag || scanPos == 0) { @@ -2251,7 +2350,15 @@ void IntraSearch::derivePLTLossy(CodingStructure& cs, Partitioner& partitioner, } } +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + TransformUnit &tu = *cs.getTU(partitioner.chType); + QpParam cQP(tu, compBegin); + int qp = cQP.Qp(true) - 12; + qp = (qp < 0) ? 0 : ((qp > 56) ? 56 : qp); + int errorLimit = g_paletteQuant[qp]; +#else int errorLimit = g_paletteQuant[cu.qp]; +#endif uint32_t totalSize = height*width; SortingElement *pelList = new SortingElement[totalSize]; SortingElement element; @@ -2340,6 +2447,11 @@ void IntraSearch::derivePLTLossy(CodingStructure& cs, Partitioner& partitioner, } const int plt_lambda_shift = (compBegin > 0) ? pcmShiftRight_C : pcmShiftRight_L; double bitCost = m_pcRdCost->getLambda() / (double) (1 << (2 * plt_lambda_shift)) * numColorBits; +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + bool reuseflag[MAXPLTPREDSIZE] = { false }; + int run; + double reuseflagCost; +#endif for (int i = 0; i < MAXPLTSIZE; i++) { if (pelListSort[i].getCnt()) @@ -2385,6 +2497,22 @@ void IntraSearch::derivePLTLossy(CodingStructure& cs, Partitioner& partitioner, } } cost *= pelListSort[i].getCnt(); +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + run = 0; + for (int t2 = t-1; t2 >= 0; t2--) + { + if (!reuseflag[t2]) + { + run++; + } + else + { + break; + } + } + reuseflagCost = m_pcRdCost->getLambda() / (double)(1 << (2 * plt_lambda_shift)) * getEpExGolombNumBins(run ? run + 1 : run, 0); + cost += reuseflagCost; +#endif if (cost < bestCost) { best = t; @@ -2397,6 +2525,9 @@ void IntraSearch::derivePLTLossy(CodingStructure& cs, Partitioner& partitioner, { cu.curPLT[comp][paletteSize] = cs.prevPLT.curPLT[comp][best]; } +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + reuseflag[best] = true; +#endif } } diff --git a/source/Lib/EncoderLib/IntraSearch.h b/source/Lib/EncoderLib/IntraSearch.h index 72ccaa02148956bceded9d45694cbe2c7c58baf5..9370c143072ad7548d439be5a43bf1270c020143 100644 --- a/source/Lib/EncoderLib/IntraSearch.h +++ b/source/Lib/EncoderLib/IntraSearch.h @@ -453,7 +453,11 @@ protected: void calcPixelPred ( CodingStructure& cs, Partitioner& partitioner, uint32_t yPos, uint32_t xPos, ComponentID compBegin, uint32_t numComp); void preCalcPLTIndexRD (CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp); void calcPixelPredRD (CodingStructure& cs, Partitioner& partitioner, Pel* orgBuf, Pel* pixelValue, Pel* recoValue, ComponentID compBegin, uint32_t numComp); +#if JVET_Q0503_Q0712_PLT_ENCODER_IMPROV_BUGFIX + void deriveIndexMap (CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp, PLTScanMode pltScanMode, double& dCost, bool* idxExist); +#else void deriveIndexMap (CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp, PLTScanMode pltScanMode, double& dCost); +#endif bool deriveSubblockIndexMap(CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, PLTScanMode pltScanMode, int minSubPos, int maxSubPos, const BinFracBits& fracBitsPltRunType, const BinFracBits* fracBitsPltIndexINDEX, const BinFracBits* fracBitsPltIndexCOPY, const double minCost, bool useRotate); double rateDistOptPLT (bool RunType, uint8_t RunIndex, bool prevRunType, uint8_t prevRunIndex, uint8_t aboveRunIndex, bool& prevCodedRunType, int& prevCodedRunPos, int scanPos, uint32_t width, int dist, int indexMaxValue, const BinFracBits* IndexfracBits, const BinFracBits& TypefracBits); void initTBCTable (int bitDepth); diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index caa3171e35b1bf5f7db95885cbd54538550d0433..19dd9cf2564fe91d3436b5a9d540459361abb036 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -427,7 +427,11 @@ void HLSWriter::codePPS( const PPS* pcPPS, const SPS* pcSPS ) WRITE_CODE( pcPPS->getPPSMvdL1ZeroIdc(), 2, "pps_mvd_l1_zero_idc"); WRITE_CODE( pcPPS->getPPSCollocatedFromL0Idc(), 2, "pps_collocated_from_l0_idc"); WRITE_UVLC( pcPPS->getPPSSixMinusMaxNumMergeCandPlus1(), "pps_six_minus_max_num_merge_cand_plus1"); +#if !JVET_Q0806 WRITE_UVLC( pcPPS->getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1(), "pps_max_num_merge_cand_minus_max_num_triangle_cand_plus1"); +#else + WRITE_UVLC(pcPPS->getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1(), "pps_max_num_merge_cand_minus_max_num_gpm_cand_plus1"); +#endif } @@ -778,10 +782,29 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_CODE(pcSPS->getNumSubPics() - 1, 8, "sps_num_subpics_minus1"); for (int picIdx = 0; picIdx < pcSPS->getNumSubPics(); picIdx++) { +#if JVET_Q0787_SUBPIC + if (pcSPS->getMaxPicWidthInLumaSamples() > pcSPS->getCTUSize()) + { + WRITE_CODE( pcSPS->getSubPicCtuTopLeftX(picIdx), ceilLog2(( pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize()), "subpic_ctu_top_left_x[ i ]" ); + } + if (pcSPS->getMaxPicHeightInLumaSamples() > pcSPS->getCTUSize()) + { + WRITE_CODE( pcSPS->getSubPicCtuTopLeftY(picIdx), ceilLog2(( pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize()), "subpic_ctu_top_left_y[ i ]" ); + } + if (pcSPS->getMaxPicWidthInLumaSamples() > pcSPS->getCTUSize()) + { + WRITE_CODE( pcSPS->getSubPicWidth(picIdx) - 1, ceilLog2(( pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize()), "subpic_width_minus1[ i ]" ); + } + if (pcSPS->getMaxPicHeightInLumaSamples() > pcSPS->getCTUSize()) + { + WRITE_CODE( pcSPS->getSubPicHeight(picIdx) - 1, ceilLog2(( pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1) / pcSPS->getCTUSize()), "subpic_height_minus1[ i ]" ); + } +#else WRITE_CODE( pcSPS->getSubPicCtuTopLeftX(picIdx), std::max(1, ceilLog2((( pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1) >> floorLog2( pcSPS->getCTUSize())))), "subpic_ctu_top_left_x[ i ]" ); WRITE_CODE( pcSPS->getSubPicCtuTopLeftY(picIdx), std::max(1, ceilLog2((( pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1) >> floorLog2( pcSPS->getCTUSize())))), "subpic_ctu_top_left_y[ i ]" ); WRITE_CODE( pcSPS->getSubPicWidth(picIdx) - 1, std::max(1, ceilLog2((( pcSPS->getMaxPicWidthInLumaSamples() + pcSPS->getCTUSize() - 1) >> floorLog2( pcSPS->getCTUSize())))), "subpic_width_minus1[ i ]" ); WRITE_CODE( pcSPS->getSubPicHeight(picIdx) - 1, std::max(1, ceilLog2((( pcSPS->getMaxPicHeightInLumaSamples() + pcSPS->getCTUSize() - 1) >> floorLog2( pcSPS->getCTUSize())))), "subpic_height_minus1[ i ]" ); +#endif WRITE_FLAG( pcSPS->getSubPicTreatedAsPicFlag(picIdx), "subpic_treated_as_pic_flag[ i ]" ); WRITE_FLAG( pcSPS->getLoopFilterAcrossSubpicEnabledFlag(picIdx), "loop_filter_across_subpic_enabled_flag[ i ]" ); } @@ -1030,7 +1053,12 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) { WRITE_FLAG( pcSPS->getFpelMmvdEnabledFlag() ? 1 : 0, "sps_fpel_mmvd_enabled_flag" ); } + +#if !JVET_Q0806 WRITE_FLAG( pcSPS->getUseTriangle() ? 1: 0, "sps_triangle_enabled_flag" ); +#else + WRITE_FLAG( pcSPS->getUseGeo() ? 1: 0, "sps_gpm_enabled_flag" ); +#endif WRITE_FLAG(pcSPS->getUseLmcs() ? 1 : 0, "sps_lmcs_enable_flag"); WRITE_FLAG( pcSPS->getUseLFNST() ? 1 : 0, "sps_lfnst_enabled_flag" ); @@ -1655,6 +1683,7 @@ void HLSWriter::codePictureHeader( PicHeader* picHeader ) picHeader->setDisProfFlag(0); } +#if !JVET_Q0806 // triangle merge candidate list size if (sps->getUseTriangle() && picHeader->getMaxNumMergeCand() >= 2) { @@ -1668,6 +1697,21 @@ void HLSWriter::codePictureHeader( PicHeader* picHeader ) picHeader->setMaxNumTriangleCand((uint32_t)(picHeader->getMaxNumMergeCand() - (pps->getPPSMaxNumMergeCandMinusMaxNumTriangleCandPlus1() - 1))); } } +#else + // geometric merge candidate list size + if (sps->getUseGeo() && picHeader->getMaxNumMergeCand() >= 2) + { + if (!pps->getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1()) + { + CHECK(picHeader->getMaxNumMergeCand() < picHeader->getMaxNumGeoCand(), "Incorrrect max number of gpm candidates!"); + WRITE_UVLC(picHeader->getMaxNumMergeCand() - picHeader->getMaxNumGeoCand(), "pic_max_num_merge_cand_minus_max_num_gpm_cand"); + } + else + { + picHeader->setMaxNumGeoCand((uint32_t)(picHeader->getMaxNumMergeCand() - (pps->getPPSMaxNumMergeCandMinusMaxNumGeoCandPlus1() - 1))); + } + } +#endif // ibc merge candidate list size if (sps->getIBCFlag()) @@ -2310,7 +2354,11 @@ void HLSWriter::codeConstraintInfo ( const ConstraintInfo* cinfo ) WRITE_FLAG(cinfo->getNoIbcConstraintFlag() ? 1 : 0, "no_ibc_constraint_flag"); WRITE_FLAG(cinfo->getNoCiipConstraintFlag() ? 1 : 0, "no_ciip_constraint_flag"); WRITE_FLAG(cinfo->getNoFPelMmvdConstraintFlag() ? 1 : 0, "no_fpel_mmvd_constraint_flag"); +#if !JVET_Q0806 WRITE_FLAG(cinfo->getNoTriangleConstraintFlag() ? 1 : 0, "no_triangle_constraint_flag"); +#else + WRITE_FLAG(cinfo->getNoGeoConstraintFlag() ? 1 : 0, "no_gpm_constraint_flag"); +#endif WRITE_FLAG(cinfo->getNoLadfConstraintFlag() ? 1 : 0, "no_ladf_constraint_flag"); WRITE_FLAG(cinfo->getNoTransformSkipConstraintFlag() ? 1 : 0, "no_transform_skip_constraint_flag"); WRITE_FLAG(cinfo->getNoBDPCMConstraintFlag() ? 1 : 0, "no_bdpcm_constraint_flag");