diff --git a/cfg/encoder_intra_vtm.cfg b/cfg/encoder_intra_vtm.cfg index ddc4dedad848dad11a83c285a8722612bbfe97b5..1a07b246f7967cb7eb0e1e5a166df3a098aeef4e 100644 --- a/cfg/encoder_intra_vtm.cfg +++ b/cfg/encoder_intra_vtm.cfg @@ -114,7 +114,7 @@ LMCSEnable : 1 # LMCS: 0: disable, 1:enable LMCSSignalType : 0 # Input signal type: 0:SDR, 1:HDR-PQ, 2:HDR-HLG LMCSUpdateCtrl : 1 # LMCS model update control: 0:RA, 1:AI, 2:LDB/LDP MIP : 1 - +JointCbCr : 1 # JointCbCr: 0: disable, 1: enable # Fast tools PBIntraFast : 1 ISPFast : 1 diff --git a/cfg/encoder_lowdelay_P_vtm.cfg b/cfg/encoder_lowdelay_P_vtm.cfg index 2d24145ce7acb6aabf6cc9e5b58d88f1aa0d3db0..73175d5e95b3ef77f04e663bc208470f3a4a0bb8 100644 --- a/cfg/encoder_lowdelay_P_vtm.cfg +++ b/cfg/encoder_lowdelay_P_vtm.cfg @@ -130,10 +130,12 @@ LMCSEnable : 1 # LMCS: 0: disable, 1:enable LMCSSignalType : 0 # Input signal type: 0:SDR, 1:HDR-PQ, 2:HDR-HLG LMCSUpdateCtrl : 2 # LMCS model update control: 0:RA, 1:AI, 2:LDB/LDP MIP : 1 +JointCbCr : 1 # JointCbCr: 0: disable, 1: enable +PROF : 1 # Fast tools PBIntraFast : 1 -ISPFast : 1 +ISPFast : 0 FastMrg : 1 AMaxBT : 1 FastMIP : 0 diff --git a/cfg/encoder_lowdelay_vtm.cfg b/cfg/encoder_lowdelay_vtm.cfg index 148f03230bde4390f01110b46104acdc695b9252..08ac2388cab1055a6acb53934bee9dfa7112a77a 100644 --- a/cfg/encoder_lowdelay_vtm.cfg +++ b/cfg/encoder_lowdelay_vtm.cfg @@ -134,11 +134,12 @@ LMCSEnable : 1 # LMCS: 0: disable, 1:enable LMCSSignalType : 0 # Input signal type: 0:SDR, 1:HDR-PQ, 2:HDR-HLG LMCSUpdateCtrl : 2 # LMCS model update control: 0:RA, 1:AI, 2:LDB/LDP MIP : 1 +JointCbCr : 1 # JointCbCr: 0: disable, 1: enable PROF : 1 # Fast tools PBIntraFast : 1 -ISPFast : 1 +ISPFast : 0 FastMrg : 1 AMaxBT : 1 FastMIP : 0 diff --git a/cfg/encoder_randomaccess_vtm.cfg b/cfg/encoder_randomaccess_vtm.cfg index 2e4c7a0332fbd01f2bda17df62aded26c0a047bd..15dd5ee617dcb6b145f48e030dac7b0c2c5367ab 100644 --- a/cfg/encoder_randomaccess_vtm.cfg +++ b/cfg/encoder_randomaccess_vtm.cfg @@ -152,11 +152,12 @@ LMCSUpdateCtrl : 0 # LMCS model update control: 0:RA, 1:AI, 2 MIP : 1 DMVR : 1 SMVD : 1 +JointCbCr : 1 # JointCbCr: 0: disable, 1: enable PROF : 1 # Fast tools PBIntraFast : 1 -ISPFast : 1 +ISPFast : 0 FastMrg : 1 AMaxBT : 1 FastMIP : 0 diff --git a/doc/software-manual.tex b/doc/software-manual.tex index a2aeb0b0287e680f9c1ae3b0243f420e709c9b20..0e0a2124c6a844c27dbd152817e01c3f133268e8 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -1165,6 +1165,12 @@ Specifies the maximum number of merge candidates to use. Specifies the maximum number of triangle merge candidates to use. \\ +\Option{MaxNumIBCMergeCand} & +%\ShortOption{\None} & +\Default{6} & +Specifies the maximum number of IBC merge candidates to use. +\\ + \Option{DisableIntraInInter} & %\ShortOption{\None} & \Default{0} & @@ -1334,6 +1340,57 @@ $\lambda = \lambda_{base} \times max(2, min(4, (sliceQP-12)/6))$ In addition, independent on the IntraQPFactor, if HadamardME=false, then for an inter slice the final $\lambda$ is scaled by a factor of $0.95$. \\ +\Option{UseIdentityTableForNon420Chroma} +\Default{1} +Specifies whether identity chroma QP mapping tables are used for 4:2:2 and 4:4:4 content. When set to 1, the identity chroma QP mapping table is used for all the three chroma components for 4:2:2 or 4:4:4 content. When set to 0, chroma QP +mapping table may be specified by other parameters in the configuration. +\\ + +\Option{SameCQPTablesForAllChroma} +\Default{1) +Specifies that the Cb, Cr and joint Cb-Cr components all use the same +chroma mapping table. When set to 1, the values of QpInValCr, +QpOutValCr, QpInValCbCr and QpOutValCbCr are ignored. When set to 0, all +Cb, Cr and joint Cb-Cr components may have different chroma QP mapping tables specified in the configuration file. \\ Note that +SameCQPTablesForAllChroma is ignored when UseIdentityTableForNon420Chroma is set to 1 for 4:2:2 and 4:4:4 content. +\\ + +\Option{QpInValCb}% +\Option{QpOutValCb}& +\Default{\NotSet} +Specifies the input and coordinates of the pivot points used to specify the chroma QP mapping tables for the Cb component. Default values are as follows: +\begin{tabular}{cp{0.45\textwidth}} + QpInValCb: 25, 33, 43 \\ + QpOutValCb: 25, 32, 37 \\ +\end{tabular} +The values specify the pivot points for the chroma QP mapping table, the unspecified QP values are interpolated from the remaining values. E.g., the default values above specify that the pivot points for the chroma QP mapping table for the Cb component are (25, 25), (33, 32), (43, 37). +\\ Note that that QpInValCr and QpOutValCr are ignored when UseIdentityTableForNon420Chroma is set to 1 for 4:2:2 and 4:4:4 content. +\\ + +\Option{QpInValCr}% +\Option{QpOutValCr}& +\Default{\NotSet} +Specifies the input and coordinates of the pivot points used to specify the chroma QP mapping tables for the Cr component. Default values are as follows: +\begin{tabular}{cp{0.45\textwidth}} + QpInValCr: 0 \\ + QpOutValCr: 0 \\ +\end{tabular} +The default values specify a pivot point of (0,0) which corresponds to an identity chroma QP mapping table. \\ Note that that QpInValCr and QpOutValCr are ignored +when SameCQPTablesForAllChroma is set to 1 or when UseIdentityTableForNon420Chroma is set to 1 for 4:2:2 and 4:4:4 content. +\\ + +\Option{QpInValCbCr}% +\Option{QpOutValCbCr}& +\Default{\NotSet} +Specifies the input and coordinates of the pivot points used to specify the chroma QP mapping tables for the joint Cb-Cr component. Default values are as follows: +\begin{tabular}{cp{0.45\textwidth}} + QpInValrCr: 0 \\ + QpOutValCbCr: 0 \\ +\end{tabular} +The default values specify a pivot point of (0,0) which corresponds to a identity chroma QP mapping table. Note that that QpInValCbCr and QpOutVaCblCr are ignored +when SameCQPTablesForAllChroma is set to 1 or when UseIdentityTableForNon420Chroma is set to 1 for 4:2:2 and 4:4:4 content. +\\ + \Option{CbQpOffset (-cbqpofs)}% \Option{CrQpOffset (-crqpofs)} & %\ShortOption{-cbqpofs}% @@ -1822,6 +1879,12 @@ Enables or disables reduced testing of non-DCT-II transforms if ISP is likely to This option has no effect if either ISP or MTS are disabled. \\ +\Option{JointCbCr} & +%\ShortOption{\None} & +\Default{false} & +Enables or disables the joint coding of chroma residuals. +\\ + \Option{SAO} & %\ShortOption{\None} & \Default{true} & diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 26d403b891480fee09c59380706099ba48bac49f..9e6bfb2080662d270dc587e2c5dbc4a870578761 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -136,6 +136,9 @@ void EncApp::xInitLibCfg() #if JVET_O1136_TS_BDPCM_SIGNALLING m_cEncLib.setNoBDPCMConstraintFlag ( !m_useBDPCM ); #endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + m_cEncLib.setNoJointCbCrConstraintFlag (!m_JointCbCrMode); +#endif m_cEncLib.setNoQpDeltaConstraintFlag ( m_bNoQpDeltaConstraintFlag ); m_cEncLib.setNoDepQuantConstraintFlag ( !m_depQuantEnabledFlag); m_cEncLib.setNoSignDataHidingConstraintFlag ( !m_signDataHidingEnabledFlag ); @@ -167,6 +170,10 @@ void EncApp::xInitLibCfg() #if X0038_LAMBDA_FROM_QP_CAPABILITY m_cEncLib.setIntraQPOffset ( m_intraQPOffset ); m_cEncLib.setLambdaFromQPEnable ( m_lambdaFromQPEnable ); +#endif +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + m_cEncLib.setChromaQpMappingTableParams (m_chromaQpMappingTableParams); + #endif m_cEncLib.setPad ( m_aiPad ); @@ -292,9 +299,12 @@ void EncApp::xInitLibCfg() m_cEncLib.setDMVR ( m_DMVR ); m_cEncLib.setMMVD ( m_MMVD ); m_cEncLib.setMmvdDisNum (m_MmvdDisNum); - m_cEncLib.setRDPCM ( m_RdpcmMode ); + m_cEncLib.setRDPCM ( m_RdpcmMode ); #if JVET_O0119_BASE_PALETTE_444 m_cEncLib.setPLTMode ( m_PLTMode); +#endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + m_cEncLib.setJointCbCr ( m_JointCbCrMode ); #endif m_cEncLib.setIBCMode ( m_IBCMode ); m_cEncLib.setIBCLocalSearchRangeX ( m_IBCLocalSearchRangeX ); @@ -386,6 +396,9 @@ void EncApp::xInitLibCfg() m_cEncLib.setMaxNumMergeCand ( m_maxNumMergeCand ); m_cEncLib.setMaxNumAffineMergeCand ( m_maxNumAffineMergeCand ); m_cEncLib.setMaxNumTriangleCand ( m_maxNumTriangleCand ); +#if JVET_O0455_IBC_MAX_MERGE_NUM + m_cEncLib.setMaxNumIBCMergeCand ( m_maxNumIBCMergeCand ); +#endif //====== Weighted Prediction ======== m_cEncLib.setUseWP ( m_useWeightedPred ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 9d3212a1f6712b6c5c55674e30c24cbe1f6bec1a..9e71362bef7e3483b05c6507a5ab6c43ff7c779c 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -137,6 +137,9 @@ EncAppCfg::EncAppCfg() #if JVET_O1136_TS_BDPCM_SIGNALLING , m_noBDPCMConstraintFlag(false) #endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG +, m_noJointCbCrConstraintFlag(false) +#endif , m_bNoQpDeltaConstraintFlag(false) , m_bNoDepQuantConstraintFlag(false) , m_bNoSignDataHidingConstraintFlag(false) @@ -714,7 +717,17 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) SMultiValueInput<int> cfg_lumaLeveltoDQPMappingLuma (0, std::numeric_limits<int>::max(), 0, LUMA_LEVEL_TO_DQP_LUT_MAXSIZE, defaultLumaLevelTodQp_LumaChangePoints, sizeof(defaultLumaLevelTodQp_LumaChangePoints)/sizeof(int)); uint32_t lumaLevelToDeltaQPMode; #endif - +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + const int qpInVals[] = { 25, 33, 43 }; // qpInVal values used to derive the chroma QP mapping table used in VTM-5.0 + const int qpOutVals[] = { 25, 32, 37 }; // qpOutVal values used to derive the chroma QP mapping table used in VTM-5.0 + SMultiValueInput<int> cfg_qpInValCb (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, qpInVals, sizeof(qpInVals)/sizeof(int)); + SMultiValueInput<int> cfg_qpOutValCb (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, qpOutVals, sizeof(qpOutVals) / sizeof(int)); + const int zeroVector[] = { 0 }; + SMultiValueInput<int> cfg_qpInValCr (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, zeroVector, 1); + SMultiValueInput<int> cfg_qpOutValCr (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, zeroVector, 1); + SMultiValueInput<int> cfg_qpInValCbCr (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, zeroVector, 1); + SMultiValueInput<int> cfg_qpOutValCbCr (MIN_QP_VALUE_FOR_16_BIT, MAX_QP, 0, MAX_NUM_QP_VALUES, zeroVector, 1); +#endif const uint32_t defaultInputKneeCodes[3] = { 600, 800, 900 }; const uint32_t defaultOutputKneeCodes[3] = { 100, 250, 450 }; SMultiValueInput<uint32_t> cfg_kneeSEIInputKneePointValue (1, 999, 0, 999, defaultInputKneeCodes, sizeof(defaultInputKneeCodes )/sizeof(uint32_t)); @@ -906,6 +919,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ( "RDPCM", m_RdpcmMode, false, "RDPCM") #if JVET_O0119_BASE_PALETTE_444 ("PLT", m_PLTMode, 0u, "PLTMode (0x1:enabled, 0x0:disabled) [default: disabled]") +#endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + ("JointCbCr", m_JointCbCrMode, false, "Enable joint coding of chroma residuals (JointCbCr, 0:off, 1:on)") #endif ( "IBC", m_IBCMode, 0u, "IBCMode (0x1:enabled, 0x0:disabled) [default: disabled]") ( "IBCLocalSearchRangeX", m_IBCLocalSearchRangeX, 128u, "Search range of IBC local search in x direction") @@ -1021,7 +1037,16 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("LumaLevelToDeltaQPMappingLuma", cfg_lumaLeveltoDQPMappingLuma, cfg_lumaLeveltoDQPMappingLuma, "Luma to Delta QP Mapping - luma thresholds") ("LumaLevelToDeltaQPMappingDQP", cfg_lumaLeveltoDQPMappingQP, cfg_lumaLeveltoDQPMappingQP, "Luma to Delta QP Mapping - DQP values") #endif - +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + ("UseIdentityTableForNon420Chroma", m_useIdentityTableForNon420Chroma, true, "True: Indicates that 422/444 chroma uses identity chroma QP mapping tables; False: explicit Qp table may be specified in config") + ("SameCQPTablesForAllChroma", m_chromaQpMappingTableParams.m_sameCQPTableForAllChromaFlag, true, "0: Different tables for Cb, Cr and joint Cb-Cr components, 1 (default): Same tables for all three chroma components") + ("QpInValCb", cfg_qpInValCb, cfg_qpInValCb, "Input coordinates for the QP table for Cb component") + ("QpOutValCb", cfg_qpOutValCb, cfg_qpOutValCb, "Output coordinates for the QP table for Cb component") + ("QpInValCr", cfg_qpInValCr, cfg_qpInValCr, "Input coordinates for the QP table for Cr component") + ("QpOutValCr", cfg_qpOutValCr, cfg_qpOutValCr, "Output coordinates for the QP table for Cr component") + ("QpInValCbCr", cfg_qpInValCbCr, cfg_qpInValCbCr, "Input coordinates for the QP table for joint Cb-Cr component") + ("QpOutValCbCr", cfg_qpOutValCbCr, cfg_qpOutValCbCr, "Output coordinates for the QP table for joint Cb-Cr component") +#endif ("CbQpOffset,-cbqpofs", m_cbQpOffset, 0, "Chroma Cb QP Offset") ("CrQpOffset,-crqpofs", m_crQpOffset, 0, "Chroma Cr QP Offset") ("CbQpOffsetDualTree", m_cbQpOffsetDualTree, 0, "Chroma Cb QP Offset for dual tree") @@ -1139,7 +1164,10 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("MaxNumMergeCand", m_maxNumMergeCand, 5u, "Maximum number of merge candidates") ("MaxNumAffineMergeCand", m_maxNumAffineMergeCand, 5u, "Maximum number of affine merge candidates") ("MaxNumTriangleCand", m_maxNumTriangleCand, 5u, "Maximum number of triangle candidates") - /* Misc. */ +#if JVET_O0455_IBC_MAX_MERGE_NUM + ("MaxNumIBCMergeCand", m_maxNumIBCMergeCand, 6u, "Maximum number of IBC merge candidates") +#endif + /* Misc. */ ("SEIDecodedPictureHash,-dph", tmpDecodedPictureHashSEIMappedType, 0, "Control generation of decode picture hash SEI messages\n" "\t3: checksum\n" "\t2: CRC\n" @@ -1910,6 +1938,53 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) } } #endif +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + + CHECK(cfg_qpInValCb.values.size() != cfg_qpOutValCb.values.size(), "Chroma QP table for Cb is incomplete."); + CHECK(cfg_qpInValCr.values.size() != cfg_qpOutValCr.values.size(), "Chroma QP table for Cr is incomplete."); + CHECK(cfg_qpInValCbCr.values.size() != cfg_qpOutValCbCr.values.size(), "Chroma QP table for CbCr is incomplete."); + if (m_useIdentityTableForNon420Chroma && m_chromaFormatIDC != CHROMA_420) + { + m_chromaQpMappingTableParams.m_sameCQPTableForAllChromaFlag = true; + cfg_qpInValCb.values = { 0 }; + cfg_qpInValCr.values = { 0 }; + cfg_qpInValCbCr.values = { 0 }; + } + m_chromaQpMappingTableParams.m_deltaQpInValMinus1[0].resize(cfg_qpInValCb.values.size()); + m_chromaQpMappingTableParams.m_deltaQpOutVal[0].resize(cfg_qpOutValCb.values.size()); + m_chromaQpMappingTableParams.m_numPtsInCQPTableMinus1[0] = (int)cfg_qpOutValCb.values.size()-1; + int qpBdOffsetC = 6 * (m_internalBitDepth[CHANNEL_TYPE_CHROMA] - 8); + for (int i = 0; i < cfg_qpInValCb.values.size(); i++) + { + CHECK(cfg_qpInValCb.values[i] < -qpBdOffsetC || cfg_qpInValCb.values[i] > MAX_QP, "Some entries cfg_qpInValCb are out of valid range of -qpBdOffsetC to 63, inclusive."); + CHECK(cfg_qpOutValCb.values[i] < -qpBdOffsetC || cfg_qpOutValCb.values[i] > MAX_QP, "Some entries cfg_qpOutValCb are out of valid range of -qpBdOffsetC to 63, inclusive."); + m_chromaQpMappingTableParams.m_deltaQpInValMinus1[0][i] = (i == 0) ? cfg_qpInValCb.values[i] + qpBdOffsetC : cfg_qpInValCb.values[i] - cfg_qpInValCb.values[i - 1] - 1; + m_chromaQpMappingTableParams.m_deltaQpOutVal[0][i] = (i == 0) ? cfg_qpOutValCb.values[i] + qpBdOffsetC : cfg_qpOutValCb.values[i] - cfg_qpOutValCb.values[i - 1]; + } + if (!m_chromaQpMappingTableParams.m_sameCQPTableForAllChromaFlag) + { + m_chromaQpMappingTableParams.m_deltaQpInValMinus1[1].resize(cfg_qpInValCr.values.size()); + m_chromaQpMappingTableParams.m_deltaQpOutVal[1].resize(cfg_qpOutValCr.values.size()); + m_chromaQpMappingTableParams.m_numPtsInCQPTableMinus1[1] = (int)cfg_qpOutValCr.values.size()-1; + for (int i = 0; i < cfg_qpInValCb.values.size(); i++) + { + CHECK(cfg_qpInValCr.values[i] < -qpBdOffsetC || cfg_qpInValCr.values[i] > MAX_QP, "Some entries cfg_qpInValCr are out of valid range of -qpBdOffsetC to 63, inclusive."); + CHECK(cfg_qpOutValCr.values[i] < -qpBdOffsetC || cfg_qpOutValCr.values[i] > MAX_QP, "Some entries cfg_qpOutValCr are out of valid range of -qpBdOffsetC to 63, inclusive."); + m_chromaQpMappingTableParams.m_deltaQpInValMinus1[1][i] = (i == 0) ? cfg_qpInValCr.values[i] + qpBdOffsetC : cfg_qpInValCr.values[i] - cfg_qpInValCr.values[i - 1] - 1; + m_chromaQpMappingTableParams.m_deltaQpOutVal[1][i] = (i == 0) ? cfg_qpOutValCr.values[i] + qpBdOffsetC : cfg_qpOutValCr.values[i] - cfg_qpOutValCr.values[i - 1]; + } + m_chromaQpMappingTableParams.m_deltaQpInValMinus1[2].resize(cfg_qpInValCbCr.values.size()); + m_chromaQpMappingTableParams.m_deltaQpOutVal[2].resize(cfg_qpOutValCbCr.values.size()); + m_chromaQpMappingTableParams.m_numPtsInCQPTableMinus1[2] = (int)cfg_qpOutValCbCr.values.size()-1; + for (int i = 0; i < cfg_qpInValCbCr.values.size(); i++) + { + CHECK(cfg_qpInValCbCr.values[i] < -qpBdOffsetC || cfg_qpInValCbCr.values[i] > MAX_QP, "Some entries cfg_qpInValCbCr are out of valid range of -qpBdOffsetC to 63, inclusive."); + CHECK(cfg_qpOutValCbCr.values[i] < -qpBdOffsetC || cfg_qpOutValCbCr.values[i] > MAX_QP, "Some entries cfg_qpOutValCbCr are out of valid range of -qpBdOffsetC to 63, inclusive."); + m_chromaQpMappingTableParams.m_deltaQpInValMinus1[2][i] = (i == 0) ? cfg_qpInValCbCr.values[i] + qpBdOffsetC : cfg_qpInValCbCr.values[i] - cfg_qpInValCbCr.values[i - 1] - 1; + m_chromaQpMappingTableParams.m_deltaQpOutVal[2][i] = (i == 0) ? cfg_qpOutValCbCr.values[i] + qpBdOffsetC : cfg_qpOutValCbCr.values[i] - cfg_qpOutValCbCr.values[i - 1]; + } + } +#endif #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET if ( m_LadfEnabed ) @@ -2215,6 +2290,9 @@ bool EncAppCfg::xCheckParameter() xConfirmPara(m_DMVR, "DMVR only allowed with NEXT profile"); xConfirmPara(m_MmvdDisNum, "Number of distance MMVD entry setting only allowed with NEXT profile"); xConfirmPara(m_RdpcmMode, "RDPCM only allowed with NEXT profile"); +#if JVET_O0376_SPS_JOINTCBCR_FLAG + xConfirmPara(m_JointCbCrMode, "JointCbCr only allowed with NEXT profile"); +#endif // ADD_NEW_TOOL : (parameter check) add a check for next tools here } else @@ -2504,11 +2582,27 @@ bool EncAppCfg::xCheckParameter() xConfirmPara( m_cbQpOffsetDualTree > 12, "Max. Chroma Cb QP Offset for dual tree is 12" ); xConfirmPara( m_crQpOffsetDualTree < -12, "Min. Chroma Cr QP Offset for dual tree is -12" ); xConfirmPara( m_crQpOffsetDualTree > 12, "Max. Chroma Cr QP Offset for dual tree is 12" ); - xConfirmPara( m_cbCrQpOffset < -12, "Min. Joint Cb-Cr QP Offset is -12" ); - xConfirmPara( m_cbCrQpOffset > 12, "Max. Joint Cb-Cr QP Offset is 12" ); - xConfirmPara( m_cbCrQpOffsetDualTree < -12, "Min. Joint Cb-Cr QP Offset for dual tree is -12" ); - xConfirmPara( m_cbCrQpOffsetDualTree > 12, "Max. Joint Cb-Cr QP Offset for dual tree is 12" ); - +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if (m_JointCbCrMode && (m_chromaFormatIDC == CHROMA_400)) + { + msg( WARNING, "****************************************************************************\n"); + msg( WARNING, "** WARNING: --JointCbCr has been disabled due to the chromaFormat is 400 **\n"); + msg( WARNING, "****************************************************************************\n"); + m_JointCbCrMode = false; + } + if (m_JointCbCrMode) + { + xConfirmPara( m_cbCrQpOffset < -12, "Min. Joint Cb-Cr QP Offset is -12"); + xConfirmPara( m_cbCrQpOffset > 12, "Max. Joint Cb-Cr QP Offset is 12"); + xConfirmPara( m_cbCrQpOffsetDualTree < -12, "Min. Joint Cb-Cr QP Offset for dual tree is -12"); + xConfirmPara( m_cbCrQpOffsetDualTree > 12, "Max. Joint Cb-Cr QP Offset for dual tree is 12"); + } +#else + xConfirmPara( m_cbCrQpOffset < -12, "Min. Joint Cb-Cr QP Offset is -12"); + xConfirmPara( m_cbCrQpOffset > 12, "Max. Joint Cb-Cr QP Offset is 12"); + xConfirmPara( m_cbCrQpOffsetDualTree < -12, "Min. Joint Cb-Cr QP Offset for dual tree is -12"); + xConfirmPara( m_cbCrQpOffsetDualTree > 12, "Max. Joint Cb-Cr QP Offset for dual tree is 12"); +#endif xConfirmPara( m_iQPAdaptationRange <= 0, "QP Adaptation Range must be more than 0" ); if (m_iDecodingRefreshType == 2) { @@ -2521,20 +2615,26 @@ bool EncAppCfg::xCheckParameter() xConfirmPara( m_uiMinQT[1] < 1<<MIN_CU_LOG2, "Minimum QT size should be larger than or equal to 4"); xConfirmPara( m_uiCTUSize < 16, "Maximum partition width size should be larger than or equal to 16"); xConfirmPara( m_uiCTUSize < 16, "Maximum partition height size should be larger than or equal to 16"); +#if !JVET_O0640_PICTURE_SIZE_CONSTRAINT xConfirmPara( (m_iSourceWidth % (1<<MIN_CU_LOG2))!=0, "Resulting coded frame width must be a multiple of the minimum unit size"); xConfirmPara( (m_iSourceHeight % (1<<MIN_CU_LOG2))!=0, "Resulting coded frame height must be a multiple of the minimum unit size"); xConfirmPara( (m_iSourceWidth % (1<<MIN_CU_LOG2))!=0, "Resulting coded frame width must be a multiple of the minimum unit size"); xConfirmPara( (m_iSourceHeight % (1<<MIN_CU_LOG2))!=0, "Resulting coded frame height must be a multiple of the minimum unit size"); xConfirmPara( (m_iSourceWidth % (1<<MIN_CU_LOG2))!=0, "Resulting coded frame width must be a multiple of the minimum unit size"); xConfirmPara( (m_iSourceHeight % (1<<MIN_CU_LOG2))!=0, "Resulting coded frame height must be a multiple of the minimum unit size"); +#endif xConfirmPara( m_uiMaxCUDepth < 1, "MaxPartitionDepth must be greater than zero"); xConfirmPara( (m_uiMaxCUWidth >> m_uiMaxCUDepth) < 4, "Minimum partition width size should be larger than or equal to 8"); xConfirmPara( (m_uiMaxCUHeight >> m_uiMaxCUDepth) < 4, "Minimum partition height size should be larger than or equal to 8"); xConfirmPara( m_uiMaxCUWidth < 16, "Maximum partition width size should be larger than or equal to 16"); xConfirmPara( m_uiMaxCUHeight < 16, "Maximum partition height size should be larger than or equal to 16"); +#if JVET_O0640_PICTURE_SIZE_CONSTRAINT + xConfirmPara( (m_iSourceWidth % (std::max(8, int(m_uiMaxCUWidth >> (m_uiMaxCUDepth - 1))))) != 0, "Resulting coded frame width must be a multiple of Max(8, the minimum CU size)"); + xConfirmPara( (m_iSourceHeight % (std::max(8, int(m_uiMaxCUHeight >> (m_uiMaxCUDepth - 1))))) != 0, "Resulting coded frame height must be a multiple of Max(8, the minimum CU size)"); +#else xConfirmPara( (m_iSourceWidth % (m_uiMaxCUWidth >> (m_uiMaxCUDepth-1)))!=0, "Resulting coded frame width must be a multiple of the minimum CU size"); xConfirmPara( (m_iSourceHeight % (m_uiMaxCUHeight >> (m_uiMaxCUDepth-1)))!=0, "Resulting coded frame height must be a multiple of the minimum CU size"); - +#endif #if MAX_TB_SIZE_SIGNALLING xConfirmPara( m_log2MaxTbSize > 6, "Log2MaxTbSize must be 6 or smaller." ); #endif @@ -2546,7 +2646,10 @@ bool EncAppCfg::xCheckParameter() 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." ); - +#if JVET_O0455_IBC_MAX_MERGE_NUM + 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." ); +#endif xConfirmPara( m_maxNumAffineMergeCand < 1, "MaxNumAffineMergeCand must be 1 or greater." ); xConfirmPara( m_maxNumAffineMergeCand > AFFINE_MRG_MAX_NUM_CANDS, "MaxNumAffineMergeCand must be no more than AFFINE_MRG_MAX_NUM_CANDS." ); if ( m_Affine == 0 ) @@ -3294,6 +3397,9 @@ void EncAppCfg::xPrintParameter() msg( DETAILS, "Max Num Merge Candidates : %d\n", m_maxNumMergeCand ); msg( DETAILS, "Max Num Affine Merge Candidates : %d\n", m_maxNumAffineMergeCand ); msg( DETAILS, "Max Num Triangle Merge Candidates : %d\n", m_maxNumTriangleCand ); +#if JVET_O0455_IBC_MAX_MERGE_NUM + msg( DETAILS, "Max Num IBC Merge Candidates : %d\n", m_maxNumIBCMergeCand ); +#endif msg( DETAILS, "\n"); msg( VERBOSE, "TOOL CFG: "); @@ -3396,6 +3502,9 @@ void EncAppCfg::xPrintParameter() msg(VERBOSE, "DMVR:%d ", m_DMVR); msg(VERBOSE, "MmvdDisNum:%d ", m_MmvdDisNum); msg(VERBOSE, "RDPCM:%d ", m_RdpcmMode ); +#if JVET_O0376_SPS_JOINTCBCR_FLAG + msg(VERBOSE, "JointCbCr:%d ", m_JointCbCrMode); +#endif } #if JVET_O0119_BASE_PALETTE_444 m_PLTMode = ( m_chromaFormatIDC == CHROMA_444) ? m_PLTMode : 0u; diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 16432d47fca4d4f4b31c9cd2fd26e106970bdb93..ebfc9e723a501e0d4ab3d4a79f75449e885a2f7e 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -145,6 +145,9 @@ protected: bool m_noTransformSkipConstraintFlag; #if JVET_O1136_TS_BDPCM_SIGNALLING bool m_noBDPCMConstraintFlag; +#endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + bool m_noJointCbCrConstraintFlag; #endif bool m_bNoQpDeltaConstraintFlag; bool m_bNoDepQuantConstraintFlag; @@ -202,6 +205,10 @@ protected: double m_fQP; ///< QP value of key-picture (floating point) #endif int m_iQP; ///< QP value of key-picture (integer) +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + bool m_useIdentityTableForNon420Chroma; + ChromaQpMappingTableParams m_chromaQpMappingTableParams; +#endif #if X0038_LAMBDA_FROM_QP_CAPABILITY int m_intraQPOffset; ///< QP offset for intra slice (integer) bool m_lambdaFromQPEnable; ///< enable flag for QP:lambda fix @@ -288,6 +295,9 @@ protected: bool m_RdpcmMode; #if JVET_O0119_BASE_PALETTE_444 unsigned m_PLTMode; +#endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + bool m_JointCbCrMode; #endif unsigned m_IBCMode; unsigned m_IBCLocalSearchRangeX; @@ -518,6 +528,9 @@ protected: uint32_t m_maxNumMergeCand; ///< Max number of merge candidates uint32_t m_maxNumAffineMergeCand; ///< Max number of affine merge candidates uint32_t m_maxNumTriangleCand; +#if JVET_O0455_IBC_MAX_MERGE_NUM + uint32_t m_maxNumIBCMergeCand; ///< Max number of IBC merge candidates +#endif int m_TMVPModeId; bool m_depQuantEnabledFlag; diff --git a/source/Lib/CommonLib/AdaptiveLoopFilter.h b/source/Lib/CommonLib/AdaptiveLoopFilter.h index 42be89b58354401bf9e554e2edc844d0e997d5b8..da2c5e064614d95f4cd2e3ba49fe81a2eadc6982 100644 --- a/source/Lib/CommonLib/AdaptiveLoopFilter.h +++ b/source/Lib/CommonLib/AdaptiveLoopFilter.h @@ -115,7 +115,7 @@ protected: static const int m_classToFilterMapping[NUM_FIXED_FILTER_SETS][MAX_NUM_ALF_CLASSES]; static const int m_fixedFilterSetCoeff[ALF_FIXED_FILTER_NUM][MAX_NUM_ALF_LUMA_COEFF]; short m_fixedFilterSetCoeffDec[NUM_FIXED_FILTER_SETS][MAX_NUM_ALF_CLASSES * MAX_NUM_ALF_LUMA_COEFF]; -#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB +#if JVET_O0090_ALF_CHROMA_FILTER_ALTERNATIVES_CTB || JVET_O_MAX_NUM_ALF_APS_8 short m_coeffApsLuma[ALF_CTB_MAX_NUM_APS][MAX_NUM_ALF_LUMA_COEFF * MAX_NUM_ALF_CLASSES]; short m_clippApsLuma[ALF_CTB_MAX_NUM_APS][MAX_NUM_ALF_LUMA_COEFF * MAX_NUM_ALF_CLASSES]; #else diff --git a/source/Lib/CommonLib/Buffer.cpp b/source/Lib/CommonLib/Buffer.cpp index 7af9b1fdf06e828e665bca22880b3f2c5230ff8f..7c671f6773363799eb1803ad84763f6e38f51951 100644 --- a/source/Lib/CommonLib/Buffer.cpp +++ b/source/Lib/CommonLib/Buffer.cpp @@ -218,6 +218,36 @@ void gradFilterCore(Pel* pSrc, int srcStride, int width, int height, int gradStr #endif } +#if JVET_O0304_SIMPLIFIED_BDOF +void calcBIOSumsCore(const Pel* srcY0Tmp, const Pel* srcY1Tmp, Pel* gradX0, Pel* gradX1, Pel* gradY0, Pel* gradY1, int xu, int yu, const int src0Stride, const int src1Stride, const int widthG, const int bitDepth, int* sumAbsGX, int* sumAbsGY, int* sumDIX, int* sumDIY, int* sumSignGY_GX) +{ + int shift4 = std::max<int>(4, (bitDepth - 8)); + int shift5 = std::max<int>(1, (bitDepth - 11)); + + for (int y = 0; y < 6; y++) + { + for (int x = 0; x < 6; x++) + { + int tmpGX = (gradX0[x] + gradX1[x]) >> shift5; + int tmpGY = (gradY0[x] + gradY1[x]) >> shift5; + int tmpDI = (int)((srcY1Tmp[x] >> shift4) - (srcY0Tmp[x] >> shift4)); + *sumAbsGX += (tmpGX < 0 ? -tmpGX : tmpGX); + *sumAbsGY += (tmpGY < 0 ? -tmpGY : tmpGY); + *sumDIX += (tmpGX < 0 ? -tmpDI : (tmpGX == 0 ? 0 : tmpDI)); + *sumDIY += (tmpGY < 0 ? -tmpDI : (tmpGY == 0 ? 0 : tmpDI)); + *sumSignGY_GX += (tmpGY < 0 ? -tmpGX : (tmpGY == 0 ? 0 : tmpGX)); + + } + srcY1Tmp += src1Stride; + srcY0Tmp += src0Stride; + gradX0 += widthG; + gradX1 += widthG; + gradY0 += widthG; + gradY1 += widthG; + } +} +#endif + void calcBIOParCore(const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG, const int bitDepth) { int shift4 = std::max<int>(4, (bitDepth - 8)); @@ -360,8 +390,12 @@ PelBufferOps::PelBufferOps() addBIOAvg4 = addBIOAvgCore; bioGradFilter = gradFilterCore; - calcBIOPar = calcBIOParCore; +#if !JVET_O0304_SIMPLIFIED_BDOF + calcBIOPar = calcBIOParCore; calcBlkGradient = calcBlkGradientCore; +#else + calcBIOSums = calcBIOSumsCore; +#endif copyBuffer = copyBufferCore; padding = paddingCore; diff --git a/source/Lib/CommonLib/Buffer.h b/source/Lib/CommonLib/Buffer.h index ed7fb47ecbaaa1d757605b64a3e17e8cfe0f190b..d04861d65f7c10eb9dab65bdbec515c30f745963 100644 --- a/source/Lib/CommonLib/Buffer.h +++ b/source/Lib/CommonLib/Buffer.h @@ -70,6 +70,9 @@ struct PelBufferOps void(*addBIOAvg4) (const Pel* src0, int src0Stride, const Pel* src1, int src1Stride, Pel *dst, int dstStride, const Pel *gradX0, const Pel *gradX1, const Pel *gradY0, const Pel*gradY1, int gradStride, int width, int height, int tmpx, int tmpy, int shift, int offset, const ClpRng& clpRng); void(*bioGradFilter) (Pel* pSrc, int srcStride, int width, int height, int gradStride, Pel* gradX, Pel* gradY, const int bitDepth); void(*calcBIOPar) (const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG, const int bitDepth); +#if JVET_O0304_SIMPLIFIED_BDOF + void(*calcBIOSums) (const Pel* srcY0Tmp, const Pel* srcY1Tmp, Pel* gradX0, Pel* gradX1, Pel* gradY0, Pel* gradY1, int xu, int yu, const int src0Stride, const int src1Stride, const int widthG, const int bitDepth, int* sumAbsGX, int* sumAbsGY, int* sumDIX, int* sumDIY, int* sumSignGY_GX); +#endif void(*calcBlkGradient)(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(*copyBuffer)(Pel *src, int srcStride, Pel *dst, int dstStride, int width, int height); void(*padding)(Pel *dst, int stride, int width, int height, int padSize); diff --git a/source/Lib/CommonLib/ChromaFormat.h b/source/Lib/CommonLib/ChromaFormat.h index 8be4be331e05168687d292ac87419a38c04be9d5..0400084e1fe7f02773ac735ed6be8b28f905e0e4 100644 --- a/source/Lib/CommonLib/ChromaFormat.h +++ b/source/Lib/CommonLib/ChromaFormat.h @@ -115,12 +115,12 @@ static inline int getTransformShift(const int channelBitDepth, const Size size, //------------------------------------------------ - +#if !JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE static inline int getScaledChromaQP(int unscaledChromaQP, const ChromaFormat chFmt) { return g_aucChromaScale[chFmt][Clip3(0, (chromaQPMappingTableSize - 1), unscaledChromaQP)]; } - +#endif //====================================================================================================================== //Scaling lists ======================================================================================================= diff --git a/source/Lib/CommonLib/CodingStructure.h b/source/Lib/CommonLib/CodingStructure.h index 4029d5cfa3770786ac4344a587d5722a9f7562b7..f641a2ba230b4de66e34caceb67199e6c895f3a6 100644 --- a/source/Lib/CommonLib/CodingStructure.h +++ b/source/Lib/CommonLib/CodingStructure.h @@ -97,7 +97,11 @@ public: bool isLossless; const SPS *sps; const PPS *pps; +#if JVET_O_MAX_NUM_ALF_APS_8 + APS* alfApss[ALF_CTB_MAX_NUM_APS]; +#else APS* alfApss[MAX_NUM_APS]; +#endif APS * lmcsAps; const VPS *vps; const PreCalcValues* pcv; diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 47b44d290747860c0e2123961d796d812a6490c3..daf78d6ff822b7d7dd250fba507518018256bba9 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -151,7 +151,10 @@ static const int AMVP_MAX_NUM_CANDS_MEM = 3; ///< AMVP static const int AMVP_DECIMATION_FACTOR = 2; static const int MRG_MAX_NUM_CANDS = 6; ///< MERGE static const int AFFINE_MRG_MAX_NUM_CANDS = 5; ///< AFFINE MERGE - +#if JVET_O0455_IBC_MAX_MERGE_NUM +static const int IBC_MRG_MAX_NUM_CANDS = 6; ///< IBC MERGE +#endif + static const int MAX_TLAYER = 7; ///< Explicit temporal layer QP offset - max number of temporal layer static const int ADAPT_SR_SCALE = 1; ///< division factor for adaptive search range @@ -187,7 +190,11 @@ static const int MAX_NUM_ALF_COEFF = MAX_ALF_FILTE static const int MAX_ALF_PADDING_SIZE = 4; static const int ALF_FIXED_FILTER_NUM = 64; +#if JVET_O_MAX_NUM_ALF_APS_8 +static const int ALF_CTB_MAX_NUM_APS = 8; +#else static const int ALF_CTB_MAX_NUM_APS = 6; +#endif static const int NUM_FIXED_FILTER_SETS = 16; static const int NUM_TOTAL_FILTER_SETS = NUM_FIXED_FILTER_SETS + ALF_CTB_MAX_NUM_APS; @@ -296,6 +303,11 @@ static const int NUM_LONG_TERM_REF_PIC_SPS = 0; static const int MAX_QP_OFFSET_LIST_SIZE = 6; ///< Maximum size of QP offset list is 6 entries +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE +static const int MAX_NUM_CQP_MAPPING_TABLES = 3; ///< Maximum number of chroma QP mapping tables (Cb, Cr and joint Cb-Cr) +static const int MIN_QP_VALUE_FOR_16_BIT = -48; ////< Minimum value for QP (-6*(bitdepth - 8) ) for bit depth 16 ; actual minimum QP value is bit depth dependent +static const int MAX_NUM_QP_VALUES = MAX_QP + 1 - MIN_QP_VALUE_FOR_16_BIT; ////< Maximum number of QP values possible - bit depth dependent +#endif // Cost mode support static const int LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP = 0; ///< QP to use for lossless coding. diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index af67152c7a99756347c8692c9679de86f34f3946..630d3ac9c06f8fe0f1aad2ccf763c1ae6ea5623d 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -446,9 +446,7 @@ public: violatesLfnstConstrained[CHANNEL_TYPE_LUMA ] = false; violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; #endif - lastScanPos[COMPONENT_Y ] = -1; - lastScanPos[COMPONENT_Cb] = -1; - lastScanPos[COMPONENT_Cr] = -1; + lfnstLastScanPos = false; } #else qgStart(false), @@ -471,9 +469,7 @@ public: violatesLfnstConstrained[CHANNEL_TYPE_LUMA ] = false; violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; #endif - lastScanPos[COMPONENT_Y ] = -1; - lastScanPos[COMPONENT_Cb] = -1; - lastScanPos[COMPONENT_Cr] = -1; + lfnstLastScanPos = false; } #else #if JVET_O0094_LFNST_ZERO_PRIM_COEFFS @@ -492,7 +488,7 @@ public: bool isChromaQpAdjCoded; bool qgStart; #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS - int lastScanPos[MAX_NUM_COMPONENT]; + bool lfnstLastScanPos; #else uint32_t numNonZeroCoeffNonTs; #endif diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index ae31a9a74c9bc98dc72441fd5c763ff6798cace7..792e3294dd5e2a6eb51fa7c37c3e35e3ae69c4bb 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -1279,7 +1279,7 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf const int shiftNum = IF_INTERNAL_PREC + 1 - bitDepth; const int offset = (1 << (shiftNum - 1)) + 2 * IF_INTERNAL_OFFS; const int limit = (1<<(std::max<int>(5, bitDepth - 7))); - +#if !JVET_O0304_SIMPLIFIED_BDOF int* dotProductTemp1 = m_dotProduct1; int* dotProductTemp2 = m_dotProduct2; int* dotProductTemp3 = m_dotProduct3; @@ -1287,6 +1287,7 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf int* dotProductTemp6 = m_dotProduct6; xCalcBIOPar(srcY0Temp, srcY1Temp, gradX0, gradX1, gradY0, gradY1, dotProductTemp1, dotProductTemp2, dotProductTemp3, dotProductTemp5, dotProductTemp6, src0Stride, src1Stride, widthG, widthG, heightG, bitDepth); +#endif int xUnit = (width >> 2); int yUnit = (height >> 2); @@ -1310,7 +1311,7 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf continue; } #endif - +#if !JVET_O0304_SIMPLIFIED_BDOF int sGxdI = 0, sGydI = 0, sGxGy = 0, sGx2 = 0, sGy2 = 0; int tmpx = 0, tmpy = 0; @@ -1336,7 +1337,29 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf tmpy = rightShiftMSB(((sGydI << 3) - tmpData), sGy2); tmpy = Clip3(-limit, limit, tmpy); } - +#else + int tmpx = 0, tmpy = 0; + int sumAbsGX = 0, sumAbsGY = 0, sumDIX = 0, sumDIY = 0; + int sumSignGY_GX = 0; + + Pel* pGradX0Tmp = m_gradX0 + (xu << 2) + (yu << 2) * widthG; + Pel* pGradX1Tmp = m_gradX1 + (xu << 2) + (yu << 2) * widthG; + Pel* pGradY0Tmp = m_gradY0 + (xu << 2) + (yu << 2) * widthG; + Pel* pGradY1Tmp = m_gradY1 + (xu << 2) + (yu << 2) * widthG; + const Pel* SrcY1Tmp = srcY1 + (xu << 2) + (yu << 2) * src1Stride; + const Pel* SrcY0Tmp = srcY0 + (xu << 2) + (yu << 2) * src0Stride; + + g_pelBufOP.calcBIOSums(SrcY0Tmp, SrcY1Tmp, pGradX0Tmp, pGradX1Tmp, pGradY0Tmp, pGradY1Tmp, xu, yu, src0Stride, src1Stride, widthG, bitDepth, &sumAbsGX, &sumAbsGY, &sumDIX, &sumDIY, &sumSignGY_GX); + tmpx = (sumAbsGX == 0 ? 0 : rightShiftMSB(sumDIX << 3, sumAbsGX)); + tmpx = Clip3(-limit, limit, tmpx); + + int mainsGxGy = sumSignGY_GX >> 12; + int secsGxGy = sumSignGY_GX & ((1 << 12) - 1); + int tmpData = tmpx * mainsGxGy; + tmpData = ((tmpData << 12) + tmpx*secsGxGy) >> 1; + tmpy = (sumAbsGY == 0 ? 0 : rightShiftMSB(((sumDIY << 3) - tmpData), sumAbsGY)); + tmpy = Clip3(-limit, limit, tmpy); +#endif srcY0Temp = srcY0 + (stridePredMC + 1) + ((yu*src0Stride + xu) << 2); srcY1Temp = srcY1 + (stridePredMC + 1) + ((yu*src0Stride + xu) << 2); gradX0 = m_gradX0 + offsetPos + ((yu*widthG + xu) << 2); @@ -2346,7 +2369,7 @@ uint64_t InterPrediction::xDMVRCost(int bitDepth, Pel* pOrg, uint32_t refStride, cDistParam.useMR = false; m_pcRdCost->setDistParam(cDistParam, pOrg, pRef, orgStride, refStride, bitDepth, COMPONENT_Y, width, height, 1); uint64_t uiCost = cDistParam.distFunc(cDistParam); - return uiCost; + return uiCost>>1; } void xDMVRSubPixelErrorSurface(bool notZeroCost, int16_t *totalDeltaMV, int16_t *deltaMV, uint64_t *pSADsArray) @@ -2466,7 +2489,7 @@ void InterPrediction::xProcessDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvDst, con int bd = pu.cs->slice->getClpRngs().comp[COMPONENT_Y].bd; #if JVET_O0055_INT_DMVR_DIS_BDOF - int bioEnabledThres = 8 * (dy >> 1) * dx; + int bioEnabledThres = 2 * dy * dx; bool bioAppliedType[MAX_NUM_SUBCU_DMVR]; #endif { @@ -2577,7 +2600,7 @@ void InterPrediction::xProcessDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvDst, con #if JVET_O0590_REDUCE_DMVR_ORIG_MV_COST minCost -= (minCost >>2); #endif - if (minCost < ((4 * dx * (dy >> 1/*for alternate line*/)))) + if (minCost < (dx * dy)) { notZeroCost = false; break; diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp index a1a40a8b246dfd12abb846530a35f322e5ae5bfa..3ae05f29d10c46ac7552891769e16920b175b3ce 100644 --- a/source/Lib/CommonLib/IntraPrediction.cpp +++ b/source/Lib/CommonLib/IntraPrediction.cpp @@ -336,8 +336,12 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co const int srcStride = m_topRefLength + 1 + (whRatio + 1) * multiRefIdx; const int srcHStride = m_leftRefLength + 1 + (hwRatio + 1) * multiRefIdx; #endif - + +#if JVET_O0502_ISP_CLEANUP + const CPelBuf& srcBuf = pu.cu->ispMode && isLuma(compID) ? getISPBuffer() : CPelBuf(getPredictorPtr(compID), srcStride, srcHStride); +#else const CPelBuf & srcBuf = CPelBuf(getPredictorPtr(compID), srcStride, srcHStride); +#endif const ClpRng& clpRng(pu.cu->cs->slice->clpRng(compID)); switch (uiDirMode) @@ -362,13 +366,14 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co { for (int y = 0; y < iHeight; y++) { - int wT = 32 >> std::min(31, ((y << 1) >> scale)); + const int wT = 32 >> std::min(31, ((y << 1) >> scale)); const Pel left = srcBuf.at(0, y + 1); for (int x = 0; x < iWidth; x++) { - const Pel top = srcBuf.at(x + 1, 0); - int wL = 32 >> std::min(31, ((x << 1) >> scale)); - dstBuf.at(x, y) = ClipPel((wL * left + wT * top + (64 - wL - wT) * dstBuf.at(x, y) + 32) >> 6, clpRng); + const int wL = 32 >> std::min(31, ((x << 1) >> scale)); + const Pel top = srcBuf.at(x + 1, 0); + const Pel val = dstBuf.at(x, y); + dstBuf.at(x, y) = val + ((wL * (left - val) + wT * (top - val) + 32) >> 6); } } } @@ -390,34 +395,6 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co } } #endif - else if (uiDirMode == HOR_IDX) - { - const Pel topLeft = srcBuf.at(0, 0); - for (int y = 0; y < iHeight; y++) - { - int wT = 32 >> std::min(31, ((y << 1) >> scale)); - for (int x = 0; x < iWidth; x++) - { - const Pel top = srcBuf.at(x + 1, 0); - int wTL = wT; - dstBuf.at(x, y) = ClipPel((wT * top - wTL * topLeft + (64 - wT + wTL) * dstBuf.at(x, y) + 32) >> 6, clpRng); - } - } - } - else if (uiDirMode == VER_IDX) - { - const Pel topLeft = srcBuf.at(0, 0); - for (int y = 0; y < iHeight; y++) - { - const Pel left = srcBuf.at(0, y + 1); - for (int x = 0; x < iWidth; x++) - { - int wL = 32 >> std::min(31, ((x << 1) >> scale)); - int wTL = wL; - dstBuf.at(x, y) = ClipPel((wL * left - wTL * topLeft + (64 - wL + wTL) * dstBuf.at(x, y) + 32) >> 6, clpRng); - } - } - } } } @@ -521,13 +498,19 @@ void IntraPrediction::initPredIntraParams(const PredictionUnit & pu, const CompA const int dirMode = PU::getFinalIntraMode(pu, chType); const int predMode = getWideAngle( blockSize.width, blockSize.height, dirMode ); +#if !JVET_O0364_PADDING m_ipaParam.whRatio = std::max( unsigned( 1 ), blockSize.width / blockSize.height ) ; m_ipaParam.hwRatio = std::max( unsigned( 1 ), blockSize.height / blockSize.width ) ; +#endif m_ipaParam.isModeVer = predMode >= DIA_IDX; m_ipaParam.multiRefIndex = isLuma (chType) ? pu.multiRefIdx : 0 ; m_ipaParam.refFilterFlag = false; m_ipaParam.interpolationFlag = false; +#if JVET_O0502_ISP_CLEANUP + m_ipaParam.applyPDPC = ((puSize.width >= MIN_TB_SIZEY && puSize.height >= MIN_TB_SIZEY) || !isLuma(compId)) && m_ipaParam.multiRefIndex == 0; +#else m_ipaParam.applyPDPC = !useISP && m_ipaParam.multiRefIndex == 0; +#endif const int intraPredAngleMode = (m_ipaParam.isModeVer) ? predMode - VER_IDX : -(predMode - HOR_IDX); @@ -581,10 +564,12 @@ void IntraPrediction::initPredIntraParams(const PredictionUnit & pu, const CompA || DC_IDX == dirMode ) { +#if !JVET_O0502_ISP_CLEANUP if (useISP) { m_ipaParam.interpolationFlag = (m_ipaParam.isModeVer ? puSize.width : puSize.height) > 8 ? true : false ; } +#endif } else if (isLuma( chType ) && pu.cu->bdpcmMode) // BDPCM { @@ -649,8 +634,10 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch int height=int(pDst.height); const bool bIsModeVer = m_ipaParam.isModeVer; +#if !JVET_O0364_PADDING const int whRatio = m_ipaParam.whRatio; const int hwRatio = m_ipaParam.hwRatio; +#endif const int multiRefIdx = m_ipaParam.multiRefIndex; const int intraPredAngle = m_ipaParam.intraPredAngle; const int invAngle = m_ipaParam.invAngle; @@ -726,11 +713,14 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch refSide = bIsModeVer ? refLeft : refAbove; // Extend main reference to right using replication - int maxIndex = multiRefIdx * (bIsModeVer ? whRatio : hwRatio) + 2; - Pel val = bIsModeVer ? pSrc.at(m_topRefLength + multiRefIdx, 0) : pSrc.at(0, m_leftRefLength + multiRefIdx); + const int log2Ratio = g_aucLog2[width] - g_aucLog2[height]; + const int s = std::max<int>(0, bIsModeVer ? log2Ratio : -log2Ratio); + const int maxIndex = (multiRefIdx << s) + 2; + const int refLength = bIsModeVer ? m_topRefLength : m_leftRefLength; + const Pel val = refMain[refLength + multiRefIdx]; for (int z = 1; z <= maxIndex; z++) { - refMain[(bIsModeVer ? m_topRefLength : m_leftRefLength) + multiRefIdx + z] = val; + refMain[refLength + multiRefIdx + z] = val; } #else for (int x = 0; x < m_topRefLength + 1 + (whRatio + 1) * multiRefIdx; x++) @@ -765,59 +755,78 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch refMain += multiRefIdx; refSide += multiRefIdx; + Pel *pDsty = pDstBuf; + if( intraPredAngle == 0 ) // pure vertical or pure horizontal { for( int y = 0; y < height; y++ ) { for( int x = 0; x < width; x++ ) { - pDstBuf[y*dstStride + x] = refMain[x + 1]; + pDsty[x] = refMain[x + 1]; + } + + if (m_ipaParam.applyPDPC) + { + const int scale = (g_aucLog2[width] + g_aucLog2[height] - 2) >> 2; + const Pel topLeft = refMain[0]; + const Pel left = refSide[1 + y]; + for (int x = 0; x < std::min(3 << scale, width); x++) + { + const int wL = 32 >> (2 * x >> scale); + const Pel val = pDsty[x]; + pDsty[x] = ClipPel(val + ((wL * (left - topLeft) + 32) >> 6), clpRng); + } } + + pDsty += dstStride; } } else { - Pel *pDsty=pDstBuf; for (int y = 0, deltaPos = intraPredAngle * (1 + multiRefIdx); y<height; y++, deltaPos += intraPredAngle, pDsty += dstStride) { const int deltaInt = deltaPos >> 5; - const int deltaFract = deltaPos & (32 - 1); + const int deltaFract = deltaPos & 31; if ( !isIntegerSlope( abs(intraPredAngle) ) ) { if( isLuma(channelType) ) { - Pel p[4]; - const bool useCubicFilter = !m_ipaParam.interpolationFlag; - TFilterCoeff const * const f = (useCubicFilter) ? InterpolationFilter::getChromaFilterTable(deltaFract) : g_intraGaussFilter[deltaFract]; + const bool useCubicFilter = !m_ipaParam.interpolationFlag; - int refMainIndex = deltaInt + 1; + const TFilterCoeff *const f = + (useCubicFilter) ? InterpolationFilter::getChromaFilterTable(deltaFract) : g_intraGaussFilter[deltaFract]; - for( int x = 0; x < width; x++, refMainIndex++ ) + for (int x = 0; x < width; x++) { - p[0] = refMain[refMainIndex - 1]; - p[1] = refMain[refMainIndex]; - p[2] = refMain[refMainIndex + 1]; - p[3] = f[3] != 0 ? refMain[refMainIndex + 2] : 0; + Pel p[4]; - pDstBuf[y*dstStride + x] = static_cast<Pel>((static_cast<int>(f[0] * p[0]) + static_cast<int>(f[1] * p[1]) + static_cast<int>(f[2] * p[2]) + static_cast<int>(f[3] * p[3]) + 32) >> 6); + p[0] = refMain[deltaInt + x]; + p[1] = refMain[deltaInt + x + 1]; + p[2] = refMain[deltaInt + x + 2]; +#if JVET_O0364_PADDING + p[3] = refMain[deltaInt + x + 3]; +#else + p[3] = f[3] != 0 ? refMain[deltaInt + x + 3] : 0; +#endif + + Pel val = (f[0] * p[0] + f[1] * p[1] + f[2] * p[2] + f[3] * p[3] + 32) >> 6; - if( useCubicFilter ) // only cubic filter has negative coefficients and requires clipping - { - pDstBuf[y*dstStride + x] = ClipPel( pDstBuf[y*dstStride + x], clpRng ); - } + pDsty[x] = ClipPel(val, clpRng); // always clip even though not always needed } } else { // Do linear filtering - const Pel *pRM = refMain + deltaInt + 1; - int lastRefMainPel = *pRM++; - for( int x = 0; x < width; pRM++, x++ ) + for (int x = 0; x < width; x++) { - int thisRefMainPel = *pRM; - pDsty[x + 0] = ( Pel ) ( ( ( 32 - deltaFract )*lastRefMainPel + deltaFract*thisRefMainPel + 16 ) >> 5 ); - lastRefMainPel = thisRefMainPel; + Pel p[2]; + + p[0] = refMain[deltaInt + x + 1]; + p[1] = refMain[deltaInt + x + 2]; + + pDsty[x] = p[0] + ((deltaFract * (p[1] - p[0]) + 16) >> 5); } } } @@ -1062,7 +1071,11 @@ void IntraPrediction::initIntraPatternChType(const CodingUnit &cu, const CompAre Pel *refBufUnfiltered = m_piYuvExt[area.compID][PRED_BUF_UNFILTERED]; Pel *refBufFiltered = m_piYuvExt[area.compID][PRED_BUF_FILTERED]; +#if JVET_O0502_ISP_CLEANUP + setReferenceArrayLengths( area ); +#else setReferenceArrayLengths( cu.ispMode && isLuma( area.compID ) ? cu.blocks[area.compID] : area ); +#endif // ----- Step 1: unfiltered reference samples ----- xFillReferenceSamples( cs.picture->getRecoBuf( area ), refBufUnfiltered, area, cu ); @@ -1073,6 +1086,130 @@ void IntraPrediction::initIntraPatternChType(const CodingUnit &cu, const CompAre } } +#if JVET_O0502_ISP_CLEANUP +void IntraPrediction::initIntraPatternChTypeISP(const CodingUnit& cu, const CompArea& area, PelBuf& recBuf, const bool forceRefFilterFlag) +{ + const CodingStructure& cs = *cu.cs; + + if (!forceRefFilterFlag) + { + initPredIntraParams(*cu.firstPU, area, *cs.sps); + } + + const Position posLT = area; + bool isLeftAvail = cs.isDecomp(posLT.offset(-1, 0), CHANNEL_TYPE_LUMA); + bool isAboveAvail = cs.isDecomp(posLT.offset(0, -1), CHANNEL_TYPE_LUMA); + // ----- Step 1: unfiltered reference samples ----- +#if JVET_O0106_ISP_4xN_PREDREG_FOR_1xN_2xN + if (cu.blocks[area.compID].x == area.x && cu.blocks[area.compID].y == area.y) +#else + if (CU::isISPFirst(cu, area, area.compID)) +#endif + { + Pel* refBufUnfiltered = m_piYuvExt[area.compID][PRED_BUF_UNFILTERED]; + // With the first subpartition all the CU reference samples are fetched at once in a single call to xFillReferenceSamples + if (cu.ispMode == HOR_INTRA_SUBPARTITIONS) + { + m_leftRefLength = cu.Y().height << 1; + m_topRefLength = cu.Y().width + area.width; + } + else //if (cu.ispMode == VER_INTRA_SUBPARTITIONS) + { + m_leftRefLength = cu.Y().height + area.height; + m_topRefLength = cu.Y().width << 1; + } + + const int srcStride = m_topRefLength + 1; + const int srcHStride = m_leftRefLength + 1; + + m_pelBufISP[0] = m_pelBufISPBase[0] = PelBuf(m_piYuvExt[area.compID][PRED_BUF_UNFILTERED], srcStride, srcHStride); + m_pelBufISP[1] = m_pelBufISPBase[1] = PelBuf(m_piYuvExt[area.compID][PRED_BUF_FILTERED], srcStride, srcHStride); + + xFillReferenceSamples(cs.picture->getRecoBuf(cu.Y()), refBufUnfiltered, cu.Y(), cu); + + // After having retrieved all the CU reference samples, the number of reference samples is now adjusted for the current subpartition + m_topRefLength = cu.blocks[area.compID].width + area.width; + m_leftRefLength = cu.blocks[area.compID].height + area.height; + } + else + { + //Now we only need to fetch the newly available reconstructed samples from the previously coded TU + Position tuPos = area; + tuPos.relativeTo(cu.Y()); + m_pelBufISP[0] = m_pelBufISPBase[0].subBuf(tuPos, area.size()); + m_pelBufISP[1] = m_pelBufISPBase[1].subBuf(tuPos, area.size()); + + PelBuf& dstBuf = m_pelBufISP[0]; + + m_topRefLength = cu.blocks[area.compID].width + area.width; + m_leftRefLength = cu.blocks[area.compID].height + area.height; + + const int predSizeHor = m_topRefLength; + const int predSizeVer = m_leftRefLength; + if (cu.ispMode == HOR_INTRA_SUBPARTITIONS) + { + Pel* src = recBuf.bufAt(0, -1); + Pel* dst = dstBuf.bufAt(1, 0); + for (int i = 0; i < area.width; i++) + { + dst[i] = src[i]; + } + Pel sample = src[area.width - 1]; + dst += area.width; + for (int i = 0; i < predSizeHor - area.width; i++) + { + dst[i] = sample; + } + if (!isLeftAvail) //if left is not avaible, then it is necessary to fetch these samples for each subpartition + { + Pel* dst = dstBuf.bufAt(0, 0); + Pel sample = src[0]; + for (int i = 0; i < predSizeVer + 1; i++) + { + *dst = sample; + dst += dstBuf.stride; + } + } + } + else + { + Pel* src = recBuf.bufAt(-1, 0); + Pel* dst = dstBuf.bufAt(0, 1); + for (int i = 0; i < area.height; i++) + { + *dst = *src; + src += recBuf.stride; + dst += dstBuf.stride; + } + Pel sample = src[-recBuf.stride]; + for (int i = 0; i < predSizeVer - area.height; i++) + { + *dst = sample; + dst += dstBuf.stride; + } + + if (!isAboveAvail) //if above is not avaible, then it is necessary to fetch these samples for each subpartition + { + Pel* dst = dstBuf.bufAt(0, 0); + Pel sample = recBuf.at(-1, 0); + for (int i = 0; i < predSizeHor + 1; i++) + { + dst[i] = sample; + } + } + } + } + // ----- Step 2: filtered reference samples ----- + if (m_ipaParam.refFilterFlag || forceRefFilterFlag) + { + Pel* refBufUnfiltered = m_pelBufISP[0].buf; + Pel* refBufFiltered = m_pelBufISP[1].buf; + xFilterReferenceSamples(refBufUnfiltered, refBufFiltered, area, *cs.sps, cu.firstPU->multiRefIdx, m_pelBufISP[0].stride); + } +} +#endif + + void IntraPrediction::xFillReferenceSamples( const CPelBuf &recoBuf, Pel* refBufUnfiltered, const CompArea &area, const CodingUnit &cu ) { const ChannelType chType = toChannelType( area.compID ); @@ -1330,6 +1467,9 @@ void IntraPrediction::xFillReferenceSamples( const CPelBuf &recoBuf, Pel* refBuf void IntraPrediction::xFilterReferenceSamples( const Pel* refBufUnfiltered, Pel* refBufFiltered, const CompArea &area, const SPS &sps , int multiRefIdx +#if JVET_O0502_ISP_CLEANUP + , int stride +#endif ) { if (area.compID != COMPONENT_Y) @@ -1345,7 +1485,11 @@ void IntraPrediction::xFilterReferenceSamples( const Pel* refBufUnfiltered, Pel* const int predSize = m_topRefLength + (whRatio + 1) * multiRefIdx; const int predHSize = m_leftRefLength + (hwRatio + 1) * multiRefIdx; #endif +#if JVET_O0502_ISP_CLEANUP + const int predStride = stride == 0 ? predSize + 1 : stride; +#else const int predStride = predSize + 1; +#endif diff --git a/source/Lib/CommonLib/IntraPrediction.h b/source/Lib/CommonLib/IntraPrediction.h index 2d498e61c4ba44a87e1b63b0363756381b579657..29ccc472f74c33e190f19c10ad4e397a2e2ad66a 100644 --- a/source/Lib/CommonLib/IntraPrediction.h +++ b/source/Lib/CommonLib/IntraPrediction.h @@ -68,6 +68,10 @@ class IntraPrediction private: Pel* m_piYuvExt[MAX_NUM_COMPONENT][NUM_PRED_BUF]; +#if JVET_O0502_ISP_CLEANUP + PelBuf m_pelBufISPBase[2]; + PelBuf m_pelBufISP[2]; +#endif int m_iYuvExtSize; Pel* m_yuvExt2[MAX_NUM_COMPONENT][4]; @@ -81,8 +85,10 @@ private: bool applyPDPC; bool isModeVer; int multiRefIndex; +#if !JVET_O0364_PADDING int whRatio; int hwRatio; +#endif int intraPredAngle; int invAngle; bool interpolationFlag; @@ -90,16 +96,25 @@ private: int angularScale; #endif - IntraPredParam() : - refFilterFlag ( false ), - applyPDPC ( false ), - isModeVer ( false ), - multiRefIndex ( -1 ), - whRatio ( 0 ), - hwRatio ( 0 ), - intraPredAngle ( std::numeric_limits<int>::max() ), - invAngle ( std::numeric_limits<int>::max() ), - interpolationFlag ( false ) {} + // clang-format off + IntraPredParam() + : refFilterFlag(false) + , applyPDPC(false) + , isModeVer(false) + , multiRefIndex(-1) +#if !JVET_O0364_PADDING + , whRatio(0) + , hwRatio(0) +#endif + , intraPredAngle(std::numeric_limits<int>::max()) + , invAngle(std::numeric_limits<int>::max()) + , interpolationFlag(false) +#if JVET_O0364_PDPC_ANGULAR + , angularScale(-1) +#endif + // clang-format on + { + } }; IntraPredParam m_ipaParam; @@ -140,6 +155,9 @@ protected: void xFillReferenceSamples ( const CPelBuf &recoBuf, Pel* refBufUnfiltered, const CompArea &area, const CodingUnit &cu ); void xFilterReferenceSamples ( const Pel* refBufUnfiltered, Pel* refBufFiltered, const CompArea &area, const SPS &sps , int multiRefIdx +#if JVET_O0502_ISP_CLEANUP + , int predStride = 0 +#endif ); static int getWideAngle ( int width, int height, int predMode ); @@ -163,6 +181,10 @@ public: void xGetLumaRecPixels(const PredictionUnit &pu, CompArea chromaArea); /// set parameters from CU data for accessing intra data void initIntraPatternChType (const CodingUnit &cu, const CompArea &area, const bool forceRefFilterFlag = false); // use forceRefFilterFlag to get both filtered and unfiltered buffers +#if JVET_O0502_ISP_CLEANUP + void initIntraPatternChTypeISP (const CodingUnit& cu, const CompArea& area, PelBuf& piReco, const bool forceRefFilterFlag = false); // use forceRefFilterFlag to get both filtered and unfiltered buffers + const PelBuf& getISPBuffer () { return m_pelBufISP[m_ipaParam.refFilterFlag ? PRED_BUF_FILTERED : PRED_BUF_UNFILTERED]; } +#endif // Matrix-based intra prediction void initIntraMip (const PredictionUnit &pu); diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp index 309c0131927d1487f22db65ebfdccc99fac58753..8ce43b547e7458e737df6e740bc0aaee895a5e2b 100644 --- a/source/Lib/CommonLib/LoopFilter.cpp +++ b/source/Lib/CommonLib/LoopFilter.cpp @@ -1300,6 +1300,10 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed const int chromaQPOffset = pps.getQpOffset( ComponentID( chromaIdx + 1 ) ); Pel* piTmpSrcChroma = (chromaIdx == 0) ? piTmpSrcCb : piTmpSrcCr; +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + int iQP = sps.getMappedChromaQpValue(ComponentID(chromaIdx + 1), ((cuP.qp + cuQ.qp + 1) >> 1)); + iQP = Clip3(0, MAX_QP, iQP + chromaQPOffset); +#else int iQP = ( ( cuP.qp + cuQ.qp + 1 ) >> 1 ) + chromaQPOffset; if (iQP >= chromaQPMappingTableSize) { @@ -1316,6 +1320,7 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed { iQP = getScaledChromaQP(iQP, sps.getChromaFormatIdc()); } +#endif const int iIndexTC = Clip3<int>(0, MAX_QP + DEFAULT_INTRA_TC_OFFSET, iQP + DEFAULT_INTRA_TC_OFFSET * (bS[chromaIdx] - 1) + (tcOffsetDiv2 << 1)); #if JVET_O0159_10BITTCTABLE_DEBLOCKING diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp index b3e3d9f9b588d2d0366592c1a5dc553c4b3977ae..a32727d252c738d8f5f1874d7b631bc489735548 100644 --- a/source/Lib/CommonLib/Picture.cpp +++ b/source/Lib/CommonLib/Picture.cpp @@ -961,7 +961,11 @@ Slice *Picture::swapSliceObject(Slice * p, uint32_t i) slices[i] = p; pTmp->setSPS(0); pTmp->setPPS(0); +#if JVET_O_MAX_NUM_ALF_APS_8 + memset(pTmp->getAlfAPSs(), 0, sizeof(*pTmp->getAlfAPSs())*ALF_CTB_MAX_NUM_APS); +#else memset(pTmp->getAlfAPSs(), 0, sizeof(*pTmp->getAlfAPSs())*MAX_NUM_APS); +#endif pTmp->setLmcsAPS(0); return pTmp; diff --git a/source/Lib/CommonLib/Quant.cpp b/source/Lib/CommonLib/Quant.cpp index 71ca554f0148e2ad52516b588d51bfb7591be9d3..f3adf0b586ba6861774d9e82b3af2edc10fc0bac 100644 --- a/source/Lib/CommonLib/Quant.cpp +++ b/source/Lib/CommonLib/Quant.cpp @@ -63,23 +63,39 @@ // ==================================================================================================================== QpParam::QpParam(const int qpy, +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + const ComponentID compID, +#else const ChannelType chType, +#endif const int qpBdOffset, #if JVET_O0919_TS_MIN_QP const int minQpPrimeTsMinus4, #endif const int chromaQPOffset, const ChromaFormat chFmt, - const int dqp ) + const int dqp +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + , const SPS *sps +#endif +) { int baseQp; - +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + if (isLuma(compID)) +#else if(isLuma(chType)) +#endif { baseQp = qpy + qpBdOffset; } else { +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + int qpi = Clip3(-qpBdOffset, MAX_QP, qpy); + baseQp = sps->getMappedChromaQpValue(compID, qpi); + baseQp = Clip3(-qpBdOffset, MAX_QP, baseQp + chromaQPOffset) + qpBdOffset; +#else baseQp = Clip3( -qpBdOffset, (chromaQPMappingTableSize - 1), qpy + chromaQPOffset ); if(baseQp < 0) @@ -90,6 +106,7 @@ QpParam::QpParam(const int qpy, { baseQp = getScaledChromaQP(baseQp, chFmt) + qpBdOffset; } +#endif } baseQp = Clip3( 0, MAX_QP+qpBdOffset, baseQp + dqp ); @@ -100,8 +117,11 @@ QpParam::QpParam(const int qpy, rems[0]=baseQp%6; int baseQpTS = baseQp; - +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + if (isLuma(compID)) +#else if( isLuma( chType ) ) +#endif { baseQpTS = std::max(baseQpTS , 4 + minQpPrimeTsMinus4); } @@ -147,10 +167,23 @@ QpParam::QpParam(const TransformUnit& tu, const ComponentID &compIDX, const int int dqp = 0; #if JVET_O0919_TS_MIN_QP +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + *this = QpParam(QP <= -MAX_INT ? tu.cu->qp : QP, compID, tu.cs->sps->getQpBDOffset(toChannelType(compID)), tu.cs->sps->getMinQpPrimeTsMinus4(toChannelType(compID)), chromaQpOffset, tu.chromaFormat, dqp, tu.cs->sps); +#else *this = QpParam(QP <= -MAX_INT ? tu.cu->qp : QP, toChannelType(compID), tu.cs->sps->getQpBDOffset(toChannelType(compID)), tu.cs->sps->getMinQpPrimeTsMinus4(toChannelType(compID)), chromaQpOffset, tu.chromaFormat, dqp); +#endif +#else +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE +#if JVET_O0105_ICT + const bool useJQP = isChroma(compID) && (abs(TU::getICTMode(tu)) == 2); +#else + const bool useJQP = isChroma(compID) && tu.jointCbCr; +#endif + *this = QpParam(QP <= -MAX_INT ? tu.cu->qp : QP, useJQP ? JOINT_CbCr : compID, tu.cs->sps->getQpBDOffset(toChannelType(compID)), chromaQpOffset, tu.chromaFormat, dqp, tu.cs->sps); #else *this = QpParam(QP <= -MAX_INT ? tu.cu->qp : QP, toChannelType(compID), tu.cs->sps->getQpBDOffset(toChannelType(compID)), chromaQpOffset, tu.chromaFormat, dqp); #endif +#endif } diff --git a/source/Lib/CommonLib/Quant.h b/source/Lib/CommonLib/Quant.h index 16eba76cbc871781b021e5b6ebfe1909bc67c25f..eb36a1a4f80646d4731ba686f75a31f5eed9c622 100644 --- a/source/Lib/CommonLib/Quant.h +++ b/source/Lib/CommonLib/Quant.h @@ -84,14 +84,22 @@ struct QpParam private: QpParam(const int qpy, +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + const ComponentID compID, +#else const ChannelType chType, +#endif const int qpBdOffset, #if JVET_O0919_TS_MIN_QP const int minQpPrimeTsMinus4, #endif const int chromaQPOffset, const ChromaFormat chFmt, - const int dqp ); + const int dqp +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + , const SPS *sps +#endif + ); public: diff --git a/source/Lib/CommonLib/Reshape.cpp b/source/Lib/CommonLib/Reshape.cpp index f404313a2143b17f73b235761f96d2ba0a8944d7..754af0b4573ddb3671c04e508683f9e01c1e80f9 100644 --- a/source/Lib/CommonLib/Reshape.cpp +++ b/source/Lib/CommonLib/Reshape.cpp @@ -49,13 +49,15 @@ // ==================================================================================================================== Reshape::Reshape() -{ - m_CTUFlag = false; - m_recReshaped = false; - m_reshape = true; +: m_CTUFlag (false) +, m_recReshaped (false) +, m_reshape (true) #if JVET_O1109_UNFIY_CRS - m_chromaScale = (1 << CSCALE_FP_PREC); +, m_chromaScale (1 << CSCALE_FP_PREC) #endif +, m_vpduX (-1) +, m_vpduY (-1) +{ } Reshape::~Reshape() diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp index f36a0692a98f74013c8e870a53dc988647a330c4..c6895b6e2d611312566f195431651cd9b980147e 100644 --- a/source/Lib/CommonLib/Rom.cpp +++ b/source/Lib/CommonLib/Rom.cpp @@ -544,7 +544,7 @@ const int g_invQuantScales[2][SCALING_LIST_REM_NUM] = // can be represented as a //-------------------------------------------------------------------------------------------------- //coefficients //-------------------------------------------------------------------------------------------------- - +#if !JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE const uint8_t g_aucChromaScale[NUM_CHROMA_FORMAT][chromaQPMappingTableSize] = { //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69 @@ -553,7 +553,7 @@ const uint8_t g_aucChromaScale[NUM_CHROMA_FORMAT][chromaQPMappingTableSize] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,63,63,63,63,63,63 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,63,63,63,63,63,63 } }; - +#endif // ==================================================================================================================== // Intra prediction // ==================================================================================================================== diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h index 7303299f15115ebbb7c97a176abb8a42cecb153a..1dc86ce08a62f22a60a4ed7e612b547a6e415ddb 100644 --- a/source/Lib/CommonLib/Rom.h +++ b/source/Lib/CommonLib/Rom.h @@ -83,14 +83,14 @@ extern const uint8_t g_intraMode65to33AngMapping[NUM_INTRA_MODE]; extern const uint8_t g_mapMipToAngular65[3][MAX_NUM_MIP_MODE]; extern const uint8_t g_mapAngular33ToMip[3][35]; extern const int g_sortedMipMpms [3][NUM_MPM_MIP]; - +#if !JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE // ==================================================================================================================== // Luma QP to Chroma QP mapping // ==================================================================================================================== static const int chromaQPMappingTableSize = (MAX_QP + 7); extern const uint8_t g_aucChromaScale[NUM_CHROMA_FORMAT][chromaQPMappingTableSize]; - +#endif // ==================================================================================================================== // Scanning order & context mapping table diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 193da424023941630c2901263cbf059bd83c87e5..2404f16821df58912232b775e2dd1a19a4a8b6dc 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -82,6 +82,9 @@ Slice::Slice() , m_maxNumMergeCand ( 0 ) , m_maxNumAffineMergeCand ( 0 ) , m_maxNumTriangleCand ( 0 ) +#if JVET_O0455_IBC_MAX_MERGE_NUM +, m_maxNumIBCMergeCand ( 0 ) +#endif , m_disFracMMVD ( false ) #if JVET_O1140_SLICE_DISABLE_BDOF_DMVR_FLAG , m_disBdofDmvrFlag ( false ) @@ -192,6 +195,9 @@ void Slice::initSlice() m_maxNumMergeCand = MRG_MAX_NUM_CANDS; m_maxNumAffineMergeCand = AFFINE_MRG_MAX_NUM_CANDS; +#if JVET_O0455_IBC_MAX_MERGE_NUM + m_maxNumIBCMergeCand = IBC_MRG_MAX_NUM_CANDS; +#endif m_bFinalized=false; @@ -703,6 +709,9 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll) m_maxNumMergeCand = pSrc->m_maxNumMergeCand; m_maxNumAffineMergeCand = pSrc->m_maxNumAffineMergeCand; m_maxNumTriangleCand = pSrc->m_maxNumTriangleCand; +#if JVET_O0455_IBC_MAX_MERGE_NUM + m_maxNumIBCMergeCand = pSrc->m_maxNumIBCMergeCand; +#endif m_disFracMMVD = pSrc->m_disFracMMVD; #if JVET_O1140_SLICE_DISABLE_BDOF_DMVR_FLAG m_disBdofDmvrFlag = pSrc->m_disBdofDmvrFlag; @@ -1411,6 +1420,9 @@ SPS::SPS() , m_transformSkipEnabledFlag (false) , m_BDPCMEnabledFlag (false) #endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG +, m_JointCbCrEnabledFlag (false) +#endif , m_bPCMFilterDisableFlag (false) , m_sbtmvpEnabledFlag (false) , m_bdofEnabledFlag (false) @@ -1502,6 +1514,62 @@ void SPS::createRPLList1(int numRPL) const int SPS::m_winUnitX[]={1,2,2,1}; const int SPS::m_winUnitY[]={1,2,1,1}; +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE +void ChromaQpMappingTable::setParams(const ChromaQpMappingTableParams ¶ms, const int qpBdOffset) +{ + m_qpBdOffset = qpBdOffset; + m_sameCQPTableForAllChromaFlag = params.m_sameCQPTableForAllChromaFlag; + for (int i = 0; i < MAX_NUM_CQP_MAPPING_TABLES; i++) + { + m_numPtsInCQPTableMinus1[i] = params.m_numPtsInCQPTableMinus1[i]; + m_deltaQpInValMinus1[i] = params.m_deltaQpInValMinus1[i]; + m_deltaQpOutVal[i] = params.m_deltaQpOutVal[i]; + } +} +void ChromaQpMappingTable::derivedChromaQPMappingTables() +{ + for (int i = 0; i < (getSameCQPTableForAllChromaFlag() ? 1 : 3); i++) + { + const int qpBdOffsetC = m_qpBdOffset; + const int numPtsInCQPTableMinus1 = getNumPtsInCQPTableMinus1(i); + std::vector<int> qpInVal(numPtsInCQPTableMinus1 + 1), qpOutVal(numPtsInCQPTableMinus1 + 1); + + qpInVal[0] = -qpBdOffsetC + getDeltaQpInValMinus1(i, 0); + qpOutVal[0] = -qpBdOffsetC + getDeltaQpOutVal(i, 0); + for (int j = 1; j <= getNumPtsInCQPTableMinus1(i); j++) + { + qpInVal[j] = qpInVal[j - 1] + getDeltaQpInValMinus1(i, j) + 1; + qpOutVal[j] = qpOutVal[j - 1] + getDeltaQpOutVal(i, j); + } + + for (int j = 0; j <= getNumPtsInCQPTableMinus1(i); j++) + { + CHECK(qpInVal[j] < -qpBdOffsetC || qpInVal[j] > MAX_QP, "qpInVal out of range"); + CHECK(qpOutVal[j] < -qpBdOffsetC || qpOutVal[j] > MAX_QP, "qpOutVal out of range"); + } + + m_chromaQpMappingTables[i][qpInVal[0]] = qpOutVal[0]; + for (int k = qpInVal[0] - 1; k >= -qpBdOffsetC; k--) + { + m_chromaQpMappingTables[i][k] = Clip3(-qpBdOffsetC, MAX_QP, m_chromaQpMappingTables[i][k + 1] - 1); + } + for (int j = 0; j < numPtsInCQPTableMinus1; j++) + { + int sh = (getDeltaQpInValMinus1(i, j + 1) + 1 + 1) >> 1; + for (int k = qpInVal[j] + 1, m = 1; k <= qpInVal[j + 1]; k++, m++) + { + m_chromaQpMappingTables[i][k] = m_chromaQpMappingTables[i][qpInVal[j]] + + (getDeltaQpOutVal(i, j + 1) * m + sh) / (getDeltaQpInValMinus1(i, j + 1) + 1); + } + } + for (int k = qpInVal[numPtsInCQPTableMinus1]+1; k <= MAX_QP; k++) + { + m_chromaQpMappingTables[i][k] = Clip3(-qpBdOffsetC, MAX_QP, m_chromaQpMappingTables[i][k - 1] + 1); + } + } +} +#endif + PPSRExt::PPSRExt() : m_log2MaxTransformSkipBlockSize (2) , m_crossComponentPredictionEnabledFlag(false) diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index c6517b756d4b0ac8d25328ae54524bcb99e308bd..bf8fa59fd884f8ffdcff9dffe16b26f7b4e71862 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -208,6 +208,9 @@ class ConstraintInfo bool m_noTransformSkipConstraintFlag; #if JVET_O1136_TS_BDPCM_SIGNALLING bool m_noBDPCMConstraintFlag; +#endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + bool m_noJointCbCrConstraintFlag; #endif bool m_noQpDeltaConstraintFlag; bool m_noDepQuantConstraintFlag; @@ -246,6 +249,9 @@ public: , m_noTransformSkipConstraintFlag(false) #if JVET_O1136_TS_BDPCM_SIGNALLING , m_noBDPCMConstraintFlag (false) +#endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + , m_noJointCbCrConstraintFlag (false) #endif , m_noQpDeltaConstraintFlag (false) , m_noDepQuantConstraintFlag (false) @@ -287,6 +293,10 @@ public: void setNoSaoConstraintFlag(bool bVal) { m_noSaoConstraintFlag = bVal; } bool getNoAlfConstraintFlag() const { return m_noAlfConstraintFlag; } void setNoAlfConstraintFlag(bool bVal) { m_noAlfConstraintFlag = bVal; } +#if JVET_O0376_SPS_JOINTCBCR_FLAG + bool getNoJointCbCrConstraintFlag() const { return m_noJointCbCrConstraintFlag; } + void setNoJointCbCrConstraintFlag(bool bVal) { m_noJointCbCrConstraintFlag = bVal; } +#endif bool getNoPcmConstraintFlag() const { return m_noPcmConstraintFlag; } void setNoPcmConstraintFlag(bool bVal) { m_noPcmConstraintFlag = bVal; } bool getNoRefWraparoundConstraintFlag() const { return m_noRefWraparoundConstraintFlag; } @@ -431,8 +441,43 @@ struct ChromaQpAdj #endif } u; }; +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE +struct ChromaQpMappingTableParams { + int m_qpBdOffset; + bool m_sameCQPTableForAllChromaFlag; + int m_numPtsInCQPTableMinus1[MAX_NUM_CQP_MAPPING_TABLES]; + std::vector<int> m_deltaQpInValMinus1[MAX_NUM_CQP_MAPPING_TABLES]; + std::vector<int> m_deltaQpOutVal[MAX_NUM_CQP_MAPPING_TABLES]; + + ChromaQpMappingTableParams() + { + m_qpBdOffset = 12; + m_sameCQPTableForAllChromaFlag = true; + m_numPtsInCQPTableMinus1[0] = 0; + m_deltaQpInValMinus1[0] = { 0 }; + m_deltaQpOutVal[0] = { 0 }; + } + void setSameCQPTableForAllChromaFlag(bool b) { m_sameCQPTableForAllChromaFlag = b; } + bool getSameCQPTableForAllChromaFlag() const { return m_sameCQPTableForAllChromaFlag; } + void setNumPtsInCQPTableMinus1(int tableIdx, int n) { m_numPtsInCQPTableMinus1[tableIdx] = n; } + int getNumPtsInCQPTableMinus1(int tableIdx) const { return m_numPtsInCQPTableMinus1[tableIdx]; } + void setDeltaQpInValMinus1(int tableIdx, std::vector<int> &inVals) { m_deltaQpInValMinus1[tableIdx] = inVals; } + void setDeltaQpInValMinus1(int tableIdx, int idx, int n) { m_deltaQpInValMinus1[tableIdx][idx] = n; } + int getDeltaQpInValMinus1(int tableIdx, int idx) const { return m_deltaQpInValMinus1[tableIdx][idx]; } + void setDeltaQpOutVal(int tableIdx, std::vector<int> &outVals) { m_deltaQpOutVal[tableIdx] = outVals; } + void setDeltaQpOutVal(int tableIdx, int idx, int n) { m_deltaQpOutVal[tableIdx][idx] = n; } + int getDeltaQpOutVal(int tableIdx, int idx) const { return m_deltaQpOutVal[tableIdx][idx]; } +}; +struct ChromaQpMappingTable : ChromaQpMappingTableParams +{ + std::map<int, int> m_chromaQpMappingTables[MAX_NUM_CQP_MAPPING_TABLES]; + int getMappedChromaQpValue(ComponentID compID, const int qpVal) const { return m_chromaQpMappingTables[m_sameCQPTableForAllChromaFlag ? 0 : (int)compID - 1].at(qpVal); } + void derivedChromaQPMappingTables(); + void setParams(const ChromaQpMappingTableParams ¶ms, const int qpBdOffset); +}; +#endif class DPS { private: @@ -734,7 +779,9 @@ private: bool m_transformSkipEnabledFlag; bool m_BDPCMEnabledFlag; #endif - +#if JVET_O0376_SPS_JOINTCBCR_FLAG + bool m_JointCbCrEnabledFlag; +#endif // Parameter BitDepths m_bitDepths; int m_qpBDOffset[MAX_NUM_CHANNEL_TYPE]; @@ -819,6 +866,9 @@ private: int m_LadfIntervalLowerBound[MAX_LADF_INTERVALS]; #endif bool m_MIP; +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + ChromaQpMappingTable m_chromaQpMappingTable; +#endif public: @@ -955,7 +1005,10 @@ public: bool getALFEnabledFlag() const { return m_alfEnabledFlag; } void setALFEnabledFlag( bool b ) { m_alfEnabledFlag = b; } - +#if JVET_O0376_SPS_JOINTCBCR_FLAG + void setJointCbCrEnabledFlag(bool bVal) { m_JointCbCrEnabledFlag = bVal; } + bool getJointCbCrEnabledFlag() const { return m_JointCbCrEnabledFlag; } +#endif bool getSBTMVPEnabledFlag() const { return m_sbtmvpEnabledFlag; } void setSBTMVPEnabledFlag(bool b) { m_sbtmvpEnabledFlag = b; } @@ -1085,6 +1138,12 @@ public: void setUseWP ( bool b ) { m_useWeightPred = b; } void setUseWPBiPred ( bool b ) { m_useWeightedBiPred = b; } #endif +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + void setChromaQpMappingTableFromParams(const ChromaQpMappingTableParams ¶ms, const int qpBdOffset) { m_chromaQpMappingTable.setParams(params, qpBdOffset); } + void derivedChromaQPMappingTables() { m_chromaQpMappingTable.derivedChromaQPMappingTables(); } + const ChromaQpMappingTable& getChromaQpMappingTable() const { return m_chromaQpMappingTable;} + int getMappedChromaQpValue(ComponentID compID, int qpVal) const { return m_chromaQpMappingTable.getMappedChromaQpValue(compID, qpVal); } +#endif }; @@ -1522,6 +1581,9 @@ private: uint32_t m_maxNumMergeCand; uint32_t m_maxNumAffineMergeCand; uint32_t m_maxNumTriangleCand; +#if JVET_O0455_IBC_MAX_MERGE_NUM + uint32_t m_maxNumIBCMergeCand; +#endif bool m_disFracMMVD; #if JVET_O1140_SLICE_DISABLE_BDOF_DMVR_FLAG bool m_disBdofDmvrFlag; @@ -1580,7 +1642,11 @@ private: uint32_t m_uiMaxTTSizeIChroma; uint32_t m_uiMaxBTSize; +#if JVET_O_MAX_NUM_ALF_APS_8 + APS* m_alfApss[ALF_CTB_MAX_NUM_APS]; +#else APS* m_alfApss[MAX_NUM_APS]; +#endif bool m_tileGroupAlfEnabledFlag[MAX_NUM_COMPONENT]; int m_tileGroupNumAps; std::vector<int> m_tileGroupLumaApsId; @@ -1771,6 +1837,10 @@ public: uint32_t getMaxNumAffineMergeCand() const { return m_maxNumAffineMergeCand; } void setMaxNumTriangleCand(uint32_t val) { m_maxNumTriangleCand = val;} uint32_t getMaxNumTriangleCand() const { return m_maxNumTriangleCand;} +#if JVET_O0455_IBC_MAX_MERGE_NUM + void setMaxNumIBCMergeCand( uint32_t val ) { m_maxNumIBCMergeCand = val; } + uint32_t getMaxNumIBCMergeCand() const { return m_maxNumIBCMergeCand; } +#endif void setDisFracMMVD( bool val ) { m_disFracMMVD = val; } bool getDisFracMMVD() const { return m_disFracMMVD; } #if JVET_O1140_SLICE_DISABLE_BDOF_DMVR_FLAG @@ -2089,7 +2159,11 @@ protected: ParameterSetMap<APS> m_apsMap; ParameterSetMap<DPS> m_dpsMap; +#if JVET_O_MAX_NUM_ALF_APS_8 + APS* m_apss[ALF_CTB_MAX_NUM_APS]; +#else APS* m_apss[MAX_NUM_APS]; +#endif int m_activeDPSId; // -1 for nothing active int m_activeSPSId; // -1 for nothing active diff --git a/source/Lib/CommonLib/TrQuant.cpp b/source/Lib/CommonLib/TrQuant.cpp index d45791d5d0dc44ec8d24bd8292d3c2fbc87faf4a..ddf049944672ecf852292f6b0c0ecdcf9e154ea2 100644 --- a/source/Lib/CommonLib/TrQuant.cpp +++ b/source/Lib/CommonLib/TrQuant.cpp @@ -1056,7 +1056,11 @@ void TrQuant::xQuant(TransformUnit &tu, const ComponentID &compID, const CCoeffB m_quant->quant( tu, compID, pSrc, uiAbsSum, cQP, ctx ); } +#if JVET_O0502_ISP_CLEANUP +void TrQuant::transformNxN( TransformUnit& tu, const ComponentID& compID, const QpParam& cQP, std::vector<TrMode>* trModes, const int maxCand ) +#else void TrQuant::transformNxN( TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, std::vector<TrMode>* trModes, const int maxCand, double* diagRatio, double* horVerRatio ) +#endif { CodingStructure &cs = *tu.cs; const CompArea &rect = tu.blocks[compID]; @@ -1111,9 +1115,11 @@ void TrQuant::transformNxN( TransformUnit &tu, const ComponentID &compID, const it++; } +#if !JVET_O0502_ISP_CLEANUP // it gets the distribution of the DCT-II coefficients energy, which will be useful to discard ISP tests CoeffBuf coeffsDCT( m_mtsCoeffs[0], rect ); xGetCoeffEnergy( tu, compID, coeffsDCT, diagRatio, horVerRatio ); +#endif int numTests = 0; std::vector<TrCost>::iterator itC = trCosts.begin(); const double fac = facBB[g_aucLog2[std::max(width, height)]-2]; @@ -1128,7 +1134,11 @@ void TrQuant::transformNxN( TransformUnit &tu, const ComponentID &compID, const } } +#if JVET_O0502_ISP_CLEANUP +void TrQuant::transformNxN( TransformUnit& tu, const ComponentID& compID, const QpParam& cQP, TCoeff& uiAbsSum, const Ctx& ctx, const bool loadTr ) +#else void TrQuant::transformNxN( TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx, const bool loadTr, double* diagRatio, double* horVerRatio ) +#endif { CodingStructure &cs = *tu.cs; const SPS &sps = *cs.sps; @@ -1207,6 +1217,7 @@ void TrQuant::transformNxN( TransformUnit &tu, const ComponentID &compID, const } } +#if !JVET_O0502_ISP_CLEANUP //we do this only with the DCT-II coefficients if( isLuma(compID) && !loadTr && tu.mtsIdx == MTS_DCT2_DCT2 @@ -1215,6 +1226,7 @@ void TrQuant::transformNxN( TransformUnit &tu, const ComponentID &compID, const //it gets the distribution of the coefficients energy, which will be useful to discard ISP tests xGetCoeffEnergy( tu, compID, tempCoeff, diagRatio, horVerRatio ); } +#endif if( sps.getUseLFNST() ) { @@ -1233,6 +1245,7 @@ void TrQuant::transformNxN( TransformUnit &tu, const ComponentID &compID, const TU::setCbfAtDepth (tu, compID, tu.depth, uiAbsSum > 0); } +#if !JVET_O0502_ISP_CLEANUP void TrQuant::xGetCoeffEnergy( TransformUnit &tu, const ComponentID &compID, const CoeffBuf& coeffs, double* diagRatio, double* horVerRatio ) { if( nullptr == diagRatio || nullptr == horVerRatio ) return; @@ -1266,6 +1279,7 @@ void TrQuant::xGetCoeffEnergy( TransformUnit &tu, const ComponentID &compID, con *diagRatio = 0 == wdtE && 0 == hgtE && 0 == diaE ? 1 : double( diaE ) / double( wdtE + hgtE ); } } +#endif void TrQuant::applyForwardRDPCM(TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const RDPCMMode &mode) { diff --git a/source/Lib/CommonLib/TrQuant.h b/source/Lib/CommonLib/TrQuant.h index f762386ac69e657895902d7540923876f41d29bd..ba4e30823bad883025a8d44e28e88d1f239a5d0c 100644 --- a/source/Lib/CommonLib/TrQuant.h +++ b/source/Lib/CommonLib/TrQuant.h @@ -94,9 +94,13 @@ protected: public: void invTransformNxN (TransformUnit &tu, const ComponentID &compID, PelBuf &pResi, const QpParam &cQPs); - +#if JVET_O0502_ISP_CLEANUP + void transformNxN ( TransformUnit& tu, const ComponentID& compID, const QpParam& cQP, std::vector<TrMode>* trModes, const int maxCand ); + void transformNxN ( TransformUnit& tu, const ComponentID& compID, const QpParam& cQP, TCoeff& uiAbsSum, const Ctx& ctx, const bool loadTr = false ); +#else void transformNxN ( TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, std::vector<TrMode>* trModes, const int maxCand, double* diagRatio = nullptr, double* horVerRatio = nullptr ); void transformNxN ( TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const Ctx &ctx, const bool loadTr = false, double* diagRatio = nullptr, double* horVerRatio = nullptr ); +#endif void rdpcmNxN (TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, RDPCMMode &rdpcmMode); void applyForwardRDPCM(TransformUnit &tu, const ComponentID &compID, const QpParam &cQP, TCoeff &uiAbsSum, const RDPCMMode &rdpcmMode); diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 0805c4173eeb90de03af2bff4c3215e4d5de18fe..2f47b2e91688c2b3651f58d05c0d5cf89e1fc96b 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,8 +50,21 @@ #include <assert.h> #include <cassert> + #define JVET_O0119_BASE_PALETTE_444 1 // JVET-O0119: Palette mode in HEVC and palette mode signaling in JVET-N0258. Only enabled for YUV444. +#define JVET_O0304_SIMPLIFIED_BDOF 1 // JVET-O0304: Reduction of number of multiplications in BDOF + +#define JVET_O0455_IBC_MAX_MERGE_NUM 1 // JVET-O0455: Control the max number of IBC merge candidates independently from regular merge candidates + +#define JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE 1 // JVET-O0650: Signal chroma QP mapping tables and move chroma PPS/slice offsets after mapping table + +#define JVET_O0502_ISP_CLEANUP 1 // JVET-O0502: Enable PDPC and all 67 intra modes and apply the cubic filter always (also included in JVET-O0341) for ISP + +#define JVET_O0640_PICTURE_SIZE_CONSTRAINT 1 // JVET-O0640: Picture width and height shall be a multiple of Max(8, minCU size) + +#define JVET_O_MAX_NUM_ALF_APS_8 1 // JVET-O: number of ALF APSs is reduced to 8 + #define JVET_O0070_PROF 1 // JVET-O0070 method 4-2.1a: Prediction refinement with optical flow for affine mode #define JVET_O0570_GRAD_SIMP 1 // JVET-O0570/JVET-O0211, SMID friendly spatial gradient calculation @@ -215,6 +228,8 @@ #define JVET_O0249_MERGE_SYNTAX 1 // JVET-O0249: merge syntax change #define JVET_O0594_BDOF_REF_SAMPLE_PADDING 1 // JVET-O0594/O0252/O0506/O0615/O0624: BDOF reference sample padding using the nearest integer sample position + +#define JVET_O0376_SPS_JOINTCBCR_FLAG 1 // JVET-O0376: add the JointCbCr control flag in SPS #define JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS 1 // JVET-O0472: LFNST index signalling depends on the position of last significant coefficient #define FIX_DB_MAX_TRANSFORM_SIZE 1 @@ -485,7 +500,12 @@ enum ISPType NOT_INTRA_SUBPARTITIONS = 0, HOR_INTRA_SUBPARTITIONS = 1, VER_INTRA_SUBPARTITIONS = 2, +#if JVET_O0502_ISP_CLEANUP + NUM_INTRA_SUBPARTITIONS_MODES = 3, + INTRA_SUBPARTITIONS_RESERVED = 4 +#else NUM_INTRA_SUBPARTITIONS_MODES = 3 +#endif }; enum SbtIdx diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index faa4c2f961c1cd5de9e651a90b1931bd255c5ab7..55da1ffc2535c31f9fa55ffab3d6bbe13b58da8e 100755 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -289,6 +289,7 @@ bool CU::divideTuInRows( const CodingUnit &cu ) return cu.ispMode == HOR_INTRA_SUBPARTITIONS ? true : false; } +#if !JVET_O0502_ISP_CLEANUP bool CU::firstTestISPHorSplit( const int width, const int height, const ComponentID compID, const CodingUnit *cuLeft, const CodingUnit *cuAbove ) { //this function decides which split mode (horizontal or vertical) is tested first (encoder only) @@ -358,6 +359,7 @@ bool CU::firstTestISPHorSplit( const int width, const int height, const Componen return true; } } +#endif PartSplit CU::getISPType( const CodingUnit &cu, const ComponentID compID ) { @@ -439,6 +441,30 @@ uint32_t CU::getISPSplitDim( const int width, const int height, const PartSplit return partitionSize; } +#if JVET_O0502_ISP_CLEANUP +bool CU::allLumaCBFsAreZero(const CodingUnit& cu) +{ + if (!cu.ispMode) + { + return TU::getCbf(*cu.firstTU, COMPONENT_Y) == false; + } + else + { + int numTotalTUs = cu.ispMode == HOR_INTRA_SUBPARTITIONS ? cu.lheight() >> g_aucLog2[cu.firstTU->lheight()] : cu.lwidth() >> g_aucLog2[cu.firstTU->lwidth()]; + TransformUnit* tuPtr = cu.firstTU; + for (int tuIdx = 0; tuIdx < numTotalTUs; tuIdx++) + { + if (TU::getCbf(*tuPtr, COMPONENT_Y) == true) + { + return false; + } + tuPtr = tuPtr->next; + } + return true; + } +} +#endif + PUTraverser CU::traversePUs( CodingUnit& cu ) { @@ -1014,7 +1040,11 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const { const CodingStructure &cs = *pu.cs; const Slice &slice = *pu.cs->slice; +#if JVET_O0455_IBC_MAX_MERGE_NUM + const uint32_t maxNumMergeCand = slice.getMaxNumIBCMergeCand(); +#else const uint32_t maxNumMergeCand = slice.getMaxNumMergeCand(); +#endif const bool canFastExit = pu.cs->pps->getLog2ParallelMergeLevelMinus2() == 0; for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index a7610dd5ea825c92393836186b4c749f3b02af7f..0530ae2dbb4e6348bb7e98e7cd58140e62fe1e72 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -99,13 +99,18 @@ namespace CU bool divideTuInRows ( const CodingUnit &cu ); +#if !JVET_O0502_ISP_CLEANUP bool firstTestISPHorSplit ( const int width, const int height, const ComponentID compID, const CodingUnit *cuLeft = nullptr, const CodingUnit *cuAbove = nullptr ); +#endif PartSplit getISPType ( const CodingUnit &cu, const ComponentID compID ); bool isISPLast ( const CodingUnit &cu, const CompArea &tuArea, const ComponentID compID ); bool isISPFirst ( const CodingUnit &cu, const CompArea &tuArea, const ComponentID compID ); bool canUseISP ( const CodingUnit &cu, const ComponentID compID ); bool canUseISP ( const int width, const int height, const int maxTrSize = MAX_TB_SIZEY ); uint32_t getISPSplitDim ( const int width, const int height, const PartSplit ispType ); +#if JVET_O0502_ISP_CLEANUP + bool allLumaCBFsAreZero ( const CodingUnit& cu ); +#endif PUTraverser traversePUs ( CodingUnit& cu); TUTraverser traverseTUs ( CodingUnit& cu); diff --git a/source/Lib/CommonLib/x86/BufferX86.h b/source/Lib/CommonLib/x86/BufferX86.h index 6e82e3f411a3b3666cc0ec707988be68d023abd2..a09ae89b2110cbaf8b3318b8a6eaf583ae53d222 100644 --- a/source/Lib/CommonLib/x86/BufferX86.h +++ b/source/Lib/CommonLib/x86/BufferX86.h @@ -278,6 +278,62 @@ void addBIOAvg4_SSE(const Pel* src0, int src0Stride, const Pel* src1, int src1St } } +#if JVET_O0304_SIMPLIFIED_BDOF +template< X86_VEXT vext > +void calcBIOSums_SSE(const Pel* srcY0Tmp, const Pel* srcY1Tmp, Pel* gradX0, Pel* gradX1, Pel* gradY0, Pel* gradY1, int xu, int yu, const int src0Stride, const int src1Stride, const int widthG, const int bitDepth, int* sumAbsGX, int* sumAbsGY, int* sumDIX, int* sumDIY, int* sumSignGY_GX) + +{ + int shift4 = std::max<int>(4, (bitDepth - 8)); + int shift5 = std::max<int>(1, (bitDepth - 11)); + + __m128i sumAbsGXTmp = _mm_setzero_si128(); + __m128i sumDIXTmp = _mm_setzero_si128(); + __m128i sumAbsGYTmp = _mm_setzero_si128(); + __m128i sumDIYTmp = _mm_setzero_si128(); + __m128i sumSignGyGxTmp = _mm_setzero_si128(); + Pel tmpStore[8]; + for (int y = 0; y < 6; y++) + { + __m128i shiftSrcY0Tmp = _mm_srai_epi16(_mm_loadu_si128((__m128i*)(srcY0Tmp)), shift4); + __m128i shiftSrcY1Tmp = _mm_srai_epi16(_mm_loadu_si128((__m128i*)(srcY1Tmp)), shift4); + __m128i loadGradX0 = _mm_loadu_si128((__m128i*)(gradX0)); + __m128i loadGradX1 = _mm_loadu_si128((__m128i*)(gradX1)); + __m128i loadGradY0 = _mm_loadu_si128((__m128i*)(gradY0)); + __m128i loadGradY1 = _mm_loadu_si128((__m128i*)(gradY1)); + __m128i subTemp1 = _mm_sub_epi16(shiftSrcY1Tmp, shiftSrcY0Tmp); + __m128i packTempX = _mm_srai_epi16(_mm_add_epi16(loadGradX0, loadGradX1), shift5); + __m128i packTempY = _mm_srai_epi16(_mm_add_epi16(loadGradY0, loadGradY1), shift5); + __m128i gX = _mm_abs_epi16(packTempX); + __m128i gY = _mm_abs_epi16(packTempY); + __m128i dIX = _mm_sign_epi16(subTemp1, packTempX ); + __m128i dIY = _mm_sign_epi16(subTemp1, packTempY ); + __m128i signGY_GX = _mm_sign_epi16(packTempX, packTempY ); + + sumAbsGXTmp = _mm_add_epi16(sumAbsGXTmp, gX); + sumDIXTmp = _mm_add_epi16(sumDIXTmp, dIX); + sumAbsGYTmp = _mm_add_epi16(sumAbsGYTmp, gY); + sumDIYTmp = _mm_add_epi16(sumDIYTmp, dIY); + sumSignGyGxTmp = _mm_add_epi16(sumSignGyGxTmp, signGY_GX); + srcY0Tmp += src0Stride; + srcY1Tmp += src1Stride; + gradX0 += widthG; + gradX1 += widthG; + gradY0 += widthG; + gradY1 += widthG; + } + _mm_storeu_si128((__m128i *)tmpStore, sumAbsGXTmp); + *sumAbsGX = tmpStore[0] + tmpStore[1] + tmpStore[2] + tmpStore[3] + tmpStore[4] + tmpStore[5]; + _mm_storeu_si128((__m128i *)tmpStore, sumAbsGYTmp); + *sumAbsGY = tmpStore[0] + tmpStore[1] + tmpStore[2] + tmpStore[3] + tmpStore[4] + tmpStore[5]; + _mm_storeu_si128((__m128i *)tmpStore, sumDIXTmp); + *sumDIX = tmpStore[0] + tmpStore[1] + tmpStore[2] + tmpStore[3] + tmpStore[4] + tmpStore[5]; + _mm_storeu_si128((__m128i *)tmpStore, sumDIYTmp); + *sumDIY = tmpStore[0] + tmpStore[1] + tmpStore[2] + tmpStore[3] + tmpStore[4] + tmpStore[5]; + _mm_storeu_si128((__m128i *)tmpStore, sumSignGyGxTmp); + *sumSignGY_GX = tmpStore[0] + tmpStore[1] + tmpStore[2] + tmpStore[3] + tmpStore[4] + tmpStore[5]; +} +#endif + #if JVET_O0070_PROF template< X86_VEXT vext > void applyPROF_SSE(Pel* dstPel, int dstStride, const Pel* srcPel, int srcStride, int width, int height, const Pel* gradX, const Pel* gradY, int gradStride, const int* dMvX, const int* dMvY, int dMvStride, int shiftNum, Pel offset, const ClpRng& clpRng) @@ -1184,8 +1240,12 @@ void PelBufferOps::_initPelBufOpsX86() addBIOAvg4 = addBIOAvg4_SSE<vext>; bioGradFilter = gradFilter_SSE<vext>; - calcBIOPar = calcBIOPar_SSE<vext>; +#if !JVET_O0304_SIMPLIFIED_BDOF + calcBIOPar = calcBIOPar_SSE<vext>; calcBlkGradient = calcBlkGradient_SSE<vext>; +#else + calcBIOSums = calcBIOSums_SSE<vext>; +#endif copyBuffer = copyBufferSimd<vext>; padding = paddingSimd<vext>; diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 7621fa18d202b70c55f1001ad21822590daaa0ad..ca63508c569648ad3d13229120c5022a75c68af0 100755 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -1362,7 +1362,11 @@ void CABACReader::intra_luma_pred_modes( CodingUnit &cu ) for( int k = 0; k < numBlocks; k++ ) { CHECK(numBlocks != 1, "not supported yet"); +#if JVET_O0502_ISP_CLEANUP + if ( cu.firstPU->multiRefIdx ) +#else if( cu.firstPU->multiRefIdx || ( cu.ispMode && isLuma( cu.chType ) ) ) +#endif { mpmFlag[0] = true; } @@ -1584,9 +1588,7 @@ void CABACReader::cu_residual( CodingUnit& cu, Partitioner &partitioner, CUCtx& cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; #endif #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS - cuCtx.lastScanPos[COMPONENT_Y ] = -1; - cuCtx.lastScanPos[COMPONENT_Cb] = -1; - cuCtx.lastScanPos[COMPONENT_Cr] = -1; + cuCtx.lfnstLastScanPos = false; #endif ChromaCbfs chromaCbfs; @@ -2399,7 +2401,7 @@ void CABACReader::merge_data( PredictionUnit& pu ) return; } - const bool triangleAvailable = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB(); + const bool triangleAvailable = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB() && pu.cu->cs->slice->getMaxNumTriangleCand() > 1; const bool ciipAvailable = pu.cs->sps->getUseMHIntra() && !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)) @@ -2533,6 +2535,12 @@ void CABACReader::merge_idx( PredictionUnit& pu ) return; } +#if JVET_O0455_IBC_MAX_MERGE_NUM + if (pu.cu->predMode == MODE_IBC) + { + numCandminus1 = int(pu.cs->slice->getMaxNumIBCMergeCand()) - 1; + } +#endif if( numCandminus1 > 0 ) { if( m_BinDecoder.decodeBin( Ctx::MergeIdx() ) ) @@ -3298,6 +3306,13 @@ void CABACReader::cu_chroma_qp_offset( CodingUnit& cu ) #if JVET_O0105_ICT void CABACReader::joint_cb_cr( TransformUnit& tu, const int cbfMask ) { +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if ( !tu.cu->slice->getSPS()->getJointCbCrEnabledFlag() ) + { + return; + } +#endif + #if JVET_O0543_ICT_ICU_ONLY if( ( CU::isIntra( *tu.cu ) && cbfMask ) || ( cbfMask == 3 ) ) #else @@ -3378,7 +3393,8 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID ) #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS if( tu.mtsIdx != MTS_SKIP && tu.blocks[ compID ].height >= 4 && tu.blocks[ compID ].width >= 4 ) { - cuCtx.lastScanPos[compID] = cctx.scanPosLast(); + const int lfnstLastScanPosTh = isLuma( compID ) ? LFNST_LAST_SIG_LUMA : LFNST_LAST_SIG_CHROMA; + cuCtx.lfnstLastScanPos |= cctx.scanPosLast() >= lfnstLastScanPosTh; } #endif // parse subblocks @@ -3546,24 +3562,20 @@ void CABACReader::residual_lfnst_mode( CodingUnit& cu ) #else bool nonZeroCoeffNonTsCorner8x8 = CU::getNumNonZeroCoeffNonTsCorner8x8( cu, lumaFlag, chromaFlag ) > 0; #endif -#if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS - const bool skipLfnst = CS::isDualITree( *cu.cs ) ? ( isLuma( cu.chType ) ? ( cuCtx.lastScanPos[ COMPONENT_Y ] < LFNST_LAST_SIG_LUMA ) : - ( cuCtx.lastScanPos[ COMPONENT_Cb ] < LFNST_LAST_SIG_CHROMA && cuCtx.lastScanPos[ COMPONENT_Cr ] < LFNST_LAST_SIG_CHROMA ) ) : - ( cuCtx.lastScanPos[ COMPONENT_Y ] < LFNST_LAST_SIG_LUMA && cuCtx.lastScanPos[ COMPONENT_Cb ] < LFNST_LAST_SIG_CHROMA && cuCtx.lastScanPos[ COMPONENT_Cr ] < LFNST_LAST_SIG_CHROMA ); -#else +#if !JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS const int nonZeroCoeffThr = CS::isDualITree( *cu.cs ) ? ( isLuma( cu.chType ) ? LFNST_SIG_NZ_LUMA : LFNST_SIG_NZ_CHROMA ) : LFNST_SIG_NZ_LUMA + LFNST_SIG_NZ_CHROMA; nonZeroCoeffNonTs = CU::getNumNonZeroCoeffNonTs( cu, lumaFlag, chromaFlag ) > nonZeroCoeffThr; #endif #if JVET_O0368_LFNST_WITH_DCT2_ONLY const bool isNonDCT2 = (TU::getCbf(*cu.firstTU, ComponentID(COMPONENT_Y)) && cu.firstTU->mtsIdx != MTS_DCT2_DCT2); #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS - if( skipLfnst || nonZeroCoeffNonTsCorner8x8 || isNonDCT2 ) + if( !cuCtx.lfnstLastScanPos || nonZeroCoeffNonTsCorner8x8 || isNonDCT2 ) #else if (!nonZeroCoeffNonTs || nonZeroCoeffNonTsCorner8x8 || isNonDCT2) #endif #else #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS - if( skipLfnst || nonZeroCoeffNonTsCorner8x8 ) + if( !cuCtx.lfnstLastScanPos || nonZeroCoeffNonTsCorner8x8 ) #else if( !nonZeroCoeffNonTs || nonZeroCoeffNonTsCorner8x8 ) #endif diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 2d698114da8bd10f55243b3d2acd8fa9eae16569..5ae1d31d1cf367047c219a18196c530ee65e3b06 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -211,8 +211,39 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID ) const PredictionUnit &pu = *tu.cs->getPU( area.pos(), chType ); const uint32_t uiChFinalMode = PU::getFinalIntraMode( pu, chType ); +#if JVET_O0502_ISP_CLEANUP + PelBuf pReco = cs.getRecoBuf(area); +#endif //===== init availability pattern ===== +#if JVET_O0502_ISP_CLEANUP +#if JVET_O0106_ISP_4xN_PREDREG_FOR_1xN_2xN + bool predRegDiffFromTB = CU::isPredRegDiffFromTB(*tu.cu, compID); + bool firstTBInPredReg = CU::isFirstTBInPredReg(*tu.cu, compID, area); + CompArea areaPredReg(COMPONENT_Y, tu.chromaFormat, area); +#endif + if (tu.cu->ispMode && isLuma(compID)) + { +#if JVET_O0106_ISP_4xN_PREDREG_FOR_1xN_2xN + if (predRegDiffFromTB) + { + if (firstTBInPredReg) + { + CU::adjustPredArea(areaPredReg); + m_pcIntraPred->initIntraPatternChTypeISP(*tu.cu, areaPredReg, pReco); + } + } + else +#endif + { + m_pcIntraPred->initIntraPatternChTypeISP(*tu.cu, area, pReco); + } + } + else + { + m_pcIntraPred->initIntraPatternChType(*tu.cu, area); + } +#else #if JVET_O0106_ISP_4xN_PREDREG_FOR_1xN_2xN bool predRegDiffFromTB = CU::isPredRegDiffFromTB(*tu.cu, compID); bool firstTBInPredReg = CU::isFirstTBInPredReg (*tu.cu, compID, area); @@ -228,6 +259,7 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID ) else #endif m_pcIntraPred->initIntraPatternChType(*tu.cu, area); +#endif //===== get prediction signal ===== if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) ) @@ -330,7 +362,9 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID ) CrossComponentPrediction::crossComponentPrediction( tu, compID, cs.getResiBuf( tu.Y() ), piResi, piResi, true ); } +#if !JVET_O0502_ISP_CLEANUP PelBuf pReco = cs.getRecoBuf( area ); +#endif if( !tu.cu->ispMode || !isLuma( compID ) ) { diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 58538bd8bc46086e2f414ee3398de10563a5bc21..a8b680961d7c05a057bdd5c29dd37484560c3795 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -740,7 +740,11 @@ void DecLib::xActivateParameterSets() if (m_bFirstSliceInPicture) { APS** apss = m_parameterSetManager.getAPSs(); +#if JVET_O_MAX_NUM_ALF_APS_8 + memset(apss, 0, sizeof(*apss) * ALF_CTB_MAX_NUM_APS); +#else memset(apss, 0, sizeof(*apss) * MAX_NUM_APS); +#endif const PPS *pps = m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId()); // this is a temporary PPS object. Do not store this value CHECK(pps == 0, "No PPS present"); @@ -935,7 +939,11 @@ void DecLib::xActivateParameterSets() { EXIT("Error - a new PPS has been decoded while processing a picture"); } +#if JVET_O_MAX_NUM_ALF_APS_8 + for (int i = 0; i < ALF_CTB_MAX_NUM_APS; i++) +#else for (int i = 0; i < MAX_NUM_APS; i++) +#endif { APS* aps = m_parameterSetManager.getAPS(i, ALF_APS); if (aps && m_parameterSetManager.getAPSChangedFlag(i, ALF_APS)) diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 819538ca3a44948e7ea2d5c78d873dec66ab18f5..7e5b0c48a79db3abc46c7e3c8786565bc02bb004 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -1189,6 +1189,12 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_UVLC(uiCode, "log2_min_luma_coding_block_size_minus2"); int log2MinCUSize = uiCode + 2; pcSPS->setLog2MinCodingBlockSize(log2MinCUSize); + +#if JVET_O0640_PICTURE_SIZE_CONSTRAINT + CHECK((pcSPS->getPicWidthInLumaSamples() % (std::max(8, int(pcSPS->getMaxCUWidth() >> (pcSPS->getMaxCodingDepth() - 1))))) != 0, "Coded frame width must be a multiple of Max(8, the minimum unit size)"); + CHECK((pcSPS->getPicHeightInLumaSamples() % (std::max(8, int(pcSPS->getMaxCUHeight() >> (pcSPS->getMaxCodingDepth() - 1))))) != 0, "Coded frame height must be a multiple of Max(8, the minimum unit size)"); +#endif + READ_FLAG(uiCode, "partition_constraints_override_enabled_flag"); pcSPS->setSplitConsOverrideEnabledFlag(uiCode); READ_UVLC(uiCode, "sps_log2_diff_min_qt_min_cb_intra_tile_group_luma"); minQT[0] = 1 << (uiCode + pcSPS->getLog2MinCodingBlockSize()); READ_UVLC(uiCode, "sps_log2_diff_min_qt_min_cb_inter_tile_group"); minQT[1] = 1 << (uiCode + pcSPS->getLog2MinCodingBlockSize()); @@ -1233,10 +1239,35 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_UVLC( uiCode, "log2_max_luma_transform_block_size_minus2" ); pcSPS->setLog2MaxTbSize( uiCode + 2 ); #endif #endif + +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + if (pcSPS->getChromaFormatIdc() != CHROMA_400) + { + ChromaQpMappingTableParams chromaQpMappingTableParams; + READ_FLAG(uiCode, "same_qp_table_for_chroma"); chromaQpMappingTableParams.setSameCQPTableForAllChromaFlag(uiCode); + for (int i = 0; i < (chromaQpMappingTableParams.getSameCQPTableForAllChromaFlag() ? 1 : 3); i++) + { + READ_UVLC(uiCode, "num_points_in_qp_table_minus1"); chromaQpMappingTableParams.setNumPtsInCQPTableMinus1(i,uiCode); + std::vector<int> deltaQpInValMinus1(chromaQpMappingTableParams.getNumPtsInCQPTableMinus1(i) + 1); + std::vector<int> deltaQpOutVal(chromaQpMappingTableParams.getNumPtsInCQPTableMinus1(i) + 1); + for (int j = 0; j <= chromaQpMappingTableParams.getNumPtsInCQPTableMinus1(i); j++) + { + READ_UVLC(uiCode, "delta_qp_in_val_minus1"); deltaQpInValMinus1[j] = uiCode; + READ_UVLC(uiCode, "delta_qp_out_val"); deltaQpOutVal[j] = uiCode; + } + chromaQpMappingTableParams.setDeltaQpInValMinus1(i, deltaQpInValMinus1); + chromaQpMappingTableParams.setDeltaQpOutVal(i, deltaQpOutVal); + } + pcSPS->setChromaQpMappingTableFromParams(chromaQpMappingTableParams, pcSPS->getQpBDOffset(CHANNEL_TYPE_CHROMA)); + pcSPS->derivedChromaQPMappingTables(); + } +#endif + #if JVET_O0244_DELTA_POC READ_FLAG( uiCode, "sps_weighted_pred_flag" ); pcSPS->setUseWP( uiCode ? true : false ); READ_FLAG( uiCode, "sps_weighted_bipred_flag" ); pcSPS->setUseWPBiPred( uiCode ? true : false ); #endif + READ_FLAG( uiCode, "sps_sao_enabled_flag" ); pcSPS->setSAOEnabledFlag ( uiCode ? true : false ); READ_FLAG( uiCode, "sps_alf_enabled_flag" ); pcSPS->setALFEnabledFlag ( uiCode ? true : false ); @@ -1257,7 +1288,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_FLAG(uiCode, "sps_bdpcm_enabled_flag"); pcSPS->setBDPCMEnabledFlag(uiCode ? true : false); } #endif - +#if JVET_O0376_SPS_JOINTCBCR_FLAG + READ_FLAG( uiCode, "sps_joint_cbcr_enabled_flag"); pcSPS->setJointCbCrEnabledFlag (uiCode ? true : false); +#endif if( pcSPS->getCTUSize() + 2*(1 << pcSPS->getLog2MinCodingBlockSize()) <= pcSPS->getPicWidthInLumaSamples() ) { READ_FLAG(uiCode, "sps_ref_wraparound_enabled_flag"); pcSPS->setWrapAroundEnabledFlag( uiCode ? true : false ); @@ -1822,7 +1855,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para if (uiCode) { #if JVET_O0288_UNIFY_ALF_SLICE_TYPE_REMOVAL +#if JVET_O_MAX_NUM_ALF_APS_8 + READ_CODE(3, uiCode, "tile_group_num_APS"); +#else xReadTruncBinCode(uiCode, ALF_CTB_MAX_NUM_APS + 1); +#endif #else if (pcSlice->isIntra()) { @@ -1830,7 +1867,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para } else { +#if JVET_O_MAX_NUM_ALF_APS_8 + READ_CODE(3, uiCode, "tile_group_num_APS"); +#else xReadTruncBinCode(uiCode, ALF_CTB_MAX_NUM_APS + 1); +#endif } #endif int numAps = uiCode; @@ -1838,7 +1879,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para std::vector<int> apsId(numAps, -1); for (int i = 0; i < numAps; i++) { +#if JVET_O_MAX_NUM_ALF_APS_8 + READ_CODE(3, uiCode, "tile_group_aps_id"); +#else READ_CODE(5, uiCode, "tile_group_aps_id"); +#endif apsId[i] = uiCode; } @@ -1859,7 +1904,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para if (alfChromaIdc) { #if JVET_O0288_UNIFY_ALF_SLICE_TYPE_REMOVAL +#if JVET_O_MAX_NUM_ALF_APS_8 + READ_CODE(3, uiCode, "tile_group_aps_id_chroma"); +#else READ_CODE(5, uiCode, "tile_group_aps_id_chroma"); +#endif #else if (pcSlice->isIntra() && pcSlice->getTileGroupNumAps() == 1) { @@ -1867,7 +1916,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para } else { +#if JVET_O_MAX_NUM_ALF_APS_8 + READ_CODE(3, uiCode, "tile_group_aps_id_chroma"); +#else READ_CODE(5, uiCode, "tile_group_aps_id_chroma"); +#endif } #endif pcSlice->setTileGroupApsIdChroma(uiCode); @@ -2065,7 +2118,11 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para } } +#if JVET_O0455_IBC_MAX_MERGE_NUM + if (!pcSlice->isIntra()) +#else if (!pcSlice->isIntra() || sps->getIBCFlag()) +#endif { READ_UVLC(uiCode, "six_minus_max_num_merge_cand"); pcSlice->setMaxNumMergeCand(MRG_MAX_NUM_CANDS - uiCode); @@ -2118,11 +2175,30 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para pcSlice->setMaxNumTriangleCand(0); } } +#if JVET_O0455_IBC_MAX_MERGE_NUM + if (sps->getIBCFlag()) + { + READ_UVLC(uiCode, "six_minus_max_num_ibc_merge_cand"); + pcSlice->setMaxNumIBCMergeCand(IBC_MRG_MAX_NUM_CANDS - uiCode); + } +#endif + #if JVET_O0105_ICT +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if (sps->getJointCbCrEnabledFlag()) + { + READ_FLAG( uiCode, "slice_joint_cbcr_sign_flag" ); pcSlice->setJointCbCrSignFlag(uiCode != 0); + } + else + { + pcSlice->setJointCbCrSignFlag(0); + } +#else if (bChroma) { - READ_FLAG( uiCode, "joint_cb_cr_sign_flag" ); pcSlice->setJointCbCrSignFlag( uiCode != 0 ); + READ_FLAG( uiCode, "slice_joint_cbcr_sign_flag" ); pcSlice->setJointCbCrSignFlag(uiCode != 0); } +#endif #endif READ_SVLC( iCode, "slice_qp_delta" ); @@ -2152,13 +2228,24 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para CHECK( pcSlice->getSliceChromaQpDelta(COMPONENT_Cr) > 12, "Invalid chroma QP offset" ); CHECK( (pps->getQpOffset(COMPONENT_Cr) + pcSlice->getSliceChromaQpDelta(COMPONENT_Cr)) < -12, "Invalid chroma QP offset" ); CHECK( (pps->getQpOffset(COMPONENT_Cr) + pcSlice->getSliceChromaQpDelta(COMPONENT_Cr)) > 12, "Invalid chroma QP offset" ); - - READ_SVLC( iCode, "slice_cb_cr_qp_offset" ); - pcSlice->setSliceChromaQpDelta(JOINT_CbCr, iCode ); - CHECK( pcSlice->getSliceChromaQpDelta(JOINT_CbCr) < -12, "Invalid chroma QP offset" ); - CHECK( pcSlice->getSliceChromaQpDelta(JOINT_CbCr) > 12, "Invalid chroma QP offset" ); - CHECK( (pps->getQpOffset(JOINT_CbCr) + pcSlice->getSliceChromaQpDelta(JOINT_CbCr)) < -12, "Invalid chroma QP offset" ); - CHECK( (pps->getQpOffset(JOINT_CbCr) + pcSlice->getSliceChromaQpDelta(JOINT_CbCr)) > 12, "Invalid chroma QP offset" ); +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if (sps->getJointCbCrEnabledFlag()) + { + READ_SVLC(iCode, "slice_joint_cbcr_qp_offset" ); + pcSlice->setSliceChromaQpDelta(JOINT_CbCr, iCode); + CHECK( pcSlice->getSliceChromaQpDelta(JOINT_CbCr) < -12, "Invalid chroma QP offset"); + CHECK( pcSlice->getSliceChromaQpDelta(JOINT_CbCr) > 12, "Invalid chroma QP offset"); + CHECK( (pps->getQpOffset(JOINT_CbCr) + pcSlice->getSliceChromaQpDelta(JOINT_CbCr)) < -12, "Invalid chroma QP offset"); + CHECK( (pps->getQpOffset(JOINT_CbCr) + pcSlice->getSliceChromaQpDelta(JOINT_CbCr)) > 12, "Invalid chroma QP offset"); + } +#else + READ_SVLC(iCode, "slice_joint_cbcr_qp_offset"); + pcSlice->setSliceChromaQpDelta(JOINT_CbCr, iCode); + CHECK( pcSlice->getSliceChromaQpDelta(JOINT_CbCr) < -12, "Invalid chroma QP offset"); + CHECK( pcSlice->getSliceChromaQpDelta(JOINT_CbCr) > 12, "Invalid chroma QP offset"); + CHECK( (pps->getQpOffset(JOINT_CbCr) + pcSlice->getSliceChromaQpDelta(JOINT_CbCr)) < -12, "Invalid chroma QP offset"); + CHECK( (pps->getQpOffset(JOINT_CbCr) + pcSlice->getSliceChromaQpDelta(JOINT_CbCr)) > 12, "Invalid chroma QP offset"); +#endif } } @@ -2351,6 +2438,10 @@ void HLSyntaxReader::parseConstraintInfo(ConstraintInfo *cinfo) READ_FLAG(symbol, "no_partition_constraints_override_constraint_flag"); cinfo->setNoPartitionConstraintsOverrideConstraintFlag(symbol > 0 ? true : false); READ_FLAG(symbol, "no_sao_constraint_flag"); cinfo->setNoSaoConstraintFlag(symbol > 0 ? true : false); READ_FLAG(symbol, "no_alf_constraint_flag"); cinfo->setNoAlfConstraintFlag(symbol > 0 ? true : false); +#if JVET_O0376_SPS_JOINTCBCR_FLAG + READ_FLAG(symbol, "no_joint_cbcr_constraint_flag"); cinfo->setNoJointCbCrConstraintFlag(symbol > 0 ? true : false); +#endif + READ_FLAG(symbol, "no_pcm_constraint_flag"); cinfo->setNoPcmConstraintFlag(symbol > 0 ? true : false); READ_FLAG(symbol, "no_ref_wraparound_constraint_flag"); cinfo->setNoRefWraparoundConstraintFlag(symbol > 0 ? true : false); READ_FLAG(symbol, "no_temporal_mvp_constraint_flag"); cinfo->setNoTemporalMvpConstraintFlag(symbol > 0 ? true : false); @@ -2816,6 +2907,9 @@ void HLSyntaxReader::alfFilter( AlfParam& alfParam, const bool isChroma ) #else coeff[ind * MAX_NUM_ALF_LUMA_COEFF + i] = alfGolombDecode( kMinTab[alfShape.golombIdx[i]] ); #endif + CHECK( isChroma && + ( coeff[ind * MAX_NUM_ALF_LUMA_COEFF + i] > 127 || coeff[ind * MAX_NUM_ALF_LUMA_COEFF + i] < -127 ) + , "AlfCoeffC shall be in the range of −127 to 127, inclusive" ); } } @@ -2859,6 +2953,8 @@ void HLSyntaxReader::alfFilter( AlfParam& alfParam, const bool isChroma ) } } #endif + CHECK( std::any_of( recCoeff, recCoeff + numFilters * MAX_NUM_ALF_LUMA_COEFF, [](short c) {return (c <-128 || c > 127);} ) + , "AlfCoeffL shall be in the range of −128 to 127, inclusive" ); } #endif diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 71755be775f6768021b9744de9acb46d3e39897a..d6b0d3ad2cf356cb0f4350f59dec0012b92f81a9 100755 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -1103,7 +1103,11 @@ void CABACWriter::intra_luma_pred_modes( const CodingUnit& cu ) break; } } +#if JVET_O0502_ISP_CLEANUP + if ( pu->multiRefIdx ) +#else if( pu->multiRefIdx || ( cu.ispMode && isLuma( cu.chType ) ) ) +#endif { CHECK(mpm_idx >= numMPMs, "use of non-MPM"); } @@ -1203,7 +1207,11 @@ void CABACWriter::intra_luma_pred_mode( const PredictionUnit& pu ) break; } } +#if JVET_O0502_ISP_CLEANUP + if ( pu.multiRefIdx ) +#else if( pu.multiRefIdx || ( pu.cu->ispMode && isLuma( pu.cu->chType ) ) ) +#endif { CHECK(mpm_idx >= numMPMs, "use of non-MPM"); } @@ -1429,9 +1437,7 @@ void CABACWriter::cu_residual( const CodingUnit& cu, Partitioner& partitioner, C cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false; #endif #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS - cuCtx.lastScanPos[COMPONENT_Y ] = -1; - cuCtx.lastScanPos[COMPONENT_Cb] = -1; - cuCtx.lastScanPos[COMPONENT_Cr] = -1; + cuCtx.lfnstLastScanPos = false; #endif #if !JVET_O0596_CBF_SIG_ALIGN_TO_SPEC @@ -2191,7 +2197,7 @@ void CABACWriter::merge_data(const PredictionUnit& pu) merge_idx(pu); return; } - const bool triangleAvailable = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB(); + const bool triangleAvailable = pu.cu->cs->slice->getSPS()->getUseTriangle() && pu.cu->cs->slice->isInterB() && pu.cu->cs->slice->getMaxNumTriangleCand() > 1; const bool ciipAvailable = pu.cs->sps->getUseMHIntra() && !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)) @@ -2368,7 +2374,15 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) encodeOneIdx(candIdx1, maxNumTriangleCand - 2); return; } - int numCandminus1 = int( pu.cs->slice->getMaxNumMergeCand() ) - 1; +#if JVET_O0455_IBC_MAX_MERGE_NUM + int numCandminus1; + if (pu.cu->predMode == MODE_IBC) + numCandminus1 = int(pu.cs->slice->getMaxNumIBCMergeCand()) - 1; + else + numCandminus1 = int(pu.cs->slice->getMaxNumMergeCand()) - 1; +#else + int numCandminus1 = int(pu.cs->slice->getMaxNumMergeCand()) - 1; +#endif if( numCandminus1 > 0 ) { if( pu.mergeIdx == 0 ) @@ -3117,6 +3131,13 @@ void CABACWriter::cu_chroma_qp_offset( const CodingUnit& cu ) #if JVET_O0105_ICT void CABACWriter::joint_cb_cr( const TransformUnit& tu, const int cbfMask ) { +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if ( !tu.cu->slice->getSPS()->getJointCbCrEnabledFlag() ) + { + return; + } +#endif + CHECK( tu.jointCbCr && tu.jointCbCr != cbfMask, "wrong value of jointCbCr (" << (int)tu.jointCbCr << " vs " << (int)cbfMask << ")" ); #if JVET_O0543_ICT_ICU_ONLY if( ( CU::isIntra( *tu.cu ) && cbfMask ) || ( cbfMask == 3 ) ) @@ -3209,7 +3230,8 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID) #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS if( cuCtx && tu.mtsIdx != MTS_SKIP && tu.blocks[ compID ].height >= 4 && tu.blocks[ compID ].width >= 4 ) { - cuCtx->lastScanPos[compID] = cctx.scanPosLast(); + const int lfnstLastScanPosTh = isLuma( compID ) ? LFNST_LAST_SIG_LUMA : LFNST_LAST_SIG_CHROMA; + cuCtx->lfnstLastScanPos |= cctx.scanPosLast() >= lfnstLastScanPosTh; } #endif // code last coeff position @@ -3370,11 +3392,7 @@ void CABACWriter::residual_lfnst_mode( const CodingUnit& cu, CUCtx& cuCtx ) #else bool nonZeroCoeffNonTsCorner8x8 = CU::getNumNonZeroCoeffNonTsCorner8x8( cu, lumaFlag, chromaFlag ) > 0; #endif -#if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS - const bool skipLfnst = CS::isDualITree( *cu.cs ) ? ( isLuma( cu.chType ) ? ( cuCtx.lastScanPos[ COMPONENT_Y ] < LFNST_LAST_SIG_LUMA ) : - ( cuCtx.lastScanPos[ COMPONENT_Cb ] < LFNST_LAST_SIG_CHROMA && cuCtx.lastScanPos[ COMPONENT_Cr ] < LFNST_LAST_SIG_CHROMA ) ) : - ( cuCtx.lastScanPos[ COMPONENT_Y ] < LFNST_LAST_SIG_LUMA && cuCtx.lastScanPos[ COMPONENT_Cb ] < LFNST_LAST_SIG_CHROMA && cuCtx.lastScanPos[ COMPONENT_Cr ] < LFNST_LAST_SIG_CHROMA ); -#else +#if !JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS const int nonZeroCoeffThr = CS::isDualITree( *cu.cs ) ? ( isLuma( cu.chType ) ? LFNST_SIG_NZ_LUMA : LFNST_SIG_NZ_CHROMA ) : LFNST_SIG_NZ_LUMA + LFNST_SIG_NZ_CHROMA; cuCtx.numNonZeroCoeffNonTs = CU::getNumNonZeroCoeffNonTs( cu, lumaFlag, chromaFlag ); nonZeroCoeffNonTs = cuCtx.numNonZeroCoeffNonTs > nonZeroCoeffThr; @@ -3382,13 +3400,13 @@ void CABACWriter::residual_lfnst_mode( const CodingUnit& cu, CUCtx& cuCtx ) #if JVET_O0368_LFNST_WITH_DCT2_ONLY const bool isNonDCT2 = (TU::getCbf(*cu.firstTU, ComponentID(COMPONENT_Y)) && cu.firstTU->mtsIdx != MTS_DCT2_DCT2); #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS - if( skipLfnst || nonZeroCoeffNonTsCorner8x8 || isNonDCT2 ) + if( !cuCtx.lfnstLastScanPos || nonZeroCoeffNonTsCorner8x8 || isNonDCT2 ) #else if (!nonZeroCoeffNonTs || nonZeroCoeffNonTsCorner8x8 || isNonDCT2 ) #endif #else #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS - if( skipLfnst || nonZeroCoeffNonTsCorner8x8 ) + if( !cuCtx.lfnstLastScanPos || nonZeroCoeffNonTsCorner8x8 ) #else if( !nonZeroCoeffNonTs || nonZeroCoeffNonTsCorner8x8 ) #endif diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp index 488b2d768ebc2ee332267273885ca9adad089851..a3c85e561c39afd65f859d1c686060d30ed4b4ab 100644 --- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp +++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp @@ -501,7 +501,11 @@ void EncAdaptiveLoopFilter::create( const EncCfg* encCfg, const int picWidth, co m_diffFilterCoeff[i] = new int[MAX_NUM_ALF_LUMA_COEFF]; } +#if JVET_O_MAX_NUM_ALF_APS_8 + m_apsIdStart = ALF_CTB_MAX_NUM_APS; +#else m_apsIdStart = (int)MAX_NUM_APS; +#endif m_ctbDistortionFixedFilter = new double[m_numCTUsInPic]; for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++) { @@ -654,10 +658,19 @@ void EncAdaptiveLoopFilter::ALFProcess(CodingStructure& cs, const double *lambda { if (cs.slice->getPendingRasInit() || cs.slice->isIDRorBLA()) { +#if JVET_O_MAX_NUM_ALF_APS_8 + memset(cs.slice->getAlfAPSs(), 0, sizeof(*cs.slice->getAlfAPSs())*ALF_CTB_MAX_NUM_APS); + m_apsIdStart = ALF_CTB_MAX_NUM_APS; +#else memset(cs.slice->getAlfAPSs(), 0, sizeof(*cs.slice->getAlfAPSs())*MAX_NUM_APS); m_apsIdStart = (int)MAX_NUM_APS; +#endif m_apsMap->clear(); +#if JVET_O_MAX_NUM_ALF_APS_8 + for (int i = 0; i < ALF_CTB_MAX_NUM_APS; i++) +#else for (int i = 0; i < MAX_NUM_APS; i++) +#endif { APS* alfAPS = m_apsMap->getPS((i << NUM_APS_TYPE_LEN) + ALF_APS); m_apsMap->clearChangedFlag((i << NUM_APS_TYPE_LEN) + ALF_APS); @@ -2966,16 +2979,28 @@ void EncAdaptiveLoopFilter::setCtuEnableFlag( uint8_t** ctuFlags, ChannelType ch std::vector<int> EncAdaptiveLoopFilter::getAvaiApsIdsLuma(CodingStructure& cs, int &newApsId) { APS** apss = cs.slice->getAlfAPSs(); +#if JVET_O_MAX_NUM_ALF_APS_8 + for (int i = 0; i < ALF_CTB_MAX_NUM_APS; i++) +#else for (int i = 0; i < MAX_NUM_APS; i++) +#endif { apss[i] = m_apsMap->getPS((i << NUM_APS_TYPE_LEN) + ALF_APS); } std::vector<int> result; int apsIdChecked = 0, curApsId = m_apsIdStart; +#if JVET_O_MAX_NUM_ALF_APS_8 + if (curApsId < ALF_CTB_MAX_NUM_APS) +#else if (curApsId < int(MAX_NUM_APS)) +#endif { +#if JVET_O_MAX_NUM_ALF_APS_8 + while (apsIdChecked < ALF_CTB_MAX_NUM_APS && !cs.slice->isIntra() && result.size() < ALF_CTB_MAX_NUM_APS && !cs.slice->getPendingRasInit() && !cs.slice->isIDRorBLA()) +#else while (apsIdChecked < MAX_NUM_APS && !cs.slice->isIntra() && result.size() < (ALF_CTB_MAX_NUM_APS - 1) && !cs.slice->getPendingRasInit() && !cs.slice->isIDRorBLA()) +#endif { APS* curAPS = cs.slice->getAlfAPSs()[curApsId]; if (curAPS && curAPS->getTemporalId() <= cs.slice->getTLayer() && curAPS->getAlfAPSParam().newFilterFlag[CHANNEL_TYPE_LUMA]) @@ -2983,7 +3008,11 @@ std::vector<int> EncAdaptiveLoopFilter::getAvaiApsIdsLuma(CodingStructure& cs, i result.push_back(curApsId); } apsIdChecked++; +#if JVET_O_MAX_NUM_ALF_APS_8 + curApsId = (curApsId + 1) % ALF_CTB_MAX_NUM_APS; +#else curApsId = (curApsId + 1) % MAX_NUM_APS; +#endif } } cs.slice->setTileGroupNumAps((int)result.size()); @@ -2991,10 +3020,17 @@ std::vector<int> EncAdaptiveLoopFilter::getAvaiApsIdsLuma(CodingStructure& cs, i newApsId = m_apsIdStart - 1; if (newApsId < 0) { +#if JVET_O_MAX_NUM_ALF_APS_8 + newApsId = ALF_CTB_MAX_NUM_APS - 1; +#else newApsId = (int)MAX_NUM_APS - 1; +#endif } - +#if JVET_O_MAX_NUM_ALF_APS_8 + CHECK(newApsId >= ALF_CTB_MAX_NUM_APS, "Wrong APS index assignment in getAvaiApsIdsLuma"); +#else CHECK(newApsId >= (int)MAX_NUM_APS, "Wrong APS index assignment in getAvaiApsIdsLuma"); +#endif return result; } void EncAdaptiveLoopFilter::initDistortion() @@ -3062,6 +3098,12 @@ void EncAdaptiveLoopFilter::alfEncoderCtb(CodingStructure& cs, AlfParam& alfPar int numIter = useNewFilter ? 2 : 1; for (int numTemporalAps = 0; numTemporalAps <= apsIds.size(); numTemporalAps++) { +#if JVET_O_MAX_NUM_ALF_APS_8 + if (numTemporalAps + useNewFilter >= ALF_CTB_MAX_NUM_APS) + { + continue; + } +#endif cs.slice->setTileGroupNumAps(numTemporalAps + useNewFilter); int numFilterSet = NUM_FIXED_FILTER_SETS + numTemporalAps + useNewFilter; if (numTemporalAps == apsIds.size() && numTemporalAps > 0 && useNewFilter && newApsId == apsIds.back()) //last temporalAPS is occupied by new filter set and this temporal APS becomes unavailable @@ -3072,7 +3114,11 @@ void EncAdaptiveLoopFilter::alfEncoderCtb(CodingStructure& cs, AlfParam& alfPar { m_alfParamTemp = alfParamNewFilters; m_alfParamTemp.enabledFlag[CHANNEL_TYPE_LUMA] = true; +#if JVET_O_MAX_NUM_ALF_APS_8 + double curCost = 3 * m_lambda[CHANNEL_TYPE_LUMA]; +#else double curCost = getTBlength(numTemporalAps + useNewFilter, ALF_CTB_MAX_NUM_APS + 1) * m_lambda[CHANNEL_TYPE_LUMA]; +#endif if (iter > 0) //re-derive new filter-set { double dDistOrgNewFilter = 0; @@ -3232,9 +3278,17 @@ void EncAdaptiveLoopFilter::alfEncoderCtb(CodingStructure& cs, AlfParam& alfPar } } //for(ctbIdx) #if JVET_O0288_UNIFY_ALF_SLICE_TYPE_REMOVAL +#if JVET_O_MAX_NUM_ALF_APS_8 + int tmpBits = bitsNewFilter + 3 * (numFilterSet - NUM_FIXED_FILTER_SETS); +#else int tmpBits = bitsNewFilter + 5 * (numFilterSet - NUM_FIXED_FILTER_SETS) + getTBlength(numFilterSet - NUM_FIXED_FILTER_SETS, ALF_CTB_MAX_NUM_APS + 1); +#endif +#else +#if JVET_O_MAX_NUM_ALF_APS_8 + int tmpBits = bitsNewFilter + 3 * (numFilterSet - NUM_FIXED_FILTER_SETS) + (cs.slice->isIntra() ? 1 : 3); #else int tmpBits = bitsNewFilter + 5 * (numFilterSet - NUM_FIXED_FILTER_SETS) + (cs.slice->isIntra() ? 1 : getTBlength(numFilterSet - NUM_FIXED_FILTER_SETS, ALF_CTB_MAX_NUM_APS + 1)); +#endif #endif curCost += tmpBits * m_lambda[COMPONENT_Y]; if (curCost < costMin) @@ -3334,7 +3388,11 @@ void EncAdaptiveLoopFilter::alfEncoderCtb(CodingStructure& cs, AlfParam& alfPar curId--; if (curId < 0) { +#if JVET_O_MAX_NUM_ALF_APS_8 + curId = ALF_CTB_MAX_NUM_APS - 1; +#else curId = (int)MAX_NUM_APS - 1; +#endif } if (std::find(bestApsIds.begin(), bestApsIds.end(), curId) == bestApsIds.end()) { @@ -3342,7 +3400,11 @@ void EncAdaptiveLoopFilter::alfEncoderCtb(CodingStructure& cs, AlfParam& alfPar } } } +#if JVET_O_MAX_NUM_ALF_APS_8 + for (int curApsId = 0; curApsId < ALF_CTB_MAX_NUM_APS; curApsId++) +#else for (int curApsId = 0; curApsId < MAX_NUM_APS; curApsId++) +#endif { if ((cs.slice->getPendingRasInit() || cs.slice->isIDRorBLA() || cs.slice->isIntra()) && curApsId != newApsIdChroma) { @@ -3350,9 +3412,17 @@ void EncAdaptiveLoopFilter::alfEncoderCtb(CodingStructure& cs, AlfParam& alfPar } APS* curAPS = m_apsMap->getPS((curApsId << NUM_APS_TYPE_LEN) + ALF_APS); #if JVET_O0288_UNIFY_ALF_SLICE_TYPE_REMOVAL +#if JVET_O_MAX_NUM_ALF_APS_8 + double curCost = m_lambda[CHANNEL_TYPE_CHROMA] * 3; +#else double curCost = m_lambda[CHANNEL_TYPE_CHROMA] * 5; +#endif +#else +#if JVET_O_MAX_NUM_ALF_APS_8 + double curCost = (cs.slice->isIntra() && cs.slice->getTileGroupNumAps() == 1) ? 0 : (m_lambda[CHANNEL_TYPE_CHROMA] * 3); #else double curCost = (cs.slice->isIntra() && cs.slice->getTileGroupNumAps() == 1) ? 0 : (m_lambda[CHANNEL_TYPE_CHROMA] * 5); +#endif #endif if (curApsId == newApsIdChroma) { diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 924e81feca44cb0ccbe826eec85c3e054fac51fd..03d0d061258b58838dcdf60b04d67c7932b6bbfa 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -204,6 +204,9 @@ protected: bool m_noTransformSkipConstraintFlag; #if JVET_O1136_TS_BDPCM_SIGNALLING bool m_noBDPCMConstraintFlag; +#endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + bool m_noJointCbCrConstraintFlag; #endif bool m_bNoQpDeltaConstraintFlag; bool m_bNoDepQuantConstraintFlag; @@ -239,6 +242,9 @@ protected: int m_numReorderPics[MAX_TLAYER]; int m_iQP; // if (AdaptiveQP == OFF) +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + ChromaQpMappingTableParams m_chromaQpMappingTableParams; +#endif #if X0038_LAMBDA_FROM_QP_CAPABILITY int m_intraQPOffset; ///< QP offset for intra slice (integer) int m_lambdaFromQPEnable; ///< enable lambda derivation from QP @@ -304,6 +310,9 @@ protected: bool m_RdpcmMode; #if JVET_O0119_BASE_PALETTE_444 unsigned m_PLTMode; +#endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + bool m_JointCbCrMode; #endif unsigned m_IBCMode; unsigned m_IBCLocalSearchRangeX; @@ -562,6 +571,9 @@ protected: uint32_t m_maxNumMergeCand; ///< Maximum number of merge candidates uint32_t m_maxNumAffineMergeCand; ///< Maximum number of affine merge candidates uint32_t m_maxNumTriangleCand; +#if JVET_O0455_IBC_MAX_MERGE_NUM + uint32_t m_maxNumIBCMergeCand; ///< Max number of IBC merge candidates +#endif ScalingListMode m_useScalingListId; ///< Using quantization matrix i.e. 0=off, 1=default, 2=file. std::string m_scalingListFileName; ///< quantization matrix file name int m_TMVPModeId; @@ -712,6 +724,10 @@ public: #if JVET_O1136_TS_BDPCM_SIGNALLING bool getNoBDPCMConstraintFlag() const { return m_noBDPCMConstraintFlag; } void setNoBDPCMConstraintFlag(bool bVal) { m_noBDPCMConstraintFlag = bVal; } +#endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + bool getNoJointCbCrConstraintFlag() const { return m_noJointCbCrConstraintFlag; } + void setNoJointCbCrConstraintFlag(bool bVal) { m_noJointCbCrConstraintFlag = bVal; } #endif bool getNoQpDeltaConstraintFlag() const { return m_bNoQpDeltaConstraintFlag; } void setNoQpDeltaConstraintFlag(bool bVal) { m_bNoQpDeltaConstraintFlag = bVal; } @@ -784,6 +800,10 @@ public: void setIntraQPOffset ( int i ) { m_intraQPOffset = i; } void setLambdaFromQPEnable ( bool b ) { m_lambdaFromQPEnable = b; } #endif +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + void setChromaQpMappingTableParams (const ChromaQpMappingTableParams ¶ms) { m_chromaQpMappingTableParams = params; } +#endif + void setPad ( int* iPad ) { for ( int i = 0; i < 2; i++ ) m_aiPad[i] = iPad[i]; } int getMaxRefPicNum () { return m_iMaxRefPicNum; } @@ -886,6 +906,10 @@ public: #if JVET_O0119_BASE_PALETTE_444 void setPLTMode ( unsigned n) { m_PLTMode = n; } unsigned getPLTMode () const { return m_PLTMode; } +#endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + void setJointCbCr ( bool b ) { m_JointCbCrMode = b; } + bool getJointCbCr () const { return m_JointCbCrMode; } #endif void setIBCMode (unsigned n) { m_IBCMode = n; } unsigned getIBCMode () const { return m_IBCMode; } @@ -1174,6 +1198,10 @@ public: #if JVET_O1136_TS_BDPCM_SIGNALLING bool getUseBDPCM () { return m_useBDPCM; } void setUseBDPCM ( bool b ) { m_useBDPCM = b; } +#endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + bool getUseJointCbCr () { return m_JointCbCrMode; } + void setUseJointCbCr (bool b) { m_JointCbCrMode = b; } #endif bool getPersistentRiceAdaptationEnabledFlag () const { return m_persistentRiceAdaptationEnabledFlag; } void setPersistentRiceAdaptationEnabledFlag (const bool value) { m_persistentRiceAdaptationEnabledFlag = value; } @@ -1416,6 +1444,10 @@ public: uint32_t getMaxNumAffineMergeCand () { return m_maxNumAffineMergeCand; } void setMaxNumTriangleCand ( uint32_t u ) { m_maxNumTriangleCand = u; } uint32_t getMaxNumTriangleCand () { return m_maxNumTriangleCand; } +#if JVET_O0455_IBC_MAX_MERGE_NUM + void setMaxNumIBCMergeCand ( uint32_t u ) { m_maxNumIBCMergeCand = u; } + uint32_t getMaxNumIBCMergeCand () { return m_maxNumIBCMergeCand; } +#endif void setUseScalingListId ( ScalingListMode u ) { m_useScalingListId = u; } ScalingListMode getUseScalingListId () { return m_useScalingListId; } void setScalingListFileName ( const std::string &s ) { m_scalingListFileName = s; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 3304b3e5f1ee226fece3774478ac5e9d8faee9dc..a9f27ffd47693410f4a834034c8a4a4977b86464 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -574,8 +574,15 @@ bool EncCu::xCheckBestMode( CodingStructure *&tempCS, CodingStructure *&bestCS, } +#if JVET_O0502_ISP_CLEANUP +void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& partitioner, double maxCostAllowed ) +#else void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner ) +#endif { +#if JVET_O0502_ISP_CLEANUP + CHECK(maxCostAllowed < 0, "Wrong value of maxCostAllowed!"); +#endif if (m_shareState == NO_SHARE) { tempCS->sharedBndPos = tempCS->area.Y().lumaPos(); @@ -706,6 +713,9 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par } #endif EncTestMode currTestMode = m_modeCtrl->currTestMode(); +#if JVET_O0502_ISP_CLEANUP + currTestMode.maxCostAllowed = maxCostAllowed; +#endif if (pps.getUseDQP() && CS::isDualITree(*tempCS) && isChroma(partitioner.chType)) { @@ -1355,7 +1365,13 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, #if JVET_O0070_PROF tempSubCS->bestParent = bestSubCS->bestParent = bestCS; #endif +#if JVET_O0502_ISP_CLEANUP + double newMaxCostAllowed = isLuma(partitioner.chType) ? std::min(encTestMode.maxCostAllowed, bestCS->cost - m_pcRdCost->calcRdCost(tempCS->fracBits, tempCS->dist)) : MAX_DOUBLE; + newMaxCostAllowed = std::max(0.0, newMaxCostAllowed); + xCompressCU(tempSubCS, bestSubCS, partitioner, newMaxCostAllowed); +#else xCompressCU( tempSubCS, bestSubCS, partitioner ); +#endif #if JVET_O0070_PROF tempSubCS->bestParent = bestSubCS->bestParent = nullptr; #endif @@ -1577,8 +1593,17 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC bool validCandRet = false; if( isLuma( partitioner.chType ) ) { +#if JVET_O0502_ISP_CLEANUP + //ISP uses the value of the best cost so far (luma if it is the fast version) to avoid test non-necessary subpartitions + double bestCostSoFar = CS::isDualITree(*tempCS) ? m_modeCtrl->getBestCostWithoutSplitFlags() : bestCU && bestCU->predMode == MODE_INTRA ? bestCS->lumaCost : bestCS->cost; + if (CS::isDualITree(*tempCS) && encTestMode.maxCostAllowed < bestCostSoFar) + { + bestCostSoFar = encTestMode.maxCostAllowed; + } +#else //the Intra SubPartitions mode uses the value of the best cost so far (luma if it is the fast version) to avoid test non-necessary lines const double bestCostSoFar = CS::isDualITree( *tempCS ) ? m_modeCtrl->getBestCostWithoutSplitFlags() : bestCU && bestCU->predMode == MODE_INTRA ? bestCS->lumaCost : bestCS->cost; +#endif validCandRet = m_pcIntraSearch->estIntraPredLumaQT( cu, partitioner, bestCostSoFar, mtsFlag, startMTSIdx[ trGrpIdx ], endMTSIdx[ trGrpIdx ], ( trGrpIdx > 0 ) ); if( sps.getUseLFNST() && ( !validCandRet || ( cu.ispMode && cu.firstTU->cbf[ COMPONENT_Y ] == 0 ) ) ) { @@ -1667,12 +1692,10 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC // Check if low frequency non-separable transform (LFNST) is too expensive #if JVET_O0472_LFNST_SIGNALLING_LAST_SCAN_POS - const bool skipLfnst = CS::isDualITree( *cu.cs ) ? ( isLuma( cu.chType ) ? ( cuCtx.lastScanPos[ COMPONENT_Y ] < LFNST_LAST_SIG_LUMA ) : - ( cuCtx.lastScanPos[ COMPONENT_Cb ] < LFNST_LAST_SIG_CHROMA && cuCtx.lastScanPos[ COMPONENT_Cr ] < LFNST_LAST_SIG_CHROMA ) ) : - ( cuCtx.lastScanPos[ COMPONENT_Y ] < LFNST_LAST_SIG_LUMA && cuCtx.lastScanPos[ COMPONENT_Cb ] < LFNST_LAST_SIG_CHROMA && cuCtx.lastScanPos[ COMPONENT_Cr ] < LFNST_LAST_SIG_CHROMA ); - if( lfnstIdx && skipLfnst ) + if( lfnstIdx && !cuCtx.lfnstLastScanPos ) { - if( cuCtx.lastScanPos[ COMPONENT_Y ] > -1 || cuCtx.lastScanPos[ COMPONENT_Cb ] > -1 || cuCtx.lastScanPos[ COMPONENT_Cr ] > -1 ) + bool cbfAtZeroDepth = CS::isDualITree( *tempCS ) ? cu.rootCbf : std::min( cu.firstTU->blocks[ 1 ].width, cu.firstTU->blocks[ 1 ].height ) < 4 ? TU::getCbfAtDepth( *cu.firstTU, COMPONENT_Y, 0 ) : cu.rootCbf; + if( cbfAtZeroDepth ) { tempCS->cost = MAX_DOUBLE; } @@ -1739,13 +1762,22 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC } } +#if JVET_O0502_ISP_CLEANUP + //we decide to skip the non-DCT-II transforms and LFNST according to the ISP results + if ((endMtsFlag > 0 || endLfnstIdx > 0) && cu.ispMode && !mtsFlag && !lfnstIdx && tempCS->slice->isIntra() && m_pcEncCfg->getUseFastISP()) +#else //we decide to skip the second emt pass or not according to the ISP results if( considerMtsSecondPass && cu.ispMode && !mtsFlag && tempCS->slice->isIntra() ) +#endif { double bestCostDct2NoIsp = m_modeCtrl->getMtsFirstPassNoIspCost(); CHECKD( bestCostDct2NoIsp <= bestIspCost, "wrong cost!" ); +#if JVET_O0502_ISP_CLEANUP + double threshold = 1.4; +#else double nSamples = ( double ) ( cu.lwidth() << g_aucLog2[ cu.lheight() ] ); double threshold = 1 + 1.4 / sqrt( nSamples ); +#endif double lfnstThreshold = 1.01 * threshold; if( bestCostDct2NoIsp > bestIspCost*lfnstThreshold ) diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h index 29912cc07a8663ce88707bac9130466cbfeabfaa..82bc30422d8ee48587975dc213a98e57757633fd 100644 --- a/source/Lib/EncoderLib/EncCu.h +++ b/source/Lib/EncoderLib/EncCu.h @@ -175,7 +175,11 @@ protected: void xCalDebCost ( CodingStructure &cs, Partitioner &partitioner, bool calDist = false ); Distortion getDistortionDb ( CodingStructure &cs, CPelBuf org, CPelBuf reco, ComponentID compID, const CompArea& compArea, bool afterDb ); +#if JVET_O0502_ISP_CLEANUP + void xCompressCU ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, double maxCostAllowed = MAX_DOUBLE ); +#else void xCompressCU ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm ); +#endif #if ENABLE_SPLIT_PARALLELISM void xCompressCUParallel ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm ); void copyState ( EncCu* other, Partitioner& pm, const UnitArea& currArea, const bool isDist ); diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index c348ae0e23623207e95894ef085a82df0ac29ec8..d710ec005e9c74873396b22f2f4171b61aa0bf0f 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -2092,7 +2092,14 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, // overwrite chroma qp offset for dual tree pcSlice->setSliceChromaQpDelta(COMPONENT_Cb, m_pcCfg->getChromaCbQpOffsetDualTree()); pcSlice->setSliceChromaQpDelta(COMPONENT_Cr, m_pcCfg->getChromaCrQpOffsetDualTree()); - pcSlice->setSliceChromaQpDelta(JOINT_CbCr, m_pcCfg->getChromaCbCrQpOffsetDualTree()); +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if (pcSlice->getSPS()->getJointCbCrEnabledFlag()) + { + pcSlice->setSliceChromaQpDelta(JOINT_CbCr, m_pcCfg->getChromaCbCrQpOffsetDualTree()); + } +#else + pcSlice->setSliceChromaQpDelta(JOINT_CbCr, m_pcCfg->getChromaCbCrQpOffsetDualTree()); +#endif m_pcSliceEncoder->setUpLambda(pcSlice, pcSlice->getLambdas()[0], pcSlice->getSliceQp()); } if (pcSlice->getSPS()->getUseReshaper()) @@ -2494,7 +2501,11 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, if (pcSlice->getSPS()->getALFEnabledFlag() && pcSlice->getTileGroupAlfEnabledFlag(COMPONENT_Y)) { +#if JVET_O_MAX_NUM_ALF_APS_8 + for (int apsId = 0; apsId < ALF_CTB_MAX_NUM_APS; apsId++) +#else for (int apsId = 0; apsId < MAX_NUM_APS; apsId++) //HD: shouldn't this be looping over slice_alf_aps_id_luma[ i ]? By looping over MAX_NUM_APS, it is possible unused ALF APS is written. Please check! +#endif { ParameterSetMap<APS> *apsMap = m_pcEncLib->getApsMap(); @@ -3410,6 +3421,18 @@ void EncGOP::xCalculateAddPSNR(Picture* pcPic, PelUnitBuf cPicD, const AccessUni if (useLumaWPSNR) { msg(NOTICE, " [WY %6.4lf dB WU %6.4lf dB WV %6.4lf dB]", dPSNRWeighted[COMPONENT_Y], dPSNRWeighted[COMPONENT_Cb], dPSNRWeighted[COMPONENT_Cr]); + + if (m_pcEncLib->getPrintHexPsnr()) + { + uint64_t xPsnrWeighted[MAX_NUM_COMPONENT]; + for (int i = 0; i < MAX_NUM_COMPONENT; i++) + { + copy(reinterpret_cast<uint8_t *>(&dPSNRWeighted[i]), + reinterpret_cast<uint8_t *>(&dPSNRWeighted[i]) + sizeof(dPSNRWeighted[i]), + reinterpret_cast<uint8_t *>(&xPsnrWeighted[i])); + } + msg(NOTICE, " [xWY %16" PRIx64 " xWU %16" PRIx64 " xWV %16" PRIx64 "]", xPsnrWeighted[COMPONENT_Y], xPsnrWeighted[COMPONENT_Cb], xPsnrWeighted[COMPONENT_Cr]); + } } #endif msg( NOTICE, " [ET %5.0f ]", dEncTime ); diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index c3fc09a16e01cd7a5b4e35779658396a1fc81bf4..daca183e0847f7c4fdb8d19e513339d9a697d83f 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -872,6 +872,9 @@ void EncLib::xInitSPS(SPS &sps) cinfo->setNoTransformSkipConstraintFlag(m_noTransformSkipConstraintFlag); #if JVET_O1136_TS_BDPCM_SIGNALLING cinfo->setNoBDPCMConstraintFlag(m_noBDPCMConstraintFlag); +#endif +#if JVET_O0376_SPS_JOINTCBCR_FLAG + cinfo->setNoJointCbCrConstraintFlag(m_noJointCbCrConstraintFlag); #endif cinfo->setNoQpDeltaConstraintFlag(m_bNoQpDeltaConstraintFlag); cinfo->setNoDepQuantConstraintFlag(m_bNoDepQuantConstraintFlag); @@ -1000,7 +1003,9 @@ void EncLib::xInitSPS(SPS &sps) #endif sps.setSAOEnabledFlag( m_bUseSAO ); - +#if JVET_O0376_SPS_JOINTCBCR_FLAG + sps.setJointCbCrEnabledFlag( m_JointCbCrMode ); +#endif sps.setMaxTLayers( m_maxTempLayer ); sps.setTemporalIdNestingFlag( ( m_maxTempLayer == 1 ) ? true : false ); @@ -1044,6 +1049,10 @@ void EncLib::xInitSPS(SPS &sps) sps.setLtRefPicPocLsbSps(k, 0); sps.setUsedByCurrPicLtSPSFlag(k, 0); } +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + sps.setChromaQpMappingTableFromParams(m_chromaQpMappingTableParams, sps.getQpBDOffset(CHANNEL_TYPE_CHROMA)); + sps.derivedChromaQPMappingTables(); +#endif #if U0132_TARGET_BITS_SATURATION if( getPictureTimingSEIEnabled() || getDecodingUnitInfoSEIEnabled() || getCpbSaturationEnabled() ) diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h index 4b50555b0d2240d3b7e0038e098b02a5f47f7620..09eaa50d4d436359042ec64f3002938493a4b37f 100644 --- a/source/Lib/EncoderLib/EncLib.h +++ b/source/Lib/EncoderLib/EncLib.h @@ -138,7 +138,11 @@ private: CacheModel m_cacheModel; #endif +#if JVET_O_MAX_NUM_ALF_APS_8 + APS* m_apss[ALF_CTB_MAX_NUM_APS]; +#else APS* m_apss[MAX_NUM_APS]; +#endif APS* m_lmcsAPS; diff --git a/source/Lib/EncoderLib/EncModeCtrl.h b/source/Lib/EncoderLib/EncModeCtrl.h index 3360e87681f649a08d37e3eb0d9910e612012047..9cb8ce809b41cccbdb8eab23ed1bf5733b8ca22a 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.h +++ b/source/Lib/EncoderLib/EncModeCtrl.h @@ -115,6 +115,9 @@ struct EncTestMode EncTestModeOpts opts; int qp; bool lossless; +#if JVET_O0502_ISP_CLEANUP + double maxCostAllowed; +#endif }; diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index c49ab3ea3fc9abcfecf4d22b5291cff9aa5b3e6f..349701bfa8041e81b363c87646fd66648e0b5797 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -117,7 +117,11 @@ EncSlice::setUpLambda( Slice* slice, const double dLambda, int iQP) { const ComponentID compID = ComponentID( compIdx ); int chromaQPOffset = slice->getPPS()->getQpOffset( compID ) + slice->getSliceChromaQpDelta( compID ); +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + int qpc = slice->getSPS()->getMappedChromaQpValue(compID, iQP) + chromaQPOffset; +#else int qpc = ( iQP + chromaQPOffset < 0 ) ? iQP : getScaledChromaQP( iQP + chromaQPOffset, m_pcCfg->getChromaFormatIdc() ); +#endif double tmpWeight = pow( 2.0, ( iQP - qpc ) / 3.0 ); // takes into account of the chroma qp mapping and chroma qp Offset if( m_pcCfg->getDepQuantEnabledFlag() && !( m_pcCfg->getLFNST() ) ) { @@ -296,7 +300,11 @@ static int applyQPAdaptationChroma (Picture* const pcPic, Slice* const pcSlice, savedLumaQP = averageAdaptedLumaQP; } // savedLumaQP < 0 +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + const int lumaChromaMappingDQP = savedLumaQP - pcSlice->getSPS()->getMappedChromaQpValue(compID, savedLumaQP); +#else const int lumaChromaMappingDQP = savedLumaQP - getScaledChromaQP (savedLumaQP, pcEncCfg->getChromaFormatIdc()); +#endif optSliceChromaQpOffset[comp-1] = std::min (3 + lumaChromaMappingDQP, adaptChromaQPOffset + lumaChromaMappingDQP); } @@ -715,6 +723,9 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr rpcSlice->setMaxNumMergeCand ( m_pcCfg->getMaxNumMergeCand() ); rpcSlice->setMaxNumAffineMergeCand( m_pcCfg->getMaxNumAffineMergeCand() ); rpcSlice->setMaxNumTriangleCand ( m_pcCfg->getMaxNumTriangleCand() ); +#if JVET_O0455_IBC_MAX_MERGE_NUM + rpcSlice->setMaxNumIBCMergeCand ( m_pcCfg->getMaxNumIBCMergeCand() ); +#endif rpcSlice->setSplitConsOverrideFlag(false); rpcSlice->setMinQTSize( rpcSlice->getSPS()->getMinQTSize(eSliceType)); rpcSlice->setMaxBTDepth( rpcSlice->isIntra() ? rpcSlice->getSPS()->getMaxBTDepthI() : rpcSlice->getSPS()->getMaxBTDepth() ); @@ -1571,7 +1582,14 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons checkDisFracMmvd( pcPic, startCtuTsAddr, boundingCtuTsAddr ); #if JVET_O0105_ICT - setJointCbCrModes( cs, Position(0, 0), cs.area.lumaSize() ); +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if (pcSlice->getSPS()->getJointCbCrEnabledFlag()) + { + setJointCbCrModes(cs, Position(0, 0), cs.area.lumaSize()); + } +#else + setJointCbCrModes(cs, Position(0, 0), cs.area.lumaSize()); +#endif #endif // for every CTU in the slice segment (may terminate sooner if there is a byte limit on the slice-segment) diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index aa185316bef82966e93cd0a1f7feed517fb2d049..c95bce6643f1a34ef114a6020d06881121a109cb 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -6889,10 +6889,18 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par m_pcTrQuant->setLambda(m_pcTrQuant->getLambda() / (cRescale*cRescale)); } #if JVET_O0105_ICT - if( isChroma( compID ) && tu.cu->cs->slice->getSliceQp() > 18 ) +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if ( sps.getJointCbCrEnabledFlag() && isChroma( compID ) && ( tu.cu->cs->slice->getSliceQp() > 18 ) ) { m_pcTrQuant->setLambda( 1.05 * m_pcTrQuant->getLambda() ); } + +#else + if ( isChroma( compID ) && tu.cu->cs->slice->getSliceQp() > 18 ) + { + m_pcTrQuant->setLambda( 1.05 * m_pcTrQuant->getLambda() ); + } +#endif #endif TCoeff currAbsSum = 0; uint64_t currCompFracBits = 0; @@ -7093,9 +7101,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par { const CompArea& cbArea = tu.blocks[COMPONENT_Cb]; const CompArea& crArea = tu.blocks[COMPONENT_Cr]; - +#if JVET_O0376_SPS_JOINTCBCR_FLAG + bool checkJointCbCr = (sps.getJointCbCrEnabledFlag()) && (!tu.noResidual) && (TU::getCbf(tu, COMPONENT_Cb) || TU::getCbf(tu, COMPONENT_Cr)); +#else bool checkJointCbCr = !tu.noResidual && (TU::getCbf(tu, COMPONENT_Cb) || TU::getCbf(tu, COMPONENT_Cr)); - +#endif #if JVET_O0105_ICT const int channelBitDepth = sps.getBitDepth(toChannelType(COMPONENT_Cb)); bool reshape = slice.getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && slice.getLmcsChromaResidualScaleFlag() @@ -7153,10 +7163,17 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par const int absIct = abs( TU::getICTMode(tu) ); const double lfact = ( absIct == 1 || absIct == 3 ? 0.8 : 0.5 ); m_pcTrQuant->setLambda( lfact * m_pcTrQuant->getLambda() ); - if( tu.cu->cs->slice->getSliceQp() > 18 ) +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if ( checkJointCbCr && (tu.cu->cs->slice->getSliceQp() > 18)) + { + m_pcTrQuant->setLambda( 1.05 * m_pcTrQuant->getLambda() ); + } +#else + if ( tu.cu->cs->slice->getSliceQp() > 18 ) { m_pcTrQuant->setLambda( 1.05 * m_pcTrQuant->getLambda() ); } +#endif #else m_pcTrQuant->setLambda( 0.60 * m_pcTrQuant->getLambda() ); #endif diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index cfc8e590066d9da4b79ecf65c9226634fadf33e5..84b60311982caf02c879ba19f0dff37c79308d58 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -324,6 +324,7 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, #else bool testISP = sps.getUseISP() && cu.mtsFlag == 0 && cu.lfnstIdx == 0 && CU::canUseISP( width, height, MAX_TB_SIZEY ); #endif +#if !JVET_O0502_ISP_CLEANUP bool ispHorIsFirstTest = testISP ? CU::firstTestISPHorSplit( width, height, COMPONENT_Y, nullptr, nullptr ) : true; int ispOptions[] = { NOT_INTRA_SUBPARTITIONS, HOR_INTRA_SUBPARTITIONS, VER_INTRA_SUBPARTITIONS }; if ( !ispHorIsFirstTest ) @@ -331,8 +332,19 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, ispOptions[1] = VER_INTRA_SUBPARTITIONS; ispOptions[2] = HOR_INTRA_SUBPARTITIONS; } +#endif if( testISP ) { +#if JVET_O0502_ISP_CLEANUP + //reset the variables used for the tests + m_ispCandListHor.clear(); + m_ispCandListVer.clear(); + m_regIntraRDListWithCosts.clear(); + m_ispTestedModes.clear(); + //save the number of subpartitions + m_ispTestedModes.numTotalParts[0] = (int)height >> g_aucLog2[CU::getISPSplitDim(width, height, TU_1D_HORZ_SPLIT)]; + m_ispTestedModes.numTotalParts[1] = (int)width >> g_aucLog2[CU::getISPSplitDim(width, height, TU_1D_VERT_SPLIT)]; +#else //variables for the full RD list without MRL modes m_rdModeListWithoutMrl .clear(); m_rdModeListWithoutMrlHor .clear(); @@ -341,6 +353,7 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, m_intraModeDiagRatio .clear(); m_intraModeHorVerRatio .clear(); m_intraModeTestedNormalIntra.clear(); +#endif } #if JVET_O1136_TS_BDPCM_SIGNALLING @@ -558,8 +571,13 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, } if ( testISP ) { +#if JVET_O0502_ISP_CLEANUP + // we save the regular intra modes list + m_ispCandListHor = uiRdModeList; +#else //we save the list with no mrl modes to keep only the Hadamard selected modes (no mpms) m_rdModeListWithoutMrl = uiRdModeList; +#endif } #if ENABLE_JVET_L0283_MRL pu.multiRefIdx = 1; @@ -672,6 +690,23 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, } if ( testISP ) { +#if JVET_O0502_ISP_CLEANUP + // we add the MPMs to the list that contains only regular intra modes + for (int j = 0; j < numCand; j++) + { + bool mostProbableModeIncluded = false; + ModeInfo mostProbableMode(false, 0, NOT_INTRA_SUBPARTITIONS, uiPreds[j]); + + for (int i = 0; i < m_ispCandListHor.size(); i++) + { + mostProbableModeIncluded |= (mostProbableMode == m_ispCandListHor[i]); + } + if (!mostProbableModeIncluded) + { + m_ispCandListHor.push_back(mostProbableMode); + } + } +#else //we add the ISP MPMs to the list without mrl modes m_rdModeListWithoutMrlHor = m_rdModeListWithoutMrl; m_rdModeListWithoutMrlVer = m_rdModeListWithoutMrl; @@ -702,6 +737,7 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, } } cu.ispMode = NOT_INTRA_SUBPARTITIONS; +#endif } } //*** Add MPMs for MIP to candidate list @@ -766,6 +802,7 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, } } +#if !JVET_O0502_ISP_CLEANUP if( testISP ) // we remove the non-MPMs from the ISP lists { static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiRdModeListCopyHor = m_rdModeListWithoutMrlHor; @@ -801,6 +838,7 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, } cu.ispMode = NOT_INTRA_SUBPARTITIONS; } +#endif CHECK( numModesForFullRD != uiRdModeList.size(), "Inconsistent state!" ); @@ -822,8 +860,12 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, uiRdModeList.resize(std::min<size_t>(uiRdModeList.size(), maxSize)); if ( testISP ) { +#if JVET_O0502_ISP_CLEANUP + m_ispCandListHor.resize(std::min<size_t>(m_ispCandListHor.size(), maxSize)); +#else m_rdModeListWithoutMrlHor.resize(std::min<size_t>(m_rdModeListWithoutMrlHor.size(), maxSize)); m_rdModeListWithoutMrlVer.resize(std::min<size_t>(m_rdModeListWithoutMrlVer.size(), maxSize)); +#endif } } if (maxSize == 0) @@ -843,8 +885,18 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, } } +#if JVET_O0502_ISP_CLEANUP + int numNonISPModes = (int)uiRdModeList.size(); +#endif + if ( testISP ) { +#if JVET_O0502_ISP_CLEANUP + // we reserve positions for ISP in the common full RD list + const int maxNumRDModesISP = 16; + for (int i = 0; i < maxNumRDModesISP; i++) + uiRdModeList.push_back(ModeInfo(false, 0, INTRA_SUBPARTITIONS_RESERVED, 0)); +#else //we create a single full RD list that includes all intra modes using regular intra, MRL and ISP auto* firstIspList = ispOptions[1] == HOR_INTRA_SUBPARTITIONS ? &m_rdModeListWithoutMrlHor : &m_rdModeListWithoutMrlVer; auto* secondIspList = ispOptions[1] == HOR_INTRA_SUBPARTITIONS ? &m_rdModeListWithoutMrlVer : &m_rdModeListWithoutMrlHor; @@ -878,6 +930,7 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, uiRdModeList.insert( uiRdModeList.end(), secondIspList->begin(), secondIspList->end() ); uiRdModeList.insert( uiRdModeList.end(), firstIspList->begin() , firstIspList->end() ); } +#endif } //===== check modes (using r-d costs) ===== @@ -921,14 +974,18 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, } // just to be sure numModesForFullRD = ( int ) uiRdModeList.size(); +#if !JVET_O0502_ISP_CLEANUP PartSplit intraSubPartitionsProcOrder = TU_NO_ISP; int bestNormalIntraModeIndex = -1; +#endif TUIntraSubPartitioner subTuPartitioner( partitioner ); if( !cu.ispMode && !cu.mtsFlag ) { m_modeCtrl->setMtsFirstPassNoIspCost( MAX_DOUBLE ); } +#if !JVET_O0502_ISP_CLEANUP bool ispHorAllZeroCbfs = false, ispVerAllZeroCbfs = false; +#endif for (int mode = -2 * int(testBDPCM); mode < (int)uiRdModeList.size(); mode++) { @@ -953,6 +1010,18 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, else { cu.bdpcmMode = 0; +#if JVET_O0502_ISP_CLEANUP + if (uiRdModeList[mode].ispMod == INTRA_SUBPARTITIONS_RESERVED) + { + if (mode == numNonISPModes) // the list needs to be sorted only once + { + xSortISPCandList(bestCurrentCost, csBest->cost); + } + xGetNextISPMode(uiRdModeList[mode], (mode > 0 ? &uiRdModeList[mode - 1] : nullptr), Size(width, height)); + if (uiRdModeList[mode].ispMod == INTRA_SUBPARTITIONS_RESERVED) + continue; + } +#endif uiOrgMode = uiRdModeList[mode]; cu.mipFlag = uiOrgMode.mipFlg; cu.ispMode = uiOrgMode.ispMod; @@ -963,6 +1032,7 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, CHECK(pu.multiRefIdx && (pu.intraDir[0] == PLANAR_IDX), "Error: combination of MRL and Planar mode not supported"); CHECK(cu.ispMode && cu.mipFlag, "Error: combination of ISP and MIP not supported"); CHECK(cu.ispMode && pu.multiRefIdx, "Error: combination of ISP and MRL not supported"); +#if !JVET_O0502_ISP_CLEANUP if( cu.ispMode ) { intraSubPartitionsProcOrder = CU::getISPType( cu, COMPONENT_Y ); @@ -980,6 +1050,7 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, continue; } } +#endif } // set context models @@ -991,8 +1062,23 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, bool tmpValidReturn = false; if( cu.ispMode ) { +#if JVET_O0502_ISP_CLEANUP + tmpValidReturn = xIntraCodingLumaISP(*csTemp, subTuPartitioner, bestCurrentCost); + if (csTemp->tus.size() == 0) + { + // no TUs were coded + csTemp->cost = MAX_DOUBLE; + continue; + } + if (!cu.mtsFlag && !cu.lfnstIdx) + { + // we save the data for future tests + m_ispTestedModes.setModeResults((ISPType)cu.ispMode, (int)uiOrgMode.modeId, (int)csTemp->tus.size(), csTemp->cus[0]->firstTU->cbf[COMPONENT_Y] ? csTemp->cost : MAX_DOUBLE, csBest->cost); + } +#else tmpValidReturn = xRecurIntraCodingLumaQT( *csTemp, subTuPartitioner, bestCurrentCost, 0, intraSubPartitionsProcOrder, false, mtsCheckRangeFlag, mtsFirstCheckId, mtsLastCheckId, moreProbMTSIdxFirst ); +#endif } else { @@ -1004,8 +1090,16 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, mtsCheckRangeFlag, mtsFirstCheckId, mtsLastCheckId, moreProbMTSIdxFirst ); } +#if JVET_O0502_ISP_CLEANUP + if (!cu.ispMode && !cu.mtsFlag && !cu.lfnstIdx && !cu.bdpcmMode && !pu.multiRefIdx && !cu.mipFlag && testISP) + { + m_regIntraRDListWithCosts.push_back(ModeInfoWithCost(cu.mipFlag, pu.multiRefIdx, cu.ispMode, uiOrgMode.modeId, csTemp->cost)); + } +#endif + if( cu.ispMode && !csTemp->cus[0]->firstTU->cbf[COMPONENT_Y] ) { +#if !JVET_O0502_ISP_CLEANUP if( !sps.getUseLFNST() ) { if ( cu.ispMode == HOR_INTRA_SUBPARTITIONS ) @@ -1017,6 +1111,7 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, ispVerAllZeroCbfs |= ( m_pcEncCfg->getUseFastISP() && csTemp->tus[0]->lwidth() > 2 && csTemp->cost >= bestCurrentCost ); } } +#endif csTemp->cost = MAX_DOUBLE; csTemp->costDbOffset = 0; tmpValidReturn = false; @@ -1028,8 +1123,13 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, m_modeCostStore[ lfnstIdx ][ testMip ? rdModeIdxList[ mode ] : mode ] = tmpValidReturn ? csTemp->cost : ( MAX_DOUBLE / 2.0 ); //(MAX_DOUBLE / 2.0) ?? } - +#if JVET_O0502_ISP_CLEANUP + DTRACE(g_trace_ctx, D_INTRA_COST, "IntraCost T [x=%d,y=%d,w=%d,h=%d] %f (%d,%d,%d,%d,%d,%d) \n", cu.blocks[0].x, + cu.blocks[0].y, (int)width, (int)height, csTemp->cost, uiOrgMode.modeId, uiOrgMode.ispMod, + pu.multiRefIdx, cu.mipFlag, cu.lfnstIdx, cu.mtsFlag); +#else DTRACE( g_trace_ctx, D_INTRA_COST, "IntraCost T %f (%d) \n", csTemp->cost, uiOrgMode.modeId ); +#endif if( tmpValidReturn ) @@ -1057,7 +1157,9 @@ bool IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner, if( !cu.ispMode && !cu.bdpcmMode && csBest->cost < bestCostNonBDPCM ) { bestCostNonBDPCM = csBest->cost; +#if !JVET_O0502_ISP_CLEANUP bestNormalIntraModeIndex = mode; +#endif } } @@ -2384,7 +2486,9 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp const bool bUseCrossCPrediction = pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && isChroma( compID ) && PU::isChromaIntraModeCrossCheckMode( pu ) && checkCrossCPrediction; const bool ccUseRecoResi = m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate(); +#if !JVET_O0502_ISP_CLEANUP const bool ispSplitIsAllowed = sps.getUseISP() && CU::canUseISP( *tu.cu, compID ); +#endif //===== init availability pattern ===== @@ -2398,6 +2502,32 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp PelBuf sharedPredTS( m_pSharedPredTransformSkip[compID], area ); if( default0Save1Load2 != 2 ) { +#if JVET_O0502_ISP_CLEANUP +#if JVET_O0106_ISP_4xN_PREDREG_FOR_1xN_2xN + bool predRegDiffFromTB = CU::isPredRegDiffFromTB(*tu.cu, compID); + bool firstTBInPredReg = CU::isFirstTBInPredReg(*tu.cu, compID, area); + CompArea areaPredReg(COMPONENT_Y, tu.chromaFormat, area); +#endif + if (tu.cu->ispMode && isLuma(compID)) + { +#if JVET_O0106_ISP_4xN_PREDREG_FOR_1xN_2xN + if (predRegDiffFromTB) + { + if (firstTBInPredReg) + { + CU::adjustPredArea(areaPredReg); + initIntraPatternChTypeISP(*tu.cu, areaPredReg, piReco); + } + } + else +#endif + initIntraPatternChTypeISP(*tu.cu, area, piReco); + } + else + { + initIntraPatternChType(*tu.cu, area); + } +#else #if JVET_O0106_ISP_4xN_PREDREG_FOR_1xN_2xN bool predRegDiffFromTB = CU::isPredRegDiffFromTB(*tu.cu, compID); bool firstTBInPredReg = CU::isFirstTBInPredReg(*tu.cu, compID, area); @@ -2413,6 +2543,7 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp else #endif initIntraPatternChType(*tu.cu, area); +#endif //===== get prediction signal ===== if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) ) @@ -2570,12 +2701,23 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp #endif } #if JVET_O0105_ICT +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if ( sps.getJointCbCrEnabledFlag() && isChroma(compID) && (tu.cu->cs->slice->getSliceQp() > 18) ) + { + m_pcTrQuant->setLambda( 1.3 * m_pcTrQuant->getLambda() ); + } +#else if( isChroma(compID) && tu.cu->cs->slice->getSliceQp() > 18 ) { m_pcTrQuant->setLambda( 1.3 * m_pcTrQuant->getLambda() ); } + #endif +#else +#if JVET_O0376_SPS_JOINTCBCR_FLAG + else if ( sps.getJointCbCrEnabledFlag() && isChroma(compID) && (tu.cu->cs->slice->getSliceQp() > 18) ) #else else if ( isChroma(compID) && tu.cu->cs->slice->getSliceQp() > 18 ) +#endif m_pcTrQuant->setLambda( 1.10 * m_pcTrQuant->getLambda() ); #endif @@ -2583,6 +2725,14 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp if( isLuma(compID) ) { #endif +#if JVET_O0502_ISP_CLEANUP + if (trModes) + { + m_pcTrQuant->transformNxN(tu, compID, cQP, trModes, CU::isIntra(*tu.cu) ? m_pcEncCfg->getIntraMTSMaxCand() : m_pcEncCfg->getInterMTSMaxCand()); + tu.mtsIdx = trModes->at(0).first; + } + m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), loadTr); +#else double diagRatio = 0, horVerRatio = 0; if( trModes ) @@ -2597,10 +2747,20 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp m_intraModeHorVerRatio .push_back(horVerRatio); m_intraModeTestedNormalIntra.push_back((int)uiChFinalMode); } +#endif DTRACE( g_trace_ctx, D_TU_ABS_SUM, "%d: comp=%d, abssum=%d\n", DTRACE_GET_COUNTER( g_trace_ctx, D_TU_ABS_SUM ), compID, uiAbsSum ); +#if JVET_O0502_ISP_CLEANUP + if (tu.cu->ispMode && isLuma(compID) && CU::isISPLast(*tu.cu, area, area.compID) && CU::allLumaCBFsAreZero(*tu.cu)) + { + // ISP has to have at least one non-zero CBF + ruiDist = MAX_INT; + return; + } +#endif + //--- inverse transform --- if (uiAbsSum > 0) @@ -2771,6 +2931,118 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp } } +#if JVET_O0502_ISP_CLEANUP +bool IntraSearch::xIntraCodingLumaISP(CodingStructure& cs, Partitioner& partitioner, const double bestCostSoFar) +{ + int subTuCounter = 0; + const CodingUnit& cu = *cs.getCU(partitioner.currArea().lumaPos(), partitioner.chType); + bool earlySkipISP = false; + bool splitCbfLuma = false; + const PartSplit ispType = CU::getISPType(cu, COMPONENT_Y); + + cs.cost = 0; + + partitioner.splitCurrArea(ispType, cs); + + do // subpartitions loop + { + uint32_t numSig = 0; + Distortion singleDistTmpLuma = 0; + uint64_t singleTmpFracBits = 0; + double singleCostTmp = 0; + + TransformUnit& tu = cs.addTU(CS::getArea(cs, partitioner.currArea(), partitioner.chType), partitioner.chType); + tu.depth = partitioner.currTrDepth; + + // Encode TU + xIntraCodingTUBlock(tu, COMPONENT_Y, false, singleDistTmpLuma, 0, &numSig); + + if (singleDistTmpLuma == MAX_INT) // all zero CBF skip + { + earlySkipISP = true; + partitioner.exitCurrSplit(); + cs.cost = MAX_DOUBLE; + return false; + } + + { + if (m_pcRdCost->calcRdCost(cs.fracBits, cs.dist + singleDistTmpLuma) > bestCostSoFar) + { + // The accumulated cost + distortion is already larger than the best cost so far, so it is not necessary to calculate the rate + earlySkipISP = true; + } + else + { + singleTmpFracBits = xGetIntraFracBitsQT(cs, partitioner, true, false, subTuCounter, ispType); + } + singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma); + } + + cs.cost += singleCostTmp; + cs.dist += singleDistTmpLuma; + cs.fracBits += singleTmpFracBits; + + subTuCounter++; + + splitCbfLuma |= TU::getCbfAtDepth(*cs.getTU(partitioner.currArea().lumaPos(), partitioner.chType, subTuCounter - 1), COMPONENT_Y, partitioner.currTrDepth); + int nSubPartitions = m_ispTestedModes.numTotalParts[cu.ispMode - 1]; + if (subTuCounter < nSubPartitions) + { + // exit condition if the accumulated cost is already larger than the best cost so far (no impact in RD performance) + if (cs.cost > bestCostSoFar) + { + earlySkipISP = true; + break; + } + else if (subTuCounter < nSubPartitions) + { + // more restrictive exit condition + double threshold = nSubPartitions == 2 ? 0.95 : subTuCounter == 1 ? 0.83 : 0.91; + if (subTuCounter < nSubPartitions && cs.cost > bestCostSoFar * threshold) + { + earlySkipISP = true; + break; + } + } + } + } while (partitioner.nextPart(cs)); // subpartitions loop + + partitioner.exitCurrSplit(); + const UnitArea& currArea = partitioner.currArea(); + const uint32_t currDepth = partitioner.currTrDepth; + + if (earlySkipISP) + { + cs.cost = MAX_DOUBLE; + } + else + { + cs.cost = m_pcRdCost->calcRdCost(cs.fracBits, cs.dist); + // The cost check is necessary here again to avoid superfluous operations if the maximum number of coded subpartitions was reached and yet ISP did not win + if (cs.cost < bestCostSoFar) + { + cs.setDecomp(cu.Y()); + cs.picture->getRecoBuf(currArea.Y()).copyFrom(cs.getRecoBuf(currArea.Y())); + + for (auto& ptu : cs.tus) + { + if (currArea.Y().contains(ptu->Y())) + { + TU::setCbfAtDepth(*ptu, COMPONENT_Y, currDepth, splitCbfLuma ? 1 : 0); + } + } + } + else + { + cs.cost = MAX_DOUBLE; + earlySkipISP = true; + } + } + return !earlySkipISP; +} +#endif + + bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &partitioner, const double bestCostSoFar, const int subTuIdx, const PartSplit ispType, const bool ispIsCurrentWinner, bool mtsCheckRangeFlag, int mtsFirstCheckId, int mtsLastCheckId, bool moreProbMTSIdxFirst ) { int subTuCounter = subTuIdx; @@ -3551,11 +3823,17 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio #if JVET_O0105_ICT bool lastIsBest = false; std::vector<int> jointCbfMasksToTest; - if( TU::getCbf(tmpTU, COMPONENT_Cb) || TU::getCbf(tmpTU, COMPONENT_Cr) ) +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if ( cs.sps->getJointCbCrEnabledFlag() && (TU::getCbf(tmpTU, COMPONENT_Cb) || TU::getCbf(tmpTU, COMPONENT_Cr))) { - jointCbfMasksToTest = m_pcTrQuant->selectICTCandidates( currTU, orgResiCb, orgResiCr ); + jointCbfMasksToTest = m_pcTrQuant->selectICTCandidates(currTU, orgResiCb, orgResiCr); } - +#else + if (TU::getCbf(tmpTU, COMPONENT_Cb) || TU::getCbf(tmpTU, COMPONENT_Cr)) + { + jointCbfMasksToTest = m_pcTrQuant->selectICTCandidates(currTU, orgResiCb, orgResiCr); + } +#endif for( int cbfMask : jointCbfMasksToTest ) #else bool checkJointCbCr = TU::getCbf(tmpTU, COMPONENT_Cb) || TU::getCbf(tmpTU, COMPONENT_Cr); @@ -3858,3 +4136,263 @@ void IntraSearch::reduceHadCandList(static_vector<T, N>& candModeList, static_ve candCostList = tempCandCostList; numModesForFullRD = int(candModeList.size()); } + +#if JVET_O0502_ISP_CLEANUP +// It decides which modes from the ISP lists can be full RD tested +void IntraSearch::xGetNextISPMode(ModeInfo& modeInfo, const ModeInfo* lastMode, const Size cuSize) +{ + static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM>* rdModeLists[2] = { &m_ispCandListHor, &m_ispCandListVer }; + + ISPType nextISPcandSplitType; + if (!m_ispTestedModes.stopTestingHorSplit && !m_ispTestedModes.stopTestingVerSplit) + { + nextISPcandSplitType = !lastMode ? HOR_INTRA_SUBPARTITIONS : lastMode->ispMod == HOR_INTRA_SUBPARTITIONS ? VER_INTRA_SUBPARTITIONS : HOR_INTRA_SUBPARTITIONS; + } + else if (!m_ispTestedModes.stopTestingHorSplit && m_ispTestedModes.stopTestingVerSplit) + { + nextISPcandSplitType = HOR_INTRA_SUBPARTITIONS; + } + else if (m_ispTestedModes.stopTestingHorSplit && !m_ispTestedModes.stopTestingVerSplit) + { + nextISPcandSplitType = VER_INTRA_SUBPARTITIONS; + } + else + { + return; // no more modes will be tested + } + + int maxNumSubPartitions = m_ispTestedModes.numTotalParts[nextISPcandSplitType - 1]; + + if (m_ispTestedModes.numTestedModes[nextISPcandSplitType - 1] >= 2) + { + // Split stop criteria after checking the performance of previously tested intra modes + const int thresholdSplit1 = maxNumSubPartitions; + + int mode1 = m_ispTestedModes.getTestedIntraMode((ISPType)nextISPcandSplitType, 0); + mode1 = mode1 == DC_IDX ? -1 : mode1; + int numSubPartsBestMode1 = mode1 != -1 ? m_ispTestedModes.getNumCompletedSubParts((ISPType)nextISPcandSplitType, mode1) : -1; + int mode2 = m_ispTestedModes.getTestedIntraMode((ISPType)nextISPcandSplitType, 1); + mode2 = mode2 == DC_IDX ? -1 : mode2; + int numSubPartsBestMode2 = mode2 != -1 ? m_ispTestedModes.getNumCompletedSubParts((ISPType)nextISPcandSplitType, mode2) : -1; + + // 1) The 2 most promising modes do not reach a certain number of sub-partitions + if (numSubPartsBestMode1 != -1 && numSubPartsBestMode2 != -1) + { + if (numSubPartsBestMode1 < thresholdSplit1 && numSubPartsBestMode2 < thresholdSplit1) + { + m_ispTestedModes.stopTestingVerSplit = nextISPcandSplitType == VER_INTRA_SUBPARTITIONS ? true : m_ispTestedModes.stopTestingVerSplit; + m_ispTestedModes.stopTestingHorSplit = nextISPcandSplitType == HOR_INTRA_SUBPARTITIONS ? true : m_ispTestedModes.stopTestingHorSplit; + return; + } + } + + // 2) One split is better than the other after PLANAR and one angle have been tested + ISPType otherSplit = nextISPcandSplitType == HOR_INTRA_SUBPARTITIONS ? VER_INTRA_SUBPARTITIONS : HOR_INTRA_SUBPARTITIONS; + int numSubPartsBestAngleOtherSplit = mode2 != -1 ? m_ispTestedModes.getNumCompletedSubParts(otherSplit, mode2) : -1; + bool stopThisSplit = false; + if (numSubPartsBestAngleOtherSplit != -1 && numSubPartsBestMode2 != -1) + { + if (numSubPartsBestAngleOtherSplit > numSubPartsBestMode2) + { + stopThisSplit = true; + } + else if (numSubPartsBestAngleOtherSplit == numSubPartsBestMode2 && numSubPartsBestAngleOtherSplit == maxNumSubPartitions) + { + double rdCostBestAngleThisSplit = m_ispTestedModes.getRDCost(nextISPcandSplitType, mode2, maxNumSubPartitions); + double rdCostBestAngleOtherSplit = m_ispTestedModes.getRDCost(otherSplit, mode2, maxNumSubPartitions); + + if (rdCostBestAngleThisSplit == MAX_DOUBLE || rdCostBestAngleOtherSplit < rdCostBestAngleThisSplit * 1.3) + { + stopThisSplit = true; + } + } + } + if (stopThisSplit) + { + m_ispTestedModes.stopTestingVerSplit = nextISPcandSplitType == VER_INTRA_SUBPARTITIONS ? true : m_ispTestedModes.stopTestingVerSplit; + m_ispTestedModes.stopTestingHorSplit = nextISPcandSplitType == HOR_INTRA_SUBPARTITIONS ? true : m_ispTestedModes.stopTestingHorSplit; + return; + } + } + + // Now a new mode is retrieved from the list and it has to be decided whether it should be tested or not + if (m_ispTestedModes.candIndexInList[nextISPcandSplitType - 1] < rdModeLists[nextISPcandSplitType - 1]->size()) + { + ModeInfo candidate = rdModeLists[nextISPcandSplitType - 1]->at(m_ispTestedModes.candIndexInList[nextISPcandSplitType - 1]); + m_ispTestedModes.candIndexInList[nextISPcandSplitType - 1]++; + + // extra modes are only tested if ISP has won so far + if (m_ispTestedModes.candIndexInList[nextISPcandSplitType - 1] > m_ispTestedModes.numOrigModesToTest) + { + if (m_ispTestedModes.bestSplitSoFar != candidate.ispMod || m_ispTestedModes.bestModeSoFar == PLANAR_IDX) + { + return; + } + } + + bool testCandidate = true; + + // we look for a reference mode that has already been tested within the window and decide to test the new one according to the reference mode costs + if (candidate.modeId >= DC_IDX && maxNumSubPartitions > 2 && m_ispTestedModes.numTestedModes[nextISPcandSplitType - 1] >= 2) + { + const int angWindowSize = 5; + int numSubPartsLeftMode, numSubPartsRightMode, numSubPartsRefMode, leftIntraMode = -1, rightIntraMode = -1; + int windowSize = candidate.modeId > DC_IDX ? angWindowSize : 1; + int numSamples = cuSize.width << g_aucLog2[cuSize.height]; + int numSubPartsLimit = numSamples >= 256 ? maxNumSubPartitions - 1 : 2; + + xFindAlreadyTestedNearbyIntraModes((int)candidate.modeId, &leftIntraMode, &rightIntraMode, (ISPType)candidate.ispMod, windowSize); + + numSubPartsLeftMode = leftIntraMode != -1 ? m_ispTestedModes.getNumCompletedSubParts((ISPType)candidate.ispMod, leftIntraMode) : -1; + numSubPartsRightMode = rightIntraMode != -1 ? m_ispTestedModes.getNumCompletedSubParts((ISPType)candidate.ispMod, rightIntraMode) : -1; + + numSubPartsRefMode = std::max(numSubPartsLeftMode, numSubPartsRightMode); + + if (numSubPartsRefMode > 0) + { + // The mode was found. Now we check the condition + testCandidate = numSubPartsRefMode > numSubPartsLimit; + } + } + + if (testCandidate) + { + modeInfo = candidate; + } + } +} + +void IntraSearch::xFindAlreadyTestedNearbyIntraModes(int currentIntraMode, int* leftIntraMode, int* rightIntraMode, ISPType ispOption, int windowSize) +{ + bool leftModeFound = false, rightModeFound = false; + *leftIntraMode = -1; + *rightIntraMode = -1; + const unsigned st = ispOption - 1; + + for (int k = 1; k <= windowSize; k++) + { + int off = currentIntraMode - 2 - k; + int leftMode = (off < 0) ? NUM_LUMA_MODE + off : currentIntraMode - k; + int rightMode = currentIntraMode > DC_IDX ? (((int)currentIntraMode - 2 + k) % 65) + 2 : PLANAR_IDX; + + leftModeFound = leftMode != (int)currentIntraMode ? m_ispTestedModes.modeHasBeenTested[leftMode][st] : false; + rightModeFound = rightMode != (int)currentIntraMode ? m_ispTestedModes.modeHasBeenTested[rightMode][st] : false; + if (leftModeFound || rightModeFound) + { + *leftIntraMode = leftModeFound ? leftMode : -1; + *rightIntraMode = rightModeFound ? rightMode : -1; + break; + } + } +} + +void IntraSearch::xSortISPCandList(double bestCostSoFar, double bestNonISPCost) +{ + if (m_pcEncCfg->getUseFastISP()) + { + double thSkipISP = 1.4; + if (bestNonISPCost > bestCostSoFar * thSkipISP) + { + m_ispTestedModes.stopTestingHorSplit = true; + m_ispTestedModes.stopTestingVerSplit = true; + return; + } + } + + for (int k = 0; k < m_ispCandListHor.size(); k++) + { + m_ispCandListHor.at(k).ispMod = HOR_INTRA_SUBPARTITIONS; //we set the correct ISP split type value + } + + auto origHadList = m_ispCandListHor; // save the original hadamard list of regular intra + bool modeIsInList[NUM_LUMA_MODE] = { false }; + + m_ispCandListHor.clear(); + m_ispCandListVer.clear(); + + // we sort the normal intra modes according to their full RD costs + std::sort(m_regIntraRDListWithCosts.begin(), m_regIntraRDListWithCosts.end(), ModeInfoWithCost::compareModeInfoWithCost); + + // we get the best angle from the regular intra list + int bestNormalIntraAngle = -1; + for (int modeIdx = 0; modeIdx < m_regIntraRDListWithCosts.size(); modeIdx++) + { + if (bestNormalIntraAngle == -1 && m_regIntraRDListWithCosts.at(modeIdx).modeId > DC_IDX) + { + bestNormalIntraAngle = m_regIntraRDListWithCosts.at(modeIdx).modeId; + break; + } + } + + int mode1 = PLANAR_IDX; + int mode2 = bestNormalIntraAngle; + + ModeInfo refMode = origHadList.at(0); + auto* destListPtr = &m_ispCandListHor; + // 1) Planar + destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, mode1)); + modeIsInList[mode1] = true; + // 2) Best angle in regular intra + if (mode2 != -1) + { + destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, mode2)); + modeIsInList[mode2] = true; + } + // 3) Remaining regular intra modes that were full RD tested (except DC, which is added after the angles from regular intra) + int dcModeIndex = -1; + for (int remModeIdx = 0; remModeIdx < m_regIntraRDListWithCosts.size(); remModeIdx++) + { + int currentMode = m_regIntraRDListWithCosts.at(remModeIdx).modeId; + if (currentMode != mode1 && currentMode != mode2) + { + if (currentMode > DC_IDX) + { + destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, currentMode)); + modeIsInList[currentMode] = true; + } + else if (currentMode == DC_IDX) + { + dcModeIndex = remModeIdx; + } + } + } + // 4) DC is added after the angles from regular intra + if (dcModeIndex != -1) + { + destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, DC_IDX)); + modeIsInList[DC_IDX] = true; + } + + // 5) We add extra candidates to the list that will only be tested if ISP is likely to win + m_ispTestedModes.numOrigModesToTest = (int)destListPtr->size(); + const int addedModesFromHadList = 3; + int newModesAdded = 0; + + for (int k = 0; k < origHadList.size(); k++) + { + if (newModesAdded == addedModesFromHadList) + { + break; + } + if (!modeIsInList[origHadList.at(k).modeId]) + { + destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, origHadList.at(k).modeId)); + newModesAdded++; + } + } + + // Copy modes to other split-type list + m_ispCandListVer = m_ispCandListHor; + for (int i = 0; i < m_ispCandListVer.size(); i++) + { + m_ispCandListVer[i].ispMod = VER_INTRA_SUBPARTITIONS; + } + + // Reset the tested modes information to 0 + for (int i = 0; i < m_ispCandListHor.size(); i++) + { + m_ispTestedModes.clearISPModeInfo(m_ispCandListHor[i].modeId); + } +} + +#endif diff --git a/source/Lib/EncoderLib/IntraSearch.h b/source/Lib/EncoderLib/IntraSearch.h index ceb359f0f762c7f0f3f980037b02bac3b435a4ec..0176b146ebc0ebe01ff53799b01fde793f9cfe0e 100644 --- a/source/Lib/EncoderLib/IntraSearch.h +++ b/source/Lib/EncoderLib/IntraSearch.h @@ -191,10 +191,131 @@ private: ModeInfo(const bool mipf, const int mrid, const uint8_t ispm, const uint32_t mode) : mipFlg(mipf), mRefId(mrid), ispMod(ispm), modeId(mode) {} bool operator==(const ModeInfo cmp) const { return (mipFlg == cmp.mipFlg && mRefId == cmp.mRefId && ispMod == cmp.ispMod && modeId == cmp.modeId); } }; +#if JVET_O0502_ISP_CLEANUP + struct ModeInfoWithCost : public ModeInfo + { + double rdCost; + ModeInfoWithCost() : ModeInfo(), rdCost(MAX_DOUBLE) {} + ModeInfoWithCost(const bool mipf, const int mrid, const uint8_t ispm, const uint32_t mode, double cost) : ModeInfo(mipf, mrid, ispm, mode), rdCost(cost) {} + bool operator==(const ModeInfoWithCost cmp) const { return (mipFlg == cmp.mipFlg && mRefId == cmp.mRefId && ispMod == cmp.ispMod && modeId == cmp.modeId && rdCost == cmp.rdCost); } + static bool compareModeInfoWithCost(ModeInfoWithCost a, ModeInfoWithCost b) { return a.rdCost < b.rdCost; } + }; + + struct ISPTestedModeInfo + { + int numCompSubParts; + double rdCost; + + ISPTestedModeInfo() {} + + void setMode(int numParts, double cost) + { + numCompSubParts = numParts; + rdCost = cost; + } + void clear() + { + numCompSubParts = -1; + rdCost = MAX_DOUBLE; + } + }; + struct ISPTestedModesInfo + { + ISPTestedModeInfo intraMode[NUM_LUMA_MODE][2]; + bool modeHasBeenTested[NUM_LUMA_MODE][2]; + int numTotalParts[2]; + static_vector<int, FAST_UDI_MAX_RDMODE_NUM> testedModes[2]; + int bestModeSoFar; + ISPType bestSplitSoFar; + int bestMode[2]; + double bestCost[2]; + int numTestedModes[2]; + int candIndexInList[2]; + bool stopTestingHorSplit; + bool stopTestingVerSplit; + int numOrigModesToTest; + + // set a tested mode results + void setModeResults(ISPType splitType, int iModeIdx, int numCompletedParts, double rdCost, double currentBestCost) + { + const unsigned st = splitType - 1; + CHECKD(st > 1, "The split type is invalid!"); + const int maxNumParts = numTotalParts[st]; + intraMode[iModeIdx][st].setMode(numCompletedParts, numCompletedParts == maxNumParts ? rdCost : MAX_DOUBLE); + testedModes[st].push_back(iModeIdx); + numTestedModes[st]++; + modeHasBeenTested[iModeIdx][st] = true; + if (numCompletedParts == maxNumParts && rdCost < bestCost[st]) // best mode update + { + bestMode[st] = iModeIdx; + bestCost[st] = rdCost; + } + if (numCompletedParts == maxNumParts && rdCost < currentBestCost) // best mode update + { + bestModeSoFar = iModeIdx; + bestSplitSoFar = splitType; + } + } + int getNumCompletedSubParts(ISPType splitType, int iModeIdx) + { + const unsigned st = splitType - 1; + CHECK(st < 0 || st > 1, "The split type is invalid!"); + CHECK(iModeIdx < 0 || iModeIdx >(NUM_LUMA_MODE - 1), "The modeIdx is invalid"); + return modeHasBeenTested[iModeIdx][st] ? intraMode[iModeIdx][st].numCompSubParts : -1; + } + + double getRDCost(ISPType splitType, int iModeIdx, int maxNumSubParts) + { + const unsigned st = splitType - 1; + CHECKD(st > 1, "The split type is invalid!"); + return modeHasBeenTested[iModeIdx][st] && intraMode[iModeIdx][st].numCompSubParts == maxNumSubParts + ? intraMode[iModeIdx][st].rdCost + : -1; + } + + // get a tested intra mode index + int getTestedIntraMode(ISPType splitType, int pos) + { + const unsigned st = splitType - 1; + CHECKD(st > 1, "The split type is invalid!"); + return pos < testedModes[st].size() ? testedModes[st].at(pos) : -1; + } + + // set everything to default values + void clear() + { + numTestedModes[0] = numTestedModes[1] = 0; + candIndexInList[0] = candIndexInList[1] = 0; + stopTestingHorSplit = false; + stopTestingVerSplit = false; + testedModes[0].clear(); + testedModes[1].clear(); + bestCost[0] = MAX_DOUBLE; + bestCost[1] = MAX_DOUBLE; + bestMode[0] = -1; + bestMode[1] = -1; + bestModeSoFar = -1; + bestSplitSoFar = NOT_INTRA_SUBPARTITIONS; + numOrigModesToTest = -1; + memset(modeHasBeenTested, 0, sizeof(modeHasBeenTested)); + } + void clearISPModeInfo(int idx) + { + intraMode[idx][0].clear(); + intraMode[idx][1].clear(); + } + }; + + static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> m_ispCandListHor, m_ispCandListVer; + static_vector<ModeInfoWithCost, FAST_UDI_MAX_RDMODE_NUM> m_regIntraRDListWithCosts; + + ISPTestedModesInfo m_ispTestedModes; +#else static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> m_rdModeListWithoutMrl; static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> m_rdModeListWithoutMrlHor; static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> m_rdModeListWithoutMrlVer; +#endif //cost variables for the EMT algorithm and new modes list double m_bestModeCostStore[ NUM_LFNST_NUM_PER_SET ]; // RD cost of the best mode for each PU using DCT2 @@ -202,9 +323,11 @@ private: ModeInfo m_savedRdModeList[ NUM_LFNST_NUM_PER_SET ][ NUM_LUMA_MODE ]; int32_t m_savedNumRdModes[ NUM_LFNST_NUM_PER_SET ]; +#if !JVET_O0502_ISP_CLEANUP static_vector<double, FAST_UDI_MAX_RDMODE_NUM> m_intraModeDiagRatio; static_vector<double, FAST_UDI_MAX_RDMODE_NUM> m_intraModeHorVerRatio; static_vector<int, FAST_UDI_MAX_RDMODE_NUM> m_intraModeTestedNormalIntra; +#endif static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> m_uiSavedRdModeListLFNST; static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> m_uiSavedHadModeListLFNST; @@ -288,7 +411,9 @@ protected: ChromaCbfs xRecurIntraChromaCodingQT( CodingStructure &cs, Partitioner& pm, const double bestCostSoFar = MAX_DOUBLE, const PartSplit ispType = TU_NO_ISP ); bool xRecurIntraCodingLumaQT ( CodingStructure &cs, Partitioner& pm, const double bestCostSoFar = MAX_DOUBLE, const int subTuIdx = -1, const PartSplit ispType = TU_NO_ISP, const bool ispIsCurrentWinner = false, bool mtsCheckRangeFlag = false, int mtsFirstCheckId = 0, int mtsLastCheckId = 0, bool moreProbMTSIdxFirst = false ); - +#if JVET_O0502_ISP_CLEANUP + bool xIntraCodingLumaISP ( CodingStructure& cs, Partitioner& pm, const double bestCostSoFar = MAX_DOUBLE ); +#endif void encPredIntraDPCM( const ComponentID &compID, PelBuf &pOrg, PelBuf &pDst, const uint32_t &uiDirMode ); static bool useDPCMForFirstPassIntraEstimation( const PredictionUnit &pu, const uint32_t &uiDirMode ); @@ -304,6 +429,11 @@ protected: void calcPixelPred(CodingStructure& cs, Partitioner& partitioner, uint32_t yPos, uint32_t xPos, ComponentID compBegin, uint32_t numComp); void preCalcPLTIndex(CodingStructure& cs, Partitioner& partitioner, ComponentID compBegin, uint32_t numComp); #endif +#if JVET_O0502_ISP_CLEANUP + void xGetNextISPMode ( ModeInfo& modeInfo, const ModeInfo* lastMode, const Size cuSize ); + void xFindAlreadyTestedNearbyIntraModes ( int currentIntraMode, int* leftIntraMode, int* rightIntraMode, ISPType ispOption, int windowSize ); + void xSortISPCandList ( double bestCostSoFar, double bestNonISPCost ); +#endif };// END CLASS DEFINITION EncSearch //! \} diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 5c0f4a6a751578e991167881dc6d59d90e8c61f8..5e6eaa0cc1b498ea19092b77ff2aaa69817c1e03 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -839,10 +839,30 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_UVLC( pcSPS->getLog2MaxTbSize() - 2, "log2_max_luma_transform_block_size_minus2" ); #endif #endif + +#if JVET_O0650_SIGNAL_CHROMAQP_MAPPING_TABLE + if (pcSPS->getChromaFormatIdc() != CHROMA_400) + { + const ChromaQpMappingTable& chromaQpMappingTable = pcSPS->getChromaQpMappingTable(); + WRITE_FLAG(chromaQpMappingTable.getSameCQPTableForAllChromaFlag(), "same_qp_table_for_chroma"); + for (int i = 0; i < (chromaQpMappingTable.getSameCQPTableForAllChromaFlag() ? 1 : 3); i++) + { + WRITE_UVLC(chromaQpMappingTable.getNumPtsInCQPTableMinus1(i), "num_points_in_qp_table_minus1"); + + for (int j = 0; j <= chromaQpMappingTable.getNumPtsInCQPTableMinus1(i); j++) + { + WRITE_UVLC(chromaQpMappingTable.getDeltaQpInValMinus1(i,j), "delta_qp_in_val_minus1"); + WRITE_UVLC(chromaQpMappingTable.getDeltaQpOutVal(i, j), "delta_qp_out_val"); + } + } + } +#endif + #if JVET_O0244_DELTA_POC WRITE_FLAG( pcSPS->getUseWP() ? 1 : 0, "sps_weighted_pred_flag" ); // Use of Weighting Prediction (P_SLICE) WRITE_FLAG( pcSPS->getUseWPBiPred() ? 1 : 0, "sps_weighted_bipred_flag" ); // Use of Weighting Bi-Prediction (B_SLICE) #endif + WRITE_FLAG( pcSPS->getSAOEnabledFlag(), "sps_sao_enabled_flag"); WRITE_FLAG( pcSPS->getALFEnabledFlag(), "sps_alf_enabled_flag" ); @@ -863,7 +883,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_FLAG(pcSPS->getBDPCMEnabledFlag() ? 1 : 0, "sps_bdpcm_enabled_flag"); } #endif - +#if JVET_O0376_SPS_JOINTCBCR_FLAG + WRITE_FLAG( pcSPS->getJointCbCrEnabledFlag(), "sps_joint_cbcr_enabled_flag"); +#endif if( pcSPS->getCTUSize() + 2*(1 << pcSPS->getLog2MinCodingBlockSize()) <= pcSPS->getPicWidthInLumaSamples() ) { WRITE_FLAG( pcSPS->getWrapAroundEnabledFlag() ? 1 : 0, "sps_ref_wraparound_enabled_flag" ); @@ -1284,7 +1306,11 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) if (alfEnabled) { #if JVET_O0288_UNIFY_ALF_SLICE_TYPE_REMOVAL +#if JVET_O_MAX_NUM_ALF_APS_8 + WRITE_CODE(pcSlice->getTileGroupNumAps(), 3, "tile_group_num_aps"); +#else xWriteTruncBinCode(pcSlice->getTileGroupNumAps(), ALF_CTB_MAX_NUM_APS + 1); +#endif #else if (pcSlice->isIntra()) { @@ -1292,13 +1318,21 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) } else { +#if JVET_O_MAX_NUM_ALF_APS_8 + WRITE_CODE(pcSlice->getTileGroupNumAps(), 3, "tile_group_num_aps"); +#else xWriteTruncBinCode(pcSlice->getTileGroupNumAps(), ALF_CTB_MAX_NUM_APS + 1); +#endif } #endif const std::vector<int>& apsId = pcSlice->getTileGroupApsIdLuma(); for (int i = 0; i < pcSlice->getTileGroupNumAps(); i++) { +#if JVET_O_MAX_NUM_ALF_APS_8 + WRITE_CODE(apsId[i], 3, "tile_group_aps_id"); +#else WRITE_CODE(apsId[i], 5, "tile_group_aps_id"); +#endif } const int alfChromaIdc = pcSlice->getTileGroupAlfEnabledFlag(COMPONENT_Cb) + pcSlice->getTileGroupAlfEnabledFlag(COMPONENT_Cr) * 2 ; @@ -1313,7 +1347,11 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) if (alfChromaIdc) { #if JVET_O0288_UNIFY_ALF_SLICE_TYPE_REMOVAL +#if JVET_O_MAX_NUM_ALF_APS_8 + WRITE_CODE(pcSlice->getTileGroupApsIdChroma(), 3, "tile_group_aps_id_chroma"); +#else WRITE_CODE(pcSlice->getTileGroupApsIdChroma(), 5, "tile_group_aps_id_chroma"); +#endif #else if (pcSlice->isIntra()&& pcSlice->getTileGroupNumAps() == 1) { @@ -1321,7 +1359,11 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) } else { +#if JVET_O_MAX_NUM_ALF_APS_8 + WRITE_CODE(pcSlice->getTileGroupApsIdChroma(), 3, "tile_group_aps_id_chroma"); +#else WRITE_CODE(pcSlice->getTileGroupApsIdChroma(), 5, "tile_group_aps_id_chroma"); +#endif } #endif } @@ -1446,7 +1488,11 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) } } } +#if JVET_O0455_IBC_MAX_MERGE_NUM + if (!cs.slice->isIntra()) +#else if (!cs.slice->isIntra() || cs.slice->getSPS()->getIBCFlag()) +#endif { CHECK(pcSlice->getMaxNumMergeCand() > MRG_MAX_NUM_CANDS, "More merge candidates signalled than supported"); WRITE_UVLC(MRG_MAX_NUM_CANDS - pcSlice->getMaxNumMergeCand(), "six_minus_max_num_merge_cand"); @@ -1496,11 +1542,25 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) pcSlice->setMaxNumTriangleCand(0); } } +#if JVET_O0455_IBC_MAX_MERGE_NUM + if ( pcSlice->getSPS()->getIBCFlag() ) + { + CHECK( pcSlice->getMaxNumIBCMergeCand() > IBC_MRG_MAX_NUM_CANDS, "More IBC merge candidates signalled than supported" ); + WRITE_UVLC( IBC_MRG_MAX_NUM_CANDS - pcSlice->getMaxNumIBCMergeCand(), "six_minus_max_num_ibc_merge_cand" ); + } +#endif #if JVET_O0105_ICT +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if (pcSlice->getSPS()->getJointCbCrEnabledFlag()) + { + WRITE_FLAG( pcSlice->getJointCbCrSignFlag() ? 1 : 0, "slice_joint_cbcr_sign_flag"); + } +#else if (chromaEnabled) { - WRITE_FLAG( pcSlice->getJointCbCrSignFlag() ? 1 : 0, "joint_cb_cr_sign_flag" ); + WRITE_FLAG( pcSlice->getJointCbCrSignFlag() ? 1 : 0, "slice_joint_cbcr_sign_flag"); } +#endif #endif int iCode = pcSlice->getSliceQp() - ( pcSlice->getPPS()->getPicInitQPMinus26() + 26 ); @@ -1514,7 +1574,14 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) if (numberValidComponents > COMPONENT_Cr) { WRITE_SVLC( pcSlice->getSliceChromaQpDelta(COMPONENT_Cr), "slice_cr_qp_offset" ); - WRITE_SVLC( pcSlice->getSliceChromaQpDelta(JOINT_CbCr), "slice_cb_cr_qp_offset" ); +#if JVET_O0376_SPS_JOINTCBCR_FLAG + if (pcSlice->getSPS()->getJointCbCrEnabledFlag()) + { + WRITE_SVLC( pcSlice->getSliceChromaQpDelta(JOINT_CbCr), "slice_joint_cbcr_qp_offset"); + } +#else + WRITE_SVLC( pcSlice->getSliceChromaQpDelta(JOINT_CbCr), "slice_joint_cbcr_qp_offset"); +#endif } CHECK(numberValidComponents < COMPONENT_Cr+1, "Too many valid components"); } @@ -1595,6 +1662,9 @@ void HLSWriter::codeConstraintInfo ( const ConstraintInfo* cinfo ) WRITE_FLAG(cinfo->getNoPartitionConstraintsOverrideConstraintFlag() ? 1 : 0, "no_partition_constraints_override_constraint_flag"); WRITE_FLAG(cinfo->getNoSaoConstraintFlag() ? 1 : 0, "no_sao_constraint_flag"); WRITE_FLAG(cinfo->getNoAlfConstraintFlag() ? 1 : 0, "no_alf_constraint_flag"); +#if JVET_O0376_SPS_JOINTCBCR_FLAG + WRITE_FLAG(cinfo->getNoJointCbCrConstraintFlag() ? 1 : 0, "no_joint_cbcr_constraint_flag"); +#endif WRITE_FLAG(cinfo->getNoPcmConstraintFlag() ? 1 : 0, "no_pcm_constraint_flag"); WRITE_FLAG(cinfo->getNoRefWraparoundConstraintFlag() ? 1 : 0, "no_ref_wraparound_constraint_flag"); WRITE_FLAG(cinfo->getNoTemporalMvpConstraintFlag() ? 1 : 0, "no_temporal_mvp_constraint_flag");