Newer
Older

Karsten Suehring
committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/* The copyright in this software is being made available under the BSD
* License, included below. This software may be subject to other third party
* and contributor rights, including patent rights, and no such rights are
* granted under this license.
*
* Copyright (c) 2010-2018, ITU/ISO/IEC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
/** \file Prediction.cpp
\brief prediction class
*/
#include "InterPrediction.h"
#include "Buffer.h"
#include "UnitTools.h"
#include <memory.h>
#include <algorithm>
//! \ingroup CommonLib
//! \{
// ====================================================================================================================
// Constructor / destructor / initialize
// ====================================================================================================================
InterPrediction::InterPrediction()
:
m_currChromaFormat( NUM_CHROMA_FORMAT )
, m_maxCompIDToPred ( MAX_NUM_COMPONENT )
, m_pcRdCost ( nullptr )
#if JVET_L0265_AFF_MINIMUM4X4
, m_storedMv ( nullptr )
#endif
, m_gradX0(nullptr)
, m_gradY0(nullptr)
, m_gradX1(nullptr)
, m_gradY1(nullptr)

Karsten Suehring
committed
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
{
for( uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++ )
{
for( uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++ )
{
m_acYuvPred[refList][ch] = nullptr;
}
}
for( uint32_t c = 0; c < MAX_NUM_COMPONENT; c++ )
{
for( uint32_t i = 0; i < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS; i++ )
{
for( uint32_t j = 0; j < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS; j++ )
{
m_filteredBlock[i][j][c] = nullptr;
}
m_filteredBlockTmp[i][c] = nullptr;
}
}
}
InterPrediction::~InterPrediction()
{
destroy();
}
void InterPrediction::destroy()
{
for( uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++ )
{
for( uint32_t c = 0; c < MAX_NUM_COMPONENT; c++ )
{
xFree( m_acYuvPred[i][c] );
m_acYuvPred[i][c] = nullptr;
}
}
for( uint32_t c = 0; c < MAX_NUM_COMPONENT; c++ )
{
for( uint32_t i = 0; i < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS; i++ )
{
for( uint32_t j = 0; j < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS; j++ )
{
xFree( m_filteredBlock[i][j][c] );
m_filteredBlock[i][j][c] = nullptr;
}
xFree( m_filteredBlockTmp[i][c] );
m_filteredBlockTmp[i][c] = nullptr;
}
}
#if JVET_L0124_L0208_TRIANGLE
#if JVET_L0265_AFF_MINIMUM4X4
if (m_storedMv != nullptr)
{
delete[]m_storedMv;
xFree(m_gradX0); m_gradX0 = nullptr;
xFree(m_gradY0); m_gradY0 = nullptr;
xFree(m_gradX1); m_gradX1 = nullptr;
xFree(m_gradY1); m_gradY1 = nullptr;

Karsten Suehring
committed
}
void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC )
{
m_pcRdCost = pcRdCost;
// if it has been initialised before, but the chroma format has changed, release the memory and start again.
if( m_acYuvPred[REF_PIC_LIST_0][COMPONENT_Y] != nullptr && m_currChromaFormat != chromaFormatIDC )
{
destroy();
}
m_currChromaFormat = chromaFormatIDC;
if( m_acYuvPred[REF_PIC_LIST_0][COMPONENT_Y] == nullptr ) // check if first is null (in which case, nothing initialised yet)
{
for( uint32_t c = 0; c < MAX_NUM_COMPONENT; c++ )
{
int extWidth = MAX_CU_SIZE + (2 * BIO_EXTEND_SIZE + 2) + 16;
int extHeight = MAX_CU_SIZE + (2 * BIO_EXTEND_SIZE + 2) + 1;

Karsten Suehring
committed
int extWidth = MAX_CU_SIZE + 16;
int extHeight = MAX_CU_SIZE + 1;

Karsten Suehring
committed
for( uint32_t i = 0; i < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS; i++ )
{
m_filteredBlockTmp[i][c] = ( Pel* ) xMalloc( Pel, ( extWidth + 4 ) * ( extHeight + 7 + 4 ) );
for( uint32_t j = 0; j < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS; j++ )
{
m_filteredBlock[i][j][c] = ( Pel* ) xMalloc( Pel, extWidth * extHeight );
}
}
// new structure
for( uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++ )
{
m_acYuvPred[i][c] = ( Pel* ) xMalloc( Pel, MAX_CU_SIZE * MAX_CU_SIZE );
}
}
#if JVET_L0124_L0208_TRIANGLE
m_triangleBuf.create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));

