Newer
Older
if (sps.getWrapAroundEnabledFlag())
wrapRef = wrapClipMv( curMv, Position( pu.Y().x + ( w << iScaleX ), pu.Y().y + ( h << iScaleY ) ), Size( blockWidth << iScaleX, blockHeight << iScaleY ), &sps, pu.cs->pps );
curMv.hor = std::min<int>(iHorMax, std::max<int>(iHorMin, curMv.hor));
curMv.ver = std::min<int>(iVerMax, std::max<int>(iVerMin, curMv.ver));
}
iMvScaleTmpHor = curMv.hor;
iMvScaleTmpVer = curMv.ver;
}
if( xPredInterBlkRPR( scalingRatio, *pu.cs->pps, CompArea( compID, chFmt, pu.blocks[compID].offset( w, h ), Size( blockWidth, blockHeight ) ), refPic, Mv( iMvScaleTmpHor, iMvScaleTmpVer ), dstBuf.buf + w + h * dstBuf.stride, dstBuf.stride, bi, wrapRef, clpRng, 2 ) )
{
CHECK( enablePROF, "PROF should be disabled with RPR" );
}
else
{

Karsten Suehring
committed
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
// get the MV in high precision
int xFrac, yFrac, xInt, yInt;
if (!iScaleX)
{
xInt = iMvScaleTmpHor >> 4;
xFrac = iMvScaleTmpHor & 15;
}
else
{
xInt = iMvScaleTmpHor >> 5;
xFrac = iMvScaleTmpHor & 31;
}
if (!iScaleY)
{
yInt = iMvScaleTmpVer >> 4;
yFrac = iMvScaleTmpVer & 15;
}
else
{
yInt = iMvScaleTmpVer >> 5;
yFrac = iMvScaleTmpVer & 31;
}
const CPelBuf refBuf = refPic->getRecoBuf( CompArea( compID, chFmt, pu.blocks[compID].offset(xInt + w, yInt + h), pu.blocks[compID] ), wrapRef );
Pel* ref = (Pel*) refBuf.buf;
Pel* dst = dstBuf.buf + w + h * dstBuf.stride;
int refStride = refBuf.stride;
int dstStride = dstBuf.stride;
int bw = blockWidth;
int bh = blockHeight;
if (enablePROF)
{
dst = dstExtBuf.bufAt(PROF_BORDER_EXT_W, PROF_BORDER_EXT_H);
dstStride = dstExtBuf.stride;
}

Karsten Suehring
committed
if ( yFrac == 0 )
{
m_if.filterHor( compID, (Pel*) ref, refStride, dst, dstStride, bw, bh, xFrac, isLast, chFmt, clpRng);

Karsten Suehring
committed
}
else if ( xFrac == 0 )
{
m_if.filterVer( compID, (Pel*) ref, refStride, dst, dstStride, bw, bh, yFrac, true, isLast, chFmt, clpRng);

Karsten Suehring
committed
}
else
{
m_if.filterHor( compID, (Pel*)ref - ((vFilterSize>>1) -1)*refStride, refStride, tmpBuf.buf, tmpBuf.stride, bw, bh+vFilterSize-1, xFrac, false, chFmt, clpRng);

Karsten Suehring
committed
JVET_J0090_SET_CACHE_ENABLE( false );
m_if.filterVer( compID, tmpBuf.buf + ((vFilterSize>>1) -1)*tmpBuf.stride, tmpBuf.stride, dst, dstStride, bw, bh, yFrac, false, isLast, chFmt, clpRng);

Karsten Suehring
committed
JVET_J0090_SET_CACHE_ENABLE( true );
}
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
if (enablePROF)
{
const int shift = std::max<int>(2, (IF_INTERNAL_PREC - clpRng.bd));
const int xOffset = xFrac >> 3;
const int yOffset = yFrac >> 3;
const int refOffset = (blockHeight + 1) * refStride;
const int dstOffset = (blockHeight + 1)* dstStride;
const Pel* refPel = ref - (1 - yOffset) * refStride + xOffset - 1;
Pel* dstPel = dst - dstStride - 1;
for (int pw = 0; pw < blockWidth + 2; pw++)
{
dstPel[pw] = leftShift_round(refPel[pw], shift) - (Pel)IF_INTERNAL_OFFS;
dstPel[pw+dstOffset] = leftShift_round(refPel[pw+refOffset], shift) - (Pel)IF_INTERNAL_OFFS;
}
refPel = ref + yOffset * refBuf.stride + xOffset;
dstPel = dst;
for (int ph = 0; ph < blockHeight; ph++, refPel += refStride, dstPel += dstStride)
{
dstPel[-1] = leftShift_round(refPel[-1], shift) - (Pel)IF_INTERNAL_OFFS;
dstPel[blockWidth] = leftShift_round(refPel[blockWidth], shift) - (Pel)IF_INTERNAL_OFFS;
}
PelBuf gradXBuf = gradXExt.subBuf(w, h, blockWidth + 2, blockHeight + 2);
PelBuf gradYBuf = gradYExt.subBuf(w, h, blockWidth + 2, blockHeight + 2);
g_pelBufOP.profGradFilter(dstExtBuf.buf, dstExtBuf.stride, blockWidth + 2, blockHeight + 2, gradXBuf.stride, gradXBuf.buf, gradYBuf.buf, clpRng.bd);
const int shiftNum = std::max<int>(2, (IF_INTERNAL_PREC - clpRng.bd));
const Pel offset = (1 << (shiftNum - 1)) + IF_INTERNAL_OFFS;
Pel* src = dstExtBuf.bufAt(PROF_BORDER_EXT_W, PROF_BORDER_EXT_H);
Pel* gX = gradXBuf.bufAt(PROF_BORDER_EXT_W, PROF_BORDER_EXT_H);
Pel* gY = gradYBuf.bufAt(PROF_BORDER_EXT_W, PROF_BORDER_EXT_H);
Pel * dstY = dstBuf.bufAt(w, h);
if (!bi)
{
g_pelBufOP.applyPROF(dstY, dstBuf.stride, src, dstExtBuf.stride, blockWidth, blockHeight, gX, gY, gradXBuf.stride, dMvScaleHor, dMvScaleVer, blockWidth, shiftNum, offset, clpRng);
}
else
{
PelBuf srcExtBuf(src, dstExtBuf.stride, Size(blockWidth, blockHeight));
PelBuf destBuf(dstY, dstBuf.stride, Size(blockWidth, blockHeight));
destBuf.copyFrom(srcExtBuf);
}
}

Karsten Suehring
committed
}
}
}
void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf &yuvSrc0, const CPelUnitBuf &yuvSrc1, const int &refIdx0, const int &refIdx1, PelUnitBuf &yuvDst, const BitDepths &clipBitDepths)
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
const int height = yuvDst.Y().height;
const int width = yuvDst.Y().width;
int heightG = height + 2 * BIO_EXTEND_SIZE;
int widthG = width + 2 * BIO_EXTEND_SIZE;
int offsetPos = widthG*BIO_EXTEND_SIZE + BIO_EXTEND_SIZE;
Pel* gradX0 = m_gradX0;
Pel* gradX1 = m_gradX1;
Pel* gradY0 = m_gradY0;
Pel* gradY1 = m_gradY1;
int stridePredMC = widthG + 2;
const Pel* srcY0 = m_filteredBlockTmp[2][COMPONENT_Y] + stridePredMC + 1;
const Pel* srcY1 = m_filteredBlockTmp[3][COMPONENT_Y] + stridePredMC + 1;
const int src0Stride = stridePredMC;
const int src1Stride = stridePredMC;
Pel* dstY = yuvDst.Y().buf;
const int dstStride = yuvDst.Y().stride;
const Pel* srcY0Temp = srcY0;
const Pel* srcY1Temp = srcY1;
for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
{
Pel* dstTempPtr = m_filteredBlockTmp[2 + refList][COMPONENT_Y] + stridePredMC + 1;
Pel* gradY = (refList == 0) ? m_gradY0 : m_gradY1;
Pel* gradX = (refList == 0) ? m_gradX0 : m_gradX1;
xBioGradFilter(dstTempPtr, stridePredMC, widthG, heightG, widthG, gradX, gradY, clipBitDepths.recon[toChannelType(COMPONENT_Y)]);
Pel* padStr = m_filteredBlockTmp[2 + refList][COMPONENT_Y] + 2 * stridePredMC + 2;
for (int y = 0; y< height; y++)
padStr[-1] = padStr[0];
padStr[width] = padStr[width - 1];
padStr += stridePredMC;
padStr = m_filteredBlockTmp[2 + refList][COMPONENT_Y] + 2 * stridePredMC + 1;
::memcpy(padStr - stridePredMC, padStr, sizeof(Pel)*(widthG));
::memcpy(padStr + height*stridePredMC, padStr + (height - 1)*stridePredMC, sizeof(Pel)*(widthG));
}
const ClpRng& clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y);
const int bitDepth = clipBitDepths.recon[toChannelType(COMPONENT_Y)];
const int shiftNum = IF_INTERNAL_PREC + 1 - bitDepth;
const int offset = (1 << (shiftNum - 1)) + 2 * IF_INTERNAL_OFFS;
#if JVET_P0653_BDOF_PROF_PARA_DEV
const int limit = (1 << 5);
#else
const int limit = (1<<(std::max<int>(5, bitDepth - 7)));
#endif
int xUnit = (width >> 2);
int yUnit = (height >> 2);
Pel *dstY0 = dstY;
gradX0 = m_gradX0; gradX1 = m_gradX1;
gradY0 = m_gradY0; gradY1 = m_gradY1;
for (int yu = 0; yu < yUnit; yu++)
{
for (int xu = 0; xu < xUnit; xu++)
{
int tmpx = 0, tmpy = 0;
int sumAbsGX = 0, sumAbsGY = 0, sumDIX = 0, sumDIY = 0;
int sumSignGY_GX = 0;
Pel* pGradX0Tmp = m_gradX0 + (xu << 2) + (yu << 2) * widthG;
Pel* pGradX1Tmp = m_gradX1 + (xu << 2) + (yu << 2) * widthG;
Pel* pGradY0Tmp = m_gradY0 + (xu << 2) + (yu << 2) * widthG;
Pel* pGradY1Tmp = m_gradY1 + (xu << 2) + (yu << 2) * widthG;
const Pel* SrcY1Tmp = srcY1 + (xu << 2) + (yu << 2) * src1Stride;
const Pel* SrcY0Tmp = srcY0 + (xu << 2) + (yu << 2) * src0Stride;
g_pelBufOP.calcBIOSums(SrcY0Tmp, SrcY1Tmp, pGradX0Tmp, pGradX1Tmp, pGradY0Tmp, pGradY1Tmp, xu, yu, src0Stride, src1Stride, widthG, bitDepth, &sumAbsGX, &sumAbsGY, &sumDIX, &sumDIY, &sumSignGY_GX);
tmpx = (sumAbsGX == 0 ? 0 : rightShiftMSB(sumDIX << 3, sumAbsGX));
#if JVET_P0057_BDOF_PROF_HARMONIZATION
tmpx = Clip3(-limit, limit - 1, tmpx);
#else
tmpx = Clip3(-limit, limit, tmpx);
int mainsGxGy = sumSignGY_GX >> 12;
int secsGxGy = sumSignGY_GX & ((1 << 12) - 1);
int tmpData = tmpx * mainsGxGy;
tmpData = ((tmpData << 12) + tmpx*secsGxGy) >> 1;
tmpy = (sumAbsGY == 0 ? 0 : rightShiftMSB(((sumDIY << 3) - tmpData), sumAbsGY));
#if JVET_P0057_BDOF_PROF_HARMONIZATION
tmpy = Clip3(-limit, limit - 1, tmpy);
#else
tmpy = Clip3(-limit, limit, tmpy);
srcY0Temp = srcY0 + (stridePredMC + 1) + ((yu*src0Stride + xu) << 2);
srcY1Temp = srcY1 + (stridePredMC + 1) + ((yu*src0Stride + xu) << 2);
gradX0 = m_gradX0 + offsetPos + ((yu*widthG + xu) << 2);
gradX1 = m_gradX1 + offsetPos + ((yu*widthG + xu) << 2);
gradY0 = m_gradY0 + offsetPos + ((yu*widthG + xu) << 2);
gradY1 = m_gradY1 + offsetPos + ((yu*widthG + xu) << 2);
dstY0 = dstY + ((yu*dstStride + xu) << 2);
xAddBIOAvg4(srcY0Temp, src0Stride, srcY1Temp, src1Stride, dstY0, dstStride, gradX0, gradX1, gradY0, gradY1, widthG, (1 << 2), (1 << 2), (int)tmpx, (int)tmpy, shiftNum, offset, clpRng);
} // xu
} // yu
}
void InterPrediction::xAddBIOAvg4(const Pel* src0, int src0Stride, const Pel* src1, int src1Stride, Pel *dst, int dstStride, const Pel *gradX0, const Pel *gradX1, const Pel *gradY0, const Pel*gradY1, int gradStride, int width, int height, int tmpx, int tmpy, int shift, int offset, const ClpRng& clpRng)
{
g_pelBufOP.addBIOAvg4(src0, src0Stride, src1, src1Stride, dst, dstStride, gradX0, gradX1, gradY0, gradY1, gradStride, width, height, tmpx, tmpy, shift, offset, clpRng);
}
void InterPrediction::xBioGradFilter(Pel* pSrc, int srcStride, int width, int height, int gradStride, Pel* gradX, Pel* gradY, int bitDepth)
{
g_pelBufOP.bioGradFilter(pSrc, srcStride, width, height, gradStride, gradX, gradY, bitDepth);
}
void InterPrediction::xCalcBIOPar(const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG, int bitDepth)
{
g_pelBufOP.calcBIOPar(srcY0Temp, srcY1Temp, gradX0, gradX1, gradY0, gradY1, dotProductTemp1, dotProductTemp2, dotProductTemp3, dotProductTemp5, dotProductTemp6, src0Stride, src1Stride, gradStride, widthG, heightG, bitDepth);
}
void InterPrediction::xCalcBlkGradient(int sx, int sy, int *arraysGx2, int *arraysGxGy, int *arraysGxdI, int *arraysGy2, int *arraysGydI, int &sGx2, int &sGy2, int &sGxGy, int &sGxdI, int &sGydI, int width, int height, int unitSize)
{
g_pelBufOP.calcBlkGradient(sx, sy, arraysGx2, arraysGxGy, arraysGxdI, arraysGy2, arraysGydI, sGx2, sGy2, sGxGy, sGxdI, sGydI, width, height, unitSize);
}
void InterPrediction::xWeightedAverage(const PredictionUnit& pu, const CPelUnitBuf& pcYuvSrc0, const CPelUnitBuf& pcYuvSrc1, PelUnitBuf& pcYuvDst, const BitDepths& clipBitDepths, const ClpRngs& clpRngs, const bool& bioApplied, PelUnitBuf* yuvDstTmp /*= NULL*/)

