diff --git a/cfg/hbd/hbd.cfg b/cfg/hbd/hbd.cfg index 5984fb8a35b7d2ec547b8e0c14ed29fdae04f0fa..b521382c43f3f7148ddb556475c3bccc68c37659 100755 --- a/cfg/hbd/hbd.cfg +++ b/cfg/hbd/hbd.cfg @@ -17,4 +17,5 @@ DMVR: 0 Affine: 0 ISP: 0 - +ExtendedRiceRRC : 1 +GolombRiceParameterAdaptation : 1 \ No newline at end of file diff --git a/doc/software-manual.tex b/doc/software-manual.tex index c2f4553bed4ae36d864c5a692eecc7813401e94b..95e18cd04001a98d272e027d3d479851eb14db86 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -1,4 +1,4 @@ -\documentclass[a4paper,11pt]{jvetdoc} +\documentclass[a4paper,11pt]{jvetdoc} \usepackage{geometry}[2010/02/12] @@ -3452,6 +3452,11 @@ When true, specifies the use of the residual rotation tool. Version 1 and some V When true, specifies the use of a single significance map context for transform-skipped and transquant-bypassed TUs. Version 1 and some Version 2 (RExt) profiles require this to be false. \\ +\Option{ExtendedRiceRRC} & +\Default{false} & +When true, specifies the that extension of the Golomb-Rice parameter derivation for RRC is used. Version 1 profiles require this to be false and some Version 2 (RExt) profiles may require this to be true. +\\ + \Option{GolombRiceParameterAdaptation} & \Default{false} & When true, enable the adaptation of the Golomb-Rice parameter over the course of each slice. Version 1 and some Version 2 (RExt) profiles require this to be false. diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 2f979b93781eaeaa5ca90fc663902f3a347488b7..a6f2e7184b561af3961a661a282b530706aca708 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -615,6 +615,9 @@ void EncApp::xInitLibCfg() m_cEncLib.setUseWPSNR ( m_bUseWPSNR ); #endif m_cEncLib.setExtendedPrecisionProcessingFlag ( m_extendedPrecisionProcessingFlag ); +#if JVET_V0106_RRC_RICE + m_cEncLib.setRrcRiceExtensionEnableFlag ( m_rrcRiceExtensionEnableFlag ); +#endif m_cEncLib.setHighPrecisionOffsetsEnabledFlag ( m_highPrecisionOffsetsEnabledFlag ); m_cEncLib.setWeightedPredictionMethod( m_weightedPredictionMethod ); @@ -784,6 +787,9 @@ void EncApp::xInitLibCfg() m_cEncLib.setUseBDPCM ( m_useBDPCM ); m_cEncLib.setTransformSkipRotationEnabledFlag ( m_transformSkipRotationEnabledFlag ); m_cEncLib.setTransformSkipContextEnabledFlag ( m_transformSkipContextEnabledFlag ); +#if JVET_V0106_RRC_RICE + m_cEncLib.setRrcRiceExtensionEnableFlag(m_rrcRiceExtensionEnableFlag); +#endif m_cEncLib.setPersistentRiceAdaptationEnabledFlag ( m_persistentRiceAdaptationEnabledFlag ); m_cEncLib.setCabacBypassAlignmentEnabledFlag ( m_cabacBypassAlignmentEnabledFlag ); m_cEncLib.setLog2MaxTransformSkipBlockSize ( m_log2MaxTransformSkipBlockSize ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 707cc04dd7cc6b95d8459fe43e7bd80fb5c52fc2..cc23dcdcc5ce8ba128f363e330e3c200c4c3eb04 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1137,6 +1137,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("ISPFast", m_useFastISP, false, "Fast encoder search for ISP") ("ResidualRotation", m_transformSkipRotationEnabledFlag, false, "Enable rotation of transform-skipped and transquant-bypassed TUs through 180 degrees prior to entropy coding (not valid in V1 profiles)") ("SingleSignificanceMapContext", m_transformSkipContextEnabledFlag, false, "Enable, for transform-skipped and transquant-bypassed TUs, the selection of a single significance map context variable for all coefficients (not valid in V1 profiles)") +#if JVET_V0106_RRC_RICE + ("ExtendedRiceRRC", m_rrcRiceExtensionEnableFlag, false, "Enable the extention of the Golomb-Rice parameter derivation for RRC") +#endif ("GolombRiceParameterAdaptation", m_persistentRiceAdaptationEnabledFlag, false, "Enable the adaptation of the Golomb-Rice parameter over the course of each slice") ("AlignCABACBeforeBypass", m_cabacBypassAlignmentEnabledFlag, false, "Align the CABAC engine to a defined fraction of a bit prior to coding bypass data. Must be 1 in high bit rate profile, 0 otherwise") ("SAO", m_bUseSAO, true, "Enable Sample Adaptive Offset") @@ -2704,6 +2707,9 @@ bool EncAppCfg::xCheckParameter() xConfirmPara(m_log2MaxTransformSkipBlockSize>=6, "Transform Skip Log2 Max Size must be less or equal to 5 for given profile."); xConfirmPara(m_transformSkipRotationEnabledFlag==true, "UseResidualRotation must not be enabled for given profile."); xConfirmPara(m_transformSkipContextEnabledFlag==true, "UseSingleSignificanceMapContext must not be enabled for given profile."); +#if JVET_V0106_RRC_RICE + xConfirmPara(m_rrcRiceExtensionEnableFlag == true, "Extention of the Golomb-Rice parameter derivation for RRC must not be enabled for given profile."); +#endif xConfirmPara(m_persistentRiceAdaptationEnabledFlag==true, "GolombRiceParameterAdaption must not be enabled for given profile."); xConfirmPara(m_extendedPrecisionProcessingFlag==true, "UseExtendedPrecision must not be enabled for given profile."); xConfirmPara(m_highPrecisionOffsetsEnabledFlag==true, "UseHighPrecisionPredictionWeighting must not be enabled for given profile."); @@ -4024,6 +4030,9 @@ void EncAppCfg::xPrintParameter() msg( DETAILS, "transform_skip_rotation_enabled_flag : %s\n", (m_transformSkipRotationEnabledFlag ? "Enabled" : "Disabled") ); msg( DETAILS, "transform_skip_context_enabled_flag : %s\n", (m_transformSkipContextEnabledFlag ? "Enabled" : "Disabled") ); msg( DETAILS, "high_precision_offsets_enabled_flag : %s\n", (m_highPrecisionOffsetsEnabledFlag ? "Enabled" : "Disabled") ); +#if JVET_V0106_RRC_RICE + msg( DETAILS, "rrc_rice_extension_flag : %s\n", (m_rrcRiceExtensionEnableFlag ? "Enabled" : "Disabled") ); +#endif msg( DETAILS, "persistent_rice_adaptation_enabled_flag: %s\n", (m_persistentRiceAdaptationEnabledFlag ? "Enabled" : "Disabled") ); msg( DETAILS, "cabac_bypass_alignment_enabled_flag : %s\n", (m_cabacBypassAlignmentEnabledFlag ? "Enabled" : "Disabled") ); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 2d2955da9a5d6367b1904419194f538c57c6fb63..626836ba53333a0f7b708dc4461f84200849e118 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -240,6 +240,9 @@ protected: uint32_t m_log2MaxTransformSkipBlockSize; ///< transform-skip maximum size (minimum of 2) bool m_transformSkipRotationEnabledFlag; ///< control flag for transform-skip/transquant-bypass residual rotation bool m_transformSkipContextEnabledFlag; ///< control flag for transform-skip/transquant-bypass single significance map context +#if JVET_V0106_RRC_RICE + bool m_rrcRiceExtensionEnableFlag; ///< control flag for enabling extension of the Golomb-Rice parameter derivation for RRC +#endif bool m_persistentRiceAdaptationEnabledFlag; ///< control flag for Golomb-Rice parameter adaptation over each slice bool m_cabacBypassAlignmentEnabledFlag; bool m_ISP; diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 5304de1a0fcbcde5d035a1268c6b384dd30ccb17..795be5caa8fd50730886ab499707ace7b1cb4c58 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -282,8 +282,11 @@ static const int MAX_NUM_QP_VALUES = MAX_QP + 1 - MIN_QP_VALUE_FOR_16_BIT; // // Cost mode support static const int LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP = 0; ///< QP to use for lossless coding. static const int LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME =4; ///< QP' to use for mixed_lossy_lossless coding. - +#if JVET_V0106_RRC_RICE +static const int RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS = MAX_NUM_COMPONENT; +#else static const int RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS = 4; +#endif static const int RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION = 0; ///< Additional fixed bit precision used during encoder-side weighting prediction analysis. Currently only used when high_precision_prediction_weighting_flag is set, for backwards compatibility reasons. diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index 5a4c03d7890fb6412c60678ef97bb0fc856af09e..44636c956b04f694098436ce8254bcc307284fb5 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -115,6 +115,21 @@ CoeffCodingContext::CoeffCodingContext(const TransformUnit &tu, ComponentID comp const_cast<int&>(m_lastShiftX) = (log2sizeX + 1) >> 2; const_cast<int&>(m_lastShiftY) = (log2sizeY + 1) >> 2; } + +#if JVET_V0106_RRC_RICE + m_cctxBaseLevel = 4; // default value for RRC rice derivation in VVCv1, is updated for extended RRC rice derivation + m_histValue = 0; // default value for RRC rice derivation in VVCv1, is updated for history-based extention of RRC rice derivation + m_updateHist = 0; // default value for RRC rice derivation (history update is disabled), is updated for history-based extention of RRC rice derivation + + if (tu.cs->sps->getSpsRangeExtension().getRrcRiceExtensionEnableFlag()) + { + deriveRiceRRC = &CoeffCodingContext::deriveRiceExt; + } + else + { + deriveRiceRRC = &CoeffCodingContext::deriveRice; + } +#endif } void CoeffCodingContext::initSubblock( int SubsetId, bool sigGroupFlag ) diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index 9d863b0167285ef76daca88a15b572f8d3520f55..b2033020dc749088ce547daff21c898f38b07e4c 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -38,7 +38,9 @@ #ifndef __CONTEXTMODELLING__ #define __CONTEXTMODELLING__ - +#if JVET_V0106_RRC_RICE +#include "Rom.h" +#endif #include "CommonDef.h" #include "Contexts.h" #include "Slice.h" @@ -192,6 +194,127 @@ public: return unsigned(std::max<TCoeff>(std::min<TCoeff>(sum - 5 * baseLevel, 31), 0)); } +#if JVET_V0106_RRC_RICE + void updateRiceStat(unsigned &riceStat, TCoeff rem, int remainderFlag) + { + if (remainderFlag) + { + riceStat = (riceStat + floorLog2((uint32_t)rem) + 2) >> 1; + } + else + { + riceStat = (riceStat + floorLog2((uint32_t)rem)) >> 1; + } + } + + unsigned templateAbsCompare(TCoeff sum) + { + int rangeIdx = 0; + if (sum < g_riceT[0]) + { + rangeIdx = 0; + } + else if (sum < g_riceT[1]) + { + rangeIdx = 1; + } + else if (sum < g_riceT[2]) + { + rangeIdx = 2; + } + else if (sum < g_riceT[3]) + { + rangeIdx = 3; + } + else + { + rangeIdx = 4; + } + + return g_riceShift[rangeIdx]; + } + + unsigned templateAbsSumExt(int scanPos, const TCoeff* coeff, int baseLevel) + { + unsigned riceParam; + const uint32_t posY = m_scan[scanPos].y; + const uint32_t posX = m_scan[scanPos].x; + const TCoeff* data = coeff + posX + posY * m_width; + TCoeff sum = 0; + if (posX < m_width - 1) + { + sum += abs(data[1]); + if (posX < m_width - 2) + { + sum += abs(data[2]); + } + else + { + sum += m_histValue; + } + + if (posY < m_height - 1) + { + sum += abs(data[m_width + 1]); + } + else + { + sum += m_histValue; + } + } + else + { + sum += 2 * m_histValue; + } + if (posY < m_height - 1) + { + sum += abs(data[m_width]); + if (posY < m_height - 2) + { + sum += abs(data[m_width << 1]); + } + else + { + sum += m_histValue; + } + } + else + { + sum += m_histValue; + } + + int currentShift = templateAbsCompare(sum); + sum = sum >> currentShift; + if (baseLevel == 0) + { + riceParam = unsigned(std::min<TCoeff>(sum, 31)); + } + else + { + riceParam = unsigned(std::max<TCoeff>(std::min<TCoeff>(sum - baseLevel, 31), 0)); + } + + riceParam = g_goRiceParsCoeff[riceParam] + currentShift; + + return riceParam; + } + + unsigned (CoeffCodingContext::*deriveRiceRRC)(int scanPos, const TCoeff* coeff, int baseLevel); + + unsigned deriveRice(int scanPos, const TCoeff* coeff, int baseLevel) + { + unsigned sumAbs = templateAbsSum(scanPos, coeff, baseLevel); + unsigned riceParam = g_goRiceParsCoeff[sumAbs]; + return riceParam; + } + + unsigned deriveRiceExt(int scanPos, const TCoeff* coeff, int baseLevel) + { + unsigned riceParam = templateAbsSumExt(scanPos, coeff, baseLevel); + return riceParam; + } +#endif + unsigned sigCtxIdAbsTS( int scanPos, const TCoeff* coeff ) { const uint32_t posY = m_scan[scanPos].y; @@ -363,6 +486,15 @@ public: int regBinLimit; +#if JVET_V0106_RRC_RICE + unsigned getBaseLevel() { return m_cctxBaseLevel; }; + void setBaseLevel(int value) { m_cctxBaseLevel = value; }; + TCoeff getHistValue() { return m_histValue; }; + void setHistValue(TCoeff value) { m_histValue = value; }; + bool getUpdateHist() { return m_updateHist; }; + void setUpdateHist(bool value) { m_updateHist = value; }; +#endif + private: // constant const ComponentID m_compID; @@ -417,6 +549,11 @@ private: int m_remainingContextBins; std::bitset<MLS_GRP_NUM> m_sigCoeffGroupFlag; const bool m_bdpcm; +#if JVET_V0106_RRC_RICE + int m_cctxBaseLevel; + TCoeff m_histValue; + bool m_updateHist; +#endif }; diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h index a5e89abf8f52bcc7f9a38aa195f85ac7d5f4173c..4337d0122eab79cbf85c9cd02036b3cb51858a9b 100644 --- a/source/Lib/CommonLib/Contexts.h +++ b/source/Lib/CommonLib/Contexts.h @@ -382,6 +382,16 @@ public: } } +#if JVET_V0106_RRC_RICE + void riceStatReset(int bitDepth) + { + for (std::size_t k = 0; k < RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS; k++) + { + m_GRAdaptStats[k] = (bitDepth > 10) ? 2 * floorLog2(bitDepth - 10) : 0; + } + } +#endif + void loadPStates( const std::vector<uint16_t>& probStates ) { switch( m_BPMType ) @@ -416,6 +426,11 @@ public: const unsigned& getGRAdaptStats ( unsigned id ) const { return m_GRAdaptStats[id]; } unsigned& getGRAdaptStats ( unsigned id ) { return m_GRAdaptStats[id]; } +#if JVET_V0106_RRC_RICE + const unsigned getBaseLevel() const { return m_baseLevel; } + void setBaseLevel(int value) { m_baseLevel = value; } +#endif + public: unsigned getBPMType () const { return m_BPMType; } const Ctx& getCtx () const { return *this; } @@ -438,6 +453,10 @@ private: CtxStore<BinProbModel_Std> m_CtxStore_Std; protected: unsigned m_GRAdaptStats[RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS]; +#if JVET_V0106_RRC_RICE + int m_baseLevel; +#endif + }; diff --git a/source/Lib/CommonLib/DepQuant.cpp b/source/Lib/CommonLib/DepQuant.cpp index a983b6c48834ec67119295d54d91326613bfd76e..f3e985de43d9ff178521d0cd3a71bc198729aaa5 100644 --- a/source/Lib/CommonLib/DepQuant.cpp +++ b/source/Lib/CommonLib/DepQuant.cpp @@ -38,7 +38,9 @@ #include <bitset> - +#if JVET_V0106_RRC_RICE +#include "ContextModelling.h" +#endif @@ -849,13 +851,38 @@ namespace DQIntern uint8_t m_memory[ 8 * ( MAX_TB_SIZEY * MAX_TB_SIZEY + MLS_GRP_NUM ) ]; }; +#if JVET_V0106_DEP_QUANT_ENC_OPT +#define RICEMAX 64 +#define RICE_ORDER_MAX 16 + const int32_t g_goRiceBits[RICE_ORDER_MAX][RICEMAX] = +#else #define RICEMAX 32 const int32_t g_goRiceBits[4][RICEMAX] = +#endif { +#if JVET_V0106_DEP_QUANT_ENC_OPT + { 32768, 65536, 98304, 131072, 163840, 196608, 262144, 262144, 327680, 327680, 327680, 327680, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288 }, + { 65536, 65536, 98304, 98304, 131072, 131072, 163840, 163840, 196608, 196608, 229376, 229376, 294912, 294912, 294912, 294912, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520 }, + { 98304, 98304, 98304, 98304, 131072, 131072, 131072, 131072, 163840, 163840, 163840, 163840, 196608, 196608, 196608, 196608, 229376, 229376, 229376, 229376, 262144, 262144, 262144, 262144, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752 }, + { 131072, 131072, 131072, 131072, 131072, 131072, 131072, 131072, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448 }, + { 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144 }, + { 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376 }, + { 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376 }, + { 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144, 262144 }, + { 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912, 294912 }, + { 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680 }, + { 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448 }, + { 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216 }, + { 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984 }, + { 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752 }, + { 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520, 491520 }, + { 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288, 524288 }, +#else { 32768, 65536, 98304, 131072, 163840, 196608, 262144, 262144, 327680, 327680, 327680, 327680, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 393216, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752, 458752}, { 65536, 65536, 98304, 98304, 131072, 131072, 163840, 163840, 196608, 196608, 229376, 229376, 294912, 294912, 294912, 294912, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 360448, 425984, 425984, 425984, 425984, 425984, 425984, 425984, 425984}, { 98304, 98304, 98304, 98304, 131072, 131072, 131072, 131072, 163840, 163840, 163840, 163840, 196608, 196608, 196608, 196608, 229376, 229376, 229376, 229376, 262144, 262144, 262144, 262144, 327680, 327680, 327680, 327680, 327680, 327680, 327680, 327680}, {131072, 131072, 131072, 131072, 131072, 131072, 131072, 131072, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 163840, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 196608, 229376, 229376, 229376, 229376, 229376, 229376, 229376, 229376} +#endif }; class State @@ -865,7 +892,11 @@ namespace DQIntern State( const RateEstimator& rateEst, CommonCtx& commonCtx, const int stateId ); template<uint8_t numIPos> +#if JVET_V0106_RRC_RICE + inline void updateState(const ScanInfo &scanInfo, const State *prevStates, const Decision &decision, const int baseLevel, const bool extRiceFlag); +#else inline void updateState(const ScanInfo &scanInfo, const State *prevStates, const Decision &decision); +#endif inline void updateStateEOS(const ScanInfo &scanInfo, const State *prevStates, const State *skipStates, const Decision &decision); @@ -1022,6 +1053,33 @@ namespace DQIntern unsigned effHeight; }; +#if JVET_V0106_RRC_RICE + unsigned templateAbsCompare(TCoeff sum) + { + int rangeIdx = 0; + if (sum < g_riceT[0]) + { + rangeIdx = 0; + } + else if (sum < g_riceT[1]) + { + rangeIdx = 1; + } + else if (sum < g_riceT[2]) + { + rangeIdx = 2; + } + else if (sum < g_riceT[3]) + { + rangeIdx = 3; + } + else + { + rangeIdx = 4; + } + return g_riceShift[rangeIdx]; + } +#endif State::State( const RateEstimator& rateEst, CommonCtx& commonCtx, const int stateId ) : m_sbbFracBits { { 0, 0 } } @@ -1033,7 +1091,11 @@ namespace DQIntern } template<uint8_t numIPos> +#if JVET_V0106_RRC_RICE + inline void State::updateState(const ScanInfo &scanInfo, const State *prevStates, const Decision &decision, const int baseLevel, const bool extRiceFlag) +#else inline void State::updateState(const ScanInfo &scanInfo, const State *prevStates, const Decision &decision) +#endif { m_rdCost = decision.rdCost; if( decision.prevId > -2 ) @@ -1138,8 +1200,24 @@ namespace DQIntern UPDATE(4); } #undef UPDATE +#if JVET_V0106_RRC_RICE + if (extRiceFlag) + { + unsigned currentShift = templateAbsCompare(sumAbs); + sumAbs = sumAbs >> currentShift; + int sumAll = std::max(std::min(31, (int)sumAbs - (int)baseLevel), 0); + m_goRicePar = g_goRiceParsCoeff[sumAll]; + m_goRicePar += currentShift; + } + else + { + int sumAll = std::max(std::min(31, (int)sumAbs - 4 * 5), 0); + m_goRicePar = g_goRiceParsCoeff[sumAll]; + } +#else int sumAll = std::max(std::min(31, (int)sumAbs - 4 * 5), 0); m_goRicePar = g_goRiceParsCoeff[sumAll]; +#endif } else { @@ -1176,8 +1254,24 @@ namespace DQIntern UPDATE(4); } #undef UPDATE +#if JVET_V0106_RRC_RICE + if (extRiceFlag) + { + unsigned currentShift = templateAbsCompare(sumAbs); + sumAbs = sumAbs >> currentShift; + sumAbs = std::min<TCoeff>(31, sumAbs); + m_goRicePar = g_goRiceParsCoeff[sumAbs]; + m_goRicePar += currentShift; + } + else + { + sumAbs = std::min<TCoeff>(31, sumAbs); + m_goRicePar = g_goRiceParsCoeff[sumAbs]; + } +#else sumAbs = std::min<TCoeff>(31, sumAbs); - m_goRicePar = g_goRiceParsCoeff[sumAbs]; + m_goRicePar = g_goRiceParsCoeff[sumAbs]; +#endif m_goRiceZero = g_goRicePosCoeff0(m_stateId, m_goRicePar); } } @@ -1308,6 +1402,11 @@ namespace DQIntern void quant ( TransformUnit& tu, const CCoeffBuf& srcCoeff, const ComponentID compID, const QpParam& cQP, const double lambda, const Ctx& ctx, TCoeff& absSum, bool enableScalingLists, int* quantCoeff ); void dequant ( const TransformUnit& tu, CoeffBuf& recCoeff, const ComponentID compID, const QpParam& cQP, bool enableScalingLists, int* quantCoeff ); +#if JVET_V0106_RRC_RICE + int m_baseLevel; + bool m_extRiceRRCFlag; +#endif + private: void xDecideAndUpdate ( const TCoeff absCoeff, const ScanInfo& scanInfo, bool zeroOut, TCoeff quantCoeff); void xDecide ( const ScanPosType spt, const TCoeff absCoeff, const int lastOffset, Decision* decisions, bool zeroOut, TCoeff quantCoeff ); @@ -1405,6 +1504,43 @@ namespace DQIntern { switch( scanInfo.nextNbInfoSbb.num ) { +#if JVET_V0106_RRC_RICE + case 0: + m_currStates[0].updateState<0>(scanInfo, m_prevStates, decisions[0], m_baseLevel, m_extRiceRRCFlag); + m_currStates[1].updateState<0>(scanInfo, m_prevStates, decisions[1], m_baseLevel, m_extRiceRRCFlag); + m_currStates[2].updateState<0>(scanInfo, m_prevStates, decisions[2], m_baseLevel, m_extRiceRRCFlag); + m_currStates[3].updateState<0>(scanInfo, m_prevStates, decisions[3], m_baseLevel, m_extRiceRRCFlag); + break; + case 1: + m_currStates[0].updateState<1>(scanInfo, m_prevStates, decisions[0], m_baseLevel, m_extRiceRRCFlag); + m_currStates[1].updateState<1>(scanInfo, m_prevStates, decisions[1], m_baseLevel, m_extRiceRRCFlag); + m_currStates[2].updateState<1>(scanInfo, m_prevStates, decisions[2], m_baseLevel, m_extRiceRRCFlag); + m_currStates[3].updateState<1>(scanInfo, m_prevStates, decisions[3], m_baseLevel, m_extRiceRRCFlag); + break; + case 2: + m_currStates[0].updateState<2>(scanInfo, m_prevStates, decisions[0], m_baseLevel, m_extRiceRRCFlag); + m_currStates[1].updateState<2>(scanInfo, m_prevStates, decisions[1], m_baseLevel, m_extRiceRRCFlag); + m_currStates[2].updateState<2>(scanInfo, m_prevStates, decisions[2], m_baseLevel, m_extRiceRRCFlag); + m_currStates[3].updateState<2>(scanInfo, m_prevStates, decisions[3], m_baseLevel, m_extRiceRRCFlag); + break; + case 3: + m_currStates[0].updateState<3>(scanInfo, m_prevStates, decisions[0], m_baseLevel, m_extRiceRRCFlag); + m_currStates[1].updateState<3>(scanInfo, m_prevStates, decisions[1], m_baseLevel, m_extRiceRRCFlag); + m_currStates[2].updateState<3>(scanInfo, m_prevStates, decisions[2], m_baseLevel, m_extRiceRRCFlag); + m_currStates[3].updateState<3>(scanInfo, m_prevStates, decisions[3], m_baseLevel, m_extRiceRRCFlag); + break; + case 4: + m_currStates[0].updateState<4>(scanInfo, m_prevStates, decisions[0], m_baseLevel, m_extRiceRRCFlag); + m_currStates[1].updateState<4>(scanInfo, m_prevStates, decisions[1], m_baseLevel, m_extRiceRRCFlag); + m_currStates[2].updateState<4>(scanInfo, m_prevStates, decisions[2], m_baseLevel, m_extRiceRRCFlag); + m_currStates[3].updateState<4>(scanInfo, m_prevStates, decisions[3], m_baseLevel, m_extRiceRRCFlag); + break; + default: + m_currStates[0].updateState<5>(scanInfo, m_prevStates, decisions[0], m_baseLevel, m_extRiceRRCFlag); + m_currStates[1].updateState<5>(scanInfo, m_prevStates, decisions[1], m_baseLevel, m_extRiceRRCFlag); + m_currStates[2].updateState<5>(scanInfo, m_prevStates, decisions[2], m_baseLevel, m_extRiceRRCFlag); + m_currStates[3].updateState<5>(scanInfo, m_prevStates, decisions[3], m_baseLevel, m_extRiceRRCFlag); +#else case 0: m_currStates[0].updateState<0>( scanInfo, m_prevStates, decisions[0] ); m_currStates[1].updateState<0>( scanInfo, m_prevStates, decisions[1] ); @@ -1440,6 +1576,7 @@ namespace DQIntern m_currStates[1].updateState<5>( scanInfo, m_prevStates, decisions[1] ); m_currStates[2].updateState<5>( scanInfo, m_prevStates, decisions[2] ); m_currStates[3].updateState<5>( scanInfo, m_prevStates, decisions[3] ); +#endif } } @@ -1458,6 +1595,10 @@ namespace DQIntern //===== reset / pre-init ===== const TUParameters& tuPars = *g_Rom.getTUPars( tu.blocks[compID], compID ); m_quant.initQuantBlock ( tu, compID, cQP, lambda ); +#if JVET_V0106_RRC_RICE + m_baseLevel = ctx.getBaseLevel(); + m_extRiceRRCFlag = tu.cs->sps->getSpsRangeExtension().getRrcRiceExtensionEnableFlag(); +#endif TCoeff* qCoeff = tu.getCoeffs( compID ).buf; const TCoeff* tCoeff = srcCoeff.buf; const int numCoeff = tu.blocks[compID].area(); diff --git a/source/Lib/CommonLib/QuantRDOQ.cpp b/source/Lib/CommonLib/QuantRDOQ.cpp index a21660487f3390eb74a161bfb3fb0208e47378df..c66e173f493fd826b0f9dcc88ff4d59a34762ce8 100644 --- a/source/Lib/CommonLib/QuantRDOQ.cpp +++ b/source/Lib/CommonLib/QuantRDOQ.cpp @@ -645,6 +645,19 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID, const TCoeff entropyCodingMaximum = (1 << maxLog2TrDynamicRange) - 1; CoeffCodingContext cctx(tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag()); +#if JVET_V0106_RRC_RICE + int baseLevel = cctx.getBaseLevel(); + if (tu.cs->slice->getSPS()->getSpsRangeExtension().getPersistentRiceAdaptationEnabledFlag()) + { + unsigned riceStats = ctx.getGRAdaptStats((unsigned)compID); + TCoeff historyValue = (TCoeff)1 << riceStats; + cctx.setHistValue(historyValue); + } + else + { + cctx.setHistValue(0); + } +#endif const int iCGSizeM1 = (1 << cctx.log2CGSize()) - 1; int iCGLastScanPos = -1; @@ -736,8 +749,12 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID, uint32_t goRiceZero = 0; if( remRegBins < 4 ) { +#if JVET_V0106_RRC_RICE + goRiceParam = (cctx.*(cctx.deriveRiceRRC))(iScanPos, piDstCoeff, 0); +#else unsigned sumAbs = cctx.templateAbsSum( iScanPos, piDstCoeff, 0 ); goRiceParam = g_goRiceParsCoeff[sumAbs]; +#endif goRiceZero = g_goRicePosCoeff0(0, goRiceParam); } @@ -793,8 +810,12 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID, } else if( remRegBins >= 4 ) { +#if JVET_V0106_RRC_RICE + goRiceParam = (cctx.*(cctx.deriveRiceRRC))(iScanPos, piDstCoeff, baseLevel); +#else int sumAll = cctx.templateAbsSum(iScanPos, piDstCoeff, 4); goRiceParam = g_goRiceParsCoeff[sumAll]; +#endif remRegBins -= (uiLevel < 2 ? uiLevel : 3) + (iScanPos != iLastScanPos); } } diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp index 5e6f5bdf4d8357bdcf8be39ff7835f4f067eb560..d35bbcbfc758d3f6b3543f8091c529a4ec9fd0c4 100644 --- a/source/Lib/CommonLib/Rom.cpp +++ b/source/Lib/CommonLib/Rom.cpp @@ -523,6 +523,10 @@ UnitScale g_miScaling( MIN_CU_LOG2, MIN_CU_LOG2 ); // ==================================================================================================================== // Scanning order & context model mapping // ==================================================================================================================== +#if JVET_V0106_RRC_RICE +int g_riceT[4] = { 32,128, 512, 2048 }; +int g_riceShift[5] = { 0, 2, 4, 6, 8 }; +#endif // scanning order table ScanElement *g_scanOrder[SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][MAX_CU_SIZE / 2 + 1][MAX_CU_SIZE / 2 + 1]; diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h index 1a9b20d26e5ac86ff5d00eff27fbdfbfcca477fa..a1cbf394c78c711cc6e552ff360dea96fac8e210 100644 --- a/source/Lib/CommonLib/Rom.h +++ b/source/Lib/CommonLib/Rom.h @@ -87,6 +87,10 @@ static const int g_transformMatrixShift[TRANSFORM_NUMBER_OF_DIRECTIONS] = { 6, // ==================================================================================================================== // Scanning order & context mapping table // ==================================================================================================================== +#if JVET_V0106_RRC_RICE +extern int g_riceT[4]; +extern int g_riceShift[5]; +#endif extern const uint32_t g_groupIdx[MAX_TB_SIZEY]; extern const uint32_t g_minInGroup[LAST_SIGNIFICANT_GROUPS]; diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 676564575a7d9355e0d4844cc4c1b8a5b3a4e7bb..0f4da102eaffb4c06f2c11c16a25fd6e92ae8d8e 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -2793,6 +2793,9 @@ SPSRExt::SPSRExt() , m_extendedPrecisionProcessingFlag (false) , m_intraSmoothingDisabledFlag (false) , m_highPrecisionOffsetsEnabledFlag (false) +#if JVET_V0106_RRC_RICE + , m_rrcRiceExtensionEnableFlag(false) +#endif , m_persistentRiceAdaptationEnabledFlag(false) , m_cabacBypassAlignmentEnabledFlag (false) { diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index d12d7e9ef0980b16a6bd596e996dd62f0bca6c59..c0beffac1e9be5812e2a57740820e1b8f3acdaad 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1304,6 +1304,9 @@ private: bool m_extendedPrecisionProcessingFlag; bool m_intraSmoothingDisabledFlag; bool m_highPrecisionOffsetsEnabledFlag; +#if JVET_V0106_RRC_RICE + bool m_rrcRiceExtensionEnableFlag; +#endif bool m_persistentRiceAdaptationEnabledFlag; bool m_cabacBypassAlignmentEnabledFlag; @@ -1317,6 +1320,9 @@ public: || getExtendedPrecisionProcessingFlag() || getIntraSmoothingDisabledFlag() || getHighPrecisionOffsetsEnabledFlag() +#if JVET_V0106_RRC_RICE + || getRrcRiceExtensionEnableFlag() +#endif || getPersistentRiceAdaptationEnabledFlag() || getCabacBypassAlignmentEnabledFlag(); } @@ -1337,6 +1343,11 @@ public: bool getHighPrecisionOffsetsEnabledFlag() const { return m_highPrecisionOffsetsEnabledFlag; } void setHighPrecisionOffsetsEnabledFlag(bool value) { m_highPrecisionOffsetsEnabledFlag = value; } +#if JVET_V0106_RRC_RICE + bool getRrcRiceExtensionEnableFlag() const { return m_rrcRiceExtensionEnableFlag; } + void setRrcRiceExtensionEnableFlag(const bool value) { m_rrcRiceExtensionEnableFlag = value; } +#endif + bool getPersistentRiceAdaptationEnabledFlag() const { return m_persistentRiceAdaptationEnabledFlag; } void setPersistentRiceAdaptationEnabledFlag(const bool value) { m_persistentRiceAdaptationEnabledFlag = value; } @@ -2641,6 +2652,9 @@ private: int m_deblockingFilterCrBetaOffsetDiv2; //< beta offset for deblocking filter int m_deblockingFilterCrTcOffsetDiv2; //< tc offset for deblocking filter bool m_depQuantEnabledFlag; //!< dependent quantization enabled flag +#if JVET_V0106_RRC_RICE + int m_riceBaseLevelValue; //< baseLevel value for abs_remainder +#endif bool m_signDataHidingEnabledFlag; //!< sign data hiding enabled flag bool m_tsResidualCodingDisabledFlag; int m_list1IdxToList0Idx[MAX_NUM_REF]; @@ -2833,6 +2847,11 @@ public: void setDeblockingFilterCrTcOffsetDiv2( int i ) { m_deblockingFilterCrTcOffsetDiv2 = i; } void setDepQuantEnabledFlag( bool b ) { m_depQuantEnabledFlag = b; } bool getDepQuantEnabledFlag() const { return m_depQuantEnabledFlag; } +#if JVET_V0106_RRC_RICE + void setRiceBaseLevel(int b) { m_riceBaseLevelValue = b; } + int getRiceBaseLevel() const { return m_riceBaseLevelValue; } +#endif + void setSignDataHidingEnabledFlag( bool b ) { m_signDataHidingEnabledFlag = b; } bool getSignDataHidingEnabledFlag() const { return m_signDataHidingEnabledFlag; } void setTSResidualCodingDisabledFlag(bool b) { m_tsResidualCodingDisabledFlag = b; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 5a2d37580cd03fa074d28824e3202bb2d8ac621b..bfc11519ba5f691f76ce05217c5e9cb99c11a045 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,7 @@ #include <assert.h> #include <cassert> +#define JVET_V0106_RRC_RICE 1 // JVET_V0106: Extension of the RRC rice derivation for high bit depth profile (VVCv2). #define JVET_V0131_CORRECT_TR_HBD 1 // correcting the 4x4 BDST7/DCT8 transform matrices for high bit-depth coding // clang-format off @@ -233,9 +234,13 @@ typedef std::pair<int, int> TrCost; #if RExt__HIGH_BIT_DEPTH_SUPPORT #define FULL_NBIT 1 ///< When enabled, use distortion measure derived from all bits of source data, otherwise discard (bitDepth - 8) least-significant bits of distortion #define RExt__HIGH_PRECISION_FORWARD_TRANSFORM 1 ///< 0 use original 6-bit transform matrices for both forward and inverse transform, 1 (default) = use original matrices for inverse transform and high precision matrices for forward transform +#if JVET_V0106_RRC_RICE +#define JVET_V0106_DEP_QUANT_ENC_OPT 1 ///< 0 use original g_goRiceBits[4][32] LUT for codeword length estimation at encoder, 1 (default) use extended g_goRiceBits[16][64] LUT for codeword length estimation at encoder +#endif #else #define FULL_NBIT 1 ///< When enabled, use distortion measure derived from all bits of source data, otherwise discard (bitDepth - 8) least-significant bits of distortion #define RExt__HIGH_PRECISION_FORWARD_TRANSFORM 0 ///< 0 (default) use original 6-bit transform matrices for both forward and inverse transform, 1 = use original matrices for inverse transform and high precision matrices for forward transform +#define JVET_V0106_DEP_QUANT_ENC_OPT 0 ///< 0 (default) use original g_goRiceBits[4][32] LUT for codeword length estimation at encoder, 1 - use extended g_goRiceBits[16][64] LUT for codeword length estimation at encoder #endif #if FULL_NBIT diff --git a/source/Lib/DecoderLib/BinDecoder.cpp b/source/Lib/DecoderLib/BinDecoder.cpp index b97e42714ba092579b8fbd9a3e7dd1d40f99f485..49291cbc65799725eca095c69df34aee0b01e02a 100644 --- a/source/Lib/DecoderLib/BinDecoder.cpp +++ b/source/Lib/DecoderLib/BinDecoder.cpp @@ -97,6 +97,12 @@ void BinDecoderBase::reset( int qp, int initId ) start(); } +#if JVET_V0106_RRC_RICE +void BinDecoderBase::riceStatReset(int bitDepth) +{ + Ctx::riceStatReset(bitDepth); +} +#endif unsigned BinDecoderBase::decodeBinEP() { diff --git a/source/Lib/DecoderLib/BinDecoder.h b/source/Lib/DecoderLib/BinDecoder.h index 1095a7477040291942924174d5f2bf8d8847bfd1..2ccb577bba276b7a0111a7a20cdbf2792dead373 100644 --- a/source/Lib/DecoderLib/BinDecoder.h +++ b/source/Lib/DecoderLib/BinDecoder.h @@ -61,6 +61,9 @@ public: void start (); void finish (); void reset ( int qp, int initId ); +#if JVET_V0106_RRC_RICE + void riceStatReset(int bitDepth); +#endif #if RExt__DECODER_DEBUG_BIT_STATISTICS void set ( const CodingStatisticsClassType& type) { ptype = &type; } #endif diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index a739c03d58055e0ec97ff72e7bedefdd6349d873..128b4a237eb56da93a94822c2a5036cbb830001b 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -83,6 +83,10 @@ void CABACReader::initCtxModels( Slice& slice ) } } m_BinDecoder.reset( qp, (int)sliceType ); +#if JVET_V0106_RRC_RICE + m_BinDecoder.setBaseLevel(slice.getRiceBaseLevel()); + m_BinDecoder.riceStatReset(slice.getSPS()->getBitDepth(CHANNEL_TYPE_LUMA)); +#endif } @@ -2961,6 +2965,17 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID, CUCtx& int ctxBinSampleRatio = (compID == COMPONENT_Y) ? MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_LUMA : MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_CHROMA; cctx.regBinLimit = (tu.getTbAreaAfterCoefZeroOut(compID) * ctxBinSampleRatio) >> 4; +#if JVET_V0106_RRC_RICE + int baseLevel = m_BinDecoder.getCtx().getBaseLevel(); + cctx.setBaseLevel(baseLevel); + if (tu.cs->slice->getSPS()->getSpsRangeExtension().getPersistentRiceAdaptationEnabledFlag()) + { + cctx.setUpdateHist(1); + unsigned riceStats = m_BinDecoder.getCtx().getGRAdaptStats((unsigned)compID); + TCoeff historyValue = (TCoeff)1 << riceStats; + cctx.setHistValue(historyValue); + } +#endif for (int subSetId = (cctx.scanPosLast() >> cctx.log2CGSize()); subSetId >= 0; subSetId--) { cctx.initSubblock(subSetId); @@ -3196,6 +3211,10 @@ void CABACReader::residual_coding_subblock( CoeffCodingContext& cctx, TCoeff* co const bool isLast = cctx.isLast(); int firstSigPos = ( isLast ? cctx.scanPosLast() : cctx.maxSubPos() ); int nextSigPos = firstSigPos; +#if JVET_V0106_RRC_RICE + int baseLevel = cctx.getBaseLevel(); + bool updateHistory = cctx.getUpdateHist(); +#endif //===== decode significant_coeffgroup_flag ===== RExt__DECODER_DEBUG_BIT_STATISTICS_SET( ctype_group ); @@ -3281,8 +3300,13 @@ void CABACReader::residual_coding_subblock( CoeffCodingContext& cctx, TCoeff* co unsigned ricePar = 0; for( int scanPos = firstSigPos; scanPos > firstPosMode2; scanPos-- ) { +#if JVET_V0106_RRC_RICE + ricePar = (cctx.*(cctx.deriveRiceRRC))(scanPos, coeff, baseLevel); +#else int sumAll = cctx.templateAbsSum(scanPos, coeff, 4); ricePar = g_goRiceParsCoeff[sumAll]; +#endif + TCoeff& tcoeff = coeff[ cctx.blockPos( scanPos ) ]; if( tcoeff >= 4 ) { @@ -3290,20 +3314,42 @@ void CABACReader::residual_coding_subblock( CoeffCodingContext& cctx, TCoeff* co int rem = m_BinDecoder.decodeRemAbsEP( ricePar, COEF_REMAIN_BIN_REDUCTION, cctx.maxLog2TrDRange() ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, ricePar ); tcoeff += (rem<<1); +#if JVET_V0106_RRC_RICE + if ((updateHistory) && (rem > 0)) + { + unsigned &riceStats = m_BinDecoder.getCtx().getGRAdaptStats((unsigned)(cctx.compID())); + cctx.updateRiceStat(riceStats, rem, 1); + cctx.setUpdateHist(0); + updateHistory = 0; + } +#endif } } //===== coeff bypass ==== for( int scanPos = firstPosMode2; scanPos >= minSubPos; scanPos-- ) { +#if JVET_V0106_RRC_RICE + int rice = (cctx.*(cctx.deriveRiceRRC))(scanPos, coeff, 0); +#else int sumAll = cctx.templateAbsSum(scanPos, coeff, 0); int rice = g_goRiceParsCoeff[sumAll]; +#endif int pos0 = g_goRicePosCoeff0(state, rice); RExt__DECODER_DEBUG_BIT_STATISTICS_SET(ctype_escs); int rem = m_BinDecoder.decodeRemAbsEP( rice, COEF_REMAIN_BIN_REDUCTION, cctx.maxLog2TrDRange() ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, rice ); TCoeff tcoeff = ( rem == pos0 ? 0 : rem < pos0 ? rem+1 : rem ); state = ( stateTransTable >> ((state<<2)+((tcoeff&1)<<1)) ) & 3; +#if JVET_V0106_RRC_RICE + if ((updateHistory) && (rem > 0)) + { + unsigned &riceStats = m_BinDecoder.getCtx().getGRAdaptStats((unsigned)(cctx.compID())); + cctx.updateRiceStat(riceStats, rem, 0); + cctx.setUpdateHist(0); + updateHistory = 0; + } +#endif if( tcoeff ) { int blkPos = cctx.blockPos( scanPos ); diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index c42c8109ab2b67473951e35010093d48434f163a..b3b4205eb4e20cc5eb6922b8f2346ee62603fef9 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -2498,6 +2498,19 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl m_pcPic->layerId = nalu.m_nuhLayerId; m_pcPic->subLayerNonReferencePictureDueToSTSA = false; +#if JVET_V0106_RRC_RICE + if (pcSlice->getSPS()->getSpsRangeExtension().getRrcRiceExtensionEnableFlag()) + { + int bitDepth = pcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA); + int baseLevel = (bitDepth > 12) ? (pcSlice->isIntra() ? 5 : 2 * 5 ) : (pcSlice->isIntra() ? 2 * 5 : 3 * 5); + pcSlice->setRiceBaseLevel(baseLevel); + } + else + { + pcSlice->setRiceBaseLevel(4); + } +#endif + if (pcSlice->getSPS()->getProfileTierLevel()->getConstraintInfo()->getNoApsConstraintFlag()) { bool flag = pcSlice->getSPS()->getCCALFEnabledFlag() || pcSlice->getPicHeader()->getNumAlfApsIdsLuma() || pcSlice->getPicHeader()->getAlfEnabledFlag(COMPONENT_Cb) || pcSlice->getPicHeader()->getAlfEnabledFlag(COMPONENT_Cr); diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 94c86d361cb37e4ad2ed33ce0a38b0da7d3bcc03..1a20c16e1ad08ad2ccdb58d0a8b7df7628176416 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -2113,6 +2113,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_FLAG( uiCode, "extended_precision_processing_flag"); spsRangeExtension.setExtendedPrecisionProcessingFlag (uiCode != 0); READ_FLAG( uiCode, "intra_smoothing_disabled_flag"); spsRangeExtension.setIntraSmoothingDisabledFlag (uiCode != 0); READ_FLAG( uiCode, "high_precision_offsets_enabled_flag"); spsRangeExtension.setHighPrecisionOffsetsEnabledFlag (uiCode != 0); +#if JVET_V0106_RRC_RICE + READ_FLAG(uiCode, "rrc_rice_extension_flag"); spsRangeExtension.setRrcRiceExtensionEnableFlag (uiCode != 0); +#endif READ_FLAG( uiCode, "persistent_rice_adaptation_enabled_flag"); spsRangeExtension.setPersistentRiceAdaptationEnabledFlag (uiCode != 0); READ_FLAG( uiCode, "cabac_bypass_alignment_enabled_flag"); spsRangeExtension.setCabacBypassAlignmentEnabledFlag (uiCode != 0); } diff --git a/source/Lib/EncoderLib/BinEncoder.h b/source/Lib/EncoderLib/BinEncoder.h index 58cb2091ceb39ce01677b4f6772f2bb99520208a..c5eb9ff9d501264c07a0de0732ce9fc7af4139f9 100644 --- a/source/Lib/EncoderLib/BinEncoder.h +++ b/source/Lib/EncoderLib/BinEncoder.h @@ -172,6 +172,9 @@ public: void finish (); void restart (); void reset ( int qp, int initId ); +#if JVET_V0106_RRC_RICE + void riceStatReset(int bitDepth); +#endif public: void resetBits (); uint64_t getEstFracBits () const { THROW( "not supported" ); return 0; } diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 25d0d121482ae2f26c3aca4151b7689a8a2dd1a5..c4c70c6848be91cd10110a03c620fc08e3dcbe0e 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -61,6 +61,10 @@ void CABACWriter::initCtxModels( const Slice& slice ) sliceType = encCABACTableIdx; } m_BinEncoder.reset( qp, (int)sliceType ); +#if JVET_V0106_RRC_RICE + m_BinEncoder.setBaseLevel(slice.getRiceBaseLevel()); + m_BinEncoder.riceStatReset(slice.getSPS()->getBitDepth(CHANNEL_TYPE_LUMA)); // provide bit depth for derivation (CE14_C method) +#endif } @@ -2706,6 +2710,17 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID, int ctxBinSampleRatio = (compID == COMPONENT_Y) ? MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_LUMA : MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_CHROMA; cctx.regBinLimit = (tu.getTbAreaAfterCoefZeroOut(compID) * ctxBinSampleRatio) >> 4; +#if JVET_V0106_RRC_RICE + int baseLevel = m_BinEncoder.getCtx().getBaseLevel(); + cctx.setBaseLevel(baseLevel); + if (tu.cs->slice->getSPS()->getSpsRangeExtension().getPersistentRiceAdaptationEnabledFlag()) + { + cctx.setUpdateHist(1); + unsigned riceStats = m_BinEncoder.getCtx().getGRAdaptStats((unsigned)compID); + TCoeff historyValue = (TCoeff)1 << riceStats; + cctx.setHistValue(historyValue); + } +#endif for( int subSetId = ( cctx.scanPosLast() >> cctx.log2CGSize() ); subSetId >= 0; subSetId--) { cctx.initSubblock ( subSetId, sigGroupFlags[subSetId] ); @@ -2908,6 +2923,10 @@ void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoe const bool isLast = cctx.isLast(); int firstSigPos = ( isLast ? cctx.scanPosLast() : cctx.maxSubPos() ); int nextSigPos = firstSigPos; +#if JVET_V0106_RRC_RICE + int baseLevel = cctx.getBaseLevel(); + bool updateHistory = cctx.getUpdateHist(); +#endif //===== encode significant_coeffgroup_flag ===== if( !isLast && cctx.isNotFirst() ) @@ -2993,14 +3012,28 @@ void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoe unsigned ricePar = 0; for( int scanPos = firstSigPos; scanPos > firstPosMode2; scanPos-- ) { +#if JVET_V0106_RRC_RICE + ricePar = (cctx.*(cctx.deriveRiceRRC))(scanPos, coeff, baseLevel); +#else int sumAll = cctx.templateAbsSum(scanPos, coeff, 4); ricePar = g_goRiceParsCoeff[sumAll]; +#endif + unsigned absLevel = (unsigned) abs( coeff[ cctx.blockPos( scanPos ) ] ); if( absLevel >= 4 ) { unsigned rem = ( absLevel - 4 ) >> 1; m_BinEncoder.encodeRemAbsEP( rem, ricePar, COEF_REMAIN_BIN_REDUCTION, cctx.maxLog2TrDRange() ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, ricePar ); +#if JVET_V0106_RRC_RICE + if ((updateHistory) && (rem > 0)) + { + unsigned &riceStats = m_BinEncoder.getCtx().getGRAdaptStats((unsigned)(cctx.compID())); + cctx.updateRiceStat(riceStats, rem, 1); + cctx.setUpdateHist(0); + updateHistory = 0; + } +#endif } } @@ -3009,13 +3042,26 @@ void CABACWriter::residual_coding_subblock( CoeffCodingContext& cctx, const TCoe { TCoeff Coeff = coeff[ cctx.blockPos( scanPos ) ]; unsigned absLevel = (unsigned) abs( Coeff ); +#if JVET_V0106_RRC_RICE + int rice = (cctx.*(cctx.deriveRiceRRC))(scanPos, coeff, 0); +#else int sumAll = cctx.templateAbsSum(scanPos, coeff, 0); int rice = g_goRiceParsCoeff[sumAll]; +#endif int pos0 = g_goRicePosCoeff0(state, rice); unsigned rem = ( absLevel == 0 ? pos0 : absLevel <= pos0 ? absLevel-1 : absLevel ); m_BinEncoder.encodeRemAbsEP( rem, rice, COEF_REMAIN_BIN_REDUCTION, cctx.maxLog2TrDRange() ); DTRACE( g_trace_ctx, D_SYNTAX_RESI, "rem_val() bin=%d ctx=%d\n", rem, rice ); state = ( stateTransTable >> ((state<<2)+((absLevel&1)<<1)) ) & 3; +#if JVET_V0106_RRC_RICE + if ((updateHistory) && (rem > 0)) + { + unsigned &riceStats = m_BinEncoder.getCtx().getGRAdaptStats((unsigned)cctx.compID()); + cctx.updateRiceStat(riceStats, rem, 0); + cctx.setUpdateHist(0); + updateHistory = 0; + } +#endif if( absLevel ) { numNonZero++; diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 061bcc41a2f68639d2b40c32c0e5ccede1f900b5..58de7d35e2005d0c26237dd38873bf2c06e3c543 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -488,6 +488,9 @@ protected: uint32_t m_log2MaxTransformSkipBlockSize; bool m_transformSkipRotationEnabledFlag; bool m_transformSkipContextEnabledFlag; +#if JVET_V0106_RRC_RICE + bool m_rrcRiceExtensionEnableFlag; +#endif bool m_persistentRiceAdaptationEnabledFlag; bool m_cabacBypassAlignmentEnabledFlag; #if SHARP_LUMA_DELTA_QP @@ -1465,6 +1468,10 @@ public: void setUseBDPCM ( bool b ) { m_useBDPCM = b; } bool getUseJointCbCr () { return m_JointCbCrMode; } void setUseJointCbCr (bool b) { m_JointCbCrMode = b; } +#if JVET_V0106_RRC_RICE + bool getRrcRiceExtensionEnableFlag() const { return m_rrcRiceExtensionEnableFlag; } + void setRrcRiceExtensionEnableFlag(const bool value) { m_rrcRiceExtensionEnableFlag = value; } +#endif bool getPersistentRiceAdaptationEnabledFlag () const { return m_persistentRiceAdaptationEnabledFlag; } void setPersistentRiceAdaptationEnabledFlag (const bool value) { m_persistentRiceAdaptationEnabledFlag = value; } bool getCabacBypassAlignmentEnabledFlag () const { return m_cabacBypassAlignmentEnabledFlag; } diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 28cd7beeceb200faf18c63b4d8bf9b5e2b806203..0992a4f6992684eb1df7d6bd75fa9d2e44d177ef 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1342,6 +1342,9 @@ void EncLib::xInitSPS( SPS& sps ) sps.getSpsRangeExtension().setExtendedPrecisionProcessingFlag(m_extendedPrecisionProcessingFlag); sps.getSpsRangeExtension().setIntraSmoothingDisabledFlag( m_intraSmoothingDisabledFlag ); sps.getSpsRangeExtension().setHighPrecisionOffsetsEnabledFlag(m_highPrecisionOffsetsEnabledFlag); +#if JVET_V0106_RRC_RICE + sps.getSpsRangeExtension().setRrcRiceExtensionEnableFlag(m_rrcRiceExtensionEnableFlag); +#endif sps.getSpsRangeExtension().setPersistentRiceAdaptationEnabledFlag(m_persistentRiceAdaptationEnabledFlag); sps.getSpsRangeExtension().setCabacBypassAlignmentEnabledFlag(m_cabacBypassAlignmentEnabledFlag); diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index 6aa39bfa91ae831842335d96d9fc968a1134aff3..fd4597d63452518d457874c4575d319da9ffde93 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -830,6 +830,20 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr } } #endif + +#if JVET_V0106_RRC_RICE + if (rpcSlice->getSPS()->getSpsRangeExtension().getRrcRiceExtensionEnableFlag()) + { + int bitDepth = rpcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA); + int baseLevel = (bitDepth > 12) ? (rpcSlice->isIntra() ? 5 : 2 * 5) : (rpcSlice->isIntra() ? 2 * 5 : 3 * 5); + rpcSlice->setRiceBaseLevel(baseLevel); + } + else + { + rpcSlice->setRiceBaseLevel(4); + } +#endif + } double EncSlice::initializeLambda(const Slice* slice, const int GOPid, const int refQP, const double dQP) @@ -1444,6 +1458,19 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c Slice* const pcSlice = pcPic->slices[getSliceSegmentIdx()]; +#if JVET_V0106_RRC_RICE + if (pcSlice->getSPS()->getSpsRangeExtension().getRrcRiceExtensionEnableFlag()) + { + int bitDepth = pcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA); + int baseLevel = (bitDepth > 12) ? (pcSlice->isIntra() ? 5 : 2 * 5 ) : (pcSlice->isIntra() ? 2 * 5 : 3 * 5); + pcSlice->setRiceBaseLevel(baseLevel); + } + else + { + pcSlice->setRiceBaseLevel(4); + } +#endif + // initialize cost values - these are used by precompressSlice (they should be parameters). m_uiPicTotalBits = 0; m_uiPicDist = 0; diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index f141c4b72a159745e836af07b06d665bd3985b7b..ec871bded70d03891b17560f78de1119d83363d5 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -1293,6 +1293,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_FLAG( (spsRangeExtension.getExtendedPrecisionProcessingFlag() ? 1 : 0), "extended_precision_processing_flag" ); WRITE_FLAG( (spsRangeExtension.getIntraSmoothingDisabledFlag() ? 1 : 0), "intra_smoothing_disabled_flag" ); WRITE_FLAG( (spsRangeExtension.getHighPrecisionOffsetsEnabledFlag() ? 1 : 0), "high_precision_offsets_enabled_flag" ); +#if JVET_V0106_RRC_RICE + WRITE_FLAG( (spsRangeExtension.getRrcRiceExtensionEnableFlag() ? 1 : 0), "rrc_rice_extension_flag"); +#endif WRITE_FLAG( (spsRangeExtension.getPersistentRiceAdaptationEnabledFlag() ? 1 : 0), "persistent_rice_adaptation_enabled_flag" ); WRITE_FLAG( (spsRangeExtension.getCabacBypassAlignmentEnabledFlag() ? 1 : 0), "cabac_bypass_alignment_enabled_flag" ); break;