Karsten Suehring
committed
m_iRefListIdx = -1;
m_gradX0 = (Pel*)xMalloc(Pel, BIO_TEMP_BUFFER_SIZE);
m_gradY0 = (Pel*)xMalloc(Pel, BIO_TEMP_BUFFER_SIZE);
m_gradX1 = (Pel*)xMalloc(Pel, BIO_TEMP_BUFFER_SIZE);
m_gradY1 = (Pel*)xMalloc(Pel, BIO_TEMP_BUFFER_SIZE);

Karsten Suehring
committed
}
#if !JVET_J0090_MEMORY_BANDWITH_MEASURE
m_if.initInterpolationFilter( true );
#endif
#if JVET_L0265_AFF_MINIMUM4X4
if (m_storedMv == nullptr)
{
const int MVBUFFER_SIZE = MAX_CU_SIZE / MIN_PU_SIZE;
m_storedMv = new Mv[MVBUFFER_SIZE*MVBUFFER_SIZE];
}

Karsten Suehring
committed
}
bool checkIdenticalMotion( const PredictionUnit &pu, bool checkAffine )
{
const Slice &slice = *pu.cs->slice;
if( slice.isInterB() && !pu.cs->pps->getWPBiPred() )
{
if( pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0 )
{
int RefPOCL0 = slice.getRefPic( REF_PIC_LIST_0, pu.refIdx[0] )->getPOC();
int RefPOCL1 = slice.getRefPic( REF_PIC_LIST_1, pu.refIdx[1] )->getPOC();
if( RefPOCL0 == RefPOCL1 )
{
if( !pu.cu->affine )
{
if( pu.mv[0] == pu.mv[1] )
{
return true;
}
}
else
{
CHECK( !checkAffine, "In this case, checkAffine should be on." );
#if JVET_L0694_AFFINE_LINEBUFFER_CLEANUP
if ( (pu.cu->affineType == AFFINEMODEL_4PARAM && (pu.mvAffi[0][0] == pu.mvAffi[1][0]) && (pu.mvAffi[0][1] == pu.mvAffi[1][1]))
|| (pu.cu->affineType == AFFINEMODEL_6PARAM && (pu.mvAffi[0][0] == pu.mvAffi[1][0]) && (pu.mvAffi[0][1] == pu.mvAffi[1][1]) && (pu.mvAffi[0][2] == pu.mvAffi[1][2])) )
#else

Karsten Suehring
committed
const CMotionBuf &mb = pu.getMotionBuf();
if ( (pu.cu->affineType == AFFINEMODEL_4PARAM && (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1]))
|| (pu.cu->affineType == AFFINEMODEL_6PARAM && (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1]) && (mb.at( 0, mb.height - 1 ).mv[0] == mb.at( 0, mb.height - 1 ).mv[1])) )

Karsten Suehring
committed
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
{
return true;
}
}
}
}
}
return false;
}
// ====================================================================================================================
// Public member functions
// ====================================================================================================================
bool InterPrediction::xCheckIdenticalMotion( const PredictionUnit &pu )
{
const Slice &slice = *pu.cs->slice;
if( slice.isInterB() && !pu.cs->pps->getWPBiPred() )
{
if( pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0 )
{
int RefPOCL0 = slice.getRefPic( REF_PIC_LIST_0, pu.refIdx[0] )->getPOC();
int RefPOCL1 = slice.getRefPic( REF_PIC_LIST_1, pu.refIdx[1] )->getPOC();
if( RefPOCL0 == RefPOCL1 )
{
if( !pu.cu->affine )
{
if( pu.mv[0] == pu.mv[1] )
{
return true;
}
}
else
{
#if JVET_L0694_AFFINE_LINEBUFFER_CLEANUP
if ( (pu.cu->affineType == AFFINEMODEL_4PARAM && (pu.mvAffi[0][0] == pu.mvAffi[1][0]) && (pu.mvAffi[0][1] == pu.mvAffi[1][1]))
|| (pu.cu->affineType == AFFINEMODEL_6PARAM && (pu.mvAffi[0][0] == pu.mvAffi[1][0]) && (pu.mvAffi[0][1] == pu.mvAffi[1][1]) && (pu.mvAffi[0][2] == pu.mvAffi[1][2])) )
#else

Karsten Suehring
committed
const CMotionBuf &mb = pu.getMotionBuf();
if ( (pu.cu->affineType == AFFINEMODEL_4PARAM && (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1]))
|| (pu.cu->affineType == AFFINEMODEL_6PARAM && (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1]) && (mb.at( 0, mb.height - 1 ).mv[0] == mb.at( 0, mb.height - 1 ).mv[1])) )

Karsten Suehring
committed
{
return true;
}
}
}
}
}
return false;
}
void InterPrediction::xSubPuMC( PredictionUnit& pu, PelUnitBuf& predBuf, const RefPicList &eRefPicList /*= REF_PIC_LIST_X*/ )
{
// compute the location of the current PU
Position puPos = pu.lumaPos();
Size puSize = pu.lumaSize();
int numPartLine, numPartCol, puHeight, puWidth;
{
#if JVET_L0198_L0468_L0104_ATMVP_8x8SUB_BLOCK
numPartLine = std::max(puSize.width >> ATMVP_SUB_BLOCK_SIZE, 1u);
numPartCol = std::max(puSize.height >> ATMVP_SUB_BLOCK_SIZE, 1u);
puHeight = numPartCol == 1 ? puSize.height : 1 << ATMVP_SUB_BLOCK_SIZE;
puWidth = numPartLine == 1 ? puSize.width : 1 << ATMVP_SUB_BLOCK_SIZE;
#else

Karsten Suehring
committed
const Slice& slice = *pu.cs->slice;
numPartLine = std::max(puSize.width >> slice.getSubPuMvpSubblkLog2Size(), 1u);
numPartCol = std::max(puSize.height >> slice.getSubPuMvpSubblkLog2Size(), 1u);
puHeight = numPartCol == 1 ? puSize.height : 1 << slice.getSubPuMvpSubblkLog2Size();
puWidth = numPartLine == 1 ? puSize.width : 1 << slice.getSubPuMvpSubblkLog2Size();

Karsten Suehring
committed
}
PredictionUnit subPu;
subPu.cs = pu.cs;
subPu.cu = pu.cu;
subPu.mergeType = MRG_TYPE_DEFAULT_N;
#if JVET_L0369_SUBBLOCK_MERGE
bool isAffine = pu.cu->affine;
subPu.cu->affine = false;
#endif

Karsten Suehring
committed
// join sub-pus containing the same motion
bool verMC = puSize.height > puSize.width;
int fstStart = (!verMC ? puPos.y : puPos.x);
int secStart = (!verMC ? puPos.x : puPos.y);
int fstEnd = (!verMC ? puPos.y + puSize.height : puPos.x + puSize.width);
int secEnd = (!verMC ? puPos.x + puSize.width : puPos.y + puSize.height);
int fstStep = (!verMC ? puHeight : puWidth);
int secStep = (!verMC ? puWidth : puHeight);
#if JVET_L0256_BIO
m_subPuMC = true;
#endif

Karsten Suehring
committed
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
for (int fstDim = fstStart; fstDim < fstEnd; fstDim += fstStep)
{
for (int secDim = secStart; secDim < secEnd; secDim += secStep)
{
int x = !verMC ? secDim : fstDim;
int y = !verMC ? fstDim : secDim;
const MotionInfo &curMi = pu.getMotionInfo(Position{ x, y });
int length = secStep;
int later = secDim + secStep;
while (later < secEnd)
{
const MotionInfo &laterMi = !verMC ? pu.getMotionInfo(Position{ later, fstDim }) : pu.getMotionInfo(Position{ fstDim, later });
if (laterMi == curMi)
{
length += secStep;
}
else
{
break;
}
later += secStep;
}
int dx = !verMC ? length : puWidth;
int dy = !verMC ? puHeight : length;
subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(x, y, dx, dy)));
subPu = curMi;
PelUnitBuf subPredBuf = predBuf.subBuf(UnitAreaRelative(pu, subPu));
motionCompensation(subPu, subPredBuf, eRefPicList);
secDim = later - secStep;
}
}
#if JVET_L0256_BIO
m_subPuMC = false;
#endif
#if JVET_L0369_SUBBLOCK_MERGE
pu.cu->affine = isAffine;

