Commit be8e884d authored by Yin Zhao's avatar Yin Zhao

JVET-M0140 Sub-block Transform (SBT) for inter blocks

parent ad7f9c65
......@@ -104,6 +104,7 @@ MTT : 1
MTS : 1
MTSIntraMaxCand : 3
MTSInterMaxCand : 4
SBT : 1
Affine : 1
SubPuMvp : 1
MaxNumMergeCand : 6
......
......@@ -120,6 +120,7 @@ MTT : 1
MTS : 1
MTSIntraMaxCand : 3
MTSInterMaxCand : 4
SBT : 1
Affine : 1
SubPuMvp : 1
MaxNumMergeCand : 6
......
......@@ -120,6 +120,7 @@ MTT : 1
MTS : 1
MTSIntraMaxCand : 3
MTSInterMaxCand : 4
SBT : 1
Affine : 1
SubPuMvp : 1
MaxNumMergeCand : 6
......
......@@ -134,6 +134,7 @@ MTT : 1
MTS : 1
MTSIntraMaxCand : 3
MTSInterMaxCand : 4
SBT : 1
Affine : 1
SubPuMvp : 1
MaxNumMergeCand : 6
......
......@@ -242,6 +242,9 @@ void EncApp::xInitLibCfg()
#endif
#if JVET_M0303_IMPLICIT_MTS
m_cEncLib.setImplicitMTS ( m_MTSImplicit );
#endif
#if JVET_M0140_SBT
m_cEncLib.setUseSBT ( m_SBT );
#endif
m_cEncLib.setUseCompositeRef ( m_compositeRefEnabled );
m_cEncLib.setUseGBi ( m_GBi );
......
......@@ -855,6 +855,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
#endif
#if JVET_M0303_IMPLICIT_MTS
("MTSImplicit", m_MTSImplicit, 0, "Enable implicit MTS (when explicit MTS is off)\n")
#endif
#if JVET_M0140_SBT
( "SBT", m_SBT, false, "Enable Sub-Block Transform for inter blocks\n" )
#endif
("CompositeLTReference", m_compositeRefEnabled, false, "Enable Composite Long Term Reference Frame")
("GBi", m_GBi, false, "Enable Generalized Bi-prediction(GBi)")
......@@ -3197,6 +3200,9 @@ void EncAppCfg::xPrintParameter()
msg( VERBOSE, "MTS: %1d(intra) %1d(inter) ", m_MTS & 1, ( m_MTS >> 1 ) & 1 );
#else
msg( VERBOSE, "EMT: %1d(intra) %1d(inter) ", m_EMT & 1, ( m_EMT >> 1 ) & 1 );
#endif
#if JVET_M0140_SBT
msg( VERBOSE, "SBT:%d ", m_SBT );
#endif
msg( VERBOSE, "CompositeLTReference:%d ", m_compositeRefEnabled);
msg( VERBOSE, "GBi:%d ", m_GBi );
......
......@@ -227,6 +227,9 @@ protected:
#if JVET_M0303_IMPLICIT_MTS
int m_MTSImplicit;
#endif
#if JVET_M0140_SBT
bool m_SBT; ///< Sub-Block Transform for inter blocks
#endif
bool m_compositeRefEnabled;
bool m_GBi;
......
......@@ -105,6 +105,9 @@ enum CodingStatisticsType
STATS__CABAC_BITS__GBI_IDX,
STATS__CABAC_BITS__EMT_CU_FLAG,
STATS__CABAC_BITS__EMT_TU_INDEX,
#if JVET_M0140_SBT
STATS__CABAC_BITS__SBT_MODE,
#endif
STATS__CABAC_BITS__MH_INTRA_FLAG,
STATS__CABAC_BITS__TRIANGLE_FLAG,
STATS__CABAC_BITS__TRIANGLE_INDEX,
......@@ -191,6 +194,9 @@ static inline const char* getName(CodingStatisticsType name)
"CABAC_BITS__GBI_IDX",
"CABAC_BITS__EMT_CU_FLAG",
"CABAC_BITS__EMT_TU_INDX",
#if JVET_M0140_SBT
"CABAC_BITS__SBT_MODE",
#endif
"CABAC_BITS__MH_INTRA_FLAG",
"CABAC_BITS__TRIANGLE_FLAG",
"CABAC_BITS__TRIANGLE_INDEX",
......
......@@ -406,6 +406,12 @@ static const int TRIANGLE_MAX_NUM_CANDS = 40;
static const int TRIANGLE_MAX_NUM_SATD_CANDS = 3;
static const int TRIANGLE_MIN_SIZE = 8 * 8;
#if JVET_M0140_SBT
static const int SBT_MAX_SIZE = 64; ///< maximum CU size for using SBT
static const int SBT_NUM_SL = 10; ///< maximum number of historical PU decision saved for a CU
static const int SBT_NUM_RDO = 2; ///< maximum number of SBT mode tried for a PU
#endif
static const int IBC_MAX_CAND_SIZE = 16; // max block size for ibc search
static const int IBC_NUM_CANDIDATES = 64; ///< Maximum number of candidates to store/test
static const int CHROMA_REFINEMENT_CANDIDATES = 8; /// 8 candidates BV to choose from
......
......@@ -1239,6 +1239,48 @@ const CtxSet ContextSetCfg::ISPMode = ContextSetCfg::addCtxSet
});
#endif
#if JVET_M0140_SBT
const CtxSet ContextSetCfg::SbtFlag = ContextSetCfg::addCtxSet
( {
{ CNU, CNU,},
{ CNU, CNU,},
{ CNU, CNU,},
#if JVET_M0453_CABAC_ENGINE
{ DWS, DWS,},
#endif
} );
const CtxSet ContextSetCfg::SbtQuadFlag = ContextSetCfg::addCtxSet
( {
{ CNU,},
{ CNU,},
{ CNU,},
#if JVET_M0453_CABAC_ENGINE
{ DWS,},
#endif
} );
const CtxSet ContextSetCfg::SbtHorFlag = ContextSetCfg::addCtxSet
( {
{ CNU, CNU, CNU,},
{ CNU, CNU, CNU,},
{ CNU, CNU, CNU,},
#if JVET_M0453_CABAC_ENGINE
{ DWS, DWS, DWS,},
#endif
} );
const CtxSet ContextSetCfg::SbtPosFlag = ContextSetCfg::addCtxSet
( {
{ CNU,},
{ CNU,},
{ CNU,},
#if JVET_M0453_CABAC_ENGINE
{ DWS,},
#endif
} );
#endif
const CtxSet ContextSetCfg::CrossCompPred = ContextSetCfg::addCtxSet
({
{ 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,},
......
......@@ -293,6 +293,12 @@ public:
#if !JVET_M0464_UNI_MTS
static const CtxSet EMTTuIndex;
static const CtxSet EMTCuFlag;
#endif
#if JVET_M0140_SBT
static const CtxSet SbtFlag;
static const CtxSet SbtQuadFlag;
static const CtxSet SbtHorFlag;
static const CtxSet SbtPosFlag;
#endif
static const CtxSet CrossCompPred;
static const CtxSet ChromaQpAdjFlag;
......
......@@ -1900,6 +1900,9 @@ SPSNext::SPSNext( SPS& sps )
#else
, m_IntraEMT ( false )
, m_InterEMT ( false )
#endif
#if JVET_M0140_SBT
, m_SBT ( false )
#endif
, m_Affine ( false )
, m_AffineType ( false )
......
......@@ -848,6 +848,10 @@ private:
#else
bool m_IntraEMT; // 18
bool m_InterEMT; // 19
#endif
#if JVET_M0140_SBT
bool m_SBT;
uint8_t m_MaxSbtSize;
#endif
bool m_Affine;
bool m_AffineType;
......@@ -928,6 +932,12 @@ public:
bool getUseIntraEMT () const { return m_IntraEMT; }
void setUseInterEMT ( bool b ) { m_InterEMT = b; }
bool getUseInterEMT () const { return m_InterEMT; }
#endif
#if JVET_M0140_SBT
void setUseSBT ( bool b ) { m_SBT = b; }
bool getUseSBT () const { return m_SBT; }
void setMaxSbtSize ( uint8_t val ) { m_MaxSbtSize = val; }
uint8_t getMaxSbtSize () const { return m_MaxSbtSize; }
#endif
void setUseGBi ( bool b ) { m_GBi = b; }
bool getUseGBi () const { return m_GBi; }
......
......@@ -311,6 +311,41 @@ void TrQuant::getTrTypes ( TransformUnit tu, const ComponentID compID, int &trTy
return;
}
#endif
#if JVET_M0140_SBT
if( tu.cu->sbtInfo && compID == COMPONENT_Y )
{
uint8_t sbtIdx = tu.cu->getSbtIdx();
uint8_t sbtPos = tu.cu->getSbtPos();
if( sbtIdx == SBT_VER_HALF || sbtIdx == SBT_VER_QUAD )
{
assert( tu.lwidth() <= MTS_INTER_MAX_CU_SIZE );
if( tu.lheight() > MTS_INTER_MAX_CU_SIZE )
{
trTypeHor = trTypeVer = DCT2;
}
else
{
if( sbtPos == SBT_POS0 ) { trTypeHor = DCT8; trTypeVer = DST7; }
else { trTypeHor = DST7; trTypeVer = DST7; }
}
}
else
{
assert( tu.lheight() <= MTS_INTER_MAX_CU_SIZE );
if( tu.lwidth() > MTS_INTER_MAX_CU_SIZE )
{
trTypeHor = trTypeVer = DCT2;
}
else
{
if( sbtPos == SBT_POS0 ) { trTypeHor = DST7; trTypeVer = DCT8; }
else { trTypeHor = DST7; trTypeVer = DST7; }
}
}
return;
}
#endif
#if JVET_M0464_UNI_MTS
if ( mtsActivated )
......@@ -568,6 +603,15 @@ void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const Q
{
tu.mtsIdx = it->first;
CoeffBuf tempCoeff( m_mtsCoeffs[tu.mtsIdx], rect );
#if JVET_M0140_SBT
if( tu.noResidual )
{
int sumAbs = 0;
trCosts.push_back( TrCost( sumAbs, pos++ ) );
it++;
continue;
}
#endif
if( isLuma(compID) && tu.mtsIdx == 1 )
{
......@@ -640,6 +684,15 @@ void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const Q
const CPelBuf resiBuf = cs.getResiBuf(rect);
CoeffBuf rpcCoeff = tu.getCoeffs(compID);
#if JVET_M0140_SBT
if( tu.noResidual )
{
uiAbsSum = 0;
TU::setCbfAtDepth( tu, compID, tu.depth, uiAbsSum > 0 );
return;
}
#endif
RDPCMMode rdpcmMode = RDPCM_OFF;
rdpcmNxN(tu, compID, cQP, uiAbsSum, rdpcmMode);
......
......@@ -115,6 +115,11 @@
#endif
#define JVET_M0502_PRED_MODE_CTX 1
#define JVET_M0140_SBT 1 // Sub-Block transform for Inter blocks
#if JVET_M0140_SBT
#define APPLY_SBT_SL_ON_MTS 1 // apply save & load fast algorithm on inter MTS when SBT is on
#endif
#define JVET_M0407_IBC_RANGE 1 // extend IBC search range to some part of left CTU
#define JVET_M0464_UNI_MTS 1
......@@ -420,6 +425,39 @@ enum ISPType
};
#endif
#if JVET_M0140_SBT
enum SbtIdx
{
SBT_OFF_DCT = 0,
SBT_VER_HALF = 1,
SBT_HOR_HALF = 2,
SBT_VER_QUAD = 3,
SBT_HOR_QUAD = 4,
NUMBER_SBT_IDX,
SBT_OFF_MTS, //note: must be after all SBT modes, only used in fast algorithm to discern the best mode is inter EMT
};
enum SbtPos
{
SBT_POS0 = 0,
SBT_POS1 = 1,
NUMBER_SBT_POS
};
enum SbtMode
{
SBT_VER_H0 = 0,
SBT_VER_H1 = 1,
SBT_HOR_H0 = 2,
SBT_HOR_H1 = 3,
SBT_VER_Q0 = 4,
SBT_VER_Q1 = 5,
SBT_HOR_Q0 = 6,
SBT_HOR_Q1 = 7,
NUMBER_SBT_MODE
};
#endif
enum RDPCMMode
{
RDPCM_OFF = 0,
......
......@@ -271,6 +271,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other )
qp = other.qp;
chromaQpAdj = other.chromaQpAdj;
rootCbf = other.rootCbf;
#if JVET_M0140_SBT
sbtInfo = other.sbtInfo;
#endif
#if !JVET_M0464_UNI_MTS
emtFlag = other.emtFlag;
#endif
......@@ -317,6 +320,9 @@ void CodingUnit::initData()
qp = 0;
chromaQpAdj = 0;
rootCbf = true;
#if JVET_M0140_SBT
sbtInfo = 0;
#endif
#if !JVET_M0464_UNI_MTS
emtFlag = 0;
#endif
......@@ -344,6 +350,70 @@ void CodingUnit::initData()
#endif
}
#if JVET_M0140_SBT
const uint8_t CodingUnit::checkAllowedSbt() const
{
if( !slice->getSPS()->getSpsNext().getUseSBT() )
{
return 0;
}
//check on prediction mode
if( predMode == MODE_INTRA ) //intra
{
return 0;
}
if( firstPU->mhIntraFlag )
{
return 0;
}
uint8_t sbtAllowed = 0;
int cuWidth = lwidth();
int cuHeight = lheight();
bool allow_type[NUMBER_SBT_IDX];
memset( allow_type, false, NUMBER_SBT_IDX * sizeof( bool ) );
//parameter
int maxSbtCUSize = cs->sps->getSpsNext().getMaxSbtSize();
int minSbtCUSize = 1 << ( MIN_CU_LOG2 + 1 );
//check on size
if( cuWidth > maxSbtCUSize || cuHeight > maxSbtCUSize )
{
return 0;
}
allow_type[SBT_VER_HALF] = cuWidth >= minSbtCUSize;
allow_type[SBT_HOR_HALF] = cuHeight >= minSbtCUSize;
allow_type[SBT_VER_QUAD] = cuWidth >= ( minSbtCUSize << 1 );
allow_type[SBT_HOR_QUAD] = cuHeight >= ( minSbtCUSize << 1 );
for( int i = 0; i < NUMBER_SBT_IDX; i++ )
{
sbtAllowed += (uint8_t)allow_type[i] << i;
}
return sbtAllowed;
}
uint8_t CodingUnit::getSbtTuSplit() const
{
uint8_t sbtTuSplitType = 0;
switch( getSbtIdx() )
{
case SBT_VER_HALF: sbtTuSplitType = ( getSbtPos() == SBT_POS0 ? 0 : 1 ) + SBT_VER_HALF_POS0_SPLIT; break;
case SBT_HOR_HALF: sbtTuSplitType = ( getSbtPos() == SBT_POS0 ? 0 : 1 ) + SBT_HOR_HALF_POS0_SPLIT; break;
case SBT_VER_QUAD: sbtTuSplitType = ( getSbtPos() == SBT_POS0 ? 0 : 1 ) + SBT_VER_QUAD_POS0_SPLIT; break;
case SBT_HOR_QUAD: sbtTuSplitType = ( getSbtPos() == SBT_POS0 ? 0 : 1 ) + SBT_HOR_QUAD_POS0_SPLIT; break;
default: assert( 0 ); break;
}
assert( sbtTuSplitType <= SBT_HOR_QUAD_POS1_SPLIT && sbtTuSplitType >= SBT_VER_HALF_POS0_SPLIT );
return sbtTuSplitType;
}
#endif
// ---------------------------------------------------------------------------
// prediction unit method definitions
......@@ -594,6 +664,9 @@ void TransformUnit::initData()
#else
emtIdx = 0;
#endif
#if JVET_M0140_SBT
noResidual = false;
#endif
#if JVET_M0427_INLOOP_RESHAPER
m_chromaResScaleInv = 0;
#endif
......@@ -636,6 +709,9 @@ TransformUnit& TransformUnit::operator=(const TransformUnit& other)
mtsIdx = other.mtsIdx;
#else
emtIdx = other.emtIdx;
#endif
#if JVET_M0140_SBT
noResidual = other.noResidual;
#endif
return *this;
}
......@@ -667,6 +743,9 @@ void TransformUnit::copyComponentFrom(const TransformUnit& other, const Componen
emtIdx = other.emtIdx;
}
#endif
#if JVET_M0140_SBT
noResidual = other.noResidual;
#endif
}
CoeffBuf TransformUnit::getCoeffs(const ComponentID id) { return CoeffBuf(m_coeffs[id], blocks[id]); }
......@@ -674,6 +753,21 @@ const CCoeffBuf TransformUnit::getCoeffs(const ComponentID id) const { return CC
PelBuf TransformUnit::getPcmbuf(const ComponentID id) { return PelBuf (m_pcmbuf[id], blocks[id]); }
const CPelBuf TransformUnit::getPcmbuf(const ComponentID id) const { return CPelBuf (m_pcmbuf[id], blocks[id]); }
#if JVET_M0140_SBT
void TransformUnit::checkTuNoResidual( unsigned idx )
{
if( CU::getSbtIdx( cu->sbtInfo ) == SBT_OFF_DCT )
{
return;
}
if( ( CU::getSbtPos( cu->sbtInfo ) == SBT_POS0 && idx == 1 ) || ( CU::getSbtPos( cu->sbtInfo ) == SBT_POS1 && idx == 0 ) )
{
noResidual = true;
}
}
#endif
#if JVET_M0427_INLOOP_RESHAPER
int TransformUnit::getChromaAdj() const { return m_chromaResScaleInv; }
void TransformUnit::setChromaAdj(int i) { m_chromaResScaleInv = i; }
......
......@@ -308,6 +308,9 @@ struct CodingUnit : public UnitArea
bool ipcm;
uint8_t imv;
bool rootCbf;
#if JVET_M0140_SBT
uint8_t sbtInfo;
#endif
#if HEVC_TILES_WPP
uint32_t tileIdx;
#endif
......@@ -353,6 +356,14 @@ struct CodingUnit : public UnitArea
int64_t cacheId;
bool cacheUsed;
#endif
#if JVET_M0140_SBT
const uint8_t getSbtIdx() const { assert( ( ( sbtInfo >> 0 ) & 0xf ) < NUMBER_SBT_IDX ); return ( sbtInfo >> 0 ) & 0xf; }
const uint8_t getSbtPos() const { return ( sbtInfo >> 4 ) & 0x3; }
void setSbtIdx( uint8_t idx ) { CHECK( idx >= NUMBER_SBT_IDX, "sbt_idx wrong" ); sbtInfo = ( idx << 0 ) + ( sbtInfo & 0xf0 ); }
void setSbtPos( uint8_t pos ) { CHECK( pos >= 4, "sbt_pos wrong" ); sbtInfo = ( pos << 4 ) + ( sbtInfo & 0xcf ); }
uint8_t getSbtTuSplit() const;
const uint8_t checkAllowedSbt() const;
#endif
};
// ---------------------------------------------------------------------------
......@@ -459,6 +470,9 @@ struct TransformUnit : public UnitArea
uint8_t mtsIdx;
#else
uint8_t emtIdx;
#endif
#if JVET_M0140_SBT
bool noResidual;
#endif
uint8_t cbf [ MAX_NUM_TBLOCKS ];
RDPCMMode rdpcm [ MAX_NUM_TBLOCKS ];
......@@ -483,6 +497,9 @@ struct TransformUnit : public UnitArea
TransformUnit& operator=(const TransformUnit& other);
void copyComponentFrom (const TransformUnit& other, const ComponentID compID);
#if JVET_M0140_SBT
void checkTuNoResidual( unsigned idx );
#endif
CoeffBuf getCoeffs(const ComponentID id);
const CCoeffBuf getCoeffs(const ComponentID id) const;
......
......@@ -255,6 +255,18 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur
case TU_MAX_TR_SPLIT:
m_partStack.push_back( PartLevel( split, PartitionerImpl::getMaxTuTiling( currArea(), cs ) ) );
break;
#if JVET_M0140_SBT
case SBT_VER_HALF_POS0_SPLIT:
case SBT_VER_HALF_POS1_SPLIT:
case SBT_HOR_HALF_POS0_SPLIT:
case SBT_HOR_HALF_POS1_SPLIT:
case SBT_VER_QUAD_POS0_SPLIT:
case SBT_VER_QUAD_POS1_SPLIT:
case SBT_HOR_QUAD_POS0_SPLIT:
case SBT_HOR_QUAD_POS1_SPLIT:
m_partStack.push_back( PartLevel( split, PartitionerImpl::getSbtTuTiling( currArea(), cs, split ) ) );
break;
#endif
default:
THROW( "Unknown split mode" );
break;
......@@ -269,6 +281,12 @@ void QTBTPartitioner::splitCurrArea( const PartSplit split, const CodingStructur
{
currTrDepth++;
}
#if JVET_M0140_SBT
else if( split >= SBT_VER_HALF_POS0_SPLIT && split <= SBT_HOR_QUAD_POS1_SPLIT )
{
currTrDepth++;
}
#endif
else
{
currTrDepth = 0;
......@@ -418,6 +436,18 @@ bool QTBTPartitioner::canSplit( const PartSplit split, const CodingStructure &cs
case TU_MAX_TR_SPLIT:
return area.width > maxTrSize || area.height > maxTrSize;
break;
#if JVET_M0140_SBT
case SBT_VER_HALF_POS0_SPLIT:
case SBT_VER_HALF_POS1_SPLIT:
case SBT_HOR_HALF_POS0_SPLIT:
case SBT_HOR_HALF_POS1_SPLIT:
case SBT_VER_QUAD_POS0_SPLIT:
case SBT_VER_QUAD_POS1_SPLIT:
case SBT_HOR_QUAD_POS0_SPLIT:
case SBT_HOR_QUAD_POS1_SPLIT:
return currTrDepth == 0;
break;
#endif
#if JVET_M0421_SPLIT_SIG
case CU_QUAD_SPLIT:
return canQt;
......@@ -622,6 +652,13 @@ void QTBTPartitioner::exitCurrSplit()
CHECK( currTrDepth == 0, "TR depth is '0', although a TU split was performed" );
currTrDepth--;
}
#if JVET_M0140_SBT
else if( currSplit >= SBT_VER_HALF_POS0_SPLIT && currSplit <= SBT_HOR_QUAD_POS1_SPLIT )
{
CHECK( currTrDepth == 0, "TR depth is '0', although a TU split was performed" );
currTrDepth--;
}
#endif
else
{
CHECK( currTrDepth > 0, "RQT found with QTBT partitioner" );
......@@ -1111,3 +1148,64 @@ Partitioning PartitionerImpl::getMaxTuTiling( const UnitArea &cuArea, const Codi
return ret;
}
#if JVET_M0140_SBT
Partitioning PartitionerImpl::getSbtTuTiling( const UnitArea& cuArea, const CodingStructure &cs, const PartSplit splitType )
{
Partitioning ret;
int numTiles = 2;
int widthFactor, heightFactor, xOffsetFactor, yOffsetFactor; // y = (x * factor) >> 2;
assert( splitType >= SBT_VER_HALF_POS0_SPLIT && splitType <= SBT_HOR_QUAD_POS1_SPLIT );
ret.resize( numTiles, cuArea );
for( int i = 0; i < numTiles; i++ )
{
if( splitType >= SBT_VER_QUAD_POS0_SPLIT )
{
if( splitType == SBT_HOR_QUAD_POS0_SPLIT || splitType == SBT_HOR_QUAD_POS1_SPLIT )
{
widthFactor = 4;
xOffsetFactor = 0;
heightFactor = ( ( i == 0 && splitType == SBT_HOR_QUAD_POS0_SPLIT ) || ( i == 1 && splitType == SBT_HOR_QUAD_POS1_SPLIT ) ) ? 1 : 3;
yOffsetFactor = ( i == 0 ) ? 0 : ( splitType == SBT_HOR_QUAD_POS0_SPLIT ? 1 : 3 );
}
else
{
widthFactor = ( ( i == 0 && splitType == SBT_VER_QUAD_POS0_SPLIT ) || ( i == 1 && splitType == SBT_VER_QUAD_POS1_SPLIT ) ) ? 1 : 3;
xOffsetFactor = ( i == 0 ) ? 0 : ( splitType == SBT_VER_QUAD_POS0_SPLIT ? 1 : 3 );
heightFactor = 4;
yOffsetFactor = 0;
}
}
else
{
if( splitType == SBT_HOR_HALF_POS0_SPLIT || splitType == SBT_HOR_HALF_POS1_SPLIT )
{
widthFactor = 4;
xOffsetFactor = 0;
heightFactor = 2;
yOffsetFactor = ( i == 0 ) ? 0 : 2;
}
else
{
widthFactor = 2;
xOffsetFactor = ( i == 0 ) ? 0 : 2;
heightFactor = 4;
yOffsetFactor = 0;
}
}
UnitArea& tile = ret[i];
for( CompArea &comp : tile.blocks )
{
if( !comp.valid() ) continue;
comp.x += ( comp.width * xOffsetFactor ) >> 2;
comp.y += ( comp.height * yOffsetFactor ) >> 2;
comp.width = ( comp.width * widthFactor ) >> 2;
comp.height = ( comp.height * heightFactor ) >> 2;
}
}
return ret;
}
#endif
\ No newline at end of file
......@@ -71,6 +71,16 @@ enum PartSplit
TU_NO_ISP,
TU_1D_HORZ_SPLIT,
TU_1D_VERT_SPLIT,
#endif
#if JVET_M0140_SBT
SBT_VER_HALF_POS0_SPLIT,
SBT_VER_HALF_POS1_SPLIT,
SBT_HOR_HALF_POS0_SPLIT,
SBT_HOR_HALF_POS1_SPLIT,
SBT_VER_QUAD_POS0_SPLIT,
SBT_VER_QUAD_POS1_SPLIT,
SBT_HOR_QUAD_POS0_SPLIT,
SBT_HOR_QUAD_POS1_SPLIT,
#endif
NUM_PART_SPLIT,
CU_MT_SPLIT = 1000, ///< dummy element to indicate the MT (multi-type-tree) split
......@@ -219,6 +229,9 @@ namespace PartitionerImpl
#if JVET_M0102_INTRA_SUBPARTITIONS
void getTUIntraSubPartitions( Partitioning &sub, const UnitArea &tuArea, const CodingStructure &cs, const PartSplit splitType );
#endif
#if JVET_M0140_SBT
Partitioning getSbtTuTiling ( const UnitArea& curArea, const CodingStructure &cs, const PartSplit splitType );
#endif
};
#endif
......@@ -5502,6 +5502,121 @@ int CU::getMaxNeighboriMVCandNum( const CodingStructure& cs, const Position& pos
return maxImvNumCand;
}
#if JVET_M0140_SBT
uint8_t CU::getSbtInfo( uint8_t idx, uint8_t pos )
{
return ( pos << 4 ) + ( idx << 0 );
}
uint8_t CU::getSbtIdx( const uint8_t sbtInfo )
{
return ( sbtInfo >> 0 ) & 0xf;
}
uint8_t CU::getSbtPos( const uint8_t sbtInfo )
{
return ( sbtInfo >> 4 ) & 0x3;
}
uint8_t CU::getSbtMode( uint8_t sbtIdx, uint8_t sbtPos )
{
uint8_t sbtMode = 0;
switch( sbtIdx )
{
case SBT_VER_HALF: sbtMode = sbtPos + SBT_VER_H0; break;
case SBT_HOR_HALF: sbtMode = sbtPos + SBT_HOR_H0; break;
case SBT_VER_QUAD: sbtMode = sbtPos + SBT_VER_Q0; break;
case SBT_HOR_QUAD: sbtMode = sbtPos + SBT_HOR_Q0; break;
default: assert( 0 );
}
assert( sbtMode < NUMBER_SBT_MODE );
return sbtMode;
}
uint8_t CU::getSbtIdxFromSbtMode( uint8_t sbtMode )
{