Commit d3941ac2 authored by Moonmo Koo's avatar Moonmo Koo Committed by Frank Bossen

JVET-N0193: Low Frequency Non-Separable Transform (LFNST)

- Previous name: Reduced Secondary Transform (RST)
- The parameter, LFNST, should be added in cfg file for enabing LFNST, i.e. LFNST = 1
parent 3f2b49e9
......@@ -98,6 +98,7 @@ MTS : 1
MTSIntraMaxCand : 3
MTSInterMaxCand : 4
SBT : 1
LFNST : 1
ISP : 1
Affine : 1
SubPuMvp : 1
......@@ -118,6 +119,7 @@ ISPFast : 1
FastMrg : 1
AMaxBT : 1
FastMIP : 1
FastLFNST : 1
# Encoder optimization tools
AffineAmvrEncOpt : 0
......
......@@ -128,6 +128,7 @@ MTS : 1
MTSIntraMaxCand : 3
MTSInterMaxCand : 4
SBT : 1
LFNST : 1
ISP : 1
MMVD : 1
Affine : 1
......@@ -156,6 +157,7 @@ ISPFast : 1
FastMrg : 1
AMaxBT : 1
FastMIP : 0
FastLFNST : 0
# Encoder optimization tools
AffineAmvrEncOpt : 1
......
......@@ -2040,6 +2040,18 @@ Enables or disables symmetric MVD mode.
Enables or disables RDPCM coding mode.
\\
\Option{LFNST} &
%\ShortOption{\None} &
\Default{false} &
Enables or disables the use of low frequency non-separable transform (LFNST).
\\
\Option{FastLFNST} &
%\ShortOption{\None} &
\Default{false} &
Enables or disables the fast encoding of low frequency non-separable transform (LFNST).
\\
\end{OptionTableNoShorthand}
%%
......
......@@ -248,6 +248,10 @@ void EncApp::xInitLibCfg()
m_cEncLib.setMinQTSizes ( m_uiMinQT );
m_cEncLib.setMaxBTDepth ( m_uiMaxBTDepth, m_uiMaxBTDepthI, m_uiMaxBTDepthIChroma );
m_cEncLib.setDualITree ( m_dualTree );
#if JVET_N0193_LFNST
m_cEncLib.setLFNST ( m_LFNST );
m_cEncLib.setUseFastLFNST ( m_useFastLFNST );
#endif
m_cEncLib.setSubPuMvpMode ( m_SubPuMvpMode );
m_cEncLib.setAffine ( m_Affine );
m_cEncLib.setAffineType ( m_AffineType );
......
......@@ -834,6 +834,10 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
("MaxBTDepthISliceL", m_uiMaxBTDepthI, 3u, "MaxBTDepthISliceL")
("MaxBTDepthISliceC", m_uiMaxBTDepthIChroma, 3u, "MaxBTDepthISliceC")
("DualITree", m_dualTree, false, "Use separate QTBT trees for intra slice luma and chroma channel types")
#if JVET_N0193_LFNST
( "LFNST", m_LFNST, false, "Enable LFNST (0:off, 1:on) [default: off]" )
( "FastLFNST", m_useFastLFNST, false, "Fast methods for LFNST" )
#endif
("SubPuMvp", m_SubPuMvpMode, 0, "Enable Sub-PU temporal motion vector prediction (0:off, 1:ATMVP, 2:STMVP, 3:ATMVP+STMVP) [default: off]")
#if JVET_N0127_MMVD_SPS_FLAG
("MMVD", m_MMVD, true, "Enable Merge mode with Motion Vector Difference (0:off, 1:on) [default: 1]")
......@@ -3159,6 +3163,9 @@ void EncAppCfg::xPrintParameter()
if( m_profile == Profile::NEXT )
{
msg( VERBOSE, "\nNEXT TOOL CFG: " );
#if JVET_N0193_LFNST
msg( VERBOSE, "LFNST:%d ", m_LFNST );
#endif
#if JVET_N0127_MMVD_SPS_FLAG
msg( VERBOSE, "MMVD:%d ", m_MMVD);
#endif
......@@ -3238,6 +3245,9 @@ void EncAppCfg::xPrintParameter()
if( m_ISP ) msg( VERBOSE, "ISPFast:%d ", m_useFastISP );
#else
msg( VERBOSE, "ISPFast:%d ", m_useFastISP );
#endif
#if JVET_N0193_LFNST
if( m_LFNST ) msg( VERBOSE, "FastLFNST:%d ", m_useFastLFNST );
#endif
msg( VERBOSE, "AMaxBT:%d ", m_useAMaxBT );
msg( VERBOSE, "E0023FastEnc:%d ", m_e0023FastEnc );
......
......@@ -238,6 +238,10 @@ protected:
unsigned m_uiMaxBTDepthI;
unsigned m_uiMaxBTDepthIChroma;
bool m_dualTree;
#if JVET_N0193_LFNST
bool m_LFNST;
bool m_useFastLFNST;
#endif
int m_SubPuMvpMode;
bool m_Affine;
bool m_AffineType;
......
......@@ -91,6 +91,9 @@ enum CodingStatisticsType
STATS__CABAC_BITS__SAO,
STATS__CABAC_BITS__ALF,
STATS__CABAC_TRM_BITS,
#if JVET_N0193_LFNST
STATS__CABAC_BITS__LFNST,
#endif
STATS__CABAC_FIXED_BITS,
STATS__CABAC_PCM_ALIGN_BITS,
STATS__CABAC_PCM_CODE_BITS,
......@@ -109,6 +112,9 @@ enum CodingStatisticsType
STATS__CABAC_BITS__TRIANGLE_FLAG,
STATS__CABAC_BITS__TRIANGLE_INDEX,
STATS__CABAC_BITS__MULTI_REF_LINE,
#if JVET_N0193_LFNST
STATS__TOOL_LFNST,
#endif
STATS__CABAC_BITS__SYMMVD_FLAG,
STATS__TOOL_TOTAL_FRAME,// This is a special case and is not included in the report.
STATS__TOOL_AFF,
......@@ -173,6 +179,9 @@ static inline const char* getName(CodingStatisticsType name)
"CABAC_BITS__SIGN_BIT",
"CABAC_BITS__ESCAPE_BITS",
"CABAC_BITS__SAO",
#if JVET_N0193_LFNST
"CABAC_BITS__LFNST",
#endif
"CABAC_BITS__ALF",
"CABAC_TRM_BITS",
"CABAC_FIXED_BITS",
......@@ -197,6 +206,9 @@ static inline const char* getName(CodingStatisticsType name)
"TOOL_FRAME",
"TOOL_AFFINE",
"TOOL_EMT",
#if JVET_N0193_LFNST
"TOOL_LFNST",
#endif
"TOOL_TOTAL"
};
CHECK( STATS__NUM_STATS != sizeof( statNames ) / sizeof( char* ) || name >= STATS__NUM_STATS, "stats out of range" );
......
......@@ -217,6 +217,10 @@ static const int NUM_LUMA_MODE = 67; ///< Plan
static const int NUM_LMC_MODE = 1 + 2; ///< LMC + MDLM_T + MDLM_L
static const int NUM_INTRA_MODE = (NUM_LUMA_MODE + NUM_LMC_MODE);
#if JVET_N0193_LFNST
static const int NUM_EXT_LUMA_MODE = 28;
#endif
static const int NUM_DIR = (((NUM_LUMA_MODE - 3) >> 2) + 1);
static const int PLANAR_IDX = 0; ///< index for intra PLANAR mode
static const int DC_IDX = 1; ///< index for intra DC mode
......@@ -253,6 +257,15 @@ static const int FAST_UDI_MAX_RDMODE_NUM = (NUM_LUMA_MODE + MAX_NUM_MIP_MODE); /
static const int FAST_UDI_MAX_RDMODE_NUM = NUM_LUMA_MODE; ///< maximum number of RD comparison in fast-UDI estimation loop
#endif
#if JVET_N0193_LFNST
static const int MAX_LFNST_COEF_NUM = 16;
static const int LFNST_SIG_NZ_LUMA = 1;
static const int LFNST_SIG_NZ_CHROMA = 1;
static const int NUM_LFNST_NUM_PER_SET = 3;
#endif
static const int MDCS_ANGLE_LIMIT = 9; ///< 0 = Horizontal/vertical only, 1 = Horizontal/vertical +/- 1, 2 = Horizontal/vertical +/- 2 etc...
static const int MDCS_MAXIMUM_WIDTH = 8; ///< (measured in pixels) TUs with width greater than this can only use diagonal scan
......
......@@ -693,6 +693,16 @@ const CtxSet ContextSetCfg::TransquantBypassFlag = ContextSetCfg::addCtxSet
{ DWS, }
});
#if JVET_N0193_LFNST
const CtxSet ContextSetCfg::LFNSTIdx = ContextSetCfg::addCtxSet
( {
{ CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
{ CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
{ CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
{ DWS, DWS, DWS, DWS, DWS, DWS, DWS, DWS, },
} );
#endif
const CtxSet ContextSetCfg::RdpcmFlag = ContextSetCfg::addCtxSet
({
{ 139, 139,},
......
......@@ -250,6 +250,9 @@ public:
static const CtxSet SaoTypeIdx;
static const CtxSet MTSIndex;
static const CtxSet TransquantBypassFlag;
#if JVET_N0193_LFNST
static const CtxSet LFNSTIdx;
#endif
static const CtxSet RdpcmFlag;
static const CtxSet RdpcmDir;
static const CtxSet SbtFlag;
......
This diff is collapsed.
......@@ -165,7 +165,6 @@ public:
/// 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_N0217_MATRIX_INTRAPRED
// Matrix-based intra prediction
void initIntraMip (const PredictionUnit &pu);
......@@ -173,6 +172,9 @@ public:
#endif
static bool useFilteredIntraRefSamples( const ComponentID &compID, const PredictionUnit &pu, bool modeSpecific, const UnitArea &tuArea );
#if HM_MDIS_AS_IN_JEM && JVET_N0193_LFNST
static bool getPlanarMDISCondition( const UnitArea &tuArea ) { return abs( PLANAR_IDX - HOR_IDX ) > m_aucIntraFilter[ CHANNEL_TYPE_LUMA ][ ( ( g_aucLog2[ tuArea.Y().width ] + g_aucLog2[ tuArea.Y().height ] ) >> 1 ) ]; }
#endif
static bool useDPCMForFirstPassIntraEstimation(const PredictionUnit &pu, const uint32_t &uiDirMode);
void geneWeightedPred (const ComponentID compId, PelBuf &pred, const PredictionUnit &pu, Pel *srcBuf);
......
......@@ -759,15 +759,36 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
DTRACE( g_trace_ctx, D_RDOQ, "%d: %3d, %3d, %dx%d, comp=%d\n", DTRACE_GET_COUNTER( g_trace_ctx, D_RDOQ ), rect.x, rect.y, rect.width, rect.height, compID );
#endif
#if JVET_N0193_LFNST
const uint32_t lfnstIdx = tu.cu->lfnstIdx;
#endif
for (int subSetId = iCGNum - 1; subSetId >= 0; subSetId--)
{
cctx.initSubblock( subSetId );
#if JVET_N0193_LFNST
uint32_t maxNonZeroPosInCG = iCGSizeM1;
if( lfnstIdx > 0 && ( ( uiWidth == 4 && uiHeight == 4 ) || ( uiWidth == 8 && uiHeight == 8 && cctx.cgPosX() == 0 && cctx.cgPosY() == 0 ) ) )
{
maxNonZeroPosInCG = 7;
}
#endif
memset( &rdStats, 0, sizeof (coeffGroupRDStats));
#if JVET_N0193_LFNST
for( int iScanPosinCG = iCGSizeM1; iScanPosinCG > maxNonZeroPosInCG; iScanPosinCG-- )
{
iScanPos = cctx.minSubPos() + iScanPosinCG;
uint32_t blkPos = cctx.blockPos( iScanPos );
piDstCoeff[ blkPos ] = 0;
}
for( int iScanPosinCG = maxNonZeroPosInCG; iScanPosinCG >= 0; iScanPosinCG-- )
#else
for (int iScanPosinCG = iCGSizeM1; iScanPosinCG >= 0; iScanPosinCG--)
#endif
{
iScanPos = cctx.minSubPos() + iScanPosinCG;
//===== quantization =====
......@@ -970,7 +991,11 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
pdCostCoeffGroupSig[ cctx.subSetId() ] = xGetRateSigCoeffGroup(fracBitsSigGroup,0);
}
// reset coeffs to 0 in this block
#if JVET_N0193_LFNST
for( int iScanPosinCG = maxNonZeroPosInCG; iScanPosinCG >= 0; iScanPosinCG-- )
#else
for (int iScanPosinCG = iCGSizeM1; iScanPosinCG >= 0; iScanPosinCG--)
#endif
{
iScanPos = cctx.minSubPos() + iScanPosinCG;
uint32_t uiBlkPos = cctx.blockPos( iScanPos );
......@@ -1088,7 +1113,16 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
d64BaseCost -= pdCostCoeffGroupSig [ iCGScanPos ];
if (cctx.isSigGroup( iCGScanPos ) )
{
#if JVET_N0193_LFNST
uint32_t maxNonZeroPosInCG = iCGSizeM1;
if( lfnstIdx > 0 && ( ( uiWidth == 4 && uiHeight == 4 ) || ( uiWidth == 8 && uiHeight == 8 && cctx.cgPosX() == 0 && cctx.cgPosY() == 0 ) ) )
{
maxNonZeroPosInCG = 7;
}
for( int iScanPosinCG = maxNonZeroPosInCG; iScanPosinCG >= 0; iScanPosinCG-- )
#else
for (int iScanPosinCG = iCGSizeM1; iScanPosinCG >= 0; iScanPosinCG--)
#endif
{
iScanPos = iCGScanPos * (iCGSizeM1 + 1) + iScanPosinCG;
......
......@@ -467,6 +467,32 @@ void initROM()
}
#endif
#if JVET_N0193_LFNST
// initialize CoefTopLeftDiagScan8x8 for LFNST
for( uint32_t blockWidthIdx = 0; blockWidthIdx < sizeInfo.numAllWidths(); blockWidthIdx++ )
{
const uint32_t blockWidth = sizeInfo.sizeFrom( blockWidthIdx );
const static uint8_t g_auiXYDiagScan8x8[ 64 ][ 2 ] =
{
{ 0, 0 }, { 0, 1 }, { 1, 0 }, { 0, 2 }, { 1, 1 }, { 2, 0 }, { 0, 3 }, { 1, 2 },
{ 2, 1 }, { 3, 0 }, { 1, 3 }, { 2, 2 }, { 3, 1 }, { 2, 3 }, { 3, 2 }, { 3, 3 },
{ 0, 4 }, { 0, 5 }, { 1, 4 }, { 0, 6 }, { 1, 5 }, { 2, 4 }, { 0, 7 }, { 1, 6 },
{ 2, 5 }, { 3, 4 }, { 1, 7 }, { 2, 6 }, { 3, 5 }, { 2, 7 }, { 3, 6 }, { 3, 7 },
{ 4, 0 }, { 4, 1 }, { 5, 0 }, { 4, 2 }, { 5, 1 }, { 6, 0 }, { 4, 3 }, { 5, 2 },
{ 6, 1 }, { 7, 0 }, { 5, 3 }, { 6, 2 }, { 7, 1 }, { 6, 3 }, { 7, 2 }, { 7, 3 },
{ 4, 4 }, { 4, 5 }, { 5, 4 }, { 4, 6 }, { 5, 5 }, { 6, 4 }, { 4, 7 }, { 5, 6 },
{ 6, 5 }, { 7, 4 }, { 5, 7 }, { 6, 6 }, { 7, 5 }, { 6, 7 }, { 7, 6 }, { 7, 7 }
};
for( int i = 0; i < 64; i++ )
{
g_coefTopLeftDiagScan8x8[ blockWidthIdx ][ i ].idx = g_auiXYDiagScan8x8[ i ][ 0 ] + g_auiXYDiagScan8x8[ i ][ 1 ] * blockWidth;
g_coefTopLeftDiagScan8x8[ blockWidthIdx ][ i ].x = g_auiXYDiagScan8x8[ i ][ 0 ];
g_coefTopLeftDiagScan8x8[ blockWidthIdx ][ i ].y = g_auiXYDiagScan8x8[ i ][ 1 ];
}
}
#endif
for( int idxH = MAX_CU_DEPTH - MIN_CU_LOG2; idxH >= 0; --idxH )
{
for( int idxW = MAX_CU_DEPTH - MIN_CU_LOG2; idxW >= 0; --idxW )
......@@ -667,6 +693,9 @@ ScanElement *g_scanOrder[SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][MAX_C
#else
ScanElement *g_scanOrder[2][SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][MAX_CU_SIZE / 2 + 1][MAX_CU_SIZE / 2 + 1];
#endif
#if JVET_N0193_LFNST
ScanElement g_coefTopLeftDiagScan8x8[ MAX_CU_SIZE / 2 + 1 ][ 64 ];
#endif
const uint32_t g_uiMinInGroup[LAST_SIGNIFICANT_GROUPS] = { 0,1,2,3,4,6,8,12,16,24,32,48,64,96 };
const uint32_t g_uiGroupIdx[MAX_TB_SIZEY] = { 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9, 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11 };
......
......@@ -76,6 +76,9 @@ extern uint32_t g_log2SbbSize [2][MAX_CU_DEPTH+1][MAX_CU_DEPTH+1][2];
extern ScanElement
*g_scanOrder[2][SCAN_NUMBER_OF_GROUP_TYPES][SCAN_NUMBER_OF_TYPES][MAX_CU_SIZE / 2 + 1][MAX_CU_SIZE / 2 + 1];
#endif
#if JVET_N0193_LFNST
extern ScanElement g_coefTopLeftDiagScan8x8[ MAX_CU_SIZE / 2 + 1 ][ 64 ];
#endif
#if JVET_N0246_MODIFIED_QUANTSCALES
extern const int g_quantScales [2/*0=4^n blocks, 1=2*4^n blocks*/][SCALING_LIST_REM_NUM]; // Q(QP%6)
......@@ -145,6 +148,12 @@ extern const TMatrixCoeff g_trCoreDST7P8 [TRANSFORM_NUMBER_OF_DIRECTIONS][ 8][
extern const TMatrixCoeff g_trCoreDST7P16 [TRANSFORM_NUMBER_OF_DIRECTIONS][ 16][ 16];
extern const TMatrixCoeff g_trCoreDST7P32 [TRANSFORM_NUMBER_OF_DIRECTIONS][ 32][ 32];
#if JVET_N0193_LFNST
extern const int8_t g_lfnst8x8[ 4 ][ 2 ][ 16 ][ 48 ];
extern const int8_t g_lfnst4x4[ 4 ][ 2 ][ 16 ][ 16 ];
extern const uint8_t g_lfnstLut[ NUM_INTRA_MODE + NUM_EXT_LUMA_MODE - 1 ];
#endif
// ====================================================================================================================
// Misc.
......
This diff is collapsed.
......@@ -1854,6 +1854,9 @@ SPS::SPS()
, m_cclmCollocatedChromaFlag ( false )
, m_IntraMTS ( false )
, m_InterMTS ( false )
#if JVET_N0193_LFNST
, m_LFNST ( false )
#endif
, m_Affine ( false )
, m_AffineType ( false )
, m_MHIntra ( false )
......
......@@ -1115,6 +1115,9 @@ private:
bool m_MTS;
bool m_IntraMTS; // 18
bool m_InterMTS; // 19
#if JVET_N0193_LFNST
bool m_LFNST;
#endif
#if JVET_N0235_SMVD_SPS
bool m_SMVD;
#endif
......@@ -1393,6 +1396,10 @@ public:
bool getUseIntraMTS () const { return m_IntraMTS; }
void setUseInterMTS ( bool b ) { m_InterMTS = b; }
bool getUseInterMTS () const { return m_InterMTS; }
#if JVET_N0193_LFNST
void setUseLFNST ( bool b ) { m_LFNST = b; }
bool getUseLFNST () const { return m_LFNST; }
#endif
#if JVET_N0235_SMVD_SPS
void setUseSMVD(bool b) { m_SMVD = b; }
bool getUseSMVD() const { return m_SMVD; }
......
This diff is collapsed.
......@@ -83,8 +83,21 @@ public:
void getTrTypes( TransformUnit tu, const ComponentID compID, int &trTypeHor, int &trTypeVer );
#endif
#if JVET_N0193_LFNST
void fwdLfnstNxN( int* src, int* dst, const uint32_t mode, const uint32_t index, const uint32_t size, int zeroOutSize );
void invLfnstNxN( int* src, int* dst, const uint32_t mode, const uint32_t index, const uint32_t size, int zeroOutSize );
uint32_t getLFNSTIntraMode( int wideAngPredMode );
bool getTransposeFlag ( uint32_t intraMode );
#endif
protected:
#if JVET_N0193_LFNST
void xFwdLfnst( const TransformUnit &tu, const ComponentID compID, const bool loadTr = false );
void xInvLfnst( const TransformUnit &tu, const ComponentID compID );
#endif
public:
void invTransformNxN (TransformUnit &tu, const ComponentID &compID, PelBuf &pResi, const QpParam &cQPs);
......@@ -124,6 +137,10 @@ protected:
private:
Quant *m_quant; //!< Quantizer
TCoeff** m_mtsCoeffs;
#if JVET_N0193_LFNST
TCoeff m_tempInMatrix [ 48 ];
TCoeff m_tempOutMatrix[ 48 ];
#endif
// forward Transform
......
......@@ -50,6 +50,7 @@
#include <assert.h>
#include <cassert>
#define JVET_N0193_LFNST 1 //Low Frequency Non-Separable Transform (LFNST), previously, Reduced Secondary Transform (RST)
#define JVET_N0217_MATRIX_INTRAPRED 1 // matrix-based intra prediction (MIP)
......
......@@ -275,6 +275,10 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other )
chromaQpAdj = other.chromaQpAdj;
rootCbf = other.rootCbf;
sbtInfo = other.sbtInfo;
#if JVET_N0193_LFNST
mtsFlag = other.mtsFlag;
lfnstIdx = other.lfnstIdx;
#endif
tileIdx = other.tileIdx;
imv = other.imv;
imvNumCand = other.imvNumCand;
......@@ -315,6 +319,10 @@ void CodingUnit::initData()
chromaQpAdj = 0;
rootCbf = true;
sbtInfo = 0;
#if JVET_N0193_LFNST
mtsFlag = 0;
lfnstIdx = 0;
#endif
tileIdx = 0;
imv = 0;
imvNumCand = 0;
......
......@@ -313,6 +313,10 @@ struct CodingUnit : public UnitArea
bool rootCbf;
uint8_t sbtInfo;
uint32_t tileIdx;
#if JVET_N0193_LFNST
uint8_t mtsFlag;
uint32_t lfnstIdx;
#endif
uint8_t GBiIdx;
int refIdxBi[2];
#if JVET_N0217_MATRIX_INTRAPRED
......
......@@ -252,17 +252,38 @@ bool CU::hasNonTsCodedBlock( const CodingUnit& cu )
return hasAnyNonTSCoded;
}
#if JVET_N0193_LFNST
uint32_t CU::getNumNonZeroCoeffNonTs( const CodingUnit& cu, const bool lumaFlag, const bool chromaFlag )
#else
uint32_t CU::getNumNonZeroCoeffNonTs( const CodingUnit& cu )
#endif
{
uint32_t count = 0;
for( auto &currTU : traverseTUs( cu ) )
{
#if JVET_N0193_LFNST
count += TU::getNumNonZeroCoeffsNonTS( currTU, lumaFlag, chromaFlag );
#else
count += TU::getNumNonZeroCoeffsNonTS( currTU );
#endif
}
return count;
}
#if JVET_N0193_LFNST
uint32_t CU::getNumNonZeroCoeffNonTsCorner8x8( const CodingUnit& cu, const bool lumaFlag, const bool chromaFlag )
{
uint32_t count = 0;
for( auto &currTU : traverseTUs( cu ) )
{
count += TU::getNumNonZeroCoeffsNonTSCorner8x8( currTU, lumaFlag, chromaFlag );
}
return count;
}
#endif
bool CU::divideTuInRows( const CodingUnit &cu )
{
CHECK( cu.ispMode != HOR_INTRA_SUBPARTITIONS && cu.ispMode != VER_INTRA_SUBPARTITIONS, "Intra Subpartitions type not recognized!" );
......@@ -1214,6 +1235,36 @@ uint32_t PU::getFinalIntraMode( const PredictionUnit &pu, const ChannelType &chT
return uiIntraMode;
}
#if JVET_N0193_LFNST
int PU::getWideAngIntraMode( const TransformUnit &tu, const uint32_t dirMode, const ComponentID compID )
{
if( dirMode < 2 )
{
return ( int ) dirMode;
}
CodingStructure& cs = *tu.cs;
const CompArea& area = tu.blocks[ compID ];
PelBuf pred = cs.getPredBuf( area );
int width = int( pred.width );
int height = int( pred.height );
int modeShift[ ] = { 0, 6, 10, 12, 14, 15 };
int deltaSize = abs( g_aucLog2[ width ] - g_aucLog2[ height ] );
int predMode = dirMode;
if( width > height && dirMode < 2 + modeShift[ deltaSize ] )
{
predMode += ( VDIA_IDX - 1 );
}
else if( height > width && predMode > VDIA_IDX - modeShift[ deltaSize ] )
{
predMode -= ( VDIA_IDX + 1 );
}
return predMode;
}
#endif
bool PU::xCheckSimilarMotion(const int mergeCandIndex, const int prevCnt, const MergeCtx mergeCandList, bool hasPruned[MRG_MAX_NUM_CANDS])
{
for (uint32_t ui = 0; ui < prevCnt; ui++)
......@@ -5824,7 +5875,11 @@ uint32_t TU::getNumNonZeroCoeffsNonTS( const TransformUnit& tu, const bool bLuma
uint32_t count = 0;
for( uint32_t i = 0; i < ::getNumberValidTBlocks( *tu.cs->pcv ); i++ )
{
#if JVET_N0193_LFNST
if( tu.blocks[ i ].valid() && tu.mtsIdx != 1 && TU::getCbf( tu, ComponentID( i ) ) )
#else
if( tu.blocks[i].valid() && ( isLuma(ComponentID(i)) ? tu.mtsIdx !=1 : true ) && TU::getCbf( tu, ComponentID( i ) ) )
#endif
{
if( isLuma ( tu.blocks[i].compID ) && !bLuma ) continue;
if( isChroma( tu.blocks[i].compID ) && !bChroma ) continue;
......@@ -5840,6 +5895,50 @@ uint32_t TU::getNumNonZeroCoeffsNonTS( const TransformUnit& tu, const bool bLuma
return count;
}
#if JVET_N0193_LFNST
uint32_t TU::getNumNonZeroCoeffsNonTSCorner8x8( const TransformUnit& tu, const bool lumaFlag, const bool chromaFlag )
{
const uint32_t lumaWidth = tu.blocks[ 0 ].width, chromaWidth = tu.blocks[ 1 ].width;
const uint32_t lumaHeight = tu.blocks[ 0 ].height, chromaHeight = tu.blocks[ 1 ].height;
bool luma4x4TUFlag = lumaWidth == 4 && lumaHeight == 4;
bool chroma4x4TUFlag = chromaWidth == 4 && chromaHeight == 4;
bool luma8x8TUFlag = lumaWidth == 8 && lumaHeight == 8;
bool chroma8x8TUFlag = chromaWidth == 8 && chromaHeight == 8;
bool lumaCountFlag = ( lumaWidth >= 8 && lumaHeight >= 8 ) || luma4x4TUFlag;
bool chromaCountFlag = ( chromaWidth >= 8 && chromaHeight >= 8 ) || chroma4x4TUFlag;
uint32_t count = 0;
for( uint32_t i = 0; i < ::getNumberValidTBlocks( *tu.cs->pcv ); i++ )
{
if( tu.blocks[ i ].valid() && tu.mtsIdx != 1 && TU::getCbf( tu, ComponentID( i ) ) )
{
if( isLuma( tu.blocks[ i ].compID ) && ( !lumaFlag || !lumaCountFlag ) ) continue;
if( isChroma( tu.blocks[ i ].compID ) && ( !chromaFlag || !chromaCountFlag ) ) continue;
const ScanElement * scan = g_coefTopLeftDiagScan8x8[ gp_sizeIdxInfo->idxFrom( tu.blocks[ i ].width ) ];
const TCoeff* coeff = tu.getCoeffs( ComponentID( i ) ).buf;
int startPos = MAX_LFNST_COEF_NUM, endPos = 47;
if( ( isLuma( tu.blocks[ i ].compID ) && luma4x4TUFlag ) || ( isChroma( tu.blocks[ i ].compID ) && chroma4x4TUFlag ) )
{
startPos = 8; endPos = 15;
}
else if( ( isLuma( tu.blocks[ i ].compID ) && luma8x8TUFlag ) || ( isChroma( tu.blocks[ i ].compID ) && chroma8x8TUFlag ) )
{
startPos = 8; endPos = 47;
}
const ScanElement *scanPtr = scan + startPos;
for( uint32_t j = startPos; j <= endPos; j++ )
{
count += coeff[ scanPtr->idx ] != 0;
scanPtr++;
}
}
}
return count;
}
#endif
bool TU::needsSqrt2Scale( const TransformUnit &tu, const ComponentID &compID )
{
const Size &size=tu.blocks[compID];
......
......@@ -78,7 +78,12 @@ namespace CU
PartSplit getSplitAtDepth (const CodingUnit& cu, const unsigned depth);
bool hasNonTsCodedBlock (const CodingUnit& cu);
#if JVET_N0193_LFNST
uint32_t getNumNonZeroCoeffNonTs ( const CodingUnit& cu, const bool lumaFlag = true, const bool chromaFlag = true );
uint32_t getNumNonZeroCoeffNonTsCorner8x8( const CodingUnit& cu, const bool lumaFlag = true, const bool chromaFlag = true );
#else
uint32_t getNumNonZeroCoeffNonTs (const CodingUnit& cu);
#endif
bool isGBiIdxCoded (const CodingUnit& cu);
uint8_t getValidGbiIdx (const CodingUnit& cu);
......@@ -134,6 +139,9 @@ namespace PU
#endif
void getIntraChromaCandModes (const PredictionUnit &pu, unsigned modeList[NUM_CHROMA_MODE]);
uint32_t getFinalIntraMode (const PredictionUnit &pu, const ChannelType &chType);
#if JVET_N0193_LFNST
int getWideAngIntraMode ( const TransformUnit &tu, const uint32_t dirMode, const ComponentID compID );
#endif
void getInterMergeCandidates (const PredictionUnit &pu, MergeCtx& mrgCtx,
int mmvdList,
const int& mrgCandIdx = -1 );
......@@ -212,6 +220,9 @@ namespace PU
namespace TU
{
uint32_t getNumNonZeroCoeffsNonTS (const TransformUnit &tu, const bool bLuma = true, const bool bChroma = true);
#if JVET_N0193_LFNST
uint32_t getNumNonZeroCoeffsNonTSCorner8x8( const TransformUnit &tu, const bool bLuma = true, const bool bChroma = true );
#endif
bool isNonTransformedResidualRotated(const TransformUnit &tu, const ComponentID &compID);
bool getCbf (const TransformUnit &tu, const ComponentID &compID);
bool getCbfAtDepth (const TransformUnit &tu, const ComponentID &compID, const unsigned &depth);
......
......@@ -1430,6 +1430,10 @@ void CABACReader::cu_residual( CodingUnit& cu, Partitioner &partitioner, CUCtx&
{
transform_tree( *cu.cs, partitioner, cuCtx, chromaCbfs );
}
#if JVET_N0193_LFNST
residual_lfnst_mode( cu );
#endif
}
void CABACReader::rqt_root_cbf( CodingUnit& cu )
......@@ -2862,6 +2866,68 @@ void CABACReader::explicit_rdpcm_mode( TransformUnit& tu, ComponentID compID )
}
}
#if JVET_N0193_LFNST
void CABACReader::residual_lfnst_mode( CodingUnit& cu )
{
#if JVET_N0217_MATRIX_INTRAPRED
if( cu.ispMode != NOT_INTRA_SUBPARTITIONS || cu.mipFlag == true ||
#else
if( cu.ispMode != NOT_INTRA_SUBPARTITIONS ||
#endif
( CS::isDualITree( *cu.cs ) && cu.chType == CHANNEL_TYPE_CHROMA && std::min( cu.blocks[ 1 ].width, cu.blocks[ 1 ].height ) < 4 ) )
{
return;
}
RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET( STATS__CABAC_BITS__LFNST );
if( cu.cs->sps->getUseLFNST() && CU::isIntra( cu ) && !CU::isLosslessCoded( cu ) )
{
const bool lumaFlag = CS::isDualITree( *cu.cs ) ? ( isLuma( cu.chType ) ? true : false ) : true;
const bool chromaFlag = CS::isDualITree( *cu.cs ) ? ( isChroma( cu.chType ) ? true : false ) : true;
bool nonZeroCoeffNonTs;
bool nonZeroCoeffNonTsCorner8x8 = CU::getNumNonZeroCoeffNonTsCorner8x8( cu, lumaFlag, chromaFlag ) > 0;
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;
if( !nonZeroCoeffNonTs || nonZeroCoeffNonTsCorner8x8 )
{
cu.lfnstIdx = 0;
return;
}
}
else
{
cu.lfnstIdx = 0;
return;
}
uint32_t ctxOff = 0;
int intraMode = cu.firstPU->intraDir[ cu.chType ];
if( intraMode == DM_CHROMA_IDX && !isLuma( cu.chType ) )
{
intraMode = PLANAR_IDX;