Karsten Suehring
committed
}
#if JVET_L0293_CPR
void InterPrediction::xChromaMC(PredictionUnit &pu, PelUnitBuf& pcYuvPred)
{
// separated tree, chroma
const CompArea lumaArea = CompArea(COMPONENT_Y, pu.chromaFormat, pu.Cb().lumaPos(), recalcSize(pu.chromaFormat, CHANNEL_TYPE_CHROMA, CHANNEL_TYPE_LUMA, pu.Cb().size()));
PredictionUnit subPu;
subPu.cs = pu.cs;
subPu.cu = pu.cu;
Picture * refPic = pu.cu->slice->getPic();
for (int y = lumaArea.y; y < lumaArea.y + lumaArea.height; y += MIN_PU_SIZE)
{
for (int x = lumaArea.x; x < lumaArea.x + lumaArea.width; x += MIN_PU_SIZE)
{
const MotionInfo &curMi = pu.cs->picture->cs->getMotionInfo(Position{ x, y });
subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(x, y, MIN_PU_SIZE, MIN_PU_SIZE)));
PelUnitBuf subPredBuf = pcYuvPred.subBuf(UnitAreaRelative(pu, subPu));
xPredInterBlk(COMPONENT_Cb, subPu, refPic, curMi.mv[0], subPredBuf, false, pu.cu->slice->clpRng(COMPONENT_Cb)
#if JVET_L0256_BIO
xPredInterBlk(COMPONENT_Cr, subPu, refPic, curMi.mv[0], subPredBuf, false, pu.cu->slice->clpRng(COMPONENT_Cr)
#if JVET_L0256_BIO
void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList& eRefPicList, PelUnitBuf& pcYuvPred, const bool& bi
, const bool& bioApplied
, const bool luma, const bool chroma

Karsten Suehring
committed
{
const SPS &sps = *pu.cs->sps;
int iRefIdx = pu.refIdx[eRefPicList];
Mv mv[3];
#if JVET_L0293_CPR
bool isCPR = false;
if (pu.cs->slice->getRefPic(eRefPicList, iRefIdx)->getPOC() == pu.cs->slice->getPOC())
{
isCPR = true;
}
#endif

Karsten Suehring
committed
if( pu.cu->affine )
{
CHECK( iRefIdx < 0, "iRefIdx incorrect." );
#if JVET_L0694_AFFINE_LINEBUFFER_CLEANUP
mv[0] = pu.mvAffi[eRefPicList][0];
mv[1] = pu.mvAffi[eRefPicList][1];
mv[2] = pu.mvAffi[eRefPicList][2];
#else

Karsten Suehring
committed
const CMotionBuf &mb = pu.getMotionBuf();
mv[0] = mb.at( 0, 0 ).mv[eRefPicList];
mv[1] = mb.at( mb.width - 1, 0 ).mv[eRefPicList];
mv[2] = mb.at( 0, mb.height - 1 ).mv[eRefPicList];

Karsten Suehring
committed
}
else
{
mv[0] = pu.mv[eRefPicList];
}
if ( !pu.cu->affine )
clipMv(mv[0], pu.cu->lumaPos(),
#if JVET_L0231_WRAPAROUND
pu.cu->lumaSize(),
#endif
sps);

Karsten Suehring
committed
for( uint32_t comp = COMPONENT_Y; comp < pcYuvPred.bufs.size() && comp <= m_maxCompIDToPred; comp++ )
{
const ComponentID compID = ComponentID( comp );
#if JVET_L0293_CPR
if (compID == COMPONENT_Y && !luma)
continue;
if (compID != COMPONENT_Y && !chroma)
continue;
#endif

Karsten Suehring
committed
if ( pu.cu->affine )
{
CHECK( bioApplied, "BIO is not allowed with affine" );

Karsten Suehring
committed
xPredAffineBlk( compID, pu, pu.cu->slice->getRefPic( eRefPicList, iRefIdx ), mv, pcYuvPred, bi, pu.cu->slice->clpRng( compID ) );
}
else
{
xPredInterBlk( compID, pu, pu.cu->slice->getRefPic( eRefPicList, iRefIdx ), mv[0], pcYuvPred, bi, pu.cu->slice->clpRng( compID )
#if JVET_L0293_CPR
, isCPR

Karsten Suehring
committed
}
}
}
void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred)
{
const PPS &pps = *pu.cs->pps;
const Slice &slice = *pu.cs->slice;
bool bioApplied = false;
if (pu.cs->sps->getSpsNext().getUseBIO())
{
if (pu.cu->affine || m_subPuMC)
{
bioApplied = false;
const bool biocheck0 = !(pps.getWPBiPred() && slice.getSliceType() == B_SLICE);
const bool biocheck1 = !(pps.getUseWP() && slice.getSliceType() == P_SLICE);
if (biocheck0
&& biocheck1
&& PU::isBiPredFromDifferentDir(pu)
&& !(pu.Y().height == 4 || (pu.Y().width == 4 && pu.Y().height == 8))
)
{
bioApplied = true;
}
}
#if JVET_L0646_GBI
if (pu.cu->cs->sps->getSpsNext().getUseGBi() && bioApplied && pu.cu->GBiIdx != GBI_DEFAULT)
bioApplied = false;

Karsten Suehring
committed
for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
{
if( pu.refIdx[refList] < 0)
{
continue;
}
RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
CHECK( pu.refIdx[refList] >= slice.getNumRefIdx( eRefPicList ), "Invalid reference index" );
m_iRefListIdx = refList;
PelUnitBuf pcMbBuf = ( pu.chromaFormat == CHROMA_400 ?
PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[refList][0], pcYuvPred.Y())) :
PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[refList][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[refList][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[refList][2], pcYuvPred.Cr())) );
if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
{
xPredInterUni ( pu, eRefPicList, pcMbBuf, true
, bioApplied
#endif
#if JVET_L0293_CPR
, true, true

Karsten Suehring
committed
}
else
{
if( ( (pps.getUseWP() && slice.getSliceType() == P_SLICE) || (pps.getWPBiPred() && slice.getSliceType() == B_SLICE) ) )
{
xPredInterUni ( pu, eRefPicList, pcMbBuf, true
#if JVET_L0256_BIO
, bioApplied
#endif
#if JVET_L0293_CPR
, true, true
#endif
);

Karsten Suehring
committed
}
else
{
#if JVET_L0124_L0208_TRIANGLE
xPredInterUni( pu, eRefPicList, pcMbBuf, pu.cu->triangle
#if JVET_L0256_BIO
, bioApplied
#endif
#if JVET_L0293_CPR
, true, true
#endif
);
xPredInterUni ( pu, eRefPicList, pcMbBuf, false
#if JVET_L0256_BIO
, bioApplied
#endif
#if JVET_L0293_CPR
, true, true
#endif
);

Karsten Suehring
committed
}
}
}
CPelUnitBuf srcPred0 = ( pu.chromaFormat == CHROMA_400 ?
CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[0][0], pcYuvPred.Y())) :
CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[0][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[0][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[0][2], pcYuvPred.Cr())) );
CPelUnitBuf srcPred1 = ( pu.chromaFormat == CHROMA_400 ?
CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y())) :
CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[1][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[1][2], pcYuvPred.Cr())) );
if( pps.getWPBiPred() && slice.getSliceType() == B_SLICE )
{
xWeightedPredictionBi( pu, srcPred0, srcPred1, pcYuvPred, m_maxCompIDToPred );
}
else if( pps.getUseWP() && slice.getSliceType() == P_SLICE )
{
xWeightedPredictionUni( pu, srcPred0, REF_PIC_LIST_0, pcYuvPred, -1, m_maxCompIDToPred );
}
else
{
xWeightedAverage( pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs(), bioApplied );

Karsten Suehring
committed
xWeightedAverage( pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs() );

Karsten Suehring
committed
}
}
void InterPrediction::xPredInterBlk ( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv& _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng
, const bool& bioApplied
#if JVET_L0293_CPR
, bool isCPR

Karsten Suehring
committed
{
JVET_J0090_SET_REF_PICTURE( refPic, compID );
const ChromaFormat chFmt = pu.chromaFormat;
const bool rndRes = !bi;
int iAddPrecShift = VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE;

Karsten Suehring
committed
int shiftHor = 2 + iAddPrecShift + ::getComponentScaleX(compID, chFmt);
int shiftVer = 2 + iAddPrecShift + ::getComponentScaleY(compID, chFmt);
int xFrac = _mv.hor & ((1 << shiftHor) - 1);
int yFrac = _mv.ver & ((1 << shiftVer) - 1);
#if JVET_L0293_CPR
if (isCPR)
{
xFrac = yFrac = 0;
JVET_J0090_SET_CACHE_ENABLE( false );

Karsten Suehring
committed
xFrac <<= VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE - iAddPrecShift;
yFrac <<= VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE - iAddPrecShift;
PelBuf &dstBuf = dstPic.bufs[compID];
unsigned width = dstBuf.width;
unsigned height = dstBuf.height;
CPelBuf refBuf;
{
Position offset = pu.blocks[compID].pos().offset( _mv.getHor() >> shiftHor, _mv.getVer() >> shiftVer );
refBuf = refPic->getRecoBuf( CompArea( compID, chFmt, offset, pu.blocks[compID].size() ) );
}
#if JVET_L0256_BIO
// backup data
int backupWidth = width;
int backupHeight = height;
Pel *backupDstBufPtr = dstBuf.buf;
int backupDstBufStride = dstBuf.stride;
if (bioApplied && compID == COMPONENT_Y)
width = width + 2 * BIO_EXTEND_SIZE + 2;
height = height + 2 * BIO_EXTEND_SIZE + 2;
// change MC output
dstBuf.stride = width;
dstBuf.buf = m_filteredBlockTmp[2 + m_iRefListIdx][compID] + 2 * dstBuf.stride + 2;
}
#endif

Karsten Suehring
committed
if( yFrac == 0 )
{
#if JVET_L0256_BIO
m_if.filterHor(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, xFrac, rndRes, chFmt, clpRng);
#else

Karsten Suehring
committed
m_if.filterHor(compID, (Pel*) refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, width, height, xFrac, rndRes, chFmt, clpRng);

Karsten Suehring
committed
}
else if( xFrac == 0 )
{
#if JVET_L0256_BIO
m_if.filterVer(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, true, rndRes, chFmt, clpRng);
#else

Karsten Suehring
committed
m_if.filterVer(compID, (Pel*) refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, width, height, yFrac, true, rndRes, chFmt, clpRng);

Karsten Suehring
committed
}
else
{
PelBuf tmpBuf = PelBuf(m_filteredBlockTmp[0][compID], pu.blocks[compID]);
#if JVET_L0256_BIO
tmpBuf.stride = dstBuf.stride;
#endif

Karsten Suehring
committed
int vFilterSize = isLuma(compID) ? NTAPS_LUMA : NTAPS_CHROMA;
#if JVET_L0256_BIO
m_if.filterHor(compID, (Pel*)refBuf.buf - ((vFilterSize >> 1) - 1) * refBuf.stride, refBuf.stride, tmpBuf.buf, tmpBuf.stride, backupWidth, backupHeight + vFilterSize - 1, xFrac, false, chFmt, clpRng);
#else

Karsten Suehring
committed
m_if.filterHor(compID, (Pel*) refBuf.buf - ((vFilterSize >> 1) - 1) * refBuf.stride, refBuf.stride, tmpBuf.buf, tmpBuf.stride, width, height + vFilterSize - 1, xFrac, false, chFmt, clpRng);

Karsten Suehring
committed
JVET_J0090_SET_CACHE_ENABLE( false );
#if JVET_L0256_BIO
m_if.filterVer(compID, (Pel*)tmpBuf.buf + ((vFilterSize >> 1) - 1) * tmpBuf.stride, tmpBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, false, rndRes, chFmt, clpRng);
#else

Karsten Suehring
committed
m_if.filterVer(compID, (Pel*) tmpBuf.buf + ((vFilterSize >> 1) - 1) * tmpBuf.stride, tmpBuf.stride, dstBuf.buf, dstBuf.stride, width, height, yFrac, false, rndRes, chFmt, clpRng);

Karsten Suehring
committed
}
JVET_J0090_SET_CACHE_ENABLE( true );
if (bioApplied && compID == COMPONENT_Y)
{
refBuf.buf = refBuf.buf - refBuf.stride - 1;
dstBuf.buf = m_filteredBlockTmp[2 + m_iRefListIdx][compID] + dstBuf.stride + 1;
bioSampleExtendBilinearFilter(refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, width - 2, height - 2, 1, xFrac, yFrac, rndRes, chFmt, clpRng);
// restore data
width = backupWidth;
height = backupHeight;
dstBuf.buf = backupDstBufPtr;
dstBuf.stride = backupDstBufStride;
}
#endif

Karsten Suehring
committed
}
void InterPrediction::xPredAffineBlk( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv* _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng )
{
if ( (pu.cu->affineType == AFFINEMODEL_6PARAM && _mv[0] == _mv[1] && _mv[0] == _mv[2])
|| (pu.cu->affineType == AFFINEMODEL_4PARAM && _mv[0] == _mv[1])
)
{
Mv mvTemp = _mv[0];
clipMv( mvTemp, pu.cu->lumaPos(),
#if JVET_L0231_WRAPAROUND
pu.cu->lumaSize(),
#endif
*pu.cs->sps );
xPredInterBlk( compID, pu, refPic, mvTemp, dstPic, bi, clpRng
#if JVET_L0256_BIO

Karsten Suehring
committed
return;
}
JVET_J0090_SET_REF_PICTURE( refPic, compID );
const ChromaFormat chFmt = pu.chromaFormat;
int iScaleX = ::getComponentScaleX( compID, chFmt );
int iScaleY = ::getComponentScaleY( compID, chFmt );
Mv mvLT =_mv[0];
Mv mvRT =_mv[1];
Mv mvLB =_mv[2];
// get affine sub-block width and height
const int width = pu.Y().width;
const int height = pu.Y().height;
int blockWidth = AFFINE_MIN_BLOCK_SIZE;
int blockHeight = AFFINE_MIN_BLOCK_SIZE;
blockWidth >>= iScaleX;
blockHeight >>= iScaleY;
#if JVET_L0265_AFF_MINIMUM4X4
blockWidth = std::max(blockWidth, AFFINE_MIN_BLOCK_SIZE);
blockHeight = std::max(blockHeight, AFFINE_MIN_BLOCK_SIZE);
CHECK(blockWidth > (width >> iScaleX ), "Sub Block width > Block width");
CHECK(blockHeight > (height >> iScaleX), "Sub Block height > Block height");
const int MVBUFFER_SIZE = MAX_CU_SIZE / MIN_PU_SIZE;

Karsten Suehring
committed
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
const int cxWidth = width >> iScaleX;
const int cxHeight = height >> iScaleY;
const int iHalfBW = blockWidth >> 1;
const int iHalfBH = blockHeight >> 1;
const int iBit = MAX_CU_DEPTH;
int iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY;
iDMvHorX = (mvRT - mvLT).getHor() << (iBit - g_aucLog2[cxWidth]);
iDMvHorY = (mvRT - mvLT).getVer() << (iBit - g_aucLog2[cxWidth]);
if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
{
iDMvVerX = (mvLB - mvLT).getHor() << (iBit - g_aucLog2[cxHeight]);
iDMvVerY = (mvLB - mvLT).getVer() << (iBit - g_aucLog2[cxHeight]);
}
else
{
iDMvVerX = -iDMvHorY;
iDMvVerY = iDMvHorX;
}
int iMvScaleHor = mvLT.getHor() << iBit;
int iMvScaleVer = mvLT.getVer() << iBit;
const SPS &sps = *pu.cs->sps;
const int iMvShift = 4;
const int iOffset = 8;
const int iHorMax = ( sps.getPicWidthInLumaSamples() + iOffset - pu.Y().x - 1 ) << iMvShift;
const int iHorMin = ( -(int)pu.cs->pcv->maxCUWidth - iOffset - (int)pu.Y().x + 1 ) << iMvShift;
const int iVerMax = ( sps.getPicHeightInLumaSamples() + iOffset - pu.Y().y - 1 ) << iMvShift;
const int iVerMin = ( -(int)pu.cs->pcv->maxCUHeight - iOffset - (int)pu.Y().y + 1 ) << iMvShift;
PelBuf tmpBuf = PelBuf(m_filteredBlockTmp[0][compID], pu.blocks[compID]);
const int vFilterSize = isLuma(compID) ? NTAPS_LUMA : NTAPS_CHROMA;
const int shift = iBit - 4 + VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE + 2;
// get prediction block by block
for ( int h = 0; h < cxHeight; h += blockHeight )
{
for ( int w = 0; w < cxWidth; w += blockWidth )
{
int iMvScaleTmpHor, iMvScaleTmpVer;
if(compID == COMPONENT_Y)
{
iMvScaleTmpHor = iMvScaleHor + iDMvHorX * (iHalfBW + w) + iDMvVerX * (iHalfBH + h);
iMvScaleTmpVer = iMvScaleVer + iDMvHorY * (iHalfBW + w) + iDMvVerY * (iHalfBH + h);
roundAffineMv(iMvScaleTmpHor, iMvScaleTmpVer, shift);
// clip and scale
{
m_storedMv[h / AFFINE_MIN_BLOCK_SIZE * MVBUFFER_SIZE + w / AFFINE_MIN_BLOCK_SIZE].set(iMvScaleTmpHor, iMvScaleTmpVer);
Mv tmpMv(iMvScaleTmpHor, iMvScaleTmpVer);
clipMv(tmpMv, Position(pu.Y().x + w, pu.Y().y + h), Size(blockWidth, blockHeight), sps);
iMvScaleTmpHor = tmpMv.getHor();
iMvScaleTmpVer = tmpMv.getVer();
}
else
{
#endif
iMvScaleTmpHor = std::min<int>(iHorMax, std::max<int>(iHorMin, iMvScaleTmpHor));
iMvScaleTmpVer = std::min<int>(iVerMax, std::max<int>(iVerMin, iMvScaleTmpVer));
m_storedMv[h / AFFINE_MIN_BLOCK_SIZE * MVBUFFER_SIZE + w / AFFINE_MIN_BLOCK_SIZE].set(iMvScaleTmpHor, iMvScaleTmpVer);
#if JVET_L0231_WRAPAROUND
}
#endif
}
else
{
Mv curMv = (m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE) * MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE)] +
m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE + 1)* MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE)] +
m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE)* MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE + 1)] +
m_storedMv[((h << iScaleY) / AFFINE_MIN_BLOCK_SIZE + 1)* MVBUFFER_SIZE + ((w << iScaleX) / AFFINE_MIN_BLOCK_SIZE + 1)] +
Mv(2, 2));
curMv.set(curMv.getHor() >> 2, curMv.getVer() >> 2);
{
clipMv(curMv, Position(pu.Y().x + (w << iScaleX), pu.Y().y + (h << iScaleY)), Size(blockWidth << iScaleX, blockHeight << iScaleY), sps);
}
#endif
iMvScaleTmpHor = curMv.hor;
iMvScaleTmpVer = curMv.ver;
}

