Commit a94405dd authored by Yu-Chi Su's avatar Yu-Chi Su

K0248: Generalized bi-Prediction (GBi)

parent c324f417
......@@ -116,6 +116,9 @@ IMV : 2
DepQuant : 1
CPR : 1
GBi : 1
GBiFast : 1
# Fast tools
PBIntraFast : 1
FastMrg : 1
......
......@@ -134,6 +134,9 @@ CPR : 1
CompositeLTReference : 0
GBi : 1
GBiFast : 1
# Fast tools
PBIntraFast : 1
FastMrg : 1
......
......@@ -134,6 +134,9 @@ CPR : 1
CompositeLTReference : 0
GBi : 1
GBiFast : 1
# Fast tools
PBIntraFast : 1
FastMrg : 1
......
......@@ -147,6 +147,9 @@ DepQuant : 1
BIO : 1
CPR : 1
GBi : 1
GBiFast : 1
# Fast tools
PBIntraFast : 1
FastMrg : 1
......
......@@ -312,6 +312,10 @@ void EncApp::xInitLibCfg()
m_cEncLib.setIBCHashSearchMaxCand ( m_IBCHashSearchMaxCand );
m_cEncLib.setIBCHashSearchRange4SmallBlk ( m_IBCHashSearchRange4SmallBlk );
m_cEncLib.setIBCFastMethod ( m_IBCFastMethod );
#endif
#if JVET_K0248_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
......
......@@ -924,6 +924,10 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
( "IBCHashSearchMaxCand", m_IBCHashSearchMaxCand, 256u, "Max candidates for hash based IBC search")
( "IBCHashSearchRange4SmallBlk", m_IBCHashSearchRange4SmallBlk, 256u, "Small block search range in based IBC search")
( "IBCFastMethod", m_IBCFastMethod, 6u, "Fast methods for IBC")
#endif
#if JVET_K0248_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
......@@ -2066,6 +2070,10 @@ bool EncAppCfg::xCheckParameter()
xConfirmPara( m_DMVR, "DMVR is only allowed with NEXT profile" );
xConfirmPara( m_MDMS, "MDMS is only allowed with NEXT profile" );
#endif
#if JVET_K0248_GBI
xConfirmPara( m_GBi, "GBi is only allowed with NEXT profile" );
xConfirmPara( m_GBiFast, "GBiFast is only allowed with NEXT profile");
#endif
#if JEM_TOOLS
xConfirmPara( m_IntraPDPC, "PDPC is only allowed with NEXT profile" );
#endif
......@@ -3448,6 +3456,10 @@ void EncAppCfg::xPrintParameter()
#endif
#if JVET_K0076_CPR
msg(VERBOSE, "CPR:%d ", m_IBCMode);
#endif
#if JVET_K0248_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)
......
......@@ -294,6 +294,10 @@ protected:
unsigned m_IBCHashSearchMaxCand;
unsigned m_IBCHashSearchRange4SmallBlk;
unsigned m_IBCFastMethod;
#endif
#if JVET_K0248_GBI
bool m_GBi;
bool m_GBiFast;
#endif
// ADD_NEW_TOOL : (encoder app) add tool enabling flags and associated parameters here
......
......@@ -91,6 +91,42 @@ void addBIOAvgCore(const Pel* src0, int src0Stride, const Pel* src1, int src1Str
pGradX0 += gradStride; pGradX1 += gradStride; pGradY0 += gradStride; pGradY1 += gradStride;
}
}
#if JVET_K0248_GBI
void addBIOAvgCoreGBI(const Pel* src0, int src0Stride, const Pel* src1, int src1Stride, Pel *dst, int dstStride, const Pel *pGradX0, const Pel *pGradX1, const Pel *pGradY0, const Pel*pGradY1, int gradStride, int width, int height, int tmpx, int tmpy, int shift, int offset, const ClpRng& clpRng, const uint8_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 iLog2WeightBase = g_GbiLog2WeightBase;
int32_t(*pMulW0)(Pel) = GET_INT_MULTIPLIER(w0);
int32_t(*pMulW1)(Pel) = GET_INT_MULTIPLIER(w1);
int b = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x += 4)
{
b = tmpx * (pGradX0[x] - pGradX1[x]) + tmpy * (pGradY0[x] - pGradY1[x]);
b = (((b << iLog2WeightBase) + 64) >> 7);
dst[x] = ClipPel((int16_t)rightShift(((int64_t)pMulW0(src0[x]) + (int64_t)pMulW1(src1[x]) + (int64_t)b + (int64_t)offset), shift), clpRng);
b = tmpx * (pGradX0[x + 1] - pGradX1[x + 1]) + tmpy * (pGradY0[x + 1] - pGradY1[x + 1]);
b = (((b << iLog2WeightBase) + 64) >> 7);
dst[x + 1] = ClipPel((int16_t)rightShift(((int64_t)pMulW0(src0[x + 1]) + (int64_t)pMulW1(src1[x + 1]) + (int64_t)b + (int64_t)offset), shift), clpRng);
b = tmpx * (pGradX0[x + 2] - pGradX1[x + 2]) + tmpy * (pGradY0[x + 2] - pGradY1[x + 2]);
b = (((b << iLog2WeightBase) + 64) >> 7);
dst[x + 2] = ClipPel((int16_t)rightShift(((int64_t)pMulW0(src0[x + 2]) + (int64_t)pMulW1(src1[x + 2]) + (int64_t)b + (int64_t)offset), shift), clpRng);
b = tmpx * (pGradX0[x + 3] - pGradX1[x + 3]) + tmpy * (pGradY0[x + 3] - pGradY1[x + 3]);
b = (((b << iLog2WeightBase) + 64) >> 7);
dst[x + 3] = ClipPel((int16_t)rightShift(((int64_t)pMulW0(src0[x + 3]) + (int64_t)pMulW1(src1[x + 3]) + (int64_t)b + (int64_t)offset), shift), clpRng);
}
dst += dstStride; src0 += src0Stride; src1 += src1Stride;
pGradX0 += gradStride; pGradX1 += gradStride; pGradY0 += gradStride; pGradY1 += gradStride;
}
}
#endif
#endif
template<typename T>
......@@ -129,6 +165,10 @@ PelBufferOps::PelBufferOps()
addAvg8 = addAvgCore<Pel>;
#if JVET_K0485_BIO
addBIOAvg4 = addBIOAvgCore;
#if JVET_K0248_GBI
addBIOAvg4GBI = addBIOAvgCoreGBI;
#endif
#endif
reco4 = reconstructCore<Pel>;
......@@ -143,6 +183,40 @@ PelBufferOps g_pelBufOP = PelBufferOps();
#endif
#endif
#if JVET_K0248_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;
int32_t(*pMulW0)(Pel) = GET_INT_MULTIPLIER(w0);
int32_t(*pMulW1)(Pel) = GET_INT_MULTIPLIER(w1);
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);
for (int i = 0; i < other1.height; i++)
{
for (int j = 0; j < other1.width; j++)
{
dest[j] = ClipPel( rightShift((pMulW0(src0[j]) + pMulW1(src2[j]) + offset), shiftNum), clpRng );
}
src0 += src1Stride;
src2 += src2Stride;
dest += destStride;
}
}
#endif
template<>
void AreaBuf<Pel>::addAvg( const AreaBuf<const Pel> &other1, const AreaBuf<const Pel> &other2, const ClpRng& clpRng)
......
......@@ -70,6 +70,9 @@ struct PelBufferOps
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 JVET_K0485_BIO
void(*addBIOAvg4) (const Pel* src0, int src0Stride, const Pel* src1, int src1Stride, Pel *dst, int dstStride, const Pel *pGradX0, const Pel *pGradX1, const Pel *pGradY0, const Pel*pGradY1, int gradStride, int width, int height, int tmpx, int tmpy, int shift, int offset, const ClpRng& clpRng);
#if JVET_K0248_GBI
void(*addBIOAvg4GBI) (const Pel* src0, int src0Stride, const Pel* src1, int src1Stride, Pel *dst, int dstStride, const Pel *pGradX0, const Pel *pGradX1, const Pel *pGradY0, const Pel*pGradY1, int gradStride, int width, int height, int tmpx, int tmpy, int shift, int offset, const ClpRng& clpRng, const uint8_t gbiIdx);
#endif
#endif
};
......@@ -105,6 +108,10 @@ struct AreaBuf : public Size
void subtract ( const AreaBuf<const T> &other );
void extendSingleBorderPel();
void extendBorderPel ( unsigned margin );
#if JVET_K0248_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;
......@@ -393,6 +400,43 @@ void AreaBuf<T>::toLast( const ClpRng& clpRng )
template<>
void AreaBuf<Pel>::toLast( const ClpRng& clpRng );
#if JVET_K0248_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;
int32_t(*pMulW)(Pel) = GET_INT_MULTIPLIER(gbiWeightOther);
double normalizer = 1.0 / (double)gbiWeight;
const Pel* src = other.buf;
const int srcStride = other.stride;
Pel* dst = buf;
const int dstStride = stride;
for ( int i = 0; i < other.height; i++ )
{
for ( int j = 0; j < other.width; j++ )
{
double temp = double((dst[j] << log2WeightBase) - pMulW(src[j]));
if (bClip)
{
dst[j] = ClipPel<T>(Pel(temp * normalizer + 0.5), clpRng);
}
else
{
dst[j] = Pel(temp * normalizer + 0.5);
}
}
src += srcStride;
dst += dstStride;
}
}
#endif
template<typename T>
void AreaBuf<T>::removeHighFreq( const AreaBuf<T>& other, const bool bClip, const ClpRng& clpRng )
{
......@@ -661,10 +705,17 @@ 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_K0248_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);
void removeHighFreq ( const UnitBuf<T>& other, const bool bClip, const ClpRngs& clpRngs
#if JVET_K0248_GBI
, const int8_t gbiWeight = g_GbiWeights[GBI_DEFAULT]
#endif
);
#if JEM_TOOLS
#if JVET_K0076_CPR_DT
......@@ -740,6 +791,22 @@ void UnitBuf<T>::reconstruct(const UnitBuf<const T> &pred, const UnitBuf<const T
}
}
#if JVET_K0248_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 */)
{
......@@ -773,10 +840,21 @@ void UnitBuf<T>::extendBorderPel( unsigned margin )
}
template<typename T>
void UnitBuf<T>::removeHighFreq( const UnitBuf<T>& other, const bool bClip, const ClpRngs& clpRngs)
void UnitBuf<T>::removeHighFreq( const UnitBuf<T>& other, const bool bClip, const ClpRngs& clpRngs
#if JVET_K0248_GBI
, const int8_t gbiWeight
#endif
)
{
for( unsigned i = 0; i < bufs.size(); i++ )
{
#if JVET_K0248_GBI
if( gbiWeight != g_GbiWeights[GBI_DEFAULT] )
{
bufs[i].removeWeightHighFreq( other.bufs[i], bClip, clpRngs.comp[i], gbiWeight);
return;
}
#endif
bufs[i].removeHighFreq(other.bufs[i], bClip, clpRngs.comp[i] );
}
}
......
......@@ -119,6 +119,9 @@ enum CodingStatisticsType
#if JEM_TOOLS || JVET_K1000_SIMPLIFIED_EMT
STATS__CABAC_BITS__EMT_CU_FLAG,
STATS__CABAC_BITS__EMT_TU_INDEX,
#endif
#if JVET_K0248_GBI
STATS__CABAC_BITS__GBI_IDX,
#endif
STATS__CABAC_BITS__OTHER,
STATS__CABAC_BITS__INVALID,
......@@ -217,6 +220,9 @@ static inline const char* getName(CodingStatisticsType name)
#if JEM_TOOLS || JVET_K1000_SIMPLIFIED_EMT
"CABAC_BITS__EMT_CU_FLAG",
"CABAC_BITS__EMT_TU_INDX",
#endif
#if JVET_K0248_GBI
"CABAC_BITS__GBI_IDX",
#endif
"CABAC_BITS__OTHER",
"CABAC_BITS__INVALID",
......
......@@ -361,6 +361,11 @@ static const int AFFINE_MAX_NUM_COMB = 12; ///< max
static const int AFFINE_MIN_BLOCK_SIZE = 4; ///< Minimum affine MC block size
#endif
#if JVET_K0248_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
#endif
#if W0038_DB_OPT
static const int MAX_ENCODER_DEBLOCKING_QUALITY_LAYERS = 8 ;
#endif
......
......@@ -778,5 +778,9 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx )
pu.cu->LICFlag = ( pu.cs->slice->getUseLIC() ? LICFlags[candIdx] : false );
}
#endif
#if JVET_K0248_GBI
pu.cu->GBiIdx = ( interDirNeighbours[candIdx]==3 ) ? GBiIdx[candIdx] : GBI_DEFAULT;
#endif
}
......@@ -556,6 +556,9 @@ public:
MvField mvFieldNeighbours [ MRG_MAX_NUM_CANDS << 1 ]; // double length for mv of both lists
#if JEM_TOOLS
bool LICFlags [ MRG_MAX_NUM_CANDS ];
#endif
#if JVET_K0248_GBI
uint8_t GBiIdx [ MRG_MAX_NUM_CANDS ];
#endif
unsigned char interDirNeighbours[ MRG_MAX_NUM_CANDS ];
MergeType mrgTypeNeighbours [ MRG_MAX_NUM_CANDS ];
......
......@@ -1018,6 +1018,16 @@ const CtxSet ContextSetCfg::AffineType = ContextSetCfg::addCtxSet
#endif
#endif
#if JVET_K0248_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
({
{ 169, 198,},
......@@ -1720,6 +1730,9 @@ void CtxWSizeStore::xInitMappingTable( const SPS* sps )
unsigned numCtxEmtCUFlag = ( spsNext.getUseLargeCTU() || spsNext.getUseQTBT() ? 6 : 4 ); // hard-wired in JEM
#if JVET_K0357_AMVR
unsigned numImvCtx = ( spsNext.getImvMode() > 1 ? 4 : 3 );
#endif
#if JVET_K0248_GBI
unsigned numGBiCtx = ( GBI_NUM + 2 );
#endif
addCtxSetToMapping ( m_codeId2ctxId, Ctx::SplitFlag, 0, numCtxSplitFlag );
if( spsNext.getUseQTBT() ) // hard-wired in JEM
......@@ -1836,6 +1849,12 @@ void CtxWSizeStore::xInitMappingTable( const SPS* sps )
addCtxSetToMapping ( m_codeId2ctxId, Ctx::LICFlag, 0, 1 );
}
#endif
#if JVET_K0248_GBI
if (true)
{
addCtxSetToMapping ( m_codeId2ctxId, Ctx::GBiIdx, 0, numGBiCtx );
}
#endif
#if !JVET_K0371_ALF
if( true /* ALF_HM3_REFACTOR */ )
{
......
......@@ -391,6 +391,9 @@ public:
static const CtxSet FrucFlag;
static const CtxSet FrucMode;
#endif
#if JVET_K0248_GBI
static const CtxSet GBiIdx;
#endif
#if JVET_K0371_ALF
static const CtxSet ctbAlfFlag;
#endif
......
......@@ -1622,8 +1622,15 @@ void InterPrediction::applyBiOptFlow( const PredictionUnit &pu, const CPelUnitBu
const ClpRng& clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
const int bitDepth = clipBitDepths.recon[ toChannelType(COMPONENT_Y) ];
#if JVET_K0248_GBI
const uint8_t gbiIdx = pu.cu->GBiIdx;
const int iLog2WeightBase = g_GbiLog2WeightBase;
const int shiftNum = IF_INTERNAL_PREC + ((gbiIdx != GBI_DEFAULT) ? iLog2WeightBase : 1) - bitDepth;
const int offset = (1 << (shiftNum - 1)) + ((gbiIdx != GBI_DEFAULT) ? (IF_INTERNAL_OFFS << iLog2WeightBase) : 2 * IF_INTERNAL_OFFS);
#else
const int shiftNum = IF_INTERNAL_PREC + 1 - bitDepth;
const int offset = ( 1 << ( shiftNum - 1 ) ) + 2 * IF_INTERNAL_OFFS;
#endif
const bool bShortRefMV = ( pu.cs->slice->getCheckLDC() && PU::isBIOLDB(pu) );
#if JVET_K0485_BIO
const int64_t limit = (16 << (IF_INTERNAL_PREC - bShortRefMV - bitDepth));
......@@ -1691,7 +1698,11 @@ void InterPrediction::applyBiOptFlow( const PredictionUnit &pu, const CPelUnitBu
pSrcY0Temp = pSrcY0 + (stridePredMC + 1) + ((yu*iSrc0Stride + xu) << 2);
pSrcY1Temp = pSrcY1 + (stridePredMC + 1) + ((yu*iSrc1Stride + xu) << 2);
pDstY0 = pDstY + ((yu*iDstStride + xu) << 2);
#if JVET_K0248_GBI
if( gbiIdx != GBI_DEFAULT )
pcYuvDst.bufs[0].addWeightedAvg(CPelBuf(pSrcY0Temp, iSrc0Stride, pu.lumaSize()), CPelBuf(pSrcY1Temp, iSrc1Stride, pu.lumaSize()), clpRng, gbiIdx);
else
#endif
g_pelBufOP.addAvg4(pSrcY0Temp, iSrc0Stride, pSrcY1Temp, iSrc1Stride, pDstY0, iDstStride, (1 << 2), (1 << 2), shiftNum, offset, clpRng);
continue;
}
......@@ -1748,7 +1759,13 @@ void InterPrediction::applyBiOptFlow( const PredictionUnit &pu, const CPelUnitBu
pGradY1 = m_pGradY1 + offsetPos + ((yu*iWidthG + xu) << 2);
pDstY0 = pDstY + ((yu*iDstStride + xu) << 2);
g_pelBufOP.addBIOAvg4(pSrcY0Temp, iSrc0Stride, pSrcY1Temp, iSrc1Stride, pDstY0, iDstStride, pGradX0, pGradX1, pGradY0, pGradY1, iWidthG, (1 << 2), (1 << 2), (int)tmpx, (int)tmpy, shiftNum, offset, clpRng);
#if JVET_K0248_GBI
if (gbiIdx != GBI_DEFAULT)
g_pelBufOP.addBIOAvg4GBI(pSrcY0Temp, iSrc0Stride, pSrcY1Temp, iSrc1Stride, pDstY0, iDstStride, pGradX0, pGradX1, pGradY0, pGradY1, iWidthG, (1 << 2), (1 << 2), (int)tmpx, (int)tmpy, shiftNum, offset, clpRng, gbiIdx);
else
#endif
g_pelBufOP.addBIOAvg4(pSrcY0Temp, iSrc0Stride, pSrcY1Temp, iSrc1Stride, pDstY0, iDstStride, pGradX0, pGradX1, pGradY0, pGradY1, iWidthG, (1 << 2), (1 << 2), (int)tmpx, (int)tmpy, shiftNum, offset, clpRng);
#else
pSrcY0Temp = pSrcY0 + ((yu*iSrc0Stride + xu) << 2);
pSrcY1Temp = pSrcY1 + ((yu*iSrc0Stride + xu) << 2);
......@@ -1759,15 +1776,35 @@ void InterPrediction::applyBiOptFlow( const PredictionUnit &pu, const CPelUnitBu
pDstY0 = pDstY + ((yu*iDstStride + xu) << 2);
#if JVET_K0248_GBI
const int8_t w0 = getGbiWeight(gbiIdx, REF_PIC_LIST_0);
const int8_t w1 = getGbiWeight(gbiIdx, REF_PIC_LIST_1);
const int8_t iLog2WeightBase = g_iGbiLog2WeightBase;
int32_t(*pMulW0)(Pel) = GET_INT_MULTIPLIER(w0);
int32_t(*pMulW1)(Pel) = GET_INT_MULTIPLIER(w1);
#endif
// apply BIO offset for the sub-block
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
int b = (int)tmpx * (pGradX0[x] - pGradX1[x]) + (int)tmpy * (pGradY0[x] - pGradY1[x]);
b = (b > 0) ? ((b + 32) >> 6) : (-((-b + 32) >> 6));
pDstY0[x] = ( ClipPel( ( int16_t ) ( ( pSrcY0Temp[x] + pSrcY1Temp[x] + b + offset ) >> shiftNum ), clpRng ) );
#if JVET_K0248_GBI
if( gbiIdx != GBI_DEFAULT)
{
b = (b>0) ? (((b << log2WeightBase) + 64) >> 7) : (-((((-b) << log2WeightBase) + 64) >> 7));
pDstY0[x] = (ClipPel((int16_t)(((int64_t)pMulW0(pSrcY0Temp[x]) + (int64_t)pMulW1(pSrcY1Temp[x]) + (int64_t)b + (int64_t)offset) >> shiftNum), clpRng));
}
else
{
#endif
b = (b > 0) ? ((b + 32) >> 6) : (-((-b + 32) >> 6));
pDstY0[x] = ( ClipPel( ( int16_t ) ( ( pSrcY0Temp[x] + pSrcY1Temp[x] + b + offset ) >> shiftNum ), clpRng ) );
#if JVET_K0248_GBI
}
#endif
}
pDstY0 += iDstStride; pSrcY0Temp += iSrc0Stride; pSrcY1Temp += iSrc1Stride;
pGradX0 += iWidthG; pGradX1 += iWidthG; pGradY0 += iWidthG; pGradY1 += iWidthG;
......@@ -1840,9 +1877,25 @@ void InterPrediction::xWeightedAverage( const PredictionUnit& pu, const CPelUnit
applyBiOptFlow( pu, pcYuvSrc0, pcYuvSrc1, iRefIdx0, iRefIdx1, pcYuvDst, clipBitDepths );
#if JVET_K0485_BIO
else
pcYuvDst.bufs[0].addAvg(CPelBuf(pSrcY0, src0Stride, pu.lumaSize()), CPelBuf(pSrcY1, src1Stride, pu.lumaSize()), clpRngs.comp[0]);
#if JVET_K0248_GBI
{
if (pu.cu->GBiIdx != GBI_DEFAULT)
pcYuvDst.bufs[0].addWeightedAvg(CPelBuf(pSrcY0, src0Stride, pu.lumaSize()), CPelBuf(pSrcY1, src1Stride, pu.lumaSize()), clpRngs.comp[0], pu.cu->GBiIdx);
else
#endif
pcYuvDst.bufs[0].addAvg(CPelBuf(pSrcY0, src0Stride, pu.lumaSize()), CPelBuf(pSrcY1, src1Stride, pu.lumaSize()), clpRngs.comp[0]);
#if JVET_K0248_GBI
}
#endif
#endif
}
#if JVET_K0248_GBI
if( pu.cu->GBiIdx != GBI_DEFAULT)
{
pcYuvDst.addWeightedAvg( pcYuvSrc0, pcYuvSrc1, clpRngs, pu.cu->GBiIdx, bBIOApplied );
return;
}
#endif
pcYuvDst.addAvg( pcYuvSrc0, pcYuvSrc1, clpRngs, bBIOApplied );
#else
pcYuvDst.addAvg( pcYuvSrc0, pcYuvSrc1, clpRngs );
......@@ -4508,7 +4561,14 @@ void InterPrediction::xProcessDMVR( PredictionUnit& pu, PelUnitBuf &pcYuvDst, co
pu.mv[1].setHighPrec();
}
#if !DMVR_JVET_K0217
pcYuvDst.addAvg( srcPred0, srcPred1, clpRngs, false, true );
#if JVET_K0248_GBI
if( pu.cu->GBiIdx != GBI_DEFAULT)
{
pcYuvDst.addWeightedAvg( srcPred0, srcPred1, clpRngs, pu.cu->GBiIdx, false, true );
}
else
#endif
pcYuvDst.addAvg( srcPred0, srcPred1, clpRngs, false, true );
//list 0
//get init cost
......
......@@ -157,4 +157,67 @@ struct MotionInfo
}
};
#if JVET_K0248_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][33];
Mv m_mvAffine[2][33][3];
Distortion m_distAffine[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() );
}
memset( m_readOnly, false, 2 * 33 * sizeof(bool));
memset( m_dist, -1, 2 * 33 * sizeof(Distortion));
memset( m_readOnlyAffine, false, 2 * 33 * sizeof(bool));
memset( m_mvAffine, 0, 2 * 33 * 3 * sizeof(Mv));
memset( m_distAffine, -1, 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 ) { m_readOnlyAffine[uiRefList][uiRefIdx] = b; }
bool isReadModeAffine( uint32_t uiRefList, uint32_t uiRefIdx ) { return m_readOnlyAffine[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 ) { return m_mvAffine[uiRefList][uiRefIdx][uiAffineMvIdx]; }
void copyAffineMvFrom( Mv(&racAffineMvs)[3], Distortion uiDist, uint32_t uiRefList, uint32_t uiRefIdx )
{
memcpy( m_mvAffine[uiRefList][uiRefIdx], racAffineMvs, 3 * sizeof( Mv ) );
m_distAffine[uiRefList][uiRefIdx] = uiDist;
}
void copyAffineMvTo( Mv acAffineMvs[3], Distortion& ruiDist, uint32_t uiRefList, uint32_t uiRefIdx )
{
memcpy( acAffineMvs, m_mvAffine[uiRefList][uiRefIdx], 3 * sizeof( Mv ) );
ruiDist = m_distAffine[uiRefList][uiRefIdx];
}
};
#endif
#endif // __MOTIONINFO__
......@@ -209,7 +209,81 @@ int g_aiLMCodeWord[LM_SYMBOL_NUM][16];
const int g_ipred_mode_table[] = { 1,1,1,2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,8,8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13,13,14,14,14,15,15,15 };
#endif
#endif
#endif
#if JVET_K0248_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)
{