Commit 378acb66 authored by Yu-Chi Su's avatar Yu-Chi Su

JVET-L0646: Generalized bi-prediction (GBi)

parent ebe60316
......@@ -127,6 +127,8 @@ LMChroma : 1 # use CCLM only
DepQuant : 1
IMV : 2
ALF : 1
GBi : 1
GBiFast : 1
# Fast tools
PBIntraFast : 1
......
......@@ -141,6 +141,8 @@ LMChroma : 1 # use CCLM only
DepQuant : 1
IMV : 2
ALF : 1
GBi : 1
GBiFast : 1
# Fast tools
PBIntraFast : 1
......
......@@ -239,6 +239,10 @@ void EncApp::xInitLibCfg()
m_cEncLib.setInterEMT ( ( m_EMT >> 1 ) & 1 );
m_cEncLib.setFastInterEMT ( ( m_FastEMT >> 1 ) & ( m_EMT >> 1 ) & 1 );
m_cEncLib.setUseCompositeRef ( m_compositeRefEnabled );
#if JVET_L0646_GBI
m_cEncLib.setUseGBi ( m_GBi );
m_cEncLib.setUseGBiFast ( m_GBiFast );
#endif
// ADD_NEW_TOOL : (encoder app) add setting of tool enabling flags and associated parameters here
m_cEncLib.setMaxCUWidth ( m_QTBT ? m_uiCTUSize : m_uiMaxCUWidth );
......
......@@ -844,6 +844,10 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
"\t2: Enable fast methods only for Inter EMT\n"
"\t3: Enable fast methods for both Intra & Inter EMT\n")
("CompositeLTReference", m_compositeRefEnabled, false, "Enable Composite Long Term Reference Frame")
#if JVET_L0646_GBI
("GBi", m_GBi, false, "Enable Generalized Bi-prediction(GBi)")
("GBiFast", m_GBiFast, false, "Fast methods for Generalized Bi-prediction(GBi)\n")
#endif
// ADD_NEW_TOOL : (encoder app) add parsing parameters here
("LCTUFast", m_useFastLCTU, false, "Fast methods for large CTU")
......@@ -1916,7 +1920,11 @@ bool EncAppCfg::xCheckParameter()
xConfirmPara( m_useFastLCTU, "Fast large CTU can only be applied when encoding with NEXT profile" );
xConfirmPara( m_EMT, "EMT only allowed with NEXT profile" );
xConfirmPara( m_FastEMT, "EMT only allowed with NEXT profile" );
xConfirmPara(m_compositeRefEnabled, "Composite Reference Frame is only allowed with NEXT profile");
xConfirmPara( m_compositeRefEnabled, "Composite Reference Frame is only allowed with NEXT profile" );
#if JVET_L0646_GBI
xConfirmPara( m_GBi, "GBi is only allowed with NEXT profile" );
xConfirmPara( m_GBiFast, "GBiFast is only allowed with NEXT profile" );
#endif
// ADD_NEW_TOOL : (parameter check) add a check for next tools here
}
else
......@@ -3111,6 +3119,10 @@ void EncAppCfg::xPrintParameter()
msg( VERBOSE, "LMChroma:%d ", m_LMChroma );
msg( VERBOSE, "EMT: %1d(intra) %1d(inter) ", m_EMT & 1, ( m_EMT >> 1 ) & 1 );
msg(VERBOSE, "CompositeLTReference:%d ", m_compositeRefEnabled);
#if JVET_L0646_GBI
msg( VERBOSE, "GBi:%d ", m_GBi );
msg( VERBOSE, "GBiFast:%d ", m_GBiFast );
#endif
}
// ADD_NEW_TOOL (add some output indicating the usage of tools)
......
......@@ -221,6 +221,10 @@ protected:
int m_FastEMT; ///< XZ: Fast Methods of Enhanced Multiple Transform
bool m_compositeRefEnabled;
#if JVET_L0646_GBI
bool m_GBi;
bool m_GBiFast;
#endif
// ADD_NEW_TOOL : (encoder app) add tool enabling flags and associated parameters here
unsigned m_uiMaxCUWidth; ///< max. CU width in pixel
......
......@@ -62,6 +62,40 @@ void addAvgCore( const T* src1, int src1Stride, const T* src2, int src2Stride, T
#undef ADD_AVG_CORE_INC
}
#if ENABLE_SIMD_OPT_GBI && JVET_L0646_GBI
void removeWeightHighFreq(int16_t* dst, int dstStride, const int16_t* src, int srcStride, int width, int height, int shift, int gbiWeight)
{
int normalizer = ((1 << 16) + (gbiWeight > 0 ? (gbiWeight >> 1) : -(gbiWeight >> 1))) / gbiWeight;
int weight0 = normalizer << g_GbiLog2WeightBase;
int weight1 = (g_GbiWeightBase - gbiWeight)*normalizer;
#define REM_HF_INC \
src += srcStride; \
dst += dstStride; \
#define REM_HF_OP( ADDR ) dst[ADDR] = (dst[ADDR]*weight0 - src[ADDR]*weight1 + (1<<15))>>16
SIZE_AWARE_PER_EL_OP(REM_HF_OP, REM_HF_INC);
#undef REM_HF_INC
#undef REM_HF_OP
#undef REM_HF_OP_CLIP
}
void removeHighFreq(int16_t* dst, int dstStride, const int16_t* src, int srcStride, int width, int height)
{
#define REM_HF_INC \
src += srcStride; \
dst += dstStride; \
#define REM_HF_OP( ADDR ) dst[ADDR] = 2 * dst[ADDR] - src[ADDR]
SIZE_AWARE_PER_EL_OP(REM_HF_OP, REM_HF_INC);
#undef REM_HF_INC
#undef REM_HF_OP
#undef REM_HF_OP_CLIP
}
#endif
template<typename T>
void reconstructCore( const T* src1, int src1Stride, const T* src2, int src2Stride, T* dest, int dstStride, int width, int height, const ClpRng& clpRng )
......@@ -103,6 +137,14 @@ PelBufferOps::PelBufferOps()
linTf4 = linTfCore<Pel>;
linTf8 = linTfCore<Pel>;
#if ENABLE_SIMD_OPT_GBI
removeWeightHighFreq8 = removeWeightHighFreq;
removeWeightHighFreq4 = removeWeightHighFreq;
removeHighFreq8 = removeHighFreq;
removeHighFreq4 = removeHighFreq;
#endif
}
PelBufferOps g_pelBufOP = PelBufferOps();
......@@ -110,6 +152,37 @@ PelBufferOps g_pelBufOP = PelBufferOps();
#endif
#endif
#if JVET_L0646_GBI
template<>
void AreaBuf<Pel>::addWeightedAvg(const AreaBuf<const Pel> &other1, const AreaBuf<const Pel> &other2, const ClpRng& clpRng, const int8_t gbiIdx)
{
const int8_t w0 = getGbiWeight(gbiIdx, REF_PIC_LIST_0);
const int8_t w1 = getGbiWeight(gbiIdx, REF_PIC_LIST_1);
const int8_t log2WeightBase = g_GbiLog2WeightBase;
const Pel* src0 = other1.buf;
const Pel* src2 = other2.buf;
Pel* dest = buf;
const unsigned src1Stride = other1.stride;
const unsigned src2Stride = other2.stride;
const unsigned destStride = stride;
const int clipbd = clpRng.bd;
const int shiftNum = std::max<int>(2, (IF_INTERNAL_PREC - clipbd)) + log2WeightBase;
const int offset = (1 << (shiftNum - 1)) + (IF_INTERNAL_OFFS << log2WeightBase);
#define ADD_AVG_OP( ADDR ) dest[ADDR] = ClipPel( rightShift( ( src0[ADDR]*w0 + src2[ADDR]*w1 + offset ), shiftNum ), clpRng )
#define ADD_AVG_INC \
src0 += src1Stride; \
src2 += src2Stride; \
dest += destStride; \
SIZE_AWARE_PER_EL_OP(ADD_AVG_OP, ADD_AVG_INC);
#undef ADD_AVG_OP
#undef ADD_AVG_INC
}
#endif
template<>
void AreaBuf<Pel>::addAvg( const AreaBuf<const Pel> &other1, const AreaBuf<const Pel> &other2, const ClpRng& clpRng)
......
......@@ -68,6 +68,12 @@ struct PelBufferOps
void ( *reco8 ) ( const Pel* src0, int src0Stride, const Pel* src1, int src1Stride, Pel *dst, int dstStride, int width, int height, const ClpRng& clpRng );
void ( *linTf4 ) ( const Pel* src0, int src0Stride, Pel *dst, int dstStride, int width, int height, int scale, int shift, int offset, const ClpRng& clpRng, bool bClip );
void ( *linTf8 ) ( const Pel* src0, int src0Stride, Pel *dst, int dstStride, int width, int height, int scale, int shift, int offset, const ClpRng& clpRng, bool bClip );
#if ENABLE_SIMD_OPT_GBI
void ( *removeWeightHighFreq8) ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height, int shift, int gbiWeight);
void ( *removeWeightHighFreq4) ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height, int shift, int gbiWeight);
void ( *removeHighFreq8) ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height);
void ( *removeHighFreq4) ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height);
#endif
};
extern PelBufferOps g_pelBufOP;
......@@ -102,6 +108,10 @@ struct AreaBuf : public Size
void subtract ( const AreaBuf<const T> &other );
void extendSingleBorderPel();
void extendBorderPel ( unsigned margin );
#if JVET_L0646_GBI
void addWeightedAvg ( const AreaBuf<const T> &other1, const AreaBuf<const T> &other2, const ClpRng& clpRng, const int8_t gbiIdx);
void removeWeightHighFreq ( const AreaBuf<T>& other, const bool bClip, const ClpRng& clpRng, const int8_t iGbiWeight);
#endif
void addAvg ( const AreaBuf<const T> &other1, const AreaBuf<const T> &other2, const ClpRng& clpRng );
void removeHighFreq ( const AreaBuf<T>& other, const bool bClip, const ClpRng& clpRng);
void updateHistogram ( std::vector<int32_t>& hist ) const;
......@@ -384,6 +394,59 @@ void AreaBuf<T>::toLast( const ClpRng& clpRng )
template<>
void AreaBuf<Pel>::toLast( const ClpRng& clpRng );
#if JVET_L0646_GBI
template<typename T>
void AreaBuf<T>::removeWeightHighFreq(const AreaBuf<T>& other, const bool bClip, const ClpRng& clpRng, const int8_t gbiWeight)
{
const int8_t gbiWeightOther = g_GbiWeightBase - gbiWeight;
const int8_t log2WeightBase = g_GbiLog2WeightBase;
const Pel* src = other.buf;
const int srcStride = other.stride;
Pel* dst = buf;
const int dstStride = stride;
#if ENABLE_SIMD_OPT_GBI
if(!bClip)
{
if(!(width & 7))
g_pelBufOP.removeWeightHighFreq8(dst, dstStride, src, srcStride, width, height, 16, gbiWeight);
else if(!(width & 3))
g_pelBufOP.removeWeightHighFreq4(dst, dstStride, src, srcStride, width, height, 16, gbiWeight);
else
CHECK(true, "Not supported");
}
else
{
#endif
int normalizer = ((1 << 16) + (gbiWeight > 0 ? (gbiWeight >> 1) : -(gbiWeight >> 1))) / gbiWeight;
int weight0 = normalizer << log2WeightBase;
int weight1 = gbiWeightOther * normalizer;
#define REM_HF_INC \
src += srcStride; \
dst += dstStride; \
#define REM_HF_OP_CLIP( ADDR ) dst[ADDR] = ClipPel<T>( (dst[ADDR]*weight0 - src[ADDR]*weight1 + (1<<15))>>16, clpRng )
#define REM_HF_OP( ADDR ) dst[ADDR] = (dst[ADDR]*weight0 - src[ADDR]*weight1 + (1<<15))>>16
if(bClip)
{
SIZE_AWARE_PER_EL_OP(REM_HF_OP_CLIP, REM_HF_INC);
}
else
{
SIZE_AWARE_PER_EL_OP(REM_HF_OP, REM_HF_INC);
}
#undef REM_HF_INC
#undef REM_HF_OP
#undef REM_HF_OP_CLIP
#if ENABLE_SIMD_OPT_GBI
}
#endif
}
#endif
template<typename T>
void AreaBuf<T>::removeHighFreq( const AreaBuf<T>& other, const bool bClip, const ClpRng& clpRng )
......@@ -394,6 +457,20 @@ void AreaBuf<T>::removeHighFreq( const AreaBuf<T>& other, const bool bClip, cons
T* dst = buf;
const int dstStride = stride;
#if ENABLE_SIMD_OPT_GBI && JVET_L0646_GBI
if (!bClip)
{
if(!(width & 7))
g_pelBufOP.removeHighFreq8(dst, dstStride, src, srcStride, width, height);
else if (!(width & 3))
g_pelBufOP.removeHighFreq4(dst, dstStride, src, srcStride, width, height);
else
CHECK(true, "Not supported");
}
else
{
#endif
#define REM_HF_INC \
src += srcStride; \
dst += dstStride; \
......@@ -413,6 +490,10 @@ void AreaBuf<T>::removeHighFreq( const AreaBuf<T>& other, const bool bClip, cons
#undef REM_HF_INC
#undef REM_HF_OP
#undef REM_HF_OP_CLIP
#if ENABLE_SIMD_OPT_GBI && JVET_L0646_GBI
}
#endif
}
......@@ -576,10 +657,16 @@ struct UnitBuf
void reconstruct ( const UnitBuf<const T> &pred, const UnitBuf<const T> &resi, const ClpRngs& clpRngs );
void copyClip ( const UnitBuf<const T> &src, const ClpRngs& clpRngs );
void subtract ( const UnitBuf<const T> &other );
#if JVET_L0646_GBI
void addWeightedAvg ( const UnitBuf<const T> &other1, const UnitBuf<const T> &other2, const ClpRngs& clpRngs, const uint8_t gbiIdx = GBI_DEFAULT, const bool chromaOnly = false, const bool lumaOnly = false);
#endif
void addAvg ( const UnitBuf<const T> &other1, const UnitBuf<const T> &other2, const ClpRngs& clpRngs, const bool chromaOnly = false, const bool lumaOnly = false);
void extendSingleBorderPel();
void extendBorderPel ( unsigned margin );
void removeHighFreq ( const UnitBuf<T>& other, const bool bClip, const ClpRngs& clpRngs
#if JVET_L0646_GBI
, const int8_t gbiWeight = g_GbiWeights[GBI_DEFAULT]
#endif
);
UnitBuf< T> subBuf (const UnitArea& subArea);
......@@ -649,6 +736,21 @@ void UnitBuf<T>::reconstruct(const UnitBuf<const T> &pred, const UnitBuf<const T
}
}
#if JVET_L0646_GBI
template<typename T>
void UnitBuf<T>::addWeightedAvg(const UnitBuf<const T> &other1, const UnitBuf<const T> &other2, const ClpRngs& clpRngs, const uint8_t gbiIdx /* = GBI_DEFAULT */, const bool chromaOnly /* = false */, const bool lumaOnly /* = false */)
{
const size_t istart = chromaOnly ? 1 : 0;
const size_t iend = lumaOnly ? 1 : bufs.size();
CHECK(lumaOnly && chromaOnly, "should not happen");
for(size_t i = istart; i < iend; i++)
{
bufs[i].addWeightedAvg(other1.bufs[i], other2.bufs[i], clpRngs.comp[i], gbiIdx);
}
}
#endif
template<typename T>
void UnitBuf<T>::addAvg(const UnitBuf<const T> &other1, const UnitBuf<const T> &other2, const ClpRngs& clpRngs, const bool chromaOnly /* = false */, const bool lumaOnly /* = false */)
......@@ -684,12 +786,25 @@ void UnitBuf<T>::extendBorderPel( unsigned margin )
template<typename T>
void UnitBuf<T>::removeHighFreq( const UnitBuf<T>& other, const bool bClip, const ClpRngs& clpRngs
#if JVET_L0646_GBI
, const int8_t gbiWeight
#endif
)
{
for( unsigned i = 0; i < bufs.size(); i++ )
#if JVET_L0646_GBI
if(gbiWeight != g_GbiWeights[GBI_DEFAULT])
{
bufs[i].removeHighFreq(other.bufs[i], bClip, clpRngs.comp[i] );
bufs[0].removeWeightHighFreq(other.bufs[0], bClip, clpRngs.comp[0], gbiWeight);
return;
}
bufs[0].removeHighFreq(other.bufs[0], bClip, clpRngs.comp[0]);
#else
for (unsigned i = 0; i <bufs.size(); i++)
{
bufs[i].removeHighFreq(other.bufs[i], bClip, clpRngs.comp[i]);
}
#endif
}
template<typename T>
......
......@@ -100,6 +100,9 @@ enum CodingStatisticsType
STATS__CABAC_BITS__PAR_FLAG,
STATS__CABAC_BITS__ALF,
STATS__CABAC_BITS__IMV_FLAG,
#if JVET_L0646_GBI
STATS__CABAC_BITS__GBI_IDX,
#endif
STATS__CABAC_BITS__EMT_CU_FLAG,
STATS__CABAC_BITS__EMT_TU_INDEX,
STATS__TOOL_EMT,
......@@ -170,6 +173,9 @@ static inline const char* getName(CodingStatisticsType name)
"CABAC_BITS__ALIGNED_SIGN_BIT",
"CABAC_BITS__ALIGNED_ESCAPE_BITS",
"CABAC_BITS__IMV_FLAG",
#if JVET_L0646_GBI
"CABAC_BITS__GBI_IDX",
#endif
"CABAC_BITS__EMT_CU_FLAG",
"CABAC_BITS__EMT_TU_INDX",
"CABAC_BITS__OTHER",
......
......@@ -291,6 +291,11 @@ static const int AFFINE_MAX_NUM_V2 = 2; ///< max
static const int AFFINE_MAX_NUM_COMB = 12; ///< max number of combined motion candidates
static const int AFFINE_MIN_BLOCK_SIZE = 4; ///< Minimum affine MC block size
#if JVET_L0646_GBI
static const int GBI_NUM = 5; ///< the number of weight options
static const int GBI_DEFAULT = ((uint8_t)(GBI_NUM >> 1)); ///< Default weighting index representing for w=0.5
static const int GBI_SIZE_CONSTRAINT = 256; ///< disabling GBi if cu size is smaller than 256
#endif
#if W0038_DB_OPT
static const int MAX_ENCODER_DEBLOCKING_QUALITY_LAYERS = 8 ;
......
......@@ -347,5 +347,8 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx )
pu.mvpNum [REF_PIC_LIST_0] = NOT_VALID;
pu.mvpNum [REF_PIC_LIST_1] = NOT_VALID;
#if JVET_L0646_GBI
pu.cu->GBiIdx = ( interDirNeighbours[candIdx] == 3 ) ? GBiIdx[candIdx] : GBI_DEFAULT;
#endif
}
......@@ -265,6 +265,9 @@ public:
~MergeCtx() {}
public:
MvField mvFieldNeighbours [ MRG_MAX_NUM_CANDS << 1 ]; // double length for mv of both lists
#if JVET_L0646_GBI
uint8_t GBiIdx [ MRG_MAX_NUM_CANDS ];
#endif
unsigned char interDirNeighbours[ MRG_MAX_NUM_CANDS ];
MergeType mrgTypeNeighbours [ MRG_MAX_NUM_CANDS ];
int numValidMergeCand;
......
......@@ -367,6 +367,15 @@ const CtxSet ContextSetCfg::AffineType = ContextSetCfg::addCtxSet
{ CNU, },
});
#if JVET_L0646_GBI
const CtxSet ContextSetCfg::GBiIdx = ContextSetCfg::addCtxSet
({
// 4 ctx for 1st bin; 1 ctx for each of rest bins
{ 95, 79, 63, 31, 31, 31, 31, },
{ 95, 79, 63, 31, 31, 31, 31, },
{ CNU, CNU, CNU, CNU, CNU, CNU, CNU, },
});
#endif
const CtxSet ContextSetCfg::Mvd = ContextSetCfg::addCtxSet
({
......
......@@ -191,6 +191,9 @@ public:
static const CtxSet ChromaQpAdjFlag;
static const CtxSet ChromaQpAdjIdc;
static const CtxSet ImvFlag;
#if JVET_L0646_GBI
static const CtxSet GBiIdx;
#endif
static const CtxSet ctbAlfFlag;
static const unsigned NumberOfContexts;
......
......@@ -620,6 +620,13 @@ void InterPrediction::xWeightedAverage( const PredictionUnit& pu, const CPelUnit
if( iRefIdx0 >= 0 && iRefIdx1 >= 0 )
{
#if JVET_L0646_GBI
if( pu.cu->GBiIdx != GBI_DEFAULT )
{
pcYuvDst.addWeightedAvg(pcYuvSrc0, pcYuvSrc1, clpRngs, pu.cu->GBiIdx);
return;
}
#endif
pcYuvDst.addAvg( pcYuvSrc0, pcYuvSrc1, clpRngs );
}
else if( iRefIdx0 >= 0 && iRefIdx1 < 0 )
......
......@@ -140,5 +140,73 @@ struct MotionInfo
}
};
#if JVET_L0646_GBI
class GBiMotionParam
{
bool m_readOnly[2][33]; // 2 RefLists, 33 RefFrams
Mv m_mv[2][33];
Distortion m_dist[2][33];
bool m_readOnlyAffine[2][2][33];
Mv m_mvAffine[2][2][33][3];
Distortion m_distAffine[2][2][33];
public:
void reset()
{
Mv* pMv = &(m_mv[0][0]);
for (int ui = 0; ui < 1 * 2 * 33; ++ui, ++pMv)
{
pMv->set(std::numeric_limits<int16_t>::max(), std::numeric_limits<int16_t>::max());
}
Mv* pAffineMv = &(m_mvAffine[0][0][0][0]);
for (int ui = 0; ui < 2 * 2 * 33 * 3; ++ui, ++pMv)
{
pAffineMv->set(0, 0);
}
memset(m_readOnly, false, 2 * 33 * sizeof(bool));
memset(m_dist, -1, 2 * 33 * sizeof(Distortion));
memset(m_readOnlyAffine, false, 2 * 2 * 33 * sizeof(bool));
memset(m_distAffine, -1, 2 * 2 * 33 * sizeof(Distortion));
}
void setReadMode(bool b, uint32_t uiRefList, uint32_t uiRefIdx) { m_readOnly[uiRefList][uiRefIdx] = b; }
bool isReadMode(uint32_t uiRefList, uint32_t uiRefIdx) { return m_readOnly[uiRefList][uiRefIdx]; }
void setReadModeAffine(bool b, uint32_t uiRefList, uint32_t uiRefIdx, int bP4) { m_readOnlyAffine[bP4][uiRefList][uiRefIdx] = b; }
bool isReadModeAffine(uint32_t uiRefList, uint32_t uiRefIdx, int bP4) { return m_readOnlyAffine[bP4][uiRefList][uiRefIdx]; }
Mv& getMv(uint32_t uiRefList, uint32_t uiRefIdx) { return m_mv[uiRefList][uiRefIdx]; }
void copyFrom(Mv& rcMv, Distortion uiDist, uint32_t uiRefList, uint32_t uiRefIdx)
{
m_mv[uiRefList][uiRefIdx] = rcMv;
m_dist[uiRefList][uiRefIdx] = uiDist;
}
void copyTo(Mv& rcMv, Distortion& ruiDist, uint32_t uiRefList, uint32_t uiRefIdx)
{
rcMv = m_mv[uiRefList][uiRefIdx];
ruiDist = m_dist[uiRefList][uiRefIdx];
}
Mv& getAffineMv(uint32_t uiRefList, uint32_t uiRefIdx, uint32_t uiAffineMvIdx, int bP4) { return m_mvAffine[bP4][uiRefList][uiRefIdx][uiAffineMvIdx]; }
void copyAffineMvFrom(Mv(&racAffineMvs)[3], Distortion uiDist, uint32_t uiRefList, uint32_t uiRefIdx, int bP4)
{
memcpy(m_mvAffine[bP4][uiRefList][uiRefIdx], racAffineMvs, 3 * sizeof(Mv));
m_distAffine[bP4][uiRefList][uiRefIdx] = uiDist;
}
void copyAffineMvTo(Mv acAffineMvs[3], Distortion& ruiDist, uint32_t uiRefList, uint32_t uiRefIdx, int bP4)
{
memcpy(acAffineMvs, m_mvAffine[bP4][uiRefList][uiRefIdx], 3 * sizeof(Mv));
ruiDist = m_distAffine[bP4][uiRefList][uiRefIdx];
}
};
#endif
#endif // __MOTIONINFO__
......@@ -183,7 +183,71 @@ public:
const int g_aiNonLMPosThrs[] = { 3, 1, 0 };
#if JVET_L0646_GBI
const int8_t g_GbiLog2WeightBase = 3;
const int8_t g_GbiWeightBase = (1 << g_GbiLog2WeightBase);
const int8_t g_GbiWeights[GBI_NUM] = { -2, 3, 4, 5, 10 };
const int8_t g_GbiSearchOrder[GBI_NUM] = { GBI_DEFAULT, GBI_DEFAULT - 2, GBI_DEFAULT + 2, GBI_DEFAULT - 1, GBI_DEFAULT + 1 };
int8_t g_GbiCodingOrder[GBI_NUM];
int8_t g_GbiParsingOrder[GBI_NUM];
int8_t getGbiWeight(uint8_t gbiIdx, uint8_t uhRefFrmList)
{
// Weghts for the model: P0 + w * (P1 - P0) = (1-w) * P0 + w * P1
// Retuning 1-w for P0 or w for P1
return (uhRefFrmList == REF_PIC_LIST_0 ? g_GbiWeightBase - g_GbiWeights[gbiIdx] : g_GbiWeights[gbiIdx]);
}
void resetGbiCodingOrder(bool bRunDecoding, const CodingStructure &cs)
{
// Form parsing order: { GBI_DEFAULT, GBI_DEFAULT+1, GBI_DEFAULT-1, GBI_DEFAULT+2, GBI_DEFAULT-2, ... }
g_GbiParsingOrder[0] = GBI_DEFAULT;
for (int i = 1; i <= (GBI_NUM >> 1); ++i)
{
g_GbiParsingOrder[2 * i - 1] = GBI_DEFAULT + (int8_t)i;
g_GbiParsingOrder[2 * i] = GBI_DEFAULT - (int8_t)i;
}
// Form encoding order
if (!bRunDecoding)
{
for (int i = 0; i < GBI_NUM; ++i)
{
g_GbiCodingOrder[(uint32_t)g_GbiParsingOrder[i]] = i;
}
}
}
uint32_t deriveWeightIdxBits(uint8_t gbiIdx) // Note: align this with TEncSbac::codeGbiIdx and TDecSbac::parseGbiIdx
{
uint32_t numBits = 1;
uint8_t gbiCodingIdx = (uint8_t)g_GbiCodingOrder[gbiIdx];
if (GBI_NUM > 2 && gbiCodingIdx != 0)
{
uint32_t prefixNumBits = GBI_NUM - 2;
uint32_t step = 1;
uint8_t prefixSymbol = gbiCodingIdx;
// Truncated unary code
uint8_t idx = 1;
for (int ui = 0; ui < prefixNumBits; ++ui)
{
if (prefixSymbol == idx)
{
++numBits;
break;
}
else
{
++numBits;
idx += step;
}
}
}
return numBits;
}
#endif
// initialize ROM variables
void initROM()
......
......@@ -212,6 +212,20 @@ extern MsgLevel g_verbosity;
extern const int g_aiNonLMPosThrs[];
#if JVET_L0646_GBI
extern const int8_t g_GbiLog2WeightBase;
extern const int8_t g_GbiWeightBase;
extern const int8_t g_GbiWeights[GBI_NUM];
extern const int8_t g_GbiSearchOrder[GBI_NUM];
extern int8_t g_GbiCodingOrder[GBI_NUM];
extern int8_t g_GbiParsingOrder[GBI_NUM];
class CodingStructure;
int8_t getGbiWeight(uint8_t gbiIdx, uint8_t uhRefFrmList);
void resetGbiCodingOrder(bool bRunDecoding, const CodingStructure &cs);
uint32_t deriveWeightIdxBits(uint8_t gbiIdx);
#endif
constexpr uint8_t g_tbMax[257] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
......
......@@ -810,6 +810,9 @@ private:
bool m_InterEMT; // 19
bool m_Affine;
bool m_AffineType;
#if JVET_L0646_GBI
bool m_GBi; //
#endif
bool m_MTTEnabled; //
#if ENABLE_WPP_PARALLELISM
bool m_NextDQP;
......@@ -876,6 +879,10 @@ public:
bool getUseIntraEMT () const { return m_IntraEMT; }
void setUseInterEMT ( bool b ) { m_InterEMT = b; }
bool getUseInterEMT () const { return m_InterEMT; }
#if JVET_L0646_GBI
void setUseGBi ( bool b ) { m_GBi = b; }
bool getUseGBi () const { return m_GBi; }
#endif
//===== additional parameters =====
// qtbt
void setCTUSize ( unsigned ctuSize ) { m_CTUSize = ctuSize; }
......
......@@ -50,6 +50,8 @@
#include <assert.h>
#include <cassert>
#define JVET_L0646_GBI 1 // Generalized bi-prediction (GBi)
#define REUSE_CU_RESULTS 1
#define REMOVE_MV_ADAPT_PREC 1 // remove the high precision flag in the MV class
......@@ -213,6 +215,10 @@
#define ENABLE_SIMD_OPT_DIST ( 1 && ENABLE_SIMD_OPT ) ///< SIMD optimization for the distortion calculations(SAD,SSE,HADAMARD), no impact on RD performance
#define ENABLE_SIMD_OPT_AFFINE_ME ( 1 && ENABLE_SIMD_OPT ) ///< SIMD optimization for affine ME, no impact on RD performance
#define ENABLE_SIMD_OPT_ALF ( 1 && ENABLE_SIMD_OPT ) ///< SIMD optimization for ALF
#if ENABLE_SIMD_OPT_BUFFER
#define ENABLE_SIMD_OPT_GBI 1 ///< SIMD optimization for GBi
#endif
// End of SIMD optimizations
......
......@@ -266,6 +266,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other )
#endif
imv = other.imv;
imvNumCand = other.imvNumCand;
#if JVET_L0646_GBI
GBiIdx = other.GBiIdx;
#endif
return *this;
}
......@@ -292,6 +295,9 @@ void CodingUnit::initData()
#endif
imv = 0;
imvNumCand = 0;
#if JVET_L0646_GBI
GBiIdx = GBI_DEFAULT;
#endif
}
......
......@@ -305,6 +305,10 @@ struct CodingUnit : public UnitArea
uint32_t tileIdx;
#endif
uint8_t emtFlag;
#if JVET_L0646_GBI
uint8_t GBiIdx;
int refIdxBi[2];
#endif
// needed for fast imv mode decisions
int8_t imvNumCand;
......
......@@ -507,6 +507,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, co
for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
{
isCandInter[ui] = false;
#if JVET_L0646_GBI
mrgCtx.GBiIdx[ui] = GBI_DEFAULT;
#endif
mrgCtx.interDirNeighbours[ui] = 0;
mrgCtx.mrgTypeNeighbours [ui] =</