Karsten Suehring
committed
int iMvScaleTmpHor = iMvScaleHor + iDMvHorX * (iHalfBW + w) + iDMvVerX * (iHalfBH + h);
int iMvScaleTmpVer = iMvScaleVer + iDMvHorY * (iHalfBW + w) + iDMvVerY * (iHalfBH + h);
roundAffineMv( iMvScaleTmpHor, iMvScaleTmpVer, shift );
// clip and scale
{
Mv tmpMv(iMvScaleTmpHor, iMvScaleTmpVer);
clipMv(tmpMv, Position(pu.Y().x + (w << iScaleX), pu.Y().y + (h << iScaleY)), Size(blockWidth << iScaleX, blockHeight << iScaleY), sps);
iMvScaleTmpHor = tmpMv.getHor();
iMvScaleTmpVer = tmpMv.getVer();
}
else
{
#endif
iMvScaleTmpHor = std::min<int>( iHorMax, std::max<int>( iHorMin, iMvScaleTmpHor ) );
iMvScaleTmpVer = std::min<int>( iVerMax, std::max<int>( iVerMin, iMvScaleTmpVer ) );
#if JVET_L0231_WRAPAROUND
}
#endif

Karsten Suehring
committed
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
// 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] ) );
PelBuf &dstBuf = dstPic.bufs[compID];
if ( yFrac == 0 )
{
m_if.filterHor( compID, (Pel*) refBuf.buf, refBuf.stride, dstBuf.buf + w + h * dstBuf.stride, dstBuf.stride, blockWidth, blockHeight, xFrac, !bi, chFmt, clpRng );
}
else if ( xFrac == 0 )
{
m_if.filterVer( compID, (Pel*) refBuf.buf, refBuf.stride, dstBuf.buf + w + h * dstBuf.stride, dstBuf.stride, blockWidth, blockHeight, yFrac, true, !bi, chFmt, clpRng );
}
else
{
m_if.filterHor( compID, (Pel*) refBuf.buf - ((vFilterSize>>1) -1)*refBuf.stride, refBuf.stride, tmpBuf.buf, tmpBuf.stride, blockWidth, blockHeight+vFilterSize-1, xFrac, false, chFmt, clpRng);
JVET_J0090_SET_CACHE_ENABLE( false );
m_if.filterVer( compID, tmpBuf.buf + ((vFilterSize>>1) -1)*tmpBuf.stride, tmpBuf.stride, dstBuf.buf + w + h * dstBuf.stride, dstBuf.stride, blockWidth, blockHeight, yFrac, false, !bi, chFmt, clpRng);
JVET_J0090_SET_CACHE_ENABLE( true );
}
}
}
}
int getMSB( unsigned x )
{
int msb = 0, bits = ( sizeof(int) << 3 ), y = 1;
while( x > 1u )
{
bits >>= 1;
y = x >> bits;
if( y )
{
x = y;
msb += bits;
}
}
msb += y;
return msb;
}
void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf &yuvSrc0, const CPelUnitBuf &yuvSrc1, const int &refIdx0, const int &refIdx1, PelUnitBuf &yuvDst, const BitDepths &clipBitDepths)
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);
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;