Karsten Suehring
committed
{
const int iRefIdx0 = pu.refIdx[0];
const int iRefIdx1 = pu.refIdx[1];
if( iRefIdx0 >= 0 && iRefIdx1 >= 0 )
{
if (pu.cu->affine && (m_applyPROF[0] || m_applyPROF[1]))
{
xApplyBiPROF(pu, pcYuvSrc0.bufs[COMPONENT_Y], pcYuvSrc1.bufs[COMPONENT_Y], pcYuvDst.bufs[COMPONENT_Y], clpRngs.comp[COMPONENT_Y]);
pcYuvDst.addWeightedAvg(pcYuvSrc0, pcYuvSrc1, clpRngs, pu.cu->GBiIdx, true);
CHECK(yuvDstTmp, "yuvDstTmp is disallowed with PROF");
return;
}
if( pu.cu->GBiIdx != GBI_DEFAULT && (yuvDstTmp || !pu.mhIntraFlag) )
CHECK(bioApplied, "GBi is disallowed with BIO");
pcYuvDst.addWeightedAvg(pcYuvSrc0, pcYuvSrc1, clpRngs, pu.cu->GBiIdx);
yuvDstTmp->addAvg(pcYuvSrc0, pcYuvSrc1, clpRngs, false);
if (bioApplied)
const int src0Stride = pu.lwidth() + 2 * BIO_EXTEND_SIZE + 2;
const int src1Stride = pu.lwidth() + 2 * BIO_EXTEND_SIZE + 2;
const Pel* pSrcY0 = m_filteredBlockTmp[2][COMPONENT_Y] + 2 * src0Stride + 2;
const Pel* pSrcY1 = m_filteredBlockTmp[3][COMPONENT_Y] + 2 * src1Stride + 2;
bool bioEnabled = true;
if (bioEnabled)
{
applyBiOptFlow(pu, pcYuvSrc0, pcYuvSrc1, iRefIdx0, iRefIdx1, pcYuvDst, clipBitDepths);
if (yuvDstTmp)
yuvDstTmp->bufs[0].addAvg(CPelBuf(pSrcY0, src0Stride, pu.lumaSize()), CPelBuf(pSrcY1, src1Stride, pu.lumaSize()), clpRngs.comp[0]);
}
else
{
pcYuvDst.bufs[0].addAvg(CPelBuf(pSrcY0, src0Stride, pu.lumaSize()), CPelBuf(pSrcY1, src1Stride, pu.lumaSize()), clpRngs.comp[0]);
if (yuvDstTmp)
yuvDstTmp->bufs[0].copyFrom(pcYuvDst.bufs[0]);
Takeshi Chujoh
committed
if (pu.cs->pps->getWPBiPred())
{
const int iRefIdx0 = pu.refIdx[0];
const int iRefIdx1 = pu.refIdx[1];
WPScalingParam *pwp0;
WPScalingParam *pwp1;
getWpScaling(pu.cu->slice, iRefIdx0, iRefIdx1, pwp0, pwp1);
if (!bioApplied)
{
addWeightBiComponent(pcYuvSrc0, pcYuvSrc1, pu.cu->slice->clpRngs(), pwp0, pwp1, pcYuvDst, true, COMPONENT_Y);
}
addWeightBiComponent(pcYuvSrc0, pcYuvSrc1, pu.cu->slice->clpRngs(), pwp0, pwp1, pcYuvDst, true, COMPONENT_Cb);
addWeightBiComponent(pcYuvSrc0, pcYuvSrc1, pu.cu->slice->clpRngs(), pwp0, pwp1, pcYuvDst, true, COMPONENT_Cr);
}
else
{
pcYuvDst.addAvg(pcYuvSrc0, pcYuvSrc1, clpRngs, bioApplied);
}
if (yuvDstTmp)
{
if (bioApplied)
{
yuvDstTmp->bufs[1].copyFrom(pcYuvDst.bufs[1]);
yuvDstTmp->bufs[2].copyFrom(pcYuvDst.bufs[2]);
}
else
yuvDstTmp->copyFrom(pcYuvDst);
}

Karsten Suehring
committed
}
else if( iRefIdx0 >= 0 && iRefIdx1 < 0 )
{
if( pu.cu->triangle )
{
pcYuvDst.copyFrom( pcYuvSrc0 );
}
else

Karsten Suehring
committed
pcYuvDst.copyClip( pcYuvSrc0, clpRngs );
if (yuvDstTmp)
yuvDstTmp->copyFrom(pcYuvDst);

Karsten Suehring
committed
}
else if( iRefIdx0 < 0 && iRefIdx1 >= 0 )
{
if( pu.cu->triangle )
{
pcYuvDst.copyFrom( pcYuvSrc1 );
}
else

Karsten Suehring
committed
pcYuvDst.copyClip( pcYuvSrc1, clpRngs );
if (yuvDstTmp)
yuvDstTmp->copyFrom(pcYuvDst);

Karsten Suehring
committed
}
}
void InterPrediction::xApplyBiPROF(const PredictionUnit &pu, const CPelBuf& pcYuvSrc0, const CPelBuf& pcYuvSrc1, PelBuf& pcYuvDst, const ClpRng& clpRng)
{
int blockWidth = AFFINE_MIN_BLOCK_SIZE;
int blockHeight = AFFINE_MIN_BLOCK_SIZE;
CHECK(!m_applyPROF[0] && !m_applyPROF[1], "xApplyBiPROF() applies PROF for at least one list.");
const int width = pu.Y().width;
const int height = pu.Y().height;
#if JVET_P0653_BDOF_PROF_PARA_DEV
const int mvShift = 8;
const int dmvLimit = (1 << 5);
#else
const int shift = bit - 4 + MV_FRACTIONAL_BITS_INTERNAL;
#if JVET_P0057_BDOF_PROF_HARMONIZATION
const int mvShift = shift + MV_FRACTIONAL_BITS_INTERNAL + 2 - std::max<int>(5, clpRng.bd - 7);
const int dmvLimit = (1 << (std::max<int>(5, clpRng.bd - 7)));
#else
const int bdlimit = std::max<int>(6, clpRng.bd - 6);
const int dmvLimit = 1 << bdlimit;
#endif
for (int list = 0; list < 2; list++)
{
if (m_applyPROF[list])
{
Mv mvLT = pu.mvAffi[list][0];
Mv mvRT = pu.mvAffi[list][1];
Mv mvLB = pu.mvAffi[list][2];
dMvHorX = (mvRT - mvLT).getHor() << (bit - floorLog2(width));
dMvHorY = (mvRT - mvLT).getVer() << (bit - floorLog2(width));
if (pu.cu->affineType == AFFINEMODEL_6PARAM)
{
dMvVerX = (mvLB - mvLT).getHor() << (bit - floorLog2(height));
dMvVerY = (mvLB - mvLT).getVer() << (bit - floorLog2(height));
}
else
{
}
int *dMvScaleHor = m_dMvBuf[list];
int *dMvScaleVer = m_dMvBuf[list] + 16;
int* dMvH = dMvScaleHor;
int* dMvV = dMvScaleVer;
int quadHorX = dMvHorX << 2;
int quadHorY = dMvHorY << 2;
int quadVerX = dMvVerX << 2;
int quadVerY = dMvVerY << 2;
dMvH[0] = ((dMvHorX + dMvVerX) << 1) - ((quadHorX + quadVerX) << 1);
dMvV[0] = ((dMvHorY + dMvVerY) << 1) - ((quadHorY + quadVerY) << 1);
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
for (int w = 1; w < blockWidth; w++)
{
dMvH[w] = dMvH[w - 1] + quadHorX;
dMvV[w] = dMvV[w - 1] + quadHorY;
}
dMvH += blockWidth;
dMvV += blockWidth;
for (int h = 1; h < blockHeight; h++)
{
for (int w = 0; w < blockWidth; w++)
{
dMvH[w] = dMvH[w - blockWidth] + quadVerX;
dMvV[w] = dMvV[w - blockWidth] + quadVerY;
}
dMvH += blockWidth;
dMvV += blockWidth;
}
if (!g_pelBufOP.roundIntVector)
{
for (int idx = 0; idx < blockWidth * blockHeight; idx++)
{
#if JVET_P0057_BDOF_PROF_HARMONIZATION
roundAffineMv(dMvScaleHor[idx], dMvScaleVer[idx], mvShift);
#else
roundAffineMv(dMvScaleHor[idx], dMvScaleVer[idx], shift);
dMvScaleHor[idx] = Clip3(-dmvLimit, dmvLimit - 1, dMvScaleHor[idx]);
dMvScaleVer[idx] = Clip3(-dmvLimit, dmvLimit - 1, dMvScaleVer[idx]);
}
}
else
{
int sz = blockWidth * blockHeight;
#if JVET_P0057_BDOF_PROF_HARMONIZATION
g_pelBufOP.roundIntVector(dMvScaleHor, sz, mvShift, dmvLimit);
g_pelBufOP.roundIntVector(dMvScaleVer, sz, mvShift, dmvLimit);
#else
g_pelBufOP.roundIntVector(dMvScaleHor, sz, shift, dmvLimit);
g_pelBufOP.roundIntVector(dMvScaleVer, sz, shift, dmvLimit);
}
}
}
const int cuExtW = width + PROF_BORDER_EXT_W * 2;
const int cuExtH = height + PROF_BORDER_EXT_H * 2;
PelBuf gradXExt0 = PelBuf(m_gradBuf[REF_PIC_LIST_0][0], cuExtW, cuExtH);
PelBuf gradYExt0 = PelBuf(m_gradBuf[REF_PIC_LIST_0][1], cuExtW, cuExtH);
PelBuf gradXExt1 = PelBuf(m_gradBuf[REF_PIC_LIST_1][0], cuExtW, cuExtH);
PelBuf gradYExt1 = PelBuf(m_gradBuf[REF_PIC_LIST_1][1], cuExtW, cuExtH);
Pel* gX0 = gradXExt0.bufAt(PROF_BORDER_EXT_W, PROF_BORDER_EXT_H);
Pel* gY0 = gradYExt0.bufAt(PROF_BORDER_EXT_W, PROF_BORDER_EXT_H);
Pel* gX1 = gradXExt1.bufAt(PROF_BORDER_EXT_W, PROF_BORDER_EXT_H);
Pel* gY1 = gradYExt1.bufAt(PROF_BORDER_EXT_W, PROF_BORDER_EXT_H);
int *dMvX0 = m_dMvBuf[REF_PIC_LIST_0];
int *dMvY0 = m_dMvBuf[REF_PIC_LIST_0] + 16;
int *dMvX1 = m_dMvBuf[REF_PIC_LIST_1];
int *dMvY1 = m_dMvBuf[REF_PIC_LIST_1] + 16;
const Pel* srcY0 = pcYuvSrc0.bufAt(0, 0);
const Pel* srcY1 = pcYuvSrc1.bufAt(0, 0);
Pel* dstY = pcYuvDst.bufAt(0, 0);
if(m_applyPROF[0] && m_applyPROF[1])
g_pelBufOP.applyBiPROF[1](dstY, pcYuvDst.stride, srcY0, srcY1, pcYuvSrc0.stride, width, height, gX0, gY0, gX1, gY1, gradXExt0.stride, dMvX0, dMvY0, dMvX1, dMvY1, blockWidth, getGbiWeight(pu.cu->GBiIdx, REF_PIC_LIST_0), clpRng);
else if (m_applyPROF[0])
g_pelBufOP.applyBiPROF[0](dstY, pcYuvDst.stride, srcY0, srcY1, pcYuvSrc0.stride, width, height, gX0, gY0, gX1, gY1, gradXExt0.stride, dMvX0, dMvY0, dMvX1, dMvY1, blockWidth, getGbiWeight(pu.cu->GBiIdx, REF_PIC_LIST_0), clpRng);
else
g_pelBufOP.applyBiPROF[0](dstY, pcYuvDst.stride, srcY1, srcY0, pcYuvSrc0.stride, width, height, gX1, gY1, gX0, gY0, gradXExt0.stride, dMvX1, dMvY1, dMvX0, dMvY0, blockWidth, getGbiWeight(pu.cu->GBiIdx, REF_PIC_LIST_1), clpRng);
}
void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBuf, const RefPicList &eRefPicList
, PelUnitBuf* predBufWOBIO /*= NULL*/

Karsten Suehring
committed
{
CHECK(predBufWOBIO && pu.mhIntraFlag, "the case should not happen!");
if (!pu.cs->pcv->isEncoder)
{
if (CU::isIBC(*pu.cu))
{
CHECK(!luma, "IBC only for Chroma is not allowed.");
xIntraBlockCopy(pu, predBuf, COMPONENT_Y);
if (chroma)
{
xIntraBlockCopy(pu, predBuf, COMPONENT_Cb);
xIntraBlockCopy(pu, predBuf, COMPONENT_Cr);
}
return;
}
}
if ((!luma || !chroma) && eRefPicList == REF_PIC_LIST_0)
{
xPredInterUni(pu, eRefPicList, predBuf, false
, false
, luma, chroma);
return;
}
// else, go with regular MC below

Karsten Suehring
committed
CodingStructure &cs = *pu.cs;
const PPS &pps = *cs.pps;
const SliceType sliceType = cs.slice->getSliceType();
if( eRefPicList != REF_PIC_LIST_X )
{
CHECK(predBufWOBIO != NULL, "the case should not happen!");

Karsten Suehring
committed
if( ( ( sliceType == P_SLICE && pps.getUseWP() ) || ( sliceType == B_SLICE && pps.getWPBiPred() ) ) )
{
xPredInterUni ( pu, eRefPicList, predBuf, true
, false
, true, true
);

Karsten Suehring
committed
xWeightedPredictionUni( pu, predBuf, eRefPicList, predBuf, -1, m_maxCompIDToPred );
}
else
{
xPredInterUni( pu, eRefPicList, predBuf, false
, false
, true, true
);

Karsten Suehring
committed
}
}
else
{
CHECK( !pu.cu->affine && pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0 && ( pu.lwidth() + pu.lheight() == 12 ), "invalid 4x8/8x4 bi-predicted blocks" );
WPScalingParam *wp0;
WPScalingParam *wp1;
int refIdx0 = pu.refIdx[REF_PIC_LIST_0];
int refIdx1 = pu.refIdx[REF_PIC_LIST_1];
pu.cs->slice->getWpScaling(REF_PIC_LIST_0, refIdx0, wp0);
pu.cs->slice->getWpScaling(REF_PIC_LIST_1, refIdx1, wp1);
bool bioApplied = false;
const Slice &slice = *pu.cs->slice;
if (pu.cs->sps->getBDOFEnabledFlag() && (!pu.cs->slice->getDisBdofDmvrFlag()))
{
if (pu.cu->affine || m_subPuMC)
{
bioApplied = false;
}
else
{
const bool biocheck0 = !((wp0[COMPONENT_Y].bPresentFlag || wp1[COMPONENT_Y].bPresentFlag) && slice.getSliceType() == B_SLICE);
const bool biocheck1 = !(pps.getUseWP() && slice.getSliceType() == P_SLICE);
if (biocheck0
&& biocheck1
#if JVET_P1023_DMVR_BDOF_RP_CONDITION
&& PU::isBiPredFromDifferentDirEqDistPoc(pu)
#else
&& (pu.Y().height >= 8)
&& (pu.Y().width >= 8)
&& ((pu.Y().height * pu.Y().width) >= 128)
)
{
bioApplied = true;
}
}
if (bioApplied && pu.mhIntraFlag)
{
bioApplied = false;
}
if (pu.cu->cs->sps->getUseGBi() && bioApplied && pu.cu->GBiIdx != GBI_DEFAULT)
if (pu.mmvdEncOptMode == 2 && pu.mmvdMergeFlag)
bioApplied = false;
}
}
bool dmvrApplied = false;
dmvrApplied = (pu.mvRefine) && PU::checkDMVRCondition(pu);
if ((pu.lumaSize().width > MAX_BDOF_APPLICATION_REGION || pu.lumaSize().height > MAX_BDOF_APPLICATION_REGION) && pu.mergeType != MRG_TYPE_SUBPU_ATMVP && (bioApplied && !dmvrApplied))
{
xSubPuBio(pu, predBuf, eRefPicList, predBufWOBIO);
if (pu.mergeType != MRG_TYPE_DEFAULT_N && pu.mergeType != MRG_TYPE_IBC)

Karsten Suehring
committed
{
CHECK(predBufWOBIO != NULL, "the case should not happen!");

Karsten Suehring
committed
xSubPuMC( pu, predBuf, eRefPicList );
}
else if( xCheckIdenticalMotion( pu ) )
{
xPredInterUni( pu, REF_PIC_LIST_0, predBuf, false
, false
, true, true
);
if (predBufWOBIO)
predBufWOBIO->copyFrom(predBuf);

Karsten Suehring
committed
}
else
{
xPredInterBi(pu, predBuf, predBufWOBIO);

Karsten Suehring
committed
}
}
return;
}
void InterPrediction::motionCompensation( CodingUnit &cu, const RefPicList &eRefPicList

Karsten Suehring
committed
{
for( auto &pu : CU::traversePUs( cu ) )
{
PelUnitBuf predBuf = cu.cs->getPredBuf( pu );
pu.mvRefine = true;
motionCompensation( pu, predBuf, eRefPicList
pu.mvRefine = false;

Karsten Suehring
committed
}
}
void InterPrediction::motionCompensation( PredictionUnit &pu, const RefPicList &eRefPicList /*= REF_PIC_LIST_X*/

Karsten Suehring
committed
{
PelUnitBuf predBuf = pu.cs->getPredBuf( pu );
motionCompensation( pu, predBuf, eRefPicList

Karsten Suehring
committed
}
int InterPrediction::rightShiftMSB(int numer, int denom)
{
return numer >> floorLog2(denom);

Karsten Suehring
committed
void InterPrediction::motionCompensation4Triangle( CodingUnit &cu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 )
{
for( auto &pu : CU::traversePUs( cu ) )
{
const UnitArea localUnitArea( cu.cs->area.chromaFormat, Area( 0, 0, pu.lwidth(), pu.lheight() ) );
PelUnitBuf tmpTriangleBuf = m_triangleBuf.getBuf( localUnitArea );
PelUnitBuf predBuf = cu.cs->getPredBuf( pu );
PU::spanMotionInfo( pu );
motionCompensation( pu, tmpTriangleBuf );
{
if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) )
{
printf( "DECODER_TRIANGLE_PU: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() );
}
}
PU::spanMotionInfo( pu );
motionCompensation( pu, predBuf );
{
if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) )
{
printf( "DECODER_TRIANGLE_PU: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() );
}
}
weightedTriangleBlk( pu, splitDir, MAX_NUM_CHANNEL_TYPE, predBuf, tmpTriangleBuf, predBuf );
void InterPrediction::weightedTriangleBlk( PredictionUnit &pu, const bool splitDir, int32_t channel, PelUnitBuf& predDst, PelUnitBuf& predSrc0, PelUnitBuf& predSrc1 )
if( channel == CHANNEL_TYPE_LUMA )
{
Yuling Hsiao
committed
m_if.weightedTriangleBlk( pu, pu.lumaSize().width, pu.lumaSize().height, COMPONENT_Y, splitDir, predDst, predSrc0, predSrc1 );
}
else if( channel == CHANNEL_TYPE_CHROMA )
{
Yuling Hsiao
committed
m_if.weightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, predDst, predSrc0, predSrc1 );
m_if.weightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 );
Yuling Hsiao
committed
m_if.weightedTriangleBlk( pu, pu.lumaSize().width, pu.lumaSize().height, COMPONENT_Y, splitDir, predDst, predSrc0, predSrc1 );
m_if.weightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cb, splitDir, predDst, predSrc0, predSrc1 );
m_if.weightedTriangleBlk( pu, pu.chromaSize().width, pu.chromaSize().height, COMPONENT_Cr, splitDir, predDst, predSrc0, predSrc1 );
void InterPrediction::xPrefetch(PredictionUnit& pu, PelUnitBuf &pcPad, RefPicList refId, bool forLuma)
{
int offset, width, height;
Mv cMv;
const Picture* refPic = pu.cu->slice->getRefPic( refId, pu.refIdx[refId] )->unscaledPic;
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
int mvShift = (MV_FRACTIONAL_BITS_INTERNAL);
int start = 0;
int end = MAX_NUM_COMPONENT;
start = forLuma ? 0 : 1;
end = forLuma ? 1 : MAX_NUM_COMPONENT;
for (int compID = start; compID < end; compID++)
{
cMv = Mv(pu.mv[refId].getHor(), pu.mv[refId].getVer());
pcPad.bufs[compID].stride = (pcPad.bufs[compID].width + (2 * DMVR_NUM_ITERATION) + NTAPS_LUMA);
int filtersize = (compID == (COMPONENT_Y)) ? NTAPS_LUMA : NTAPS_CHROMA;
width = pcPad.bufs[compID].width;
height = pcPad.bufs[compID].height;
offset = (DMVR_NUM_ITERATION) * (pcPad.bufs[compID].stride + 1);
int mvshiftTemp = mvShift + getComponentScaleX((ComponentID)compID, pu.chromaFormat);
width += (filtersize - 1);
height += (filtersize - 1);
cMv += Mv(-(((filtersize >> 1) - 1) << mvshiftTemp),
-(((filtersize >> 1) - 1) << mvshiftTemp));
if( pu.cs->sps->getWrapAroundEnabledFlag() )
wrapRef = wrapClipMv( cMv, pu.blocks[0].pos(), pu.blocks[0].size(), pu.cs->sps, pu.cs->pps );
}
else
{
clipMv( cMv, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps );
}
/* Pre-fetch similar to HEVC*/
{
CPelBuf refBuf;
Position Rec_offset = pu.blocks[compID].pos().offset(cMv.getHor() >> mvshiftTemp, cMv.getVer() >> mvshiftTemp);
refBuf = refPic->getRecoBuf(CompArea((ComponentID)compID, pu.chromaFormat, Rec_offset, pu.blocks[compID].size()), wrapRef);
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
PelBuf &dstBuf = pcPad.bufs[compID];
g_pelBufOP.copyBuffer((Pel *)refBuf.buf, refBuf.stride, ((Pel *)dstBuf.buf) + offset, dstBuf.stride, width, height);
}
}
}
void InterPrediction::xPad(PredictionUnit& pu, PelUnitBuf &pcPad, RefPicList refId)
{
int offset = 0, width, height;
int padsize;
Mv cMv;
for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++)
{
int filtersize = (compID == (COMPONENT_Y)) ? NTAPS_LUMA : NTAPS_CHROMA;
width = pcPad.bufs[compID].width;
height = pcPad.bufs[compID].height;
offset = (DMVR_NUM_ITERATION) * (pcPad.bufs[compID].stride + 1);
padsize = (DMVR_NUM_ITERATION) >> getComponentScaleX((ComponentID)compID, pu.chromaFormat);
width += (filtersize - 1);
height += (filtersize - 1);
/*padding on all side of size DMVR_PAD_LENGTH*/
{
g_pelBufOP.padding(pcPad.bufs[compID].buf + offset, pcPad.bufs[compID].stride, width, height, padsize);
}
}
}
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
inline int32_t div_for_maxq7(int64_t N, int64_t D)
{
int32_t sign, q;
sign = 0;
if (N < 0)
{
sign = 1;
N = -N;
}
q = 0;
D = (D << 3);
if (N >= D)
{
N -= D;
q++;
}
q = (q << 1);
D = (D >> 1);
if (N >= D)
{
N -= D;
q++;
}
q = (q << 1);
if (N >= (D >> 1))
q++;
if (sign)
return (-q);
return(q);
}
void xSubPelErrorSrfc(uint64_t *sadBuffer, int32_t *deltaMv)
{
int64_t numerator, denominator;
int32_t mvDeltaSubPel;
int32_t mvSubPelLvl = 4;/*1: half pel, 2: Qpel, 3:1/8, 4: 1/16*/
numerator = (int64_t)((sadBuffer[1] - sadBuffer[3]) << mvSubPelLvl);
denominator = (int64_t)((sadBuffer[1] + sadBuffer[3] - (sadBuffer[0] << 1)));
{
if ((sadBuffer[1] != sadBuffer[0]) && (sadBuffer[3] != sadBuffer[0]))
{
mvDeltaSubPel = div_for_maxq7(numerator, denominator);
deltaMv[0] = (mvDeltaSubPel);
}
else
{
if (sadBuffer[1] == sadBuffer[0])
{
deltaMv[0] = -8;// half pel
}
else
{
deltaMv[0] = 8;// half pel
}
}
}
/*vertical*/
numerator = (int64_t)((sadBuffer[2] - sadBuffer[4]) << mvSubPelLvl);
denominator = (int64_t)((sadBuffer[2] + sadBuffer[4] - (sadBuffer[0] << 1)));
if (0 != denominator)
{
if ((sadBuffer[2] != sadBuffer[0]) && (sadBuffer[4] != sadBuffer[0]))
{
mvDeltaSubPel = div_for_maxq7(numerator, denominator);
deltaMv[1] = (mvDeltaSubPel);
}
else
{
if (sadBuffer[2] == sadBuffer[0])
{
deltaMv[1] = -8;// half pel
}
else
{
deltaMv[1] = 8;// half pel
}
}
}
return;
}
void InterPrediction::xBIPMVRefine(int bd, Pel *pRefL0, Pel *pRefL1, uint64_t& minCost, int16_t *deltaMV, uint64_t *pSADsArray, int width, int height)
{
const int32_t refStrideL0 = m_biLinearBufStride;
const int32_t refStrideL1 = m_biLinearBufStride;
Pel *pRefL0Orig = pRefL0;
Pel *pRefL1Orig = pRefL1;
int32_t sadOffset = ((m_pSearchOffset[nIdx].getVer() * ((2 * DMVR_NUM_ITERATION) + 1)) + m_pSearchOffset[nIdx].getHor());
pRefL0 = pRefL0Orig + m_pSearchOffset[nIdx].hor + (m_pSearchOffset[nIdx].ver * refStrideL0);
pRefL1 = pRefL1Orig - m_pSearchOffset[nIdx].hor - (m_pSearchOffset[nIdx].ver * refStrideL1);
if (*(pSADsArray + sadOffset) == MAX_UINT64)
{
const uint64_t cost = xDMVRCost(bd, pRefL0, refStrideL0, pRefL1, refStrideL1, width, height);
minCost = *(pSADsArray + sadOffset);
deltaMV[0] = m_pSearchOffset[nIdx].getHor();
deltaMV[1] = m_pSearchOffset[nIdx].getVer();
}
}
}
void InterPrediction::xFinalPaddedMCForDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvSrc0, PelUnitBuf &pcYuvSrc1, PelUnitBuf &pcPad0, PelUnitBuf &pcPad1, const bool bioApplied
, const Mv mergeMV[NUM_REF_PIC_LIST_01]
)
{
int offset, deltaIntMvX, deltaIntMvY;
PelUnitBuf pcYUVTemp = pcYuvSrc0;
PelUnitBuf pcPadTemp = pcPad0;
/*always high precision MVs are used*/
for (int k = 0; k < NUM_REF_PIC_LIST_01; k++)
{
RefPicList refId = (RefPicList)k;
Mv cMv = pu.mv[refId];
m_iRefListIdx = refId;
const Picture* refPic = pu.cu->slice->getRefPic( refId, pu.refIdx[refId] )->unscaledPic;
clipMv( cMvClipped, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps );
Mv startMv = mergeMV[refId];
if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvForMCTSConstraint( pu, startMv, MV_PRECISION_INTERNAL ) )
{
const Area& tileArea = pu.cs->picture->mctsInfo.getTileArea();
printf( "Attempt an access over tile boundary at block %d,%d %d,%d with MV %d,%d (in Tile TL: %d,%d BR: %d,%d)\n",
pu.lx(), pu.ly(), pu.lwidth(), pu.lheight(), startMv.getHor(), startMv.getVer(), tileArea.topLeft().x, tileArea.topLeft().y, tileArea.bottomRight().x, tileArea.bottomRight().y );
THROW( "MCTS constraint failed!" );
}
for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++)
{
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
Pel *srcBufPelPtr = NULL;
int pcPadstride = 0;
if (blockMoved || (compID == 0))
{
pcPadstride = pcPadTemp.bufs[compID].stride;
int mvshiftTemp = mvShift + getComponentScaleX((ComponentID)compID, pu.chromaFormat);
int leftPixelExtra;
if (compID == COMPONENT_Y)
{
leftPixelExtra = (NTAPS_LUMA >> 1) - 1;
}
else
{
leftPixelExtra = (NTAPS_CHROMA >> 1) - 1;
}
PelBuf &srcBuf = pcPadTemp.bufs[compID];
deltaIntMvX = (cMv.getHor() >> mvshiftTemp) -
(startMv.getHor() >> mvshiftTemp);
deltaIntMvY = (cMv.getVer() >> mvshiftTemp) -
(startMv.getVer() >> mvshiftTemp);
CHECK((abs(deltaIntMvX) > DMVR_NUM_ITERATION) || (abs(deltaIntMvY) > DMVR_NUM_ITERATION), "not expected DMVR movement");
offset = (DMVR_NUM_ITERATION + leftPixelExtra) * (pcPadTemp.bufs[compID].stride + 1);
offset += (deltaIntMvY)* pcPadTemp.bufs[compID].stride;
offset += (deltaIntMvX);
srcBufPelPtr = (srcBuf.buf + offset);
}
xPredInterBlk( (ComponentID)compID, pu, refPic, cMvClipped, pcYUVTemp, true, pu.cs->slice->getClpRngs().comp[compID],
bioApplied, false, pu.cu->slice->getScalingRatio( refId, pu.refIdx[refId] ), 0, 0, 0, srcBufPelPtr, pcPadstride );
}
pcYUVTemp = pcYuvSrc1;
pcPadTemp = pcPad1;
}
}
uint64_t InterPrediction::xDMVRCost(int bitDepth, Pel* pOrg, uint32_t refStride, const Pel* pRef, uint32_t orgStride, int width, int height)
{
DistParam cDistParam;
cDistParam.applyWeight = false;
cDistParam.useMR = false;
m_pcRdCost->setDistParam(cDistParam, pOrg, pRef, orgStride, refStride, bitDepth, COMPONENT_Y, width, height, 1);
uint64_t uiCost = cDistParam.distFunc(cDistParam);
void xDMVRSubPixelErrorSurface(bool notZeroCost, int16_t *totalDeltaMV, int16_t *deltaMV, uint64_t *pSADsArray)
int sadStride = (((2 * DMVR_NUM_ITERATION) + 1));
uint64_t sadbuffer[5];
if (notZeroCost && (abs(totalDeltaMV[0]) != (2 << MV_FRACTIONAL_BITS_INTERNAL))
&& (abs(totalDeltaMV[1]) != (2 << MV_FRACTIONAL_BITS_INTERNAL)))
sadbuffer[0] = pSADsArray[0];
sadbuffer[1] = pSADsArray[-1];
sadbuffer[2] = pSADsArray[-sadStride];
sadbuffer[3] = pSADsArray[1];
sadbuffer[4] = pSADsArray[sadStride];
xSubPelErrorSrfc(sadbuffer, tempDeltaMv);
totalDeltaMV[0] += tempDeltaMv[0];
totalDeltaMV[1] += tempDeltaMv[1];
}
}
void InterPrediction::xinitMC(PredictionUnit& pu, const ClpRngs &clpRngs)
{
const int refIdx0 = pu.refIdx[0];
const int refIdx1 = pu.refIdx[1];
/*use merge MV as starting MV*/
Mv mergeMVL0(pu.mv[REF_PIC_LIST_0]);
Mv mergeMVL1(pu.mv[REF_PIC_LIST_1]);
/*Clip the starting MVs*/
clipMv( mergeMVL0, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps );
clipMv( mergeMVL1, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps );