Coverage Report

Created: 2026-06-10 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/CommonLib/UnitTools.cpp
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
The copyright in this software is being made available under the Clear BSD
3
License, included below. No patent rights, trademark rights and/or 
4
other Intellectual Property Rights other than the copyrights concerning 
5
the Software are granted under this license.
6
7
The Clear BSD License
8
9
Copyright (c) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors.
10
All rights reserved.
11
12
Redistribution and use in source and binary forms, with or without modification,
13
are permitted (subject to the limitations in the disclaimer below) provided that
14
the following conditions are met:
15
16
     * Redistributions of source code must retain the above copyright notice,
17
     this list of conditions and the following disclaimer.
18
19
     * Redistributions in binary form must reproduce the above copyright
20
     notice, this list of conditions and the following disclaimer in the
21
     documentation and/or other materials provided with the distribution.
22
23
     * Neither the name of the copyright holder nor the names of its
24
     contributors may be used to endorse or promote products derived from this
25
     software without specific prior written permission.
26
27
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
28
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
32
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
40
41
------------------------------------------------------------------------------------------- */
42
43
44
/** \file     UnitTool.cpp
45
 *  \brief    defines operations for basic units
46
 */
47
48
#include "UnitTools.h"
49
#include "Unit.h"
50
#include "Slice.h"
51
#include "Picture.h"
52
#include "dtrace_next.h"
53
54
#include <utility>
55
#include <algorithm>
56
57
//! \ingroup CommonLib
58
//! \{
59
60
namespace vvenc {
61
62
// CS tools
63
64
void clipColPos(int& posX, int& posY, const CodingUnit& cu);
65
66
67
bool CS::isDualITree( const CodingStructure &cs )
68
10.1M
{
69
10.1M
  return cs.slice->isIntra() && !cs.pcv->ISingleTree;
70
10.1M
}
71
72
UnitArea CS::getArea( const CodingStructure &cs, const UnitArea& area, const ChannelType chType, const TreeType treeType )
73
545k
{
74
18.4E
  return isDualITree( cs ) || treeType != TREE_D ? area.singleChan( chType ) : area;
75
545k
}
76
77
int CS::signalModeCons( const CodingStructure &cs, const UnitArea &currArea, const PartSplit split, const ModeType modeTypeParent )
78
396k
{
79
396k
  const ChromaFormat chromaFormat = currArea.chromaFormat;
80
81
396k
  if( CS::isDualITree( cs ) || modeTypeParent != MODE_TYPE_ALL || chromaFormat == CHROMA_444 || chromaFormat == CHROMA_400 )
82
396k
    return LDT_MODE_TYPE_INHERIT;
83
84
1
  int minLumaArea = currArea.lumaSize().area();
85
1
  if( split == CU_QUAD_SPLIT || split == CU_TRIH_SPLIT || split == CU_TRIV_SPLIT ) // the area is split into 3 or 4 parts
86
0
  {
87
0
    minLumaArea = minLumaArea >> 2;
88
0
  }
89
1
  else if( split == CU_VERT_SPLIT || split == CU_HORZ_SPLIT ) // the area is split into 2 parts
90
0
  {
91
0
    minLumaArea = minLumaArea >> 1;
92
0
  }
93
94
1
  int minChromaBlock = minLumaArea >> ( getChannelTypeScaleX( CH_C, chromaFormat ) + getChannelTypeScaleY( CH_C, chromaFormat ) );
95
1
  bool is2xNChroma   = ( currArea.chromaSize().width == 4 && split == CU_VERT_SPLIT ) || ( currArea.chromaSize().width == 8 && split == CU_TRIV_SPLIT );
96
1
  return minChromaBlock >= 16 && !is2xNChroma ? LDT_MODE_TYPE_INHERIT
97
1
                                              : ( ( minLumaArea < 32 ) || cs.slice->isIntra() ) ? LDT_MODE_TYPE_INFER
98
1
                                                                                                : LDT_MODE_TYPE_SIGNAL;
99
396k
}
100
101
void refineCU( const CodingUnit& cu, MotionBuf& mb, MotionInfo* orgPtr )
102
0
{
103
0
  const int dy = std::min<int>( cu.lumaSize().height, DMVR_SUBCU_SIZE );
104
0
  const int dx = std::min<int>( cu.lumaSize().width,  DMVR_SUBCU_SIZE );
105
      
106
0
  static const unsigned scale = 4 * std::max<int>( 1, 4 * AMVP_DECIMATION_FACTOR / 4 );
107
0
  static const unsigned mask  = scale - 1;
108
109
0
  const Position puPos = cu.lumaPos();
110
0
  const Mv mv0 = cu.mv[0][0];
111
0
  const Mv mv1 = cu.mv[1][0];
112
113
0
  for( int y = puPos.y, num = 0; y < ( puPos.y + cu.lumaSize().height ); y = y + dy )
114
0
  {
115
0
    for( int x = puPos.x; x < ( puPos.x + cu.lumaSize().width ); x = x + dx, num++ )
116
0
    {
117
0
      if( cu.mvdL0SubPu[num] == Mv( 0, 0 ) ) continue;
118
119
0
      const Mv subPuMv0 = mv0 + cu.mvdL0SubPu[num];
120
0
      const Mv subPuMv1 = mv1 - cu.mvdL0SubPu[num];
121
122
0
      int y2 = ( ( y - 1 ) & ~mask ) + scale;
123
124
0
      for( ; y2 < y + dy; y2 += scale )
125
0
      {
126
0
        int x2 = ( ( x - 1 ) & ~mask ) + scale;
127
128
0
        for( ; x2 < x + dx; x2 += scale )
129
0
        {
130
0
          const Position mbPos = g_miScaling.scale( Position{ x2, y2 } );
131
0
          mb.buf = orgPtr + rsAddr( mbPos, mb.stride );
132
133
0
          MotionInfo& mi = *mb.buf;
134
135
0
          mi.mv[0] = subPuMv0;
136
0
          mi.mv[1] = subPuMv1;
137
0
        }
138
0
      }
139
0
    }
140
0
  }
141
0
}
142
143
void CS::setRefinedMotionFieldCTU( CodingStructure& cs, const int ctuX, const int ctuY )
144
3.46k
{
145
3.46k
  MotionBuf   mb     = cs.getMotionBuf();
146
3.46k
  MotionInfo* orgPtr = mb.buf;
147
148
3.46k
  const int xPos = ctuX << cs.pcv->maxCUSizeLog2;
149
3.46k
  const int yPos = ctuY << cs.pcv->maxCUSizeLog2;
150
  
151
  // first CU in CTU
152
3.46k
  const CodingUnit *ptrCU = cs.getCU( Position( xPos, yPos ), CH_L, TREE_D );
153
39.4k
  while( ptrCU )
154
35.9k
  {
155
35.9k
    const CodingUnit& cu = *ptrCU;
156
    
157
35.9k
    if( isLuma( cu.chType ) && cu.mvdL0SubPu && CU::checkDMVRCondition( cu ) )
158
0
    {
159
0
      refineCU( cu, mb, orgPtr );
160
0
    }
161
162
35.9k
    ptrCU = ptrCU->next;
163
35.9k
  }
164
3.46k
}
165
void CS::setRefinedMotionField( CodingStructure& cs )
166
0
{
167
0
  for( int j = 0; j < cs.pcv->heightInCtus; j++ )
168
0
  {
169
0
    for( int i = 0; i < cs.pcv->widthInCtus; i++ )
170
0
    {
171
0
      CS::setRefinedMotionFieldCTU( cs, i, j );
172
0
    }
173
0
  }
174
0
}
175
// CU tools
176
177
bool CU::checkCCLMAllowed(const CodingUnit& cu) 
178
835k
{
179
835k
  bool allowCCLM = false;
180
181
835k
  if( !CS::isDualITree( *cu.cs ) ) //single tree I slice or non-I slice (Note: judging chType is no longer equivalent to checking dual-tree I slice since the local dual-tree is introduced)
182
0
  {
183
0
    allowCCLM = true;
184
0
  }
185
835k
  else if( cu.slice->sps->CTUSize <= 32 ) //dual tree, CTUsize < 64
186
0
  {
187
0
    allowCCLM = true;
188
0
  }
189
835k
  else //dual tree, CTU size 64 or 128
190
835k
  {
191
835k
    int depthFor64x64Node = cu.slice->sps->CTUSize == 128 ? 1 : 0;
192
835k
    const PartSplit cuSplitTypeDepth1 = CU::getSplitAtDepth( cu, depthFor64x64Node );
193
835k
    const PartSplit cuSplitTypeDepth2 = CU::getSplitAtDepth( cu, depthFor64x64Node + 1 );
194
195
    //allow CCLM if 64x64 chroma tree node uses QT split or HBT+VBT split combination
196
835k
    if( cuSplitTypeDepth1 == CU_QUAD_SPLIT || (cuSplitTypeDepth1 == CU_HORZ_SPLIT && cuSplitTypeDepth2 == CU_VERT_SPLIT) )
197
498k
    {
198
498k
      if( cu.chromaFormat == CHROMA_420 )
199
498k
      {
200
498k
        CHECK( !(cu.blocks[COMP_Cb].width <= 16 && cu.blocks[COMP_Cb].height <= 16), "chroma cu size shall be <= 16x16 for YUV420 format" );
201
498k
      }
202
498k
      allowCCLM = true;
203
498k
    }
204
    //allow CCLM if 64x64 chroma tree node uses NS (No Split) and becomes a chroma CU containing 32x32 chroma blocks
205
337k
    else if( cuSplitTypeDepth1 == CU_DONT_SPLIT )
206
74.7k
    {
207
74.7k
      if( cu.chromaFormat == CHROMA_420 )
208
74.7k
      {
209
74.7k
        CHECK( !(cu.blocks[COMP_Cb].width == 32 && cu.blocks[COMP_Cb].height == 32), "chroma cu size shall be 32x32 for YUV420 format" );
210
74.7k
      }
211
74.7k
      allowCCLM = true;
212
74.7k
    }
213
    //allow CCLM if 64x32 chroma tree node uses NS and becomes a chroma CU containing 32x16 chroma blocks
214
262k
    else if( cuSplitTypeDepth1 == CU_HORZ_SPLIT && cuSplitTypeDepth2 == CU_DONT_SPLIT )
215
31.4k
    {
216
31.4k
      if( cu.chromaFormat == CHROMA_420 )
217
31.4k
      {
218
31.4k
        CHECK( !(cu.blocks[COMP_Cb].width == 32 && cu.blocks[COMP_Cb].height == 16), "chroma cu size shall be 32x16 for YUV420 format" );
219
31.4k
      }
220
31.4k
      allowCCLM = true;
221
31.4k
    }
222
223
    //further check luma conditions
224
835k
    if( allowCCLM )
225
604k
    {
226
      //disallow CCLM if luma 64x64 block uses BT or TT or NS with ISP
227
604k
      const Position lumaRefPos( cu.chromaPos().x << getComponentScaleX( COMP_Cb, cu.chromaFormat ), cu.chromaPos().y << getComponentScaleY( COMP_Cb, cu.chromaFormat ) );
228
604k
      const CodingUnit* colLumaCu = cu.cs->lumaCS->getCU( lumaRefPos, CH_L, TREE_D );
229
230
604k
      if( colLumaCu->lwidth() < 64 || colLumaCu->lheight() < 64 ) //further split at 64x64 luma node
231
304k
      {
232
304k
        const PartSplit cuSplitTypeDepth1Luma = CU::getSplitAtDepth( *colLumaCu, depthFor64x64Node );
233
304k
        CHECK( !(cuSplitTypeDepth1Luma >= CU_QUAD_SPLIT && cuSplitTypeDepth1Luma <= CU_TRIV_SPLIT), "split mode shall be BT, TT or QT" );
234
304k
        if( cuSplitTypeDepth1Luma != CU_QUAD_SPLIT )
235
0
        {
236
0
          allowCCLM = false;
237
0
        }
238
304k
      }
239
299k
      else if( colLumaCu->lwidth() == 64 && colLumaCu->lheight() == 64 && colLumaCu->ispMode ) //not split at 64x64 luma node and use ISP mode
240
0
      {
241
0
        allowCCLM = false;
242
0
      }
243
604k
    }
244
835k
  }
245
246
835k
  return allowCCLM;
247
835k
}
248
249
uint8_t CU::checkAllowedSbt(const CodingUnit& cu) 
250
129
{
251
129
  if( !cu.slice->sps->SBT || cu.predMode != MODE_INTER || cu.ciip || cu.predMode == MODE_IBC || cu.Y().maxDim() > cu.cs->sps->getMaxTbSize() )
252
129
  {
253
129
    return 0;
254
129
  }
255
256
0
  const int cuWidth       = cu.lwidth();
257
0
  const int cuHeight      = cu.lheight();
258
0
  const int minSbtCUSize  = 1 << ( MIN_CU_LOG2 + 1 );
259
0
  const int minQuadCUSize = 1 << ( MIN_CU_LOG2 + 2 );
260
261
0
  uint8_t sbtAllowed = 0;
262
0
  if( cuWidth  >= minSbtCUSize )  sbtAllowed += 1 << SBT_VER_HALF;
263
0
  if( cuHeight >= minSbtCUSize )  sbtAllowed += 1 << SBT_HOR_HALF;
264
0
  if( cuWidth  >= minQuadCUSize ) sbtAllowed += 1 << SBT_VER_QUAD;
265
0
  if( cuHeight >= minQuadCUSize ) sbtAllowed += 1 << SBT_HOR_QUAD;
266
267
0
  return sbtAllowed;
268
129
}
269
270
271
bool CU::getRprScaling( const SPS* sps, const PPS* curPPS, Picture* refPic, int& xScale, int& yScale )
272
0
{
273
0
  const Window& curScalingWindow = curPPS->scalingWindow;
274
0
  int curPicWidth = curPPS->picWidthInLumaSamples   - SPS::getWinUnitX( sps->chromaFormatIdc ) * (curScalingWindow.winLeftOffset + curScalingWindow.winRightOffset);
275
0
  int curPicHeight = curPPS->picHeightInLumaSamples - SPS::getWinUnitY( sps->chromaFormatIdc ) * (curScalingWindow.winTopOffset  + curScalingWindow.winBottomOffset);
276
277
0
  const Window& refScalingWindow = refPic->cs->pps->scalingWindow;
278
0
  int refPicWidth = refPic->cs->pps->picWidthInLumaSamples   - SPS::getWinUnitX( sps->chromaFormatIdc ) * (refScalingWindow.winLeftOffset + refScalingWindow.winRightOffset);
279
0
  int refPicHeight = refPic->cs->pps->picHeightInLumaSamples - SPS::getWinUnitY( sps->chromaFormatIdc) * (refScalingWindow.winTopOffset  + refScalingWindow.winBottomOffset);
280
281
0
  xScale = ( ( refPicWidth << SCALE_RATIO_BITS ) + ( curPicWidth >> 1 ) ) / curPicWidth;
282
0
  yScale = ( ( refPicHeight << SCALE_RATIO_BITS ) + ( curPicHeight >> 1 ) ) / curPicHeight;
283
284
0
  int curSeqMaxPicWidthY = sps->maxPicWidthInLumaSamples;                  // pic_width_max_in_luma_samples
285
0
  int curSeqMaxPicHeightY = sps->maxPicHeightInLumaSamples;                // pic_height_max_in_luma_samples
286
0
  int curPicWidthY = curPPS->picWidthInLumaSamples;                        // pic_width_in_luma_samples
287
0
  int curPicHeightY = curPPS->picHeightInLumaSamples;                      // pic_height_in_luma_samples 
288
0
  int max8MinCbSizeY = std::max((int)8, (1<<sps->log2MinCodingBlockSize)); // Max(8, MinCbSizeY)
289
290
0
  CHECK((curPicWidth * curSeqMaxPicWidthY) < refPicWidth * (curPicWidthY - max8MinCbSizeY), "(curPicWidth * curSeqMaxPicWidthY) should be greater than or equal to refPicWidth * (curPicWidthY - max8MinCbSizeY))");
291
0
  CHECK((curPicHeight * curSeqMaxPicHeightY) < refPicHeight * (curPicHeightY - max8MinCbSizeY), "(curPicHeight * curSeqMaxPicHeightY) should be greater than or equal to refPicHeight * (curPicHeightY - max8MinCbSizeY))");
292
293
0
  return refPic->cs->pps->isRefScaled( *curPPS );
294
0
}
295
296
bool CU::isSameSubPic(const CodingUnit& cu, const CodingUnit& cu2)
297
0
{
298
0
  return (cu.slice->pps->getSubPicFromCU(cu).subPicIdx == cu2.slice->pps->getSubPicFromCU(cu2).subPicIdx) ;
299
0
}
300
301
bool CU::isSameCtu(const CodingUnit& cu, const CodingUnit& cu2)
302
0
{
303
0
  uint32_t ctuSizeBit = cu.cs->pcv->maxCUSizeLog2;
304
305
0
  Position pos1Ctu(cu.lumaPos().x  >> ctuSizeBit, cu.lumaPos().y  >> ctuSizeBit);
306
0
  Position pos2Ctu(cu2.lumaPos().x >> ctuSizeBit, cu2.lumaPos().y >> ctuSizeBit);
307
308
0
  return pos1Ctu.x == pos2Ctu.x && pos1Ctu.y == pos2Ctu.y;
309
0
}
310
311
bool CU::isLastSubCUOfCtu( const CodingUnit &cu )
312
72.4k
{
313
72.4k
  const Area cuAreaY = CU::isSepTree(cu) ? Area( recalcPosition( cu.chromaFormat, cu.chType, CH_L, cu.blocks[cu.chType].pos() ), recalcSize( cu.chromaFormat, cu.chType, CH_L, cu.blocks[cu.chType].size() ) ) : (const Area&)cu.Y();
314
315
72.4k
  return ( ( ( ( cuAreaY.x + cuAreaY.width  ) & cu.cs->pcv->maxCUSizeMask ) == 0 || cuAreaY.x + cuAreaY.width  == cu.cs->pcv->lumaWidth  ) &&
316
32.2k
           ( ( ( cuAreaY.y + cuAreaY.height ) & cu.cs->pcv->maxCUSizeMask ) == 0 || cuAreaY.y + cuAreaY.height == cu.cs->pcv->lumaHeight ) );
317
72.4k
}
318
319
uint32_t CU::getCtuAddr( const CodingUnit &cu )
320
24.9k
{
321
24.9k
  return getCtuAddr( cu.blocks[cu.chType].lumaPos(), *cu.cs->pcv );
322
24.9k
}
323
324
int CU::predictQP( const CodingUnit& cu, const int prevQP )
325
24.9k
{
326
24.9k
  const ChannelType      chType   = cu.chType;
327
24.9k
  const CodingStructure& cs       = *cu.cs;
328
24.9k
  const Slice&           slice    = *cs.slice;
329
24.9k
  const bool             inCtuA   = ( cu.blocks[cu.chType].y & ( cs.pcv->maxCUSizeMask >> getChannelTypeScaleY( cu.chType, cu.chromaFormat ) ) );
330
24.9k
  const bool             inCtuL   = ( cu.blocks[cu.chType].x & ( cs.pcv->maxCUSizeMask >> getChannelTypeScaleX( cu.chType, cu.chromaFormat ) ) );
331
24.9k
  const CodingUnit*      cuAbove  =          cs.getCURestricted( cu.blocks[chType].pos().offset( 0, -1 ), cu, chType );
332
24.9k
  const CodingUnit*      cuLeft   = inCtuL ? cs.getCURestricted( cu.blocks[chType].pos().offset( -1, 0 ), cu, chType ) : nullptr;
333
  
334
24.9k
  const uint32_t ctuRsAddr       = getCtuAddr( cu );
335
24.9k
  const uint32_t ctuXPosInCtus   = ctuRsAddr % cs.pcv->widthInCtus;
336
24.9k
  const uint32_t tileXPosInCtus  = slice.pps->tileColBd[cs.pps->ctuToTileCol[ctuXPosInCtus]];
337
  
338
24.9k
  if( ctuXPosInCtus == tileXPosInCtus && !inCtuL && !inCtuA && cuAbove )
339
4.21k
  {
340
4.21k
    return cuAbove->qp;
341
4.21k
  }
342
20.7k
  else
343
20.7k
  {
344
20.7k
    const int a = inCtuA ? cuAbove->qp : prevQP;
345
20.7k
    const int b = inCtuL ? cuLeft->qp  : prevQP;
346
  
347
20.7k
    return ( a + b + 1 ) >> 1;
348
20.7k
  }
349
24.9k
}
350
351
352
void CU::saveMotionInHMVP( const CodingUnit& cu, const bool isToBeDone )
353
0
{
354
0
  if (!cu.geo && !cu.affine && !isToBeDone)
355
0
  {
356
0
    MotionInfo puMi = cu.getMotionInfo();
357
0
    HPMVInfo     mi ( puMi, ( puMi.interDir() == 3 ) ? cu.BcwIdx : BCW_DEFAULT, cu.imv == IMV_HPEL, CU::isIBC( cu ) );
358
359
0
    const unsigned log2ParallelMergeLevel = (cu.cs->sps->log2ParallelMergeLevelMinus2 + 2);
360
0
    const unsigned xBr = cu.Y().width + cu.Y().x;
361
0
    const unsigned yBr = cu.Y().height + cu.Y().y;
362
0
    bool enableHmvp = ((xBr >> log2ParallelMergeLevel) > (cu.Y().x >> log2ParallelMergeLevel)) && ((yBr >> log2ParallelMergeLevel) > (cu.Y().y >> log2ParallelMergeLevel));
363
0
    bool enableInsertion = CU::isIBC(cu) || enableHmvp;
364
0
    if (enableInsertion)
365
0
      cu.cs->addMiToLut( CU::isIBC(cu) ? cu.cs->motionLut.lutIbc : cu.cs->motionLut.lut, mi);
366
0
  }
367
0
}
368
369
PartSplit CU::getSplitAtDepth( const CodingUnit& cu, const unsigned depth )
370
2.27M
{
371
2.27M
  if( depth >= cu.depth ) return CU_DONT_SPLIT;
372
373
1.84M
  const PartSplit cuSplitType = PartSplit( ( cu.splitSeries >> ( depth * SPLIT_DMULT ) ) & SPLIT_MASK );
374
375
1.84M
  if     ( cuSplitType == CU_QUAD_SPLIT    ) return CU_QUAD_SPLIT;
376
377
845k
  else if( cuSplitType == CU_HORZ_SPLIT    ) return CU_HORZ_SPLIT;
378
379
422k
  else if( cuSplitType == CU_VERT_SPLIT    ) return CU_VERT_SPLIT;
380
381
3.14k
  else if( cuSplitType == CU_TRIH_SPLIT    ) return CU_TRIH_SPLIT;
382
18.4E
  else if( cuSplitType == CU_TRIV_SPLIT    ) return CU_TRIV_SPLIT;
383
18.4E
  else   { THROW( "Unknown split mode"    ); return CU_QUAD_SPLIT; }
384
1.84M
}
385
386
ModeType CU::getModeTypeAtDepth( const CodingUnit& cu, const unsigned depth )
387
69.8k
{
388
69.8k
  ModeType modeType = ModeType( (cu.modeTypeSeries >> (depth * 3)) & 0x07 );
389
69.8k
  CHECK( depth > cu.depth, " depth is wrong" );
390
69.8k
  return modeType;
391
69.8k
}
392
393
bool CU::divideTuInRows( const CodingUnit &cu )
394
33.9k
{
395
33.9k
  CHECK( cu.ispMode != HOR_INTRA_SUBPARTITIONS && cu.ispMode != VER_INTRA_SUBPARTITIONS, "Intra Subpartitions type not recognized!" );
396
33.9k
  return cu.ispMode == HOR_INTRA_SUBPARTITIONS ? true : false;
397
33.9k
}
398
399
400
PartSplit CU::getISPType( const CodingUnit &cu, const ComponentID compID )
401
72.5k
{
402
72.5k
  if( cu.ispMode && isLuma( compID ) )
403
33.9k
  {
404
33.9k
    const bool tuIsDividedInRows = CU::divideTuInRows( cu );
405
406
33.9k
    return tuIsDividedInRows ? TU_1D_HORZ_SPLIT : TU_1D_VERT_SPLIT;
407
33.9k
  }
408
38.5k
  return TU_NO_ISP;
409
72.5k
}
410
411
bool CU::isISPLast( const CodingUnit &cu, const CompArea& tuArea, const ComponentID compID )
412
28.9k
{
413
28.9k
  PartSplit partitionType = CU::getISPType( cu, compID );
414
415
28.9k
  Area originalArea = cu.blocks[compID];
416
28.9k
  switch( partitionType )
417
28.9k
  {
418
15.4k
    case TU_1D_HORZ_SPLIT:
419
15.4k
      return tuArea.y + tuArea.height == originalArea.y + originalArea.height;
420
13.5k
    case TU_1D_VERT_SPLIT:
421
13.5k
      return tuArea.x + tuArea.width == originalArea.x + originalArea.width;
422
0
    default:
423
0
      THROW( "Unknown ISP processing order type!" );
424
0
      return false;
425
28.9k
  }
426
28.9k
}
427
428
bool CU::isISPFirst( const CodingUnit &cu, const CompArea& tuArea, const ComponentID compID )
429
0
{
430
0
  return tuArea == cu.firstTU->blocks[compID];
431
0
}
432
433
bool CU::canUseISP( const CodingUnit &cu, const ComponentID compID )
434
678k
{
435
678k
  const int width     = cu.blocks[compID].width;
436
678k
  const int height    = cu.blocks[compID].height;
437
678k
  const int maxTrSize = cu.cs->sps->getMaxTbSize();
438
678k
  return CU::canUseISP( width, height, maxTrSize );
439
678k
}
440
441
bool CU::canUseISP( const int width, const int height, const int maxTrSize )
442
702k
{
443
702k
  bool  notEnoughSamplesToSplit = ( Log2(width) + Log2(height) <= ( MIN_TB_LOG2_SIZEY << 1 ) );
444
702k
  bool  cuSizeLargerThanMaxTrSize = width > maxTrSize || height > maxTrSize;
445
702k
  if ( notEnoughSamplesToSplit || cuSizeLargerThanMaxTrSize )
446
0
  {
447
0
    return false;
448
0
  }
449
702k
  return true;
450
702k
}
451
452
bool CU::canUseLfnstWithISP( const CompArea& cuArea, const ISPType ispSplitType )
453
52.0k
{
454
52.0k
  if( ispSplitType == NOT_INTRA_SUBPARTITIONS )
455
0
  {
456
0
    return false;
457
0
  }
458
52.0k
  Size tuSize = ( ispSplitType == HOR_INTRA_SUBPARTITIONS ) ? Size( cuArea.width, CU::getISPSplitDim( cuArea.width, cuArea.height, TU_1D_HORZ_SPLIT ) ) :
459
52.0k
    Size( CU::getISPSplitDim( cuArea.width, cuArea.height, TU_1D_VERT_SPLIT ), cuArea.height );
460
461
52.0k
  if( !( tuSize.width >= MIN_TB_SIZEY && tuSize.height >= MIN_TB_SIZEY ) )
462
7.83k
  {
463
7.83k
    return false;
464
7.83k
  }
465
44.2k
  return true;
466
52.0k
}
467
468
bool CU::canUseLfnstWithISP( const CodingUnit& cu, const ChannelType chType )
469
5.84k
{
470
5.84k
  CHECK( !isLuma( chType ), "Wrong ISP mode!" );
471
5.84k
  return CU::canUseLfnstWithISP( cu.blocks[chType == CH_L ? 0 : 1], (ISPType)cu.ispMode );
472
5.84k
}
473
474
uint32_t CU::getISPSplitDim( const int width, const int height, const PartSplit ispType )
475
117k
{
476
117k
  bool divideTuInRows = ispType == TU_1D_HORZ_SPLIT;
477
117k
  uint32_t splitDimensionSize, nonSplitDimensionSize, partitionSize, divShift = 2;
478
479
117k
  if( divideTuInRows )
480
58.3k
  {
481
58.3k
    splitDimensionSize    = height;
482
58.3k
    nonSplitDimensionSize = width;
483
58.3k
  }
484
58.9k
  else
485
58.9k
  {
486
58.9k
    splitDimensionSize    = width;
487
58.9k
    nonSplitDimensionSize = height;
488
58.9k
  }
489
490
117k
  const int minNumberOfSamplesPerCu = 1 << ( ( MIN_TB_LOG2_SIZEY << 1 ) );
491
117k
  const int factorToMinSamples = nonSplitDimensionSize < minNumberOfSamplesPerCu ? minNumberOfSamplesPerCu >> Log2(nonSplitDimensionSize) : 1;
492
117k
  partitionSize = ( splitDimensionSize >> divShift ) < factorToMinSamples ? factorToMinSamples : ( splitDimensionSize >> divShift );
493
494
117k
  CHECK( Log2(partitionSize) + Log2(nonSplitDimensionSize) < Log2(minNumberOfSamplesPerCu), "A partition has less than the minimum amount of samples!" );
495
117k
  return partitionSize;
496
117k
}
497
498
bool CU::allLumaCBFsAreZero(const CodingUnit& cu)
499
1.32k
{
500
1.32k
  if (!cu.ispMode)
501
0
  {
502
0
    return TU::getCbf(*cu.firstTU, COMP_Y) == false;
503
0
  }
504
1.32k
  else
505
1.32k
  {
506
1.32k
    int numTotalTUs = cu.ispMode == HOR_INTRA_SUBPARTITIONS ? cu.lheight() >> Log2(cu.firstTU->lheight()) : cu.lwidth() >> Log2(cu.firstTU->lwidth());
507
1.32k
    TransformUnit* tuPtr = cu.firstTU;
508
1.32k
    for (int tuIdx = 0; tuIdx < numTotalTUs; tuIdx++)
509
1.32k
    {
510
1.32k
      if (TU::getCbf(*tuPtr, COMP_Y) == true)
511
1.32k
      {
512
1.32k
        return false;
513
1.32k
      }
514
0
      tuPtr = tuPtr->next;
515
0
    }
516
0
    return true;
517
1.32k
  }
518
1.32k
}
519
520
TUTraverser CU::traverseTUs( CodingUnit& cu )
521
0
{
522
0
  return TUTraverser( cu.firstTU, cu.lastTU->next );
523
0
}
524
525
cTUTraverser CU::traverseTUs( const CodingUnit& cu )
526
0
{
527
0
  return cTUTraverser( cu.firstTU, cu.lastTU->next );
528
0
}
529
530
const CodingUnit* CU::getLeft(const CodingUnit& curr)
531
83.2k
{
532
83.2k
  const Position& pos = curr.blocks[curr.chType].pos();
533
83.2k
  return curr.cs->getCU(pos.offset(-1, 0), curr.chType, curr.treeType);
534
83.2k
}
535
536
const CodingUnit* CU::getAbove(const CodingUnit& curr)
537
84.9k
{
538
84.9k
  const Position& pos = curr.blocks[curr.chType].pos();
539
84.9k
  return curr.cs->getCU(pos.offset(0, -1), curr.chType, curr.treeType);
540
84.9k
}
541
542
// PU tools
543
544
int CU::getIntraMPMs( const CodingUnit& cu, unsigned* mpm )
545
240k
{
546
240k
  const int numMPMs = NUM_MOST_PROBABLE_MODES;
547
240k
  {
548
240k
    int numCand      = -1;
549
240k
    int leftIntraDir = PLANAR_IDX, aboveIntraDir = PLANAR_IDX;
550
551
240k
    const CompArea& area = cu.Y();
552
240k
    const Position posRT = area.topRight();
553
240k
    const Position posLB = area.bottomLeft();
554
555
    // Get intra direction of left PU
556
240k
    const CodingUnit* puLeft = (posLB.x & cu.cs->pcv->maxCUSizeMask) ? cu.cs->getCU(posLB.offset(-1, 0), CH_L, cu.treeType) : cu.cs->picture->cs->getCURestricted(posLB.offset(-1, 0), cu, CH_L);
557
240k
    if (puLeft && CU::isIntra(*puLeft) && !CU::isMIP(*puLeft))
558
171k
    {
559
171k
      leftIntraDir = puLeft->intraDir[CH_L];
560
171k
    }
561
562
    // Get intra direction of above PU, but only from the same CU
563
240k
    const CodingUnit* puAbove = (posRT.y & cu.cs->pcv->maxCUSizeMask) ? cu.cs->getCU(posRT.offset(0, -1), CH_L, cu.treeType) : nullptr;
564
240k
    if (puAbove && CU::isIntra(*puAbove) && !CU::isMIP(*puAbove))
565
142k
    {
566
142k
      aboveIntraDir = puAbove->intraDir[CH_L];
567
142k
    }
568
569
240k
    CHECK(2 >= numMPMs, "Invalid number of most probable modes");
570
571
240k
    const int offset = (int)NUM_LUMA_MODE - 6;
572
240k
    const int mod = offset + 3;
573
574
240k
    {
575
240k
      mpm[0] = PLANAR_IDX;
576
240k
      mpm[1] = DC_IDX;
577
240k
      mpm[2] = VER_IDX;
578
240k
      mpm[3] = HOR_IDX;
579
240k
      mpm[4] = VER_IDX - 4;
580
240k
      mpm[5] = VER_IDX + 4;
581
582
240k
      if (leftIntraDir == aboveIntraDir)
583
234k
      {
584
234k
        numCand = 1;
585
234k
        if (leftIntraDir > DC_IDX)
586
3.80k
        {
587
3.80k
          mpm[0] = PLANAR_IDX;
588
3.80k
          mpm[1] = leftIntraDir;
589
3.80k
          mpm[2] = ((leftIntraDir + offset) % mod) + 2;
590
3.80k
          mpm[3] = ((leftIntraDir - 1) % mod) + 2;
591
3.80k
          mpm[4] = ((leftIntraDir + offset - 1) % mod) + 2;
592
3.80k
          mpm[5] = ( leftIntraDir               % mod) + 2;
593
3.80k
        }
594
234k
      }
595
5.81k
      else //L!=A
596
5.81k
      {
597
5.81k
        numCand = 2;
598
5.81k
        int  maxCandModeIdx = mpm[0] > mpm[1] ? 0 : 1;
599
600
5.81k
        if ((leftIntraDir > DC_IDX) && (aboveIntraDir > DC_IDX))
601
0
        {
602
0
          mpm[0] = PLANAR_IDX;
603
0
          mpm[1] = leftIntraDir;
604
0
          mpm[2] = aboveIntraDir;
605
0
          maxCandModeIdx = mpm[1] > mpm[2] ? 1 : 2;
606
0
          int minCandModeIdx = mpm[1] > mpm[2] ? 2 : 1;
607
0
          if (mpm[maxCandModeIdx] - mpm[minCandModeIdx] == 1)
608
0
          {
609
0
            mpm[3] = ((mpm[minCandModeIdx] + offset)     % mod) + 2;
610
0
            mpm[4] = ((mpm[maxCandModeIdx] - 1)          % mod) + 2;
611
0
            mpm[5] = ((mpm[minCandModeIdx] + offset - 1) % mod) + 2;
612
0
          }
613
0
          else if (mpm[maxCandModeIdx] - mpm[minCandModeIdx] >= 62)
614
0
          {
615
0
            mpm[3] = ((mpm[minCandModeIdx] - 1)      % mod) + 2;
616
0
            mpm[4] = ((mpm[maxCandModeIdx] + offset) % mod) + 2;
617
0
            mpm[5] = ( mpm[minCandModeIdx]           % mod) + 2;
618
0
          }
619
0
          else if (mpm[maxCandModeIdx] - mpm[minCandModeIdx] == 2)
620
0
          {
621
0
            mpm[3] = ((mpm[minCandModeIdx] - 1)      % mod) + 2;
622
0
            mpm[4] = ((mpm[minCandModeIdx] + offset) % mod) + 2;
623
0
            mpm[5] = ((mpm[maxCandModeIdx] - 1)      % mod) + 2;
624
0
          }
625
0
          else
626
0
          {
627
0
            mpm[3] = ((mpm[minCandModeIdx] + offset) % mod) + 2;
628
0
            mpm[4] = ((mpm[minCandModeIdx] - 1)      % mod) + 2;
629
0
            mpm[5] = ((mpm[maxCandModeIdx] + offset) % mod) + 2;
630
0
          }
631
0
        }
632
5.81k
        else if (leftIntraDir + aboveIntraDir >= 2)
633
5.32k
        {
634
5.32k
          mpm[0] = PLANAR_IDX;
635
5.32k
          mpm[1] = (leftIntraDir < aboveIntraDir) ? aboveIntraDir : leftIntraDir;
636
5.32k
          maxCandModeIdx = 1;
637
5.32k
          mpm[2] = ((mpm[maxCandModeIdx] + offset)     % mod) + 2;
638
5.32k
          mpm[3] = ((mpm[maxCandModeIdx] - 1)          % mod) + 2;
639
5.32k
          mpm[4] = ((mpm[maxCandModeIdx] + offset - 1) % mod) + 2;
640
5.32k
          mpm[5] = ( mpm[maxCandModeIdx]               % mod) + 2;
641
5.32k
        }
642
5.81k
      }
643
240k
    }
644
1.68M
    for (int i = 0; i < numMPMs; i++)
645
1.44M
    {
646
1.44M
      CHECK(mpm[i] >= NUM_LUMA_MODE, "Invalid MPM");
647
1.44M
    }
648
240k
    CHECK(numCand == 0, "No candidates found");
649
240k
    return numCand;
650
240k
  }
651
240k
}
652
653
bool CU::isMIP(const CodingUnit& cu, const ChannelType chType)
654
3.51M
{
655
3.51M
  return chType == CH_L ? cu.mipFlag : ((cu.intraDir[CH_C] == DM_CHROMA_IDX) && isDMChromaMIP(cu));
656
3.51M
}
657
658
bool CU::isDMChromaMIP(const CodingUnit& cu)
659
558k
{
660
558k
  return !CU::isSepTree(cu) && (cu.chromaFormat == CHROMA_444) && getCoLocatedLumaPU(cu).mipFlag;
661
558k
}
662
663
664
uint32_t CU::getIntraDirLuma(const CodingUnit& cu)
665
900k
{
666
900k
  if (isMIP(cu))
667
195k
  {
668
195k
    return PLANAR_IDX;
669
195k
  }
670
704k
  else
671
704k
  {
672
704k
    return cu.intraDir[CH_L];
673
704k
  }
674
900k
}
675
676
677
void CU::getIntraChromaCandModes( const CodingUnit& cu, unsigned modeList[NUM_CHROMA_MODE] )
678
290k
{
679
290k
  {
680
290k
    modeList[0] = PLANAR_IDX;
681
290k
    modeList[1] = VER_IDX;
682
290k
    modeList[2] = HOR_IDX;
683
290k
    modeList[3] = DC_IDX;
684
290k
    modeList[4] = LM_CHROMA_IDX;
685
290k
    modeList[5] = MDLM_L_IDX;
686
290k
    modeList[6] = MDLM_T_IDX;
687
290k
    modeList[7] = DM_CHROMA_IDX;
688
689
    // If Direct Mode is MIP, mode cannot be already in the list.
690
290k
    if (isDMChromaMIP(cu))
691
0
    {
692
0
      return;
693
0
    }
694
695
290k
    const uint32_t lumaMode = getCoLocatedIntraLumaMode(cu);
696
315k
    for( int i = 0; i < 4; i++ )
697
315k
    {
698
315k
      if( lumaMode == modeList[i] )
699
290k
      {
700
290k
        modeList[i] = VDIA_IDX;
701
290k
        break;
702
290k
      }
703
315k
    }
704
290k
  }
705
290k
}
706
707
bool CU::isLMCMode(unsigned mode)
708
3.37M
{
709
3.37M
  return (mode >= LM_CHROMA_IDX && mode <= MDLM_T_IDX);
710
3.37M
}
711
712
bool CU::isLMCModeEnabled(const CodingUnit& cu, unsigned mode)
713
495k
{
714
495k
  return ( cu.cs->sps->LMChroma && CU::checkCCLMAllowed(cu) );
715
495k
}
716
717
int CU::getLMSymbolList(const CodingUnit& cu, int *modeList)
718
31.3k
{
719
31.3k
  int idx = 0;
720
721
31.3k
  modeList[idx++] = LM_CHROMA_IDX;
722
31.3k
  modeList[idx++] = MDLM_L_IDX;
723
31.3k
  modeList[idx++] = MDLM_T_IDX;
724
31.3k
  return idx;
725
31.3k
}
726
727
uint32_t CU::getFinalIntraMode( const CodingUnit& cu, const ChannelType chType )
728
5.01M
{
729
5.01M
  uint32_t uiIntraMode = cu.intraDir[chType];
730
731
5.01M
  if( uiIntraMode == DM_CHROMA_IDX && !isLuma( chType ) )
732
437k
  {
733
437k
    uiIntraMode = getCoLocatedIntraLumaMode(cu);
734
437k
  }
735
5.01M
  if( cu.chromaFormat == CHROMA_422 && !isLuma( chType ) && uiIntraMode < NUM_LUMA_MODE ) // map directional, planar and dc
736
0
  {
737
0
    uiIntraMode = g_chroma422IntraAngleMappingTable[uiIntraMode];
738
0
  }
739
5.01M
  return uiIntraMode;
740
5.01M
}
741
742
const CodingUnit& CU::getCoLocatedLumaPU(const CodingUnit& cu)
743
900k
{
744
900k
  Position              topLeftPos = cu.blocks[cu.chType].lumaPos();
745
900k
  Position              refPos     = topLeftPos.offset(cu.blocks[cu.chType].lumaSize().width  >> 1,
746
900k
                                                       cu.blocks[cu.chType].lumaSize().height >> 1);
747
900k
  const CodingUnit& lumaCU     = CU::isSepTree(cu) ? *cu.cs->lumaCS->getCU(refPos, CH_L, TREE_D)
748
900k
                                                : *cu.cs->getCU(topLeftPos, CH_L, TREE_D);
749
750
900k
  return lumaCU;
751
900k
}
752
753
uint32_t CU::getCoLocatedIntraLumaMode(const CodingUnit& cu)
754
900k
{
755
900k
  return CU::getIntraDirLuma(CU::getCoLocatedLumaPU(cu));
756
900k
}
757
758
bool CU::addMergeHMVPCand(const CodingStructure &cs, MergeCtx& mrgCtx, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const bool isAvailableA1, const MotionInfo& miLeft, const bool isAvailableB1, const MotionInfo& miAbove, const bool ibcFlag, const bool isGt4x4)
759
69.3k
{
760
69.3k
  const Slice& slice = *cs.slice;
761
69.3k
  HPMVInfo miNeighbor;
762
69.3k
  auto& lut = ibcFlag ? cs.motionLut.lutIbc : cs.motionLut.lut;
763
69.3k
  int num_avai_candInLUT = (int) lut.size();
764
765
69.3k
  for (int mrgIdx = 1; mrgIdx <= num_avai_candInLUT; mrgIdx++)
766
0
  {
767
0
    miNeighbor = lut[num_avai_candInLUT - mrgIdx];
768
769
0
    if ( mrgIdx > 2 || ((mrgIdx > 1 || !isGt4x4) && ibcFlag)
770
0
      || ((!isAvailableA1 || (miNeighbor != miLeft)) && (!isAvailableB1 || (miNeighbor != miAbove))) )
771
0
    {
772
0
      mrgCtx.interDirNeighbours[cnt]    = miNeighbor.interDir();
773
0
      mrgCtx.useAltHpelIf      [cnt]    = !ibcFlag && miNeighbor.useAltHpelIf;
774
0
      mrgCtx.BcwIdx            [cnt]    = miNeighbor.interDir() == 3 ? miNeighbor.BcwIdx : BCW_DEFAULT;
775
0
      mrgCtx.mvFieldNeighbours [cnt][0] . setMvField( miNeighbor.mv[0], miNeighbor.mhRefIdx[0] );
776
777
0
      if (slice.isInterB())
778
0
      {
779
0
        mrgCtx.mvFieldNeighbours[cnt][1].setMvField( miNeighbor.mv[1], miNeighbor.mhRefIdx[1] );
780
0
      }
781
782
0
      if (mrgCandIdx == cnt)
783
0
      {
784
0
        return true;
785
0
      }
786
0
      cnt ++;
787
788
0
      if (cnt  == maxNumMergeCandMin1)
789
0
      {
790
0
        break;
791
0
      }
792
0
    }
793
0
  }
794
795
69.3k
  if (cnt < maxNumMergeCandMin1)
796
69.3k
  {
797
69.3k
    mrgCtx.useAltHpelIf[cnt] = false;
798
69.3k
  }
799
800
69.3k
  return false;
801
69.3k
}
802
803
void CU::getIBCMergeCandidates(const CodingUnit& cu, MergeCtx& mrgCtx, const int& mrgCandIdx)
804
69.3k
{
805
69.3k
  const CodingStructure& cs = *cu.cs;
806
69.3k
  const uint32_t maxNumMergeCand = cu.cs->sps->maxNumIBCMergeCand;
807
485k
  for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
808
415k
  {
809
415k
    mrgCtx.BcwIdx             [ui]           = BCW_DEFAULT;
810
415k
    mrgCtx.interDirNeighbours [ui]           = 0;
811
415k
    mrgCtx.mrgTypeNeighbours  [ui]           = MRG_TYPE_IBC;
812
415k
    mrgCtx.mvFieldNeighbours  [ui][0].refIdx = NOT_VALID;
813
415k
    mrgCtx.mvFieldNeighbours  [ui][1].refIdx = NOT_VALID;
814
415k
    mrgCtx.useAltHpelIf       [ui]           = false;
815
415k
  }
816
817
69.3k
  mrgCtx.numValidMergeCand = maxNumMergeCand;
818
  // compute the location of the current PU
819
820
69.3k
  int cnt = 0;
821
822
69.3k
  const Position posRT = cu.Y().topRight();
823
69.3k
  const Position posLB = cu.Y().bottomLeft();
824
825
69.3k
  MotionInfo miAbove, miLeft, miAboveLeft, miAboveRight, miBelowLeft;
826
827
  //left
828
69.3k
  const CodingUnit* cuLeft = cs.getCURestricted(posLB.offset(-1, 0), cu, cu.chType);
829
69.3k
  bool isGt4x4 = cu.lwidth() * cu.lheight() > 16;
830
69.3k
  const bool isAvailableA1 = cuLeft && cu != *cuLeft && CU::isIBC(*cuLeft);
831
69.3k
  if( isGt4x4 && isAvailableA1 )
832
0
  {
833
0
    miLeft             = cuLeft->getMotionInfo( posLB.offset( -1, 0 ) );
834
0
    miLeft.miRefIdx[0] = MI_NOT_VALID + 1;
835
836
    // get Inter Dir
837
0
    mrgCtx.interDirNeighbours[cnt] = miLeft.interDir();
838
    // get Mv from Left
839
0
    mrgCtx.mvFieldNeighbours[cnt][0].setMvField(miLeft.mv[0], miLeft.miRefIdx[0]);
840
0
    if (mrgCandIdx == cnt)
841
0
    {
842
0
      return;
843
0
    }
844
0
    cnt++;
845
0
  }
846
847
  // early termination
848
69.3k
  if (cnt == maxNumMergeCand)
849
0
  {
850
0
    return;
851
0
  }
852
853
  // above
854
69.3k
  const CodingUnit* cuAbove = cs.getCURestricted(posRT.offset(0, -1), cu, cu.chType);
855
69.3k
  bool isAvailableB1 = cuAbove && cu != *cuAbove && CU::isIBC(*cuAbove);
856
69.3k
  if (isGt4x4 && isAvailableB1)
857
0
  {
858
0
    miAbove             = cuAbove->getMotionInfo( posRT.offset( 0, -1 ) );
859
0
    miAbove.miRefIdx[0] = MI_NOT_VALID + 1;
860
861
0
    if( !isAvailableA1 || ( miAbove != miLeft ) )
862
0
    {
863
      // get Inter Dir
864
0
      mrgCtx.interDirNeighbours[cnt] = miAbove.interDir();
865
      // get Mv from Above
866
0
      mrgCtx.mvFieldNeighbours[cnt][0].setMvField(miAbove.mv[0], miAbove.miRefIdx[0]);
867
0
      if (mrgCandIdx == cnt)
868
0
      {
869
0
        return;
870
0
      }
871
872
0
      cnt++;
873
0
    }
874
0
  }
875
876
  // early termination
877
69.3k
  if (cnt == maxNumMergeCand)
878
0
  {
879
0
    return;
880
0
  }
881
69.3k
  else
882
69.3k
  {
883
69.3k
    bool bFound = addMergeHMVPCand( cs, mrgCtx, mrgCandIdx, maxNumMergeCand, cnt, isAvailableA1, miLeft, isAvailableB1, miAbove, true, isGt4x4 );
884
885
69.3k
    if (bFound)
886
0
    {
887
0
      return;
888
0
    }
889
69.3k
  }
890
891
254k
  while (cnt < maxNumMergeCand)
892
231k
  {
893
231k
    mrgCtx.mvFieldNeighbours[cnt][0].setMvField(Mv(0, 0), MAX_NUM_REF);
894
231k
    mrgCtx.interDirNeighbours[cnt] = 1;
895
231k
    if (mrgCandIdx == cnt)
896
46.2k
    {
897
46.2k
      return;
898
46.2k
    }
899
184k
    cnt++;
900
184k
  }
901
902
23.1k
  mrgCtx.numValidMergeCand = cnt;
903
23.1k
}
904
905
void CU::getInterMergeCandidates( const CodingUnit& cu, MergeCtx& mrgCtx, int mmvdList, const int mrgCandIdx )
906
0
{
907
0
  const unsigned plevel = cu.cs->sps->log2ParallelMergeLevelMinus2 + 2;
908
0
  const CodingStructure &cs  = *cu.cs;
909
0
  const Slice &slice         = *cu.cs->slice;
910
0
  const uint32_t maxNumMergeCand = slice.sps->maxNumMergeCand;
911
912
0
  for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
913
0
  {
914
0
    mrgCtx.BcwIdx            [ui]           = BCW_DEFAULT;
915
0
    mrgCtx.interDirNeighbours[ui]           = 0;
916
0
    mrgCtx.mrgTypeNeighbours [ui]           = MRG_TYPE_DEFAULT_N;
917
0
    mrgCtx.mvFieldNeighbours [ui][0].refIdx = NOT_VALID;
918
0
    mrgCtx.mvFieldNeighbours [ui][1].refIdx = NOT_VALID;
919
0
    mrgCtx.useAltHpelIf      [ui]           = false;
920
0
  }
921
922
0
  mrgCtx.numValidMergeCand = maxNumMergeCand;
923
  // compute the location of the current PU
924
925
0
  int cnt = 0;
926
927
0
  const Position posLT = cu.Y().topLeft();
928
0
  const Position posRT = cu.Y().topRight();
929
0
  const Position posLB = cu.Y().bottomLeft();
930
0
  MotionInfo miAbove, miLeft, miAboveLeft, miAboveRight, miBelowLeft;
931
932
  // above
933
0
  const CodingUnit* puAbove = cs.getCURestricted(posRT.offset(0, -1), cu, cu.chType);
934
935
0
  bool isAvailableB1 = puAbove && isDiffMER(cu.lumaPos(), posRT.offset(0, -1), plevel) && &cu != puAbove && CU::isInter(*puAbove);
936
937
0
  if (isAvailableB1)
938
0
  {
939
0
    miAbove = puAbove->getMotionInfo(posRT.offset(0, -1));
940
941
    // get Inter Dir
942
0
    mrgCtx.interDirNeighbours[cnt]    = miAbove.interDir();
943
0
    mrgCtx.useAltHpelIf      [cnt]    = puAbove->imv == IMV_HPEL;
944
0
    mrgCtx.BcwIdx            [cnt]    = mrgCtx.interDirNeighbours[cnt] == 3 ? puAbove->BcwIdx : BCW_DEFAULT;
945
0
    mrgCtx.mvFieldNeighbours [cnt][0] . setMvField(miAbove.mv[0], miAbove.miRefIdx[0]);
946
947
0
    if (slice.isInterB())
948
0
    {
949
0
      mrgCtx.mvFieldNeighbours[cnt][1]. setMvField(miAbove.mv[1], miAbove.miRefIdx[1]);
950
0
    }
951
0
    if (mrgCandIdx == cnt)
952
0
    {
953
0
      return;
954
0
    }
955
956
0
    cnt++;
957
0
  }
958
959
  // early termination
960
0
  if (cnt == maxNumMergeCand)
961
0
  {
962
0
    return;
963
0
  }
964
965
  //left
966
0
  const CodingUnit* puLeft = cs.getCURestricted(posLB.offset(-1, 0), cu, cu.chType);
967
968
0
  const bool isAvailableA1 = puLeft && isDiffMER(cu.lumaPos(), posLB.offset(-1, 0), plevel) && &cu != puLeft && CU::isInter(*puLeft);
969
970
0
  if (isAvailableA1)
971
0
  {
972
0
    miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0));
973
974
0
    if (!isAvailableB1 || (miAbove != miLeft))
975
0
    {
976
      // get Inter Dir
977
0
      mrgCtx.interDirNeighbours[cnt]    = miLeft.interDir();
978
0
      mrgCtx.useAltHpelIf      [cnt]    = puLeft->imv == IMV_HPEL;
979
0
      mrgCtx.BcwIdx            [cnt]    = mrgCtx.interDirNeighbours[cnt] == 3 ? puLeft->BcwIdx : BCW_DEFAULT;
980
0
      mrgCtx.mvFieldNeighbours [cnt][0] . setMvField(miLeft.mv[0], miLeft.miRefIdx[0]);
981
982
0
      if (slice.isInterB())
983
0
      {
984
0
        mrgCtx.mvFieldNeighbours[cnt][1]. setMvField(miLeft.mv[1], miLeft.miRefIdx[1]);
985
0
      }
986
0
      if (mrgCandIdx == cnt)
987
0
      {
988
0
        return;
989
0
      }
990
991
0
      cnt++;
992
0
    }
993
0
  }
994
995
  // early termination
996
0
  if( cnt == maxNumMergeCand )
997
0
  {
998
0
    return;
999
0
  }
1000
1001
  // above right
1002
0
  const CodingUnit* puAboveRight = cs.getCURestricted( posRT.offset( 1, -1 ), cu, cu.chType );
1003
1004
0
  bool isAvailableB0 = puAboveRight && isDiffMER( cu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter( *puAboveRight );
1005
1006
0
  if( isAvailableB0 )
1007
0
  {
1008
0
    miAboveRight = puAboveRight->getMotionInfo( posRT.offset( 1, -1 ) );
1009
1010
0
    if( !isAvailableB1 || ( miAbove != miAboveRight ) )
1011
0
    {
1012
      // get Inter Dir
1013
0
      mrgCtx.interDirNeighbours[cnt]    = miAboveRight.interDir();
1014
0
      mrgCtx.useAltHpelIf      [cnt]    = puAboveRight->imv == IMV_HPEL;
1015
0
      mrgCtx.BcwIdx            [cnt]    = mrgCtx.interDirNeighbours[cnt] == 3 ? puAboveRight->BcwIdx : BCW_DEFAULT;
1016
0
      mrgCtx.mvFieldNeighbours [cnt][0] . setMvField( miAboveRight.mv[0], miAboveRight.miRefIdx[0] );
1017
1018
0
      if( slice.isInterB() )
1019
0
      {
1020
0
        mrgCtx.mvFieldNeighbours[cnt][1]. setMvField( miAboveRight.mv[1], miAboveRight.miRefIdx[1] );
1021
0
      }
1022
0
      if (mrgCandIdx == cnt)
1023
0
      {
1024
0
        return;
1025
0
      }
1026
1027
0
      cnt++;
1028
0
    }
1029
0
  }
1030
  // early termination
1031
0
  if( cnt == maxNumMergeCand )
1032
0
  {
1033
0
    return;
1034
0
  }
1035
1036
  //left bottom
1037
0
  const CodingUnit* puLeftBottom = cs.getCURestricted( posLB.offset( -1, 1 ), cu, cu.chType );
1038
1039
0
  bool isAvailableA0 = puLeftBottom && isDiffMER( cu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter( *puLeftBottom );
1040
1041
0
  if( isAvailableA0 )
1042
0
  {
1043
0
    miBelowLeft = puLeftBottom->getMotionInfo( posLB.offset( -1, 1 ) );
1044
1045
0
    if( !isAvailableA1 || ( miBelowLeft != miLeft ) )
1046
0
    {
1047
      // get Inter Dir
1048
0
      mrgCtx.interDirNeighbours [cnt]    = miBelowLeft.interDir();
1049
0
      mrgCtx.useAltHpelIf       [cnt]    = puLeftBottom->imv == IMV_HPEL;
1050
0
      mrgCtx.BcwIdx             [cnt]    = mrgCtx.interDirNeighbours[cnt] == 3 ? puLeftBottom->BcwIdx : BCW_DEFAULT;
1051
      // get Mv from Bottom-Left
1052
0
      mrgCtx.mvFieldNeighbours  [cnt][0] . setMvField( miBelowLeft.mv[0], miBelowLeft.miRefIdx[0] );
1053
1054
0
      if( slice.isInterB() )
1055
0
      {
1056
0
        mrgCtx.mvFieldNeighbours[cnt][1] . setMvField( miBelowLeft.mv[1], miBelowLeft.miRefIdx[1] );
1057
0
      }
1058
0
      if (mrgCandIdx == cnt)
1059
0
      {
1060
0
        return;
1061
0
      }
1062
1063
0
      cnt++;
1064
0
    }
1065
0
  }
1066
  // early termination
1067
0
  if( cnt == maxNumMergeCand )
1068
0
  {
1069
0
    return;
1070
0
  }
1071
1072
1073
  // above left
1074
0
  if ( cnt < 4 )
1075
0
  {
1076
0
    const CodingUnit* puAboveLeft = cs.getCURestricted( posLT.offset( -1, -1 ), cu, cu.chType );
1077
1078
0
    bool isAvailableB2 = puAboveLeft && isDiffMER( cu.lumaPos(), posLT.offset(-1, -1), plevel ) && CU::isInter( *puAboveLeft );
1079
1080
0
    if( isAvailableB2 )
1081
0
    {
1082
0
      miAboveLeft = puAboveLeft->getMotionInfo( posLT.offset( -1, -1 ) );
1083
1084
0
      if( ( !isAvailableA1 || ( miLeft != miAboveLeft ) ) && ( !isAvailableB1 || ( miAbove != miAboveLeft ) ) )
1085
0
      {
1086
        // get Inter Dir
1087
0
        mrgCtx.interDirNeighbours [cnt]    = miAboveLeft.interDir();
1088
0
        mrgCtx.useAltHpelIf       [cnt]    = puAboveLeft->imv == IMV_HPEL;
1089
0
        mrgCtx.BcwIdx             [cnt]    = mrgCtx.interDirNeighbours[cnt] == 3 ? puAboveLeft->BcwIdx : BCW_DEFAULT;
1090
        // get Mv from Above-Left
1091
0
        mrgCtx.mvFieldNeighbours  [cnt][0] . setMvField( miAboveLeft.mv[0], miAboveLeft.miRefIdx[0] );
1092
1093
0
        if( slice.isInterB() )
1094
0
        {
1095
0
          mrgCtx.mvFieldNeighbours[cnt][1] . setMvField( miAboveLeft.mv[1], miAboveLeft.miRefIdx[1] );
1096
0
        }
1097
0
        if (mrgCandIdx == cnt)
1098
0
        {
1099
0
          return;
1100
0
        }
1101
1102
0
        cnt++;
1103
0
      }
1104
0
    }
1105
0
  }
1106
  // early termination
1107
0
  if (cnt == maxNumMergeCand)
1108
0
  {
1109
0
    return;
1110
0
  }
1111
1112
0
  if (slice.picHeader->enableTMVP && (cu.lumaSize().width + cu.lumaSize().height > 12))
1113
0
  {
1114
    //>> MTK colocated-RightBottom
1115
    // offset the pos to be sure to "point" to the same position the uiAbsPartIdx would've pointed to
1116
0
    Position posRB = cu.Y().bottomRight().offset( -3, -3 );
1117
0
    const PreCalcValues& pcv = *cs.pcv;
1118
1119
0
    Position posC0;
1120
0
    Position posC1 = cu.Y().center();
1121
0
    bool C0Avail = false;
1122
0
    bool boundaryCond = ((posRB.x + pcv.minCUSize) < pcv.lumaWidth) && ((posRB.y + pcv.minCUSize) < pcv.lumaHeight);
1123
0
    const SubPic& curSubPic = cu.cs->slice->pps->getSubPicFromPos(cu.lumaPos());
1124
0
    if (curSubPic.treatedAsPic )
1125
0
    {
1126
0
      boundaryCond = ((posRB.x + pcv.minCUSize) <= curSubPic.subPicRight &&
1127
0
                      (posRB.y + pcv.minCUSize) <= curSubPic.subPicBottom);
1128
0
    }    
1129
0
    if (boundaryCond)
1130
0
    {
1131
0
      int posYInCtu = posRB.y & pcv.maxCUSizeMask;
1132
0
      if (posYInCtu + 4 < pcv.maxCUSize)
1133
0
      {
1134
0
        posC0 = posRB.offset(4, 4);
1135
0
        C0Avail = true;
1136
0
      }
1137
0
    }
1138
1139
0
    Mv        cColMv;
1140
0
    int       iRefIdx     = 0;
1141
0
    int       dir         = 0;
1142
0
    unsigned  uiArrayAddr = cnt;
1143
0
    bool      bExistMV    = ( C0Avail && getColocatedMVP( cu, REF_PIC_LIST_0, posC0, cColMv, iRefIdx ) )
1144
0
                                      || getColocatedMVP( cu, REF_PIC_LIST_0, posC1, cColMv, iRefIdx );
1145
0
    if (bExistMV)
1146
0
    {
1147
0
      dir     |= 1;
1148
0
      mrgCtx.mvFieldNeighbours[uiArrayAddr][0].setMvField(cColMv, iRefIdx);
1149
0
    }
1150
1151
0
    if (slice.isInterB())
1152
0
    {
1153
0
      bExistMV = ( C0Avail && getColocatedMVP( cu, REF_PIC_LIST_1, posC0, cColMv, iRefIdx ) )
1154
0
                           || getColocatedMVP( cu, REF_PIC_LIST_1, posC1, cColMv, iRefIdx );
1155
0
      if (bExistMV)
1156
0
      {
1157
0
        dir     |= 2;
1158
0
        mrgCtx.mvFieldNeighbours[uiArrayAddr][1].setMvField(cColMv, iRefIdx);
1159
0
      }
1160
0
    }
1161
1162
0
    if( dir != 0 )
1163
0
    {
1164
0
      bool addTMvp = true;
1165
0
      if( addTMvp )
1166
0
      {
1167
0
        mrgCtx.interDirNeighbours[uiArrayAddr] = dir;
1168
0
        mrgCtx.BcwIdx            [uiArrayAddr] = BCW_DEFAULT;
1169
0
        mrgCtx.useAltHpelIf      [uiArrayAddr] = false;
1170
0
        if (mrgCandIdx == cnt)
1171
0
        {
1172
0
          return;
1173
0
        }
1174
1175
0
        cnt++;
1176
0
      }
1177
0
    }
1178
0
  }
1179
1180
  // early termination
1181
0
  if (cnt == maxNumMergeCand)
1182
0
  {
1183
0
    return;
1184
0
  }
1185
1186
0
  int maxNumMergeCandMin1 = maxNumMergeCand - 1;
1187
0
  if( cnt != maxNumMergeCandMin1 )
1188
0
  {
1189
0
    bool isGt4x4 = true;
1190
0
    bool bFound  = addMergeHMVPCand( cs, mrgCtx, mrgCandIdx, maxNumMergeCandMin1, cnt, isAvailableA1, miLeft, isAvailableB1, miAbove, CU::isIBC( cu ), isGt4x4 );
1191
1192
0
    if (bFound)
1193
0
    {
1194
0
      return;
1195
0
    }
1196
0
  }
1197
1198
  // pairwise-average candidates
1199
0
  {
1200
0
    if (cnt > 1 && cnt < maxNumMergeCand)
1201
0
    {
1202
0
      mrgCtx.mvFieldNeighbours[cnt][0].setMvField( Mv( 0, 0 ), NOT_VALID );
1203
0
      mrgCtx.mvFieldNeighbours[cnt][1].setMvField( Mv( 0, 0 ), NOT_VALID );
1204
      // calculate average MV for L0 and L1 seperately
1205
0
      unsigned char interDir = 0;
1206
1207
1208
0
      mrgCtx.useAltHpelIf[cnt] = (mrgCtx.useAltHpelIf[0] == mrgCtx.useAltHpelIf[1]) ? mrgCtx.useAltHpelIf[0] : false;
1209
0
      for( int refListId = 0; refListId < (slice.isInterB() ? 2 : 1); refListId++ )
1210
0
      {
1211
0
        const short refIdxI = mrgCtx.mvFieldNeighbours[0][refListId].refIdx;
1212
0
        const short refIdxJ = mrgCtx.mvFieldNeighbours[1][refListId].refIdx;
1213
1214
        // both MVs are invalid, skip
1215
0
        if( (refIdxI == NOT_VALID) && (refIdxJ == NOT_VALID) )
1216
0
        {
1217
0
          continue;
1218
0
        }
1219
1220
0
        interDir += 1 << refListId;
1221
        // both MVs are valid, average these two MVs
1222
0
        if( (refIdxI != NOT_VALID) && (refIdxJ != NOT_VALID) )
1223
0
        {
1224
0
          const Mv& MvI = mrgCtx.mvFieldNeighbours[0][refListId].mv;
1225
0
          const Mv& MvJ = mrgCtx.mvFieldNeighbours[1][refListId].mv;
1226
1227
          // average two MVs
1228
0
          Mv avgMv = MvI;
1229
0
          avgMv += MvJ;
1230
0
          roundAffineMv(avgMv.hor, avgMv.ver, 1);
1231
1232
0
          mrgCtx.mvFieldNeighbours[cnt][refListId].setMvField( avgMv, refIdxI );
1233
0
        }
1234
        // only one MV is valid, take the only one MV
1235
0
        else if( refIdxI != NOT_VALID )
1236
0
        {
1237
0
          Mv singleMv = mrgCtx.mvFieldNeighbours[0][refListId].mv;
1238
0
          mrgCtx.mvFieldNeighbours[cnt][refListId].setMvField( singleMv, refIdxI );
1239
0
        }
1240
0
        else if( refIdxJ != NOT_VALID )
1241
0
        {
1242
0
          Mv singleMv = mrgCtx.mvFieldNeighbours[1][refListId].mv;
1243
0
          mrgCtx.mvFieldNeighbours[cnt][refListId].setMvField( singleMv, refIdxJ );
1244
0
        }
1245
0
      }
1246
1247
0
      mrgCtx.interDirNeighbours[cnt] = interDir;
1248
0
      if( interDir > 0 )
1249
0
      {
1250
0
        cnt++;
1251
0
      }
1252
0
    }
1253
1254
    // early termination
1255
0
    if( cnt == maxNumMergeCand )
1256
0
    {
1257
0
      return;
1258
0
    }
1259
0
  }
1260
1261
0
  uint32_t uiArrayAddr = cnt;
1262
1263
0
  int iNumRefIdx = slice.isInterB() ? std::min(slice.numRefIdx[ REF_PIC_LIST_0 ], slice.numRefIdx[ REF_PIC_LIST_1 ]) : slice.numRefIdx[ REF_PIC_LIST_0 ];
1264
1265
0
  int r = 0;
1266
0
  int refcnt = 0;
1267
0
  while (uiArrayAddr < maxNumMergeCand && uiArrayAddr < MRG_MAX_NUM_CANDS)
1268
0
  {
1269
0
    mrgCtx.interDirNeighbours  [uiArrayAddr]    = 1;
1270
0
    mrgCtx.BcwIdx              [uiArrayAddr]    = BCW_DEFAULT;
1271
0
    mrgCtx.mvFieldNeighbours   [uiArrayAddr][0] . setMvField( Mv(0, 0), r );
1272
0
    mrgCtx.useAltHpelIf        [uiArrayAddr]    = false;
1273
1274
0
    if (slice.isInterB())
1275
0
    {
1276
0
      mrgCtx.interDirNeighbours[uiArrayAddr]    = 3;
1277
0
      mrgCtx.mvFieldNeighbours [uiArrayAddr][1] . setMvField( Mv(0, 0), r );
1278
0
    }
1279
1280
0
    if ( mrgCtx.interDirNeighbours[uiArrayAddr] == 1 && cu.cs->slice->getRefPic(REF_PIC_LIST_0, mrgCtx.mvFieldNeighbours[uiArrayAddr][0].refIdx)->getPOC() == cu.cs->slice->poc)
1281
0
    {
1282
0
      mrgCtx.mrgTypeNeighbours[uiArrayAddr] = MRG_TYPE_IBC;
1283
0
    }
1284
1285
0
    uiArrayAddr++;
1286
1287
0
    if (refcnt == iNumRefIdx - 1)
1288
0
    {
1289
0
      r = 0;
1290
0
    }
1291
0
    else
1292
0
    {
1293
0
      ++r;
1294
0
      ++refcnt;
1295
0
    }
1296
0
  }
1297
0
  mrgCtx.numValidMergeCand = uiArrayAddr;
1298
0
}
1299
1300
bool CU::checkDMVRCondition(const CodingUnit& cu)
1301
21.3k
{
1302
21.3k
  if( !cu.cs->sps->DMVR || cu.cs->slice->picHeader->disDmvrFlag )
1303
0
  {
1304
0
    return false;
1305
0
  }
1306
1307
21.3k
  return  cu.mergeFlag
1308
0
      &&  cu.mergeType == MRG_TYPE_DEFAULT_N
1309
0
      && !cu.ciip
1310
0
      && !cu.affine
1311
0
      && !cu.mmvdMergeFlag
1312
0
      && !cu.mmvdSkip
1313
0
      &&  CU::isBiPredFromDifferentDirEqDistPoc( cu )
1314
0
      &&  cu.lumaSize().minDim() >= 8
1315
0
      &&  cu.lumaSize().area() >= 128
1316
0
      &&  cu.BcwIdx == BCW_DEFAULT;
1317
21.3k
}
1318
1319
int convertMvFixedToFloat(int32_t val)
1320
0
{
1321
0
  int sign  = val >> 31;
1322
0
  int scale = floorLog2((val ^ sign) | MV_MANTISSA_UPPER_LIMIT) - (MV_MANTISSA_BITCOUNT - 1);
1323
1324
0
  int exponent;
1325
0
  int mantissa;
1326
0
  if (scale >= 0)
1327
0
  {
1328
0
    int round = (1 << scale) >> 1;
1329
0
    int n     = (val + round) >> scale;
1330
0
    exponent  = scale + ((n ^ sign) >> (MV_MANTISSA_BITCOUNT - 1));
1331
0
    mantissa  = (n & MV_MANTISSA_UPPER_LIMIT) | (sign * (1 << (MV_MANTISSA_BITCOUNT - 1)));
1332
0
  }
1333
0
  else
1334
0
  {
1335
0
    exponent = 0;
1336
0
    mantissa = val;
1337
0
  }
1338
1339
0
  return exponent | (mantissa * (1 << MV_EXPONENT_BITCOUNT));
1340
0
}
1341
1342
int convertMvFloatToFixed(int val)
1343
0
{
1344
0
  int exponent = val & MV_EXPONENT_MASK;
1345
0
  int mantissa = val >> MV_EXPONENT_BITCOUNT;
1346
0
  return exponent == 0 ? mantissa : (mantissa ^ MV_MANTISSA_LIMIT) * (1 << (exponent - 1));
1347
0
}
1348
1349
int roundMvComp(int x)
1350
0
{
1351
0
  return convertMvFloatToFixed(convertMvFixedToFloat(x));
1352
0
}
1353
1354
int CU::getDistScaleFactor(const int currPOC, const int currRefPOC, const int colPOC, const int colRefPOC)
1355
0
{
1356
0
  int iDiffPocD = colPOC - colRefPOC;
1357
0
  int iDiffPocB = currPOC - currRefPOC;
1358
1359
0
  if (iDiffPocD == iDiffPocB)
1360
0
  {
1361
0
    return 4096;
1362
0
  }
1363
0
  else
1364
0
  {
1365
0
    int iTDB = Clip3(-128, 127, iDiffPocB);
1366
0
    int iTDD = Clip3(-128, 127, iDiffPocD);
1367
0
    int iX = (0x4000 + abs(iTDD / 2)) / iTDD;
1368
0
    int iScale = Clip3(-4096, 4095, (iTDB * iX + 32) >> 6);
1369
0
    return iScale;
1370
0
  }
1371
0
}
1372
1373
void CU::getInterMMVDMergeCandidates( const CodingUnit &cu, MergeCtx &mrgCtx )
1374
0
{
1375
0
  int refIdxList0, refIdxList1;
1376
0
  int k;
1377
0
  int currBaseNum = 0;
1378
0
  const uint16_t maxNumMergeCand = mrgCtx.numValidMergeCand;
1379
1380
0
  for( k = 0; k < maxNumMergeCand; k++ )
1381
0
  {
1382
0
    if( mrgCtx.mrgTypeNeighbours[k] == MRG_TYPE_DEFAULT_N )
1383
0
    {
1384
0
      refIdxList0 = mrgCtx.mvFieldNeighbours[k][0].refIdx;
1385
0
      refIdxList1 = mrgCtx.mvFieldNeighbours[k][1].refIdx;
1386
1387
0
      if( ( refIdxList0 >= 0 ) && ( refIdxList1 >= 0 ) )
1388
0
      {
1389
0
        mrgCtx.mmvdBaseMv[currBaseNum][0] = mrgCtx.mvFieldNeighbours[k][0];
1390
0
        mrgCtx.mmvdBaseMv[currBaseNum][1] = mrgCtx.mvFieldNeighbours[k][1];
1391
0
      }
1392
0
      else if( refIdxList0 >= 0 )
1393
0
      {
1394
0
        mrgCtx.mmvdBaseMv[currBaseNum][0] = mrgCtx.mvFieldNeighbours[k][0];
1395
0
        mrgCtx.mmvdBaseMv[currBaseNum][1] = MvField( Mv( 0, 0 ), -1 );
1396
0
      }
1397
0
      else if( refIdxList1 >= 0 )
1398
0
      {
1399
0
        mrgCtx.mmvdBaseMv[currBaseNum][0] = MvField( Mv( 0, 0 ), -1 );
1400
0
        mrgCtx.mmvdBaseMv[currBaseNum][1] = mrgCtx.mvFieldNeighbours[k][1];
1401
0
      }
1402
0
      mrgCtx.mmvdUseAltHpelIf[currBaseNum] = mrgCtx.useAltHpelIf[k];
1403
1404
0
      currBaseNum++;
1405
1406
0
      if( currBaseNum == MMVD_BASE_MV_NUM )
1407
0
        break;
1408
0
    }
1409
0
  }
1410
0
}
1411
1412
bool CU::getColocatedMVP(const CodingUnit& cu, const RefPicList refPicList, const Position& _pos, Mv& rcMv, const int refIdx, bool sbFlag )
1413
0
{
1414
0
  if( CU::isIBC( cu ) )
1415
0
  {
1416
0
    return false;
1417
0
  }
1418
1419
  // don't perform MV compression when generally disabled or SbTMVP is used
1420
0
  const unsigned scale = 4 * std::max<int>(1, 4 * AMVP_DECIMATION_FACTOR / 4);
1421
0
  const unsigned mask  = ~( scale - 1 );
1422
1423
0
  const Position pos = Position{ PosType( _pos.x & mask ), PosType( _pos.y & mask ) };
1424
1425
0
  const Slice &slice = *cu.cs->slice;
1426
1427
  // use coldir.
1428
0
  const Picture* const pColPic = slice.getRefPic(RefPicList(slice.isInterB() ? 1 - slice.colFromL0Flag : 0), slice.colRefIdx);
1429
1430
0
  if( !pColPic )
1431
0
  {
1432
0
    return false;
1433
0
  }
1434
1435
  // Check the position of colocated block is within a subpicture
1436
0
  const SubPic& curSubPic = cu.cs->slice->pps->getSubPicFromPos(cu.lumaPos());
1437
0
  if (curSubPic.treatedAsPic)
1438
0
  {
1439
0
    if (!curSubPic.isContainingPos(pos))
1440
0
      return false;
1441
0
  }
1442
1443
0
  RefPicList eColRefPicList = slice.checkLDC ? refPicList : RefPicList(slice.colFromL0Flag);
1444
1445
0
  const MotionInfo& mi = pColPic->cs->getMotionInfo( pos );
1446
1447
0
  if( !mi.isInter() )
1448
0
  {
1449
0
    return false;
1450
0
  }
1451
1452
0
  int iColRefIdx = mi.miRefIdx[eColRefPicList];
1453
1454
0
  if (sbFlag && !slice.checkLDC)
1455
0
  {
1456
0
    eColRefPicList = refPicList;
1457
0
    iColRefIdx = mi.miRefIdx[eColRefPicList];
1458
0
    if (iColRefIdx < 0)
1459
0
    {
1460
0
      return false;
1461
0
    }
1462
0
  }
1463
0
  else
1464
0
  {
1465
0
    if (iColRefIdx < 0)
1466
0
    {
1467
0
      eColRefPicList = RefPicList(1 - eColRefPicList);
1468
0
      iColRefIdx = mi.miRefIdx[eColRefPicList];
1469
1470
0
      if (iColRefIdx < 0)
1471
0
      {
1472
0
        return false;
1473
0
      }
1474
0
    }
1475
0
  }
1476
1477
0
  int ctuRsAddr = getCtuAddr( pos, *pColPic->cs->pcv );
1478
0
  const Slice* sliceCol = pColPic->ctuSlice[ ctuRsAddr ];
1479
1480
0
  CHECK( sliceCol == nullptr, "Slice segment not found" );
1481
1482
0
  const bool bIsCurrRefLongTerm = slice.getRefPic(refPicList, refIdx)->isLongTerm;
1483
0
  const bool bIsColRefLongTerm  = sliceCol->isUsedAsLongTerm[eColRefPicList][iColRefIdx];
1484
1485
0
  if (bIsCurrRefLongTerm != bIsColRefLongTerm)
1486
0
  {
1487
0
    return false;
1488
0
  }
1489
1490
1491
  // Scale the vector.
1492
0
  Mv cColMv = mi.mv[eColRefPicList];
1493
0
  cColMv.hor = roundMvComp( cColMv.hor );
1494
0
  cColMv.ver = roundMvComp( cColMv.ver );
1495
1496
0
  if (bIsCurrRefLongTerm)
1497
0
  {
1498
0
    rcMv = cColMv;
1499
0
    rcMv.clipToStorageBitDepth();
1500
0
  }
1501
0
  else
1502
0
  {
1503
0
    const int currPOC    = slice.poc;
1504
0
    const int colPOC     = sliceCol->poc;
1505
0
    const int colRefPOC  = sliceCol->getRefPOC(eColRefPicList, iColRefIdx);
1506
0
    const int currRefPOC = slice.getRefPic(refPicList, refIdx)->getPOC();
1507
0
    const int distscale  = getDistScaleFactor(currPOC, currRefPOC, colPOC, colRefPOC);
1508
1509
0
    if (distscale == 4096)
1510
0
    {
1511
0
      rcMv = cColMv;
1512
0
      rcMv.clipToStorageBitDepth();
1513
0
    }
1514
0
    else
1515
0
    {
1516
0
      rcMv = cColMv.scaleMv(distscale);
1517
0
    }
1518
0
  }
1519
1520
0
  return true;
1521
0
}
1522
1523
static void isAddNeighborMvIBC( const Mv& currMv, Mv* neighborMvs, int& numNeighborMv )
1524
0
{
1525
0
  Mv bv = currMv;
1526
0
  bv.changePrecision( MV_PRECISION_INTERNAL, MV_PRECISION_INT );
1527
1528
0
  bool existed = false;
1529
0
  for( uint32_t cand = 0; cand < numNeighborMv && !existed; cand++ )
1530
0
  {
1531
0
    if( bv == neighborMvs[cand] )
1532
0
    {
1533
0
      existed = true;
1534
0
    }
1535
0
  }
1536
1537
0
  if( !existed )
1538
0
  {
1539
0
    neighborMvs[numNeighborMv++] = bv;
1540
0
  }
1541
0
}
1542
1543
static bool getDerivedMvIbc( CodingUnit& cu, const Mv& currentBv, Mv& derivedMv )
1544
0
{
1545
0
  int cuPelX  = cu.lumaPos().x;
1546
0
  int cuPelY  = cu.lumaPos().y;
1547
0
  int rX      = cuPelX + currentBv.hor;
1548
0
  int rY      = cuPelY + currentBv.ver;
1549
0
  int offsetX = currentBv.hor;
1550
0
  int offsetY = currentBv.ver;
1551
1552
0
  if( rX < 0 || rY < 0 || rX >= cu.cs->slice->pps->picWidthInLumaSamples || rY >= cu.cs->slice->pps->picHeightInLumaSamples )
1553
0
  {
1554
0
    return false;
1555
0
  }
1556
1557
0
  const CodingUnit* neibRefCU = cu.cs->getCURestricted( cu.lumaPos().offset( offsetX, offsetY ), cu, CH_L );
1558
1559
0
  if( neibRefCU && CU::isIBC( *neibRefCU ) )
1560
0
  {
1561
0
    Mv currMv  = currentBv; currMv.changePrecision( MV_PRECISION_INT, MV_PRECISION_INTERNAL );
1562
0
    derivedMv  = neibRefCU->mv[0][0];
1563
0
    derivedMv += currMv;
1564
0
    return true;
1565
0
  }
1566
1567
0
  return false;
1568
0
}
1569
1570
void CU::getIbcMVPsEncOnly(CodingUnit& cu, Mv* mvPred, int& nbPred)
1571
23.1k
{
1572
23.1k
  const PreCalcValues& pcv = *cu.cs->pcv;
1573
23.1k
  const int  cuWidth = cu.blocks[COMP_Y].width;
1574
23.1k
  const int  cuHeight = cu.blocks[COMP_Y].height;
1575
23.1k
  const int  log2UnitWidth = floorLog2(pcv.minCUSize); //(pcv.minCUWidth);
1576
23.1k
  const int  log2UnitHeight = floorLog2(pcv.minCUSize); //(pcv.minCUHeight);
1577
23.1k
  const int  totalAboveUnits = (cuWidth >> log2UnitHeight) + 1; // log2UnitWidth) + 1;
1578
23.1k
  const int  totalLeftUnits = (cuHeight >> log2UnitHeight) + 1;
1579
1580
23.1k
  nbPred = 0;
1581
23.1k
  Position posLT = cu.Y().topLeft();
1582
1583
  // above-left
1584
23.1k
  const CodingUnit* aboveLeftCU = cu.cs->getCURestricted(posLT.offset(-1, -1), cu, CH_L);
1585
23.1k
  if( aboveLeftCU && CU::isIBC( *aboveLeftCU ) )
1586
0
  {
1587
0
    isAddNeighborMvIBC(aboveLeftCU->mv[0][0], mvPred, nbPred);
1588
0
  }
1589
1590
  // above neighbors
1591
222k
  for( uint32_t dx = 0; dx < totalAboveUnits && nbPred < IBC_NUM_CANDIDATES; dx++ )
1592
198k
  {
1593
198k
    const CodingUnit* tmpCU = cu.cs->getCURestricted( posLT.offset( ( dx << log2UnitWidth ), -1 ), cu, CH_L );
1594
198k
    if( tmpCU && CU::isIBC( *tmpCU ) )
1595
0
    {
1596
0
      isAddNeighborMvIBC( tmpCU->mv[0][0], mvPred, nbPred );
1597
0
    }
1598
198k
  }
1599
1600
  // left neighbors
1601
221k
  for( uint32_t dy = 0; dy < totalLeftUnits && nbPred < IBC_NUM_CANDIDATES; dy++ )
1602
198k
  {
1603
198k
    const CodingUnit* tmpCU = cu.cs->getCURestricted( posLT.offset( -1, ( dy << log2UnitHeight ) ), cu, CH_L );
1604
198k
    if( tmpCU && CU::isIBC( *tmpCU ) )
1605
0
    {
1606
0
      isAddNeighborMvIBC( tmpCU->mv[0][0], mvPred, nbPred );
1607
0
    }
1608
198k
  }
1609
1610
23.1k
  size_t numAvaiCandInLUT = cu.cs->motionLut.lutIbc.size();
1611
23.1k
  for( uint32_t cand = 0; cand < numAvaiCandInLUT && nbPred < IBC_NUM_CANDIDATES; cand++ )
1612
0
  {
1613
0
    auto& neibMi = cu.cs->motionLut.lutIbc;
1614
0
    isAddNeighborMvIBC( neibMi[cand].mv[0], mvPred, nbPred );
1615
0
  }
1616
1617
23.1k
  bool isBvCandDerived[IBC_NUM_CANDIDATES];
1618
23.1k
  ::memset(isBvCandDerived, false, IBC_NUM_CANDIDATES);
1619
1620
23.1k
  int curNbPred = nbPred;
1621
23.1k
  if( curNbPred < IBC_NUM_CANDIDATES )
1622
23.1k
  {
1623
23.1k
    do
1624
23.1k
    {
1625
23.1k
      curNbPred = nbPred;
1626
23.1k
      for( uint32_t idx = 0; idx < curNbPred && nbPred < IBC_NUM_CANDIDATES; idx++ )
1627
0
      {
1628
0
        if( !isBvCandDerived[idx] )
1629
0
        {
1630
0
          Mv derivedMv;
1631
0
          if( getDerivedMvIbc( cu, mvPred[idx], derivedMv ) )
1632
0
          {
1633
0
            isAddNeighborMvIBC( derivedMv, mvPred, nbPred );
1634
0
          }
1635
0
          isBvCandDerived[idx] = true;
1636
0
        }
1637
0
      }
1638
23.1k
    } while( nbPred > curNbPred && nbPred < IBC_NUM_CANDIDATES );
1639
23.1k
  }
1640
23.1k
}
1641
1642
void CU::fillIBCMvpCand(CodingUnit& cu, AMVPInfo& amvpInfo)
1643
46.2k
{
1644
46.2k
  AMVPInfo* pInfo = &amvpInfo;
1645
1646
46.2k
  pInfo->numCand = 0;
1647
1648
46.2k
  MergeCtx mergeCtx;
1649
46.2k
  CU::getIBCMergeCandidates(cu, mergeCtx, AMVP_MAX_NUM_CANDS - 1);
1650
46.2k
  int candIdx = 0;
1651
138k
  while (pInfo->numCand < AMVP_MAX_NUM_CANDS)
1652
92.4k
  {
1653
92.4k
    pInfo->mvCand[pInfo->numCand] = mergeCtx.mvFieldNeighbours[candIdx][0].mv;;
1654
92.4k
    pInfo->numCand++;
1655
92.4k
    candIdx++;
1656
92.4k
  }
1657
1658
46.2k
  for (Mv& mv : pInfo->mvCand)
1659
138k
  {
1660
138k
    mv.roundIbcPrecInternal2Amvr(cu.imv);
1661
138k
  }
1662
46.2k
}
1663
1664
bool CU::isDiffMER(const Position &pos1, const Position &pos2, const unsigned plevel)
1665
0
{
1666
0
  const unsigned xN = pos1.x;
1667
0
  const unsigned yN = pos1.y;
1668
0
  const unsigned xP = pos2.x;
1669
0
  const unsigned yP = pos2.y;
1670
1671
0
  if ((xN >> plevel) != (xP >> plevel))
1672
0
  {
1673
0
    return true;
1674
0
  }
1675
1676
0
  if ((yN >> plevel) != (yP >> plevel))
1677
0
  {
1678
0
    return true;
1679
0
  }
1680
1681
0
  return false;
1682
0
}
1683
1684
1685
/** Constructs a list of candidates for AMVP (See specification, section "Derivation process for motion vector predictor candidates")
1686
* \param uiPartIdx
1687
* \param uiPartAddr
1688
* \param refPicList
1689
* \param iRefIdx
1690
* \param pInfo
1691
*/
1692
void CU::fillMvpCand(CodingUnit& cu, const RefPicList refPicList, const int refIdx, AMVPInfo &amvpInfo)
1693
0
{
1694
0
  CodingStructure &cs = *cu.cs;
1695
1696
0
  AMVPInfo *pInfo = &amvpInfo;
1697
1698
0
  pInfo->numCand = 0;
1699
1700
0
  if (refIdx < 0)
1701
0
  {
1702
0
    return;
1703
0
  }
1704
1705
  //-- Get Spatial MV
1706
0
  Position posLT = cu.Y().topLeft();
1707
0
  Position posRT = cu.Y().topRight();
1708
0
  Position posLB = cu.Y().bottomLeft();
1709
1710
0
  {
1711
0
    bool bAdded = addMVPCandUnscaled( cu, refPicList, refIdx, posLB, MD_BELOW_LEFT, *pInfo );
1712
1713
0
    if( !bAdded )
1714
0
    {
1715
0
      bAdded = addMVPCandUnscaled( cu, refPicList, refIdx, posLB, MD_LEFT, *pInfo );
1716
1717
0
    }
1718
0
  }
1719
1720
  // Above predictor search
1721
0
  {
1722
0
    bool bAdded = addMVPCandUnscaled( cu, refPicList, refIdx, posRT, MD_ABOVE_RIGHT, *pInfo );
1723
1724
0
    if( !bAdded )
1725
0
    {
1726
0
      bAdded = addMVPCandUnscaled( cu, refPicList, refIdx, posRT, MD_ABOVE, *pInfo );
1727
1728
0
      if( !bAdded )
1729
0
      {
1730
0
        addMVPCandUnscaled( cu, refPicList, refIdx, posLT, MD_ABOVE_LEFT, *pInfo );
1731
0
      }
1732
0
    }
1733
0
  }
1734
1735
1736
0
  for( int i = 0; i < pInfo->numCand; i++ )
1737
0
  {
1738
0
    pInfo->mvCand[i].roundTransPrecInternal2Amvr(cu.imv);
1739
0
  }
1740
1741
0
  if( pInfo->numCand == 2 )
1742
0
  {
1743
0
    if( pInfo->mvCand[0] == pInfo->mvCand[1] )
1744
0
    {
1745
0
      pInfo->numCand = 1;
1746
0
    }
1747
0
  }
1748
1749
0
  if (cs.picHeader->enableTMVP && pInfo->numCand < AMVP_MAX_NUM_CANDS && (cu.lumaSize().width + cu.lumaSize().height > 12))
1750
0
  {
1751
    // Get Temporal Motion Predictor
1752
0
    const int refIdx_Col = refIdx;
1753
1754
0
    Position posRB = cu.Y().bottomRight().offset(-3, -3);
1755
1756
0
    const PreCalcValues& pcv = *cs.pcv;
1757
1758
0
    Position posC0;
1759
0
    bool C0Avail = false;
1760
0
    Position posC1 = cu.Y().center();
1761
0
    Mv cColMv;
1762
1763
0
    bool boundaryCond = ((posRB.x + pcv.minCUSize) < pcv.lumaWidth) && ((posRB.y + pcv.minCUSize) < pcv.lumaHeight);
1764
0
    const SubPic& curSubPic = cu.cs->slice->pps->getSubPicFromPos(cu.lumaPos());
1765
0
    if (curSubPic.treatedAsPic)
1766
0
    {
1767
0
      boundaryCond = ((posRB.x + pcv.minCUSize) <= curSubPic.subPicRight &&
1768
0
                      (posRB.y + pcv.minCUSize) <= curSubPic.subPicBottom);
1769
0
    }    
1770
0
    if (boundaryCond)
1771
0
    {
1772
0
      int posYInCtu = posRB.y & pcv.maxCUSizeMask;
1773
0
      if (posYInCtu + 4 < pcv.maxCUSize)
1774
0
      {
1775
0
        posC0 = posRB.offset(4, 4);
1776
0
        C0Avail = true;
1777
0
      }
1778
0
    }
1779
0
    if ( ( C0Avail && getColocatedMVP( cu, refPicList, posC0, cColMv, refIdx_Col ) ) || getColocatedMVP( cu, refPicList, posC1, cColMv, refIdx_Col ) )
1780
0
    {
1781
0
      cColMv.roundTransPrecInternal2Amvr(cu.imv);
1782
0
      pInfo->mvCand[pInfo->numCand++] = cColMv;
1783
0
    }
1784
0
  }
1785
1786
0
  if (pInfo->numCand < AMVP_MAX_NUM_CANDS)
1787
0
  {
1788
0
    const int        currRefPOC = cs.slice->getRefPic(refPicList, refIdx)->getPOC();
1789
0
    addAMVPHMVPCand(cu, refPicList, currRefPOC, *pInfo);
1790
0
  }
1791
1792
0
  if (pInfo->numCand > AMVP_MAX_NUM_CANDS)
1793
0
  {
1794
0
    pInfo->numCand = AMVP_MAX_NUM_CANDS;
1795
0
  }
1796
1797
0
  while (pInfo->numCand < AMVP_MAX_NUM_CANDS)
1798
0
  {
1799
0
    pInfo->mvCand[pInfo->numCand] = Mv( 0, 0 );
1800
0
    pInfo->numCand++;
1801
0
  }
1802
1803
0
  for (Mv &mv : pInfo->mvCand)
1804
0
  {
1805
0
    mv.roundTransPrecInternal2Amvr(cu.imv);
1806
0
  }
1807
0
}
1808
1809
bool CU::addAffineMVPCandUnscaled(const CodingUnit& cu, const RefPicList refPicList, const int refIdx, const Position& pos, const MvpDir dir, AffineAMVPInfo &affiAMVPInfo)
1810
0
{
1811
0
  CodingStructure &cs = *cu.cs;
1812
0
  const CodingUnit* neibPU = NULL;
1813
0
  Position neibPos;
1814
1815
0
  switch (dir)
1816
0
  {
1817
0
  case MD_LEFT:
1818
0
    neibPos = pos.offset(-1, 0);
1819
0
    break;
1820
0
  case MD_ABOVE:
1821
0
    neibPos = pos.offset(0, -1);
1822
0
    break;
1823
0
  case MD_ABOVE_RIGHT:
1824
0
    neibPos = pos.offset(1, -1);
1825
0
    break;
1826
0
  case MD_BELOW_LEFT:
1827
0
    neibPos = pos.offset(-1, 1);
1828
0
    break;
1829
0
  case MD_ABOVE_LEFT:
1830
0
    neibPos = pos.offset(-1, -1);
1831
0
    break;
1832
0
  default:
1833
0
    break;
1834
0
  }
1835
1836
0
  neibPU = cs.getCURestricted(neibPos, cu, cu.chType);
1837
1838
0
  if (neibPU == NULL || !CU::isInter(*neibPU) || !neibPU->affine
1839
0
    || neibPU->mergeType != MRG_TYPE_DEFAULT_N
1840
0
    )
1841
0
  {
1842
0
    return false;
1843
0
  }
1844
1845
0
  Mv outputAffineMv[3];
1846
0
  const MotionInfo& neibMi = neibPU->getMotionInfo(neibPos);
1847
1848
0
  const int        currRefPOC = cs.slice->getRefPic(refPicList, refIdx)->getPOC();
1849
0
  const RefPicList refPicList2nd = (refPicList == REF_PIC_LIST_0) ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
1850
1851
0
  for (int predictorSource = 0; predictorSource < 2; predictorSource++) // examine the indicated reference picture list, then if not available, examine the other list.
1852
0
  {
1853
0
    const RefPicList refPicListIndex = (predictorSource == 0) ? refPicList : refPicList2nd;
1854
0
    const int        neibRefIdx = neibMi.miRefIdx[refPicListIndex];
1855
1856
0
    if (((neibPU->interDir & (refPicListIndex + 1)) == 0) || cu.slice->getRefPOC(refPicListIndex, neibRefIdx) != currRefPOC)
1857
0
    {
1858
0
      continue;
1859
0
    }
1860
1861
0
    xInheritedAffineMv(cu, neibPU, refPicListIndex, outputAffineMv);
1862
0
    outputAffineMv[0].roundAffinePrecInternal2Amvr(cu.imv);
1863
0
    outputAffineMv[1].roundAffinePrecInternal2Amvr(cu.imv);
1864
0
    affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[0];
1865
0
    affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[1];
1866
0
    if (cu.affineType == AFFINEMODEL_6PARAM)
1867
0
    {
1868
0
      outputAffineMv[2].roundAffinePrecInternal2Amvr(cu.imv);
1869
0
      affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[2];
1870
0
    }
1871
0
    affiAMVPInfo.numCand++;
1872
0
    return true;
1873
0
  }
1874
1875
0
  return false;
1876
0
}
1877
1878
void CU::xInheritedAffineMv(const CodingUnit& cu, const CodingUnit* cuNeighbour, RefPicList refPicList, Mv rcMv[3])
1879
0
{
1880
0
  int posNeiX = cuNeighbour->Y().pos().x;
1881
0
  int posNeiY = cuNeighbour->Y().pos().y;
1882
0
  int posCurX = cu.Y().pos().x;
1883
0
  int posCurY = cu.Y().pos().y;
1884
1885
0
  int neiW = cuNeighbour->Y().width;
1886
0
  int curW = cu.Y().width;
1887
0
  int neiH = cuNeighbour->Y().height;
1888
0
  int curH = cu.Y().height;
1889
1890
0
  Mv mvLT, mvRT, mvLB;
1891
0
  mvLT = cuNeighbour->mv[refPicList][0];
1892
0
  mvRT = cuNeighbour->mv[refPicList][1];
1893
0
  mvLB = cuNeighbour->mv[refPicList][2];
1894
1895
0
  bool isTopCtuBoundary = false;
1896
0
  if ((posNeiY + neiH) % cu.cs->sps->CTUSize == 0 && (posNeiY + neiH) == posCurY)
1897
0
  {
1898
    // use bottom-left and bottom-right sub-block MVs for inheritance
1899
0
    const Position posRB = cuNeighbour->Y().bottomRight();
1900
0
    const Position posLB = cuNeighbour->Y().bottomLeft();
1901
0
    mvLT = cuNeighbour->getMotionInfo(posLB).mv[refPicList];
1902
0
    mvRT = cuNeighbour->getMotionInfo(posRB).mv[refPicList];
1903
0
    posNeiY += neiH;
1904
0
    isTopCtuBoundary = true;
1905
0
  }
1906
1907
0
  int shift = MAX_CU_DEPTH;
1908
0
  int iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY;
1909
1910
0
  iDMvHorX = (mvRT - mvLT).hor * (1<< (shift - Log2(neiW)));
1911
0
  iDMvHorY = (mvRT - mvLT).ver * (1<< (shift - Log2(neiW)));
1912
0
  if (cuNeighbour->affineType == AFFINEMODEL_6PARAM && !isTopCtuBoundary)
1913
0
  {
1914
0
    iDMvVerX = (mvLB - mvLT).hor * (1<< (shift - Log2(neiH)));
1915
0
    iDMvVerY = (mvLB - mvLT).ver * (1<< (shift - Log2(neiH)));
1916
0
  }
1917
0
  else
1918
0
  {
1919
0
    iDMvVerX = -iDMvHorY;
1920
0
    iDMvVerY = iDMvHorX;
1921
0
  }
1922
1923
0
  int iMvScaleHor = mvLT.hor * (1<< shift);
1924
0
  int iMvScaleVer = mvLT.ver * (1<< shift);
1925
0
  int horTmp, verTmp;
1926
1927
  // v0
1928
0
  horTmp = iMvScaleHor + iDMvHorX * (posCurX - posNeiX) + iDMvVerX * (posCurY - posNeiY);
1929
0
  verTmp = iMvScaleVer + iDMvHorY * (posCurX - posNeiX) + iDMvVerY * (posCurY - posNeiY);
1930
0
  roundAffineMv(horTmp, verTmp, shift);
1931
0
  rcMv[0].hor = horTmp;
1932
0
  rcMv[0].ver = verTmp;
1933
0
  rcMv[0].clipToStorageBitDepth();
1934
1935
  // v1
1936
0
  horTmp = iMvScaleHor + iDMvHorX * (posCurX + curW - posNeiX) + iDMvVerX * (posCurY - posNeiY);
1937
0
  verTmp = iMvScaleVer + iDMvHorY * (posCurX + curW - posNeiX) + iDMvVerY * (posCurY - posNeiY);
1938
0
  roundAffineMv(horTmp, verTmp, shift);
1939
0
  rcMv[1].hor = horTmp;
1940
0
  rcMv[1].ver = verTmp;
1941
0
  rcMv[1].clipToStorageBitDepth();
1942
1943
  // v2
1944
0
  if (cu.affineType == AFFINEMODEL_6PARAM)
1945
0
  {
1946
0
    horTmp = iMvScaleHor + iDMvHorX * (posCurX - posNeiX) + iDMvVerX * (posCurY + curH - posNeiY);
1947
0
    verTmp = iMvScaleVer + iDMvHorY * (posCurX - posNeiX) + iDMvVerY * (posCurY + curH - posNeiY);
1948
0
    roundAffineMv(horTmp, verTmp, shift);
1949
0
    rcMv[2].hor = horTmp;
1950
0
    rcMv[2].ver = verTmp;
1951
0
    rcMv[2].clipToStorageBitDepth();
1952
0
  }
1953
0
}
1954
1955
void CU::fillAffineMvpCand(CodingUnit& cu, const RefPicList refPicList, const int refIdx, AffineAMVPInfo &affiAMVPInfo)
1956
0
{
1957
0
  affiAMVPInfo.numCand = 0;
1958
1959
0
  if (refIdx < 0)
1960
0
  {
1961
0
    return;
1962
0
  }
1963
1964
  // insert inherited affine candidates
1965
0
  Mv outputAffineMv[3];
1966
0
  Position posLT = cu.Y().topLeft();
1967
0
  Position posRT = cu.Y().topRight();
1968
0
  Position posLB = cu.Y().bottomLeft();
1969
1970
  // check left neighbor
1971
0
  if (!addAffineMVPCandUnscaled(cu, refPicList, refIdx, posLB, MD_BELOW_LEFT, affiAMVPInfo))
1972
0
  {
1973
0
    addAffineMVPCandUnscaled(cu, refPicList, refIdx, posLB, MD_LEFT, affiAMVPInfo);
1974
0
  }
1975
1976
  // check above neighbor
1977
0
  if (!addAffineMVPCandUnscaled(cu, refPicList, refIdx, posRT, MD_ABOVE_RIGHT, affiAMVPInfo))
1978
0
  {
1979
0
    if (!addAffineMVPCandUnscaled(cu, refPicList, refIdx, posRT, MD_ABOVE, affiAMVPInfo))
1980
0
    {
1981
0
      addAffineMVPCandUnscaled(cu, refPicList, refIdx, posLT, MD_ABOVE_LEFT, affiAMVPInfo);
1982
0
    }
1983
0
  }
1984
1985
0
  if (affiAMVPInfo.numCand >= AMVP_MAX_NUM_CANDS)
1986
0
  {
1987
0
    for (int i = 0; i < affiAMVPInfo.numCand; i++)
1988
0
    {
1989
0
      affiAMVPInfo.mvCandLT[i].roundAffinePrecInternal2Amvr(cu.imv);
1990
0
      affiAMVPInfo.mvCandRT[i].roundAffinePrecInternal2Amvr(cu.imv);
1991
0
      affiAMVPInfo.mvCandLB[i].roundAffinePrecInternal2Amvr(cu.imv);
1992
0
    }
1993
0
    return;
1994
0
  }
1995
1996
  // insert constructed affine candidates
1997
0
  int cornerMVPattern = 0;
1998
1999
  //-------------------  V0 (START) -------------------//
2000
0
  AMVPInfo amvpInfo0;
2001
0
  amvpInfo0.numCand = 0;
2002
2003
  // A->C: Above Left, Above, Left
2004
0
  addMVPCandUnscaled(cu, refPicList, refIdx, posLT, MD_ABOVE_LEFT, amvpInfo0);
2005
0
  if (amvpInfo0.numCand < 1)
2006
0
  {
2007
0
    addMVPCandUnscaled(cu, refPicList, refIdx, posLT, MD_ABOVE, amvpInfo0);
2008
0
  }
2009
0
  if (amvpInfo0.numCand < 1)
2010
0
  {
2011
0
    addMVPCandUnscaled(cu, refPicList, refIdx, posLT, MD_LEFT, amvpInfo0);
2012
0
  }
2013
0
  cornerMVPattern = cornerMVPattern | amvpInfo0.numCand;
2014
2015
  //-------------------  V1 (START) -------------------//
2016
0
  AMVPInfo amvpInfo1;
2017
0
  amvpInfo1.numCand = 0;
2018
2019
  // D->E: Above, Above Right
2020
0
  addMVPCandUnscaled(cu, refPicList, refIdx, posRT, MD_ABOVE, amvpInfo1);
2021
0
  if (amvpInfo1.numCand < 1)
2022
0
  {
2023
0
    addMVPCandUnscaled(cu, refPicList, refIdx, posRT, MD_ABOVE_RIGHT, amvpInfo1);
2024
0
  }
2025
0
  cornerMVPattern = cornerMVPattern | (amvpInfo1.numCand << 1);
2026
2027
  //-------------------  V2 (START) -------------------//
2028
0
  AMVPInfo amvpInfo2;
2029
0
  amvpInfo2.numCand = 0;
2030
2031
  // F->G: Left, Below Left
2032
0
  addMVPCandUnscaled(cu, refPicList, refIdx, posLB, MD_LEFT, amvpInfo2);
2033
0
  if (amvpInfo2.numCand < 1)
2034
0
  {
2035
0
    addMVPCandUnscaled(cu, refPicList, refIdx, posLB, MD_BELOW_LEFT, amvpInfo2);
2036
0
  }
2037
0
  cornerMVPattern = cornerMVPattern | (amvpInfo2.numCand << 2);
2038
2039
0
  outputAffineMv[0] = amvpInfo0.mvCand[0];
2040
0
  outputAffineMv[1] = amvpInfo1.mvCand[0];
2041
0
  outputAffineMv[2] = amvpInfo2.mvCand[0];
2042
2043
0
  outputAffineMv[0].roundAffinePrecInternal2Amvr(cu.imv);
2044
0
  outputAffineMv[1].roundAffinePrecInternal2Amvr(cu.imv);
2045
0
  outputAffineMv[2].roundAffinePrecInternal2Amvr(cu.imv);
2046
2047
0
  if (cornerMVPattern == 7 || (cornerMVPattern == 3 && cu.affineType == AFFINEMODEL_4PARAM))
2048
0
  {
2049
0
    affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[0];
2050
0
    affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[1];
2051
0
    affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[2];
2052
0
    affiAMVPInfo.numCand++;
2053
0
  }
2054
2055
0
  if (affiAMVPInfo.numCand < 2)
2056
0
  {
2057
    // check corner MVs
2058
0
    for (int i = 2; i >= 0 && affiAMVPInfo.numCand < AMVP_MAX_NUM_CANDS; i--)
2059
0
    {
2060
0
      if (cornerMVPattern & (1 << i)) // MV i exist
2061
0
      {
2062
0
        affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[i];
2063
0
        affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[i];
2064
0
        affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[i];
2065
0
        affiAMVPInfo.numCand++;
2066
0
      }
2067
0
    }
2068
2069
    // Get Temporal Motion Predictor
2070
0
    if (affiAMVPInfo.numCand < 2 && cu.cs->picHeader->enableTMVP)
2071
0
    {
2072
0
      const int refIdxCol = refIdx;
2073
2074
0
      Position posRB = cu.Y().bottomRight().offset(-3, -3);
2075
2076
0
      const PreCalcValues& pcv = *cu.cs->pcv;
2077
2078
0
      Position posC0;
2079
0
      bool C0Avail = false;
2080
0
      Position posC1 = cu.Y().center();
2081
0
      Mv cColMv;
2082
0
      bool boundaryCond = ((posRB.x + pcv.minCUSize) < pcv.lumaWidth) && ((posRB.y + pcv.minCUSize) < pcv.lumaHeight);
2083
0
      const SubPic& curSubPic = cu.cs->slice->pps->getSubPicFromPos(cu.lumaPos());
2084
0
      if (curSubPic.treatedAsPic)
2085
0
      {
2086
0
        boundaryCond = ((posRB.x + pcv.minCUSize) <= curSubPic.subPicRight &&
2087
0
          (posRB.y + pcv.minCUSize) <= curSubPic.subPicBottom);
2088
0
      }
2089
0
      if (boundaryCond)
2090
0
      {
2091
0
        int posYInCtu = posRB.y & pcv.maxCUSizeMask;
2092
0
        if (posYInCtu + 4 < pcv.maxCUSize)
2093
0
        {
2094
0
          posC0 = posRB.offset(4, 4);
2095
0
          C0Avail = true;
2096
0
        }
2097
0
      }
2098
0
      if ((C0Avail && getColocatedMVP(cu, refPicList, posC0, cColMv, refIdxCol)) || getColocatedMVP(cu, refPicList, posC1, cColMv, refIdxCol))
2099
0
      {
2100
0
        cColMv.roundAffinePrecInternal2Amvr(cu.imv);
2101
0
        affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = cColMv;
2102
0
        affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = cColMv;
2103
0
        affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = cColMv;
2104
0
        affiAMVPInfo.numCand++;
2105
0
      }
2106
0
    }
2107
2108
0
    if (affiAMVPInfo.numCand < 2)
2109
0
    {
2110
      // add zero MV
2111
0
      for (int i = affiAMVPInfo.numCand; i < AMVP_MAX_NUM_CANDS; i++)
2112
0
      {
2113
0
        affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand].setZero();
2114
0
        affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand].setZero();
2115
0
        affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand].setZero();
2116
0
        affiAMVPInfo.numCand++;
2117
0
      }
2118
0
    }
2119
0
  }
2120
2121
0
  for (int i = 0; i < affiAMVPInfo.numCand; i++)
2122
0
  {
2123
0
    affiAMVPInfo.mvCandLT[i].roundAffinePrecInternal2Amvr(cu.imv);
2124
0
    affiAMVPInfo.mvCandRT[i].roundAffinePrecInternal2Amvr(cu.imv);
2125
0
    affiAMVPInfo.mvCandLB[i].roundAffinePrecInternal2Amvr(cu.imv);
2126
0
  }
2127
0
}
2128
2129
bool CU::addMVPCandUnscaled( const CodingUnit& cu, const RefPicList refPicList, const int iRefIdx, const Position& pos, const MvpDir dir, AMVPInfo &info )
2130
0
{
2131
0
        CodingStructure &cs    = *cu.cs;
2132
0
  const CodingUnit* neibPU = NULL;
2133
0
        Position neibPos;
2134
2135
0
  switch (dir)
2136
0
  {
2137
0
  case MD_LEFT:
2138
0
    neibPos = pos.offset( -1,  0 );
2139
0
    break;
2140
0
  case MD_ABOVE:
2141
0
    neibPos = pos.offset(  0, -1 );
2142
0
    break;
2143
0
  case MD_ABOVE_RIGHT:
2144
0
    neibPos = pos.offset(  1, -1 );
2145
0
    break;
2146
0
  case MD_BELOW_LEFT:
2147
0
    neibPos = pos.offset( -1,  1 );
2148
0
    break;
2149
0
  case MD_ABOVE_LEFT:
2150
0
    neibPos = pos.offset( -1, -1 );
2151
0
    break;
2152
0
  default:
2153
0
    break;
2154
0
  }
2155
2156
0
  neibPU = cs.getCURestricted( neibPos, cu, cu.chType );
2157
2158
0
  if( neibPU == NULL || !CU::isInter( *neibPU ) )
2159
0
  {
2160
0
    return false;
2161
0
  }
2162
2163
0
  const MotionInfo& neibMi        = neibPU->getMotionInfo( neibPos );
2164
2165
0
  const int        currRefPOC     = cs.slice->getRefPic( refPicList, iRefIdx )->getPOC();
2166
0
  const RefPicList refPicList2nd = ( refPicList == REF_PIC_LIST_0 ) ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
2167
2168
0
  for( int predictorSource = 0; predictorSource < 2; predictorSource++ ) // examine the indicated reference picture list, then if not available, examine the other list.
2169
0
  {
2170
0
    const RefPicList refPicListIndex = ( predictorSource == 0 ) ? refPicList : refPicList2nd;
2171
0
    const int        neibRefIdx       = neibMi.miRefIdx[refPicListIndex];
2172
2173
0
    if( neibRefIdx >= 0 && currRefPOC == cs.slice->getRefPOC( refPicListIndex, neibRefIdx ) )
2174
0
    {
2175
0
      info.mvCand[info.numCand++] = neibMi.mv[refPicListIndex];
2176
0
      return true;
2177
0
    }
2178
0
  }
2179
2180
0
  return false;
2181
0
}
2182
2183
2184
void CU::addAMVPHMVPCand(const CodingUnit& cu, const RefPicList refPicList, const int currRefPOC, AMVPInfo &info)
2185
0
{
2186
0
  const Slice &slice = *(*cu.cs).slice;
2187
0
  auto& lut = CU::isIBC(cu) ? cu.cs->motionLut.lutIbc : cu.cs->motionLut.lut;
2188
0
  int num_avai_candInLUT = (int) lut.size();
2189
0
  int num_allowedCand = std::min(MAX_NUM_HMVP_AVMPCANDS, num_avai_candInLUT);
2190
0
  const RefPicList refPicList2nd = (refPicList == REF_PIC_LIST_0) ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
2191
2192
0
  for (int mrgIdx = 1; mrgIdx <= num_allowedCand; mrgIdx++)
2193
0
  {
2194
0
    if (info.numCand >= AMVP_MAX_NUM_CANDS)
2195
0
    {
2196
0
      return;
2197
0
    }
2198
0
    const HPMVInfo& neibMi = lut[mrgIdx - 1];
2199
2200
0
    for (int predictorSource = 0; predictorSource < 2; predictorSource++)
2201
0
    {
2202
0
      const RefPicList refPicListIndex = (predictorSource == 0) ? refPicList : refPicList2nd;
2203
0
      const int        neibRefIdx = neibMi.mhRefIdx[refPicListIndex];
2204
2205
0
      if (neibRefIdx != MH_NOT_VALID && (CU::isIBC(cu) || (currRefPOC == slice.getRefPOC(refPicListIndex, neibRefIdx))))
2206
0
      {
2207
0
        Mv pmv = neibMi.mv[refPicListIndex];
2208
0
        pmv.roundTransPrecInternal2Amvr(cu.imv);
2209
2210
0
        info.mvCand[info.numCand++] = pmv;
2211
0
        if (info.numCand >= AMVP_MAX_NUM_CANDS)
2212
0
        {
2213
0
          return;
2214
0
        }
2215
0
      }
2216
0
    }
2217
0
  }
2218
0
}
2219
2220
bool CU::isBipredRestriction(const CodingUnit& cu)
2221
138k
{
2222
138k
  if(cu.lumaSize().width == 4 && cu.lumaSize().height ==4 )
2223
0
  {
2224
0
    return true;
2225
0
  }
2226
  /* disable bi-prediction for 4x8/8x4 */
2227
138k
  if ( cu.lumaSize().width + cu.lumaSize().height == 12 )
2228
0
  {
2229
0
    return true;
2230
0
  }
2231
138k
  return false;
2232
138k
}
2233
2234
void CU::getAffineControlPointCand(const CodingUnit& cu, MotionInfo mi[4], bool isAvailable[4], int verIdx[4], int8_t BcwIdx, int modelIdx, int verNum, AffineMergeCtx& affMrgType)
2235
0
{
2236
0
  int cuW = cu.Y().width;
2237
0
  int cuH = cu.Y().height;
2238
0
  int vx, vy;
2239
0
  int shift = MAX_CU_DEPTH;
2240
0
  int shiftHtoW = shift + Log2(cuW) - Log2(cuH);
2241
2242
  // motion info
2243
0
  Mv cMv[2][4];
2244
0
  int refIdx[2] = { -1, -1 };
2245
0
  int dir = 0;
2246
0
  EAffineModel curType = (verNum == 2) ? AFFINEMODEL_4PARAM : AFFINEMODEL_6PARAM;
2247
2248
0
  if (verNum == 2)
2249
0
  {
2250
0
    int idx0 = verIdx[0], idx1 = verIdx[1];
2251
0
    if (!isAvailable[idx0] || !isAvailable[idx1])
2252
0
    {
2253
0
      return;
2254
0
    }
2255
2256
0
    for (int l = 0; l < 2; l++)
2257
0
    {
2258
0
      if (mi[idx0].miRefIdx[l] != MI_NOT_VALID && mi[idx1].miRefIdx[l] != MI_NOT_VALID)
2259
0
      {
2260
        // check same refidx and different mv
2261
0
        if (mi[idx0].miRefIdx[l] == mi[idx1].miRefIdx[l])
2262
0
        {
2263
0
          dir |= (l + 1);
2264
0
          refIdx[l] = mi[idx0].miRefIdx[l];
2265
0
        }
2266
0
      }
2267
0
    }
2268
0
  }
2269
0
  else if (verNum == 3)
2270
0
  {
2271
0
    int idx0 = verIdx[0], idx1 = verIdx[1], idx2 = verIdx[2];
2272
0
    if (!isAvailable[idx0] || !isAvailable[idx1] || !isAvailable[idx2])
2273
0
    {
2274
0
      return;
2275
0
    }
2276
2277
0
    for (int l = 0; l < 2; l++)
2278
0
    {
2279
0
      if (mi[idx0].miRefIdx[l] != MI_NOT_VALID && mi[idx1].miRefIdx[l] != MI_NOT_VALID && mi[idx2].miRefIdx[l] != MI_NOT_VALID)
2280
0
      {
2281
        // check same refidx and different mv
2282
0
        if (mi[idx0].miRefIdx[l] == mi[idx1].miRefIdx[l] && mi[idx0].miRefIdx[l] == mi[idx2].miRefIdx[l])
2283
0
        {
2284
0
          dir |= (l + 1);
2285
0
          refIdx[l] = mi[idx0].miRefIdx[l];
2286
0
        }
2287
0
      }
2288
0
      }
2289
0
    }
2290
2291
0
  if (dir == 0)
2292
0
  {
2293
0
    return;
2294
0
  }
2295
2296
2297
0
  for (int l = 0; l < 2; l++)
2298
0
  {
2299
0
    if (dir & (l + 1))
2300
0
    {
2301
0
      for (int i = 0; i < verNum; i++)
2302
0
      {
2303
0
        cMv[l][verIdx[i]] = mi[verIdx[i]].mv[l];
2304
0
      }
2305
2306
      // convert to LT, RT[, [LB]]
2307
0
      switch (modelIdx)
2308
0
      {
2309
0
      case 0: // 0 : LT, RT, LB
2310
0
        break;
2311
2312
0
      case 1: // 1 : LT, RT, RB
2313
0
        cMv[l][2].hor = cMv[l][3].hor + cMv[l][0].hor - cMv[l][1].hor;
2314
0
        cMv[l][2].ver = cMv[l][3].ver + cMv[l][0].ver - cMv[l][1].ver;
2315
0
        cMv[l][2].clipToStorageBitDepth();
2316
0
        break;
2317
2318
0
      case 2: // 2 : LT, LB, RB
2319
0
        cMv[l][1].hor = cMv[l][3].hor + cMv[l][0].hor - cMv[l][2].hor;
2320
0
        cMv[l][1].ver = cMv[l][3].ver + cMv[l][0].ver - cMv[l][2].ver;
2321
0
        cMv[l][1].clipToStorageBitDepth();
2322
0
        break;
2323
2324
0
      case 3: // 3 : RT, LB, RB
2325
0
        cMv[l][0].hor = cMv[l][1].hor + cMv[l][2].hor - cMv[l][3].hor;
2326
0
        cMv[l][0].ver = cMv[l][1].ver + cMv[l][2].ver - cMv[l][3].ver;
2327
0
        cMv[l][0].clipToStorageBitDepth();
2328
0
        break;
2329
2330
0
      case 4: // 4 : LT, RT
2331
0
        break;
2332
2333
0
      case 5: // 5 : LT, LB
2334
0
        vx = (cMv[l][0].hor *(1<< shift)) + ((cMv[l][2].ver - cMv[l][0].ver) * (1<< shiftHtoW));
2335
0
        vy = (cMv[l][0].ver *(1<< shift)) - ((cMv[l][2].hor - cMv[l][0].hor) * (1<< shiftHtoW));
2336
0
        roundAffineMv(vx, vy, shift);
2337
0
        cMv[l][1].set(vx, vy);
2338
0
        cMv[l][1].clipToStorageBitDepth();
2339
0
        break;
2340
2341
0
      default:
2342
0
        CHECK(1, "Invalid model index!\n");
2343
0
        break;
2344
0
      }
2345
0
    }
2346
0
    else
2347
0
    {
2348
0
      for (int i = 0; i < 4; i++)
2349
0
      {
2350
0
        cMv[l][i].hor = 0;
2351
0
        cMv[l][i].ver = 0;
2352
0
      }
2353
0
    }
2354
0
  }
2355
2356
0
  for (int i = 0; i < 3; i++)
2357
0
  {
2358
0
    affMrgType.mvFieldNeighbours[affMrgType.numValidMergeCand][0][i].mv     = cMv[0][i];
2359
0
    affMrgType.mvFieldNeighbours[affMrgType.numValidMergeCand][0][i].refIdx = refIdx[0];
2360
2361
0
    affMrgType.mvFieldNeighbours[affMrgType.numValidMergeCand][1][i].mv     = cMv[1][i];
2362
0
    affMrgType.mvFieldNeighbours[affMrgType.numValidMergeCand][1][i].refIdx = refIdx[1];
2363
0
  }
2364
0
  affMrgType.interDirNeighbours [affMrgType.numValidMergeCand]              = dir;
2365
0
  affMrgType.affineType         [affMrgType.numValidMergeCand]              = curType;
2366
0
  affMrgType.BcwIdx             [affMrgType.numValidMergeCand]              = dir == 3 ? BcwIdx : BCW_DEFAULT;
2367
0
  affMrgType.numValidMergeCand++;
2368
2369
2370
0
  return;
2371
0
}
2372
2373
2374
bool CU::getInterMergeSbTMVPCand(const CodingUnit& cu, AffineMergeCtx& mrgCtx, const int count)
2375
0
{
2376
0
  const Slice   &slice = *cu.cs->slice;
2377
0
  const unsigned scale = 4 * std::max<int>(1, 4 * AMVP_DECIMATION_FACTOR / 4);
2378
0
  const unsigned mask = ~(scale - 1);
2379
2380
0
  const Picture *pColPic = slice.getRefPic(RefPicList(slice.isInterB() ? 1 - slice.colFromL0Flag : 0), slice.colRefIdx);
2381
0
  Mv cTMv;
2382
2383
0
  if (count)
2384
0
  {
2385
0
    if ((mrgCtx.interDirNeighbours[0] & (1 << REF_PIC_LIST_0)) && slice.getRefPic(REF_PIC_LIST_0, mrgCtx.mvFieldNeighbours[0][REF_PIC_LIST_0][0].refIdx) == pColPic )
2386
0
    {
2387
0
      cTMv = mrgCtx.mvFieldNeighbours[0][REF_PIC_LIST_0][0].mv;
2388
0
    }
2389
0
    else if (slice.isInterB() && (mrgCtx.interDirNeighbours[0] & (1 << REF_PIC_LIST_1)) && slice.getRefPic(REF_PIC_LIST_1, mrgCtx.mvFieldNeighbours[0][REF_PIC_LIST_1][0].refIdx) == pColPic )
2390
0
    {
2391
0
      cTMv = mrgCtx.mvFieldNeighbours[0][REF_PIC_LIST_1][0].mv;
2392
0
    }
2393
0
  }
2394
2395
  ///////////////////////////////////////////////////////////////////////
2396
  ////////          GET Initial Temporal Vector                  ////////
2397
  ///////////////////////////////////////////////////////////////////////
2398
0
  Mv cTempVector = cTMv;
2399
2400
  // compute the location of the current PU
2401
0
  Position puPos = cu.lumaPos();
2402
0
  Size puSize = cu.lumaSize();
2403
0
  int numPartLine = std::max(puSize.width >> ATMVP_SUB_BLOCK_SIZE, 1u);
2404
0
  int numPartCol = std::max(puSize.height >> ATMVP_SUB_BLOCK_SIZE, 1u);
2405
0
  int puHeight = numPartCol == 1 ? puSize.height : 1 << ATMVP_SUB_BLOCK_SIZE;
2406
0
  int puWidth = numPartLine == 1 ? puSize.width : 1 << ATMVP_SUB_BLOCK_SIZE;
2407
2408
0
  Mv cColMv;
2409
0
  int refIdx = 0;
2410
  // use coldir.
2411
0
  bool     bBSlice = slice.isInterB();
2412
2413
0
  Position centerPos;
2414
2415
0
  bool found = false;
2416
0
  cTempVector = cTMv;
2417
2418
0
  cTempVector.changePrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT);
2419
0
  int tempX = cTempVector.hor;
2420
0
  int tempY = cTempVector.ver;
2421
2422
0
  centerPos.x = puPos.x + (puSize.width >> 1) + tempX;
2423
0
  centerPos.y = puPos.y + (puSize.height >> 1) + tempY;
2424
2425
0
  clipColPos(centerPos.x, centerPos.y, cu);
2426
2427
0
  centerPos = Position{ PosType(centerPos.x & mask), PosType(centerPos.y & mask) };
2428
2429
  // derivation of center motion parameters from the collocated CU
2430
0
  const MotionInfo &mi = pColPic->cs->getMotionInfo(centerPos);
2431
2432
0
  if (mi.isInter())
2433
0
  {
2434
0
    mrgCtx.interDirNeighbours[0] = 0;
2435
2436
0
    for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++)
2437
0
    {
2438
0
      RefPicList  currRefPicList = RefPicList(currRefListId);
2439
2440
0
      if (getColocatedMVP(cu, currRefPicList, centerPos, cColMv, refIdx, true))
2441
0
      {
2442
        // set as default, for further motion vector field spanning
2443
0
        mrgCtx.mvFieldNeighbours [0][currRefListId][0] . setMvField(cColMv, 0);
2444
0
        mrgCtx.interDirNeighbours[0]                  |= (1 << currRefListId);
2445
0
        mrgCtx.BcwIdx            [0]                   = BCW_DEFAULT;
2446
0
        found = true;
2447
0
      }
2448
0
      else
2449
0
      {
2450
0
        mrgCtx.mvFieldNeighbours [0][currRefListId][0] . setMvField(Mv(), NOT_VALID);
2451
0
        mrgCtx.interDirNeighbours[0]                  &= ~(1 << currRefListId);
2452
0
      }
2453
0
    }
2454
0
  }
2455
2456
0
  if (!found)
2457
0
  {
2458
0
    return false;
2459
0
  }
2460
2461
0
  int xOff = (puWidth >> 1) + tempX;
2462
0
  int yOff = (puHeight >> 1) + tempY;
2463
2464
0
  MotionBuf& mb = mrgCtx.subPuMvpMiBuf;
2465
2466
0
  const bool isBiPred = isBipredRestriction(cu);
2467
2468
0
  for (int y = puPos.y; y < puPos.y + puSize.height; y += puHeight)
2469
0
  {
2470
0
    for (int x = puPos.x; x < puPos.x + puSize.width; x += puWidth)
2471
0
    {
2472
0
      Position colPos{ x + xOff, y + yOff };
2473
2474
0
      clipColPos(colPos.x, colPos.y, cu);
2475
2476
0
      colPos = Position{ PosType(colPos.x & mask), PosType(colPos.y & mask) };
2477
2478
0
      const MotionInfo &colMi = pColPic->cs->getMotionInfo(colPos);
2479
2480
0
      MotionInfo mi;
2481
2482
0
      found = false;
2483
0
      if (colMi.isInter())
2484
0
      {
2485
0
        for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++)
2486
0
        {
2487
0
          RefPicList currRefPicList = RefPicList(currRefListId);
2488
0
          if (getColocatedMVP(cu, currRefPicList, colPos, cColMv, refIdx, true))
2489
0
          {
2490
0
            mi.miRefIdx[currRefListId] = 0;
2491
0
            mi.mv[currRefListId] = cColMv;
2492
0
            found = true;
2493
0
          }
2494
0
        }
2495
0
      }
2496
0
      if (!found)
2497
0
      {
2498
0
        mi.mv[0]       = mrgCtx.mvFieldNeighbours[0][0][0].mv;
2499
0
        mi.mv[1]       = mrgCtx.mvFieldNeighbours[0][1][0].mv;
2500
0
        mi.miRefIdx[0] = mrgCtx.mvFieldNeighbours[0][0][0].refIdx;
2501
0
        mi.miRefIdx[1] = mrgCtx.mvFieldNeighbours[0][1][0].refIdx;
2502
0
      }
2503
2504
0
      if (isBiPred && mi.interDir() == 3)
2505
0
      {
2506
0
        mi.mv[1]       = Mv();
2507
0
        mi.miRefIdx[1] = MI_NOT_VALID;
2508
0
      }
2509
2510
0
      mb.subBuf(g_miScaling.scale(Position{ x, y } -cu.lumaPos()), g_miScaling.scale(Size(puWidth, puHeight))).fill(mi);
2511
0
    }
2512
0
  }
2513
2514
0
  return true;
2515
0
}
2516
2517
2518
const int getAvailableAffineNeighboursForLeftPredictor(const CodingUnit& cu, const CodingUnit* npu[])
2519
0
{
2520
0
  const Position posLB = cu.Y().bottomLeft();
2521
0
  int num = 0;
2522
0
  const unsigned plevel = cu.cs->sps->log2ParallelMergeLevelMinus2 + 2;
2523
2524
0
  const CodingUnit* puLeftBottom = cu.cs->getCURestricted(posLB.offset(-1, 1), cu, cu.chType);
2525
0
  if (puLeftBottom && puLeftBottom->affine
2526
0
    && puLeftBottom->mergeType == MRG_TYPE_DEFAULT_N
2527
0
    && CU::isDiffMER(cu.lumaPos(), posLB.offset(-1, 1), plevel)
2528
0
    )
2529
0
  {
2530
0
    npu[num++] = puLeftBottom;
2531
0
    return num;
2532
0
  }
2533
2534
0
  const CodingUnit* puLeft = cu.cs->getCURestricted(posLB.offset(-1, 0), cu, cu.chType);
2535
0
  if (puLeft && puLeft->affine
2536
0
    && puLeft->mergeType == MRG_TYPE_DEFAULT_N
2537
0
    && CU::isDiffMER(cu.lumaPos(), posLB.offset(-1, 0), plevel)
2538
0
    )
2539
0
  {
2540
0
    npu[num++] = puLeft;
2541
0
    return num;
2542
0
  }
2543
2544
0
  return num;
2545
0
}
2546
2547
const int getAvailableAffineNeighboursForAbovePredictor(const CodingUnit& cu, const CodingUnit* npu[], int numAffNeighLeft)
2548
0
{
2549
0
  const Position posLT = cu.Y().topLeft();
2550
0
  const Position posRT = cu.Y().topRight();
2551
0
  const unsigned plevel = cu.cs->sps->log2ParallelMergeLevelMinus2 + 2;
2552
0
  int num = numAffNeighLeft;
2553
2554
0
  const CodingUnit* puAboveRight = cu.cs->getCURestricted(posRT.offset(1, -1), cu, cu.chType);
2555
0
  if (puAboveRight && puAboveRight->affine
2556
0
    && puAboveRight->mergeType == MRG_TYPE_DEFAULT_N
2557
0
    && CU::isDiffMER(cu.lumaPos(), posRT.offset(1, -1), plevel)
2558
0
    )
2559
0
  {
2560
0
    npu[num++] = puAboveRight;
2561
0
    return num;
2562
0
  }
2563
2564
0
  const CodingUnit* puAbove = cu.cs->getCURestricted(posRT.offset(0, -1), cu, cu.chType);
2565
0
  if (puAbove && puAbove->affine
2566
0
    && puAbove->mergeType == MRG_TYPE_DEFAULT_N
2567
0
    && CU::isDiffMER(cu.lumaPos(), posRT.offset(0, -1), plevel)
2568
0
    )
2569
0
  {
2570
0
    npu[num++] = puAbove;
2571
0
    return num;
2572
0
  }
2573
2574
0
  const CodingUnit* puAboveLeft = cu.cs->getCURestricted(posLT.offset(-1, -1), cu, cu.chType);
2575
0
  if (puAboveLeft && puAboveLeft->affine
2576
0
    && puAboveLeft->mergeType == MRG_TYPE_DEFAULT_N
2577
0
    && CU::isDiffMER(cu.lumaPos(), posLT.offset(-1, -1), plevel)
2578
0
    )
2579
0
  {
2580
0
    npu[num++] = puAboveLeft;
2581
0
    return num;
2582
0
  }
2583
2584
0
  return num;
2585
0
}
2586
2587
void CU::getAffineMergeCand( CodingUnit& cu, AffineMergeCtx& affMrgCtx, const int mrgCandIdx)
2588
0
{
2589
0
  const CodingStructure &cs = *cu.cs;
2590
0
  const Slice &slice = *cu.cs->slice;
2591
0
  const uint32_t maxNumAffineMergeCand = slice.picHeader->maxNumAffineMergeCand;
2592
0
  const unsigned plevel = cu.cs->sps->log2ParallelMergeLevelMinus2 + 2;
2593
2594
0
  for (int i = 0; i < maxNumAffineMergeCand; i++)
2595
0
  {
2596
0
    for (int mvNum = 0; mvNum < 3; mvNum++)
2597
0
    {
2598
0
      affMrgCtx.mvFieldNeighbours[i][0][mvNum].setMvField(Mv(), -1);
2599
0
      affMrgCtx.mvFieldNeighbours[i][1][mvNum].setMvField(Mv(), -1);
2600
0
    }
2601
0
    affMrgCtx.interDirNeighbours[i] = 0;
2602
0
    affMrgCtx.affineType[i] = AFFINEMODEL_4PARAM;
2603
0
    affMrgCtx.mergeType[i] = MRG_TYPE_DEFAULT_N;
2604
0
    affMrgCtx.BcwIdx[i] = BCW_DEFAULT;
2605
0
  }
2606
2607
0
  affMrgCtx.numValidMergeCand = 0;
2608
0
  affMrgCtx.maxNumMergeCand = maxNumAffineMergeCand;
2609
0
  bool enableSbTMVP = slice.sps->SbtMvp && !(slice.poc == slice.getRefPic(REF_PIC_LIST_0, 0)->getPOC() && slice.isIRAP());
2610
0
  bool isAvailableSubPu = false;
2611
2612
0
  if (enableSbTMVP && slice.picHeader->enableTMVP)
2613
0
  {
2614
0
    CHECK(affMrgCtx.subPuMvpMiBuf.area() == 0 || !affMrgCtx.subPuMvpMiBuf.buf, "Buffer not initialized");
2615
0
    affMrgCtx.subPuMvpMiBuf.fill(MotionInfo());
2616
2617
0
    int pos = 0;
2618
    // Get spatial MV
2619
0
    const Position posCurLB = cu.Y().bottomLeft();
2620
0
    MotionInfo miLeft;
2621
2622
    //left
2623
0
    const CodingUnit* puLeft = cs.getCURestricted(posCurLB.offset(-1, 0), cu, cu.chType);
2624
0
    const bool isAvailableA1 = puLeft && isDiffMER(cu.lumaPos(), posCurLB.offset(-1, 0), plevel) && &cu != puLeft && CU::isInter(*puLeft);
2625
0
    if (isAvailableA1)
2626
0
    {
2627
0
      miLeft = puLeft->getMotionInfo(posCurLB.offset(-1, 0));
2628
      // get Inter Dir
2629
0
      affMrgCtx.interDirNeighbours[pos] = miLeft.interDir();
2630
2631
      // get Mv from Left
2632
0
      affMrgCtx.mvFieldNeighbours[pos][0][0].setMvField(miLeft.mv[0], miLeft.miRefIdx[0]);
2633
2634
0
      if (slice.isInterB())
2635
0
      {
2636
0
        affMrgCtx.mvFieldNeighbours[pos][1][0].setMvField(miLeft.mv[1], miLeft.miRefIdx[1]);
2637
0
      }
2638
0
      pos++;
2639
0
    }
2640
2641
0
    isAvailableSubPu = getInterMergeSbTMVPCand(cu, affMrgCtx, pos);
2642
2643
0
    if (isAvailableSubPu)
2644
0
    {
2645
0
      for (int mvNum = 1; mvNum < 3; mvNum++)
2646
0
      {
2647
0
        affMrgCtx.mvFieldNeighbours[affMrgCtx.numValidMergeCand][0][mvNum] = affMrgCtx.mvFieldNeighbours[pos][0][0];
2648
0
        affMrgCtx.mvFieldNeighbours[affMrgCtx.numValidMergeCand][1][mvNum] = affMrgCtx.mvFieldNeighbours[pos][1][0];
2649
0
      }
2650
2651
0
      affMrgCtx.affineType[affMrgCtx.numValidMergeCand] = AFFINE_MODEL_NUM;
2652
0
      affMrgCtx.mergeType[affMrgCtx.numValidMergeCand] = MRG_TYPE_SUBPU_ATMVP;
2653
2654
0
      affMrgCtx.numValidMergeCand++;
2655
2656
0
      if (affMrgCtx.numValidMergeCand == mrgCandIdx + 1)
2657
0
      {
2658
0
        return;
2659
0
      }
2660
2661
      // early termination
2662
0
      if (affMrgCtx.numValidMergeCand == maxNumAffineMergeCand)
2663
0
      {
2664
0
        return;
2665
0
      }
2666
0
    }
2667
0
  }
2668
2669
0
  if (slice.sps->Affine)
2670
0
  {
2671
    ///> Start: inherited affine candidates
2672
0
    const CodingUnit* npu[5];
2673
0
    int numAffNeighLeft = getAvailableAffineNeighboursForLeftPredictor(cu, npu);
2674
0
    int numAffNeigh = getAvailableAffineNeighboursForAbovePredictor(cu, npu, numAffNeighLeft);
2675
0
    for (int idx = 0; idx < numAffNeigh; idx++)
2676
0
    {
2677
      // derive Mv from Neigh affine PU
2678
0
      Mv cMv[2][3];
2679
0
      const CodingUnit* cuNeigh = npu[idx];
2680
0
      cu.affineType = cuNeigh->affineType;
2681
0
      if (cuNeigh->interDir != 2)
2682
0
      {
2683
0
        xInheritedAffineMv(cu, cuNeigh, REF_PIC_LIST_0, cMv[0]);
2684
0
      }
2685
0
      if (slice.isInterB())
2686
0
      {
2687
0
        if (cuNeigh->interDir != 1)
2688
0
        {
2689
0
          xInheritedAffineMv(cu, cuNeigh, REF_PIC_LIST_1, cMv[1]);
2690
0
        }
2691
0
      }
2692
2693
0
      for (int mvNum = 0; mvNum < 3; mvNum++)
2694
0
      {
2695
0
        affMrgCtx.mvFieldNeighbours[affMrgCtx.numValidMergeCand][0][mvNum] . setMvField(cMv[0][mvNum], cuNeigh->refIdx[0]);
2696
0
        affMrgCtx.mvFieldNeighbours[affMrgCtx.numValidMergeCand][1][mvNum] . setMvField(cMv[1][mvNum], cuNeigh->refIdx[1]);
2697
0
      }
2698
0
      affMrgCtx.interDirNeighbours [affMrgCtx.numValidMergeCand]           = cuNeigh->interDir;
2699
0
      affMrgCtx.affineType         [affMrgCtx.numValidMergeCand]           = EAffineModel( cuNeigh->affineType );
2700
0
      affMrgCtx.BcwIdx             [affMrgCtx.numValidMergeCand]           = cuNeigh->BcwIdx;
2701
2702
0
      if( affMrgCtx.numValidMergeCand == mrgCandIdx )
2703
0
      {
2704
0
        return;
2705
0
      }
2706
2707
      // early termination
2708
0
      affMrgCtx.numValidMergeCand++;
2709
0
      if (affMrgCtx.numValidMergeCand == maxNumAffineMergeCand)
2710
0
      {
2711
0
        return;
2712
0
      }
2713
0
    }
2714
    ///> End: inherited affine candidates
2715
2716
    ///> Start: Constructed affine candidates
2717
0
    {
2718
0
      MotionInfo mi[4];
2719
0
      bool isAvailable[4] = { false };
2720
2721
0
      int8_t neighBcw[2] = { BCW_DEFAULT, BCW_DEFAULT };
2722
      // control point: LT B2->B3->A2
2723
0
      const Position posLT[3] = { cu.Y().topLeft().offset(-1, -1), cu.Y().topLeft().offset(0, -1), cu.Y().topLeft().offset(-1, 0) };
2724
0
      for (int i = 0; i < 3; i++)
2725
0
      {
2726
0
        const Position pos = posLT[i];
2727
0
        const CodingUnit* cuNeigh = cs.getCURestricted(pos, cu, cu.chType);
2728
2729
0
        if (cuNeigh && CU::isInter(*cuNeigh) && CU::isDiffMER(cu.lumaPos(), pos, plevel))
2730
0
        {
2731
0
          isAvailable[0] = true;
2732
0
          mi[0] = cuNeigh->getMotionInfo(pos);
2733
0
          neighBcw[0] = cuNeigh->BcwIdx;
2734
0
          break;
2735
0
        }
2736
0
      }
2737
2738
      // control point: RT B1->B0
2739
0
      const Position posRT[2] = { cu.Y().topRight().offset(0, -1), cu.Y().topRight().offset(1, -1) };
2740
0
      for (int i = 0; i < 2; i++)
2741
0
      {
2742
0
        const Position pos = posRT[i];
2743
0
        const CodingUnit* cuNeigh = cs.getCURestricted(pos, cu, cu.chType);
2744
2745
0
        if (cuNeigh && CU::isInter(*cuNeigh) && CU::isDiffMER(cu.lumaPos(), pos, plevel))
2746
0
        {
2747
0
          isAvailable[1] = true;
2748
0
          mi[1] = cuNeigh->getMotionInfo(pos);
2749
0
          neighBcw[1] = cuNeigh->BcwIdx;
2750
0
          break;
2751
0
        }
2752
0
      }
2753
2754
      // control point: LB A1->A0
2755
0
      const Position posLB[2] = { cu.Y().bottomLeft().offset(-1, 0), cu.Y().bottomLeft().offset(-1, 1) };
2756
0
      for (int i = 0; i < 2; i++)
2757
0
      {
2758
0
        const Position pos = posLB[i];
2759
0
        const CodingUnit* cuNeigh = cs.getCURestricted(pos, cu, cu.chType);
2760
2761
0
        if (cuNeigh && CU::isInter(*cuNeigh) && CU::isDiffMER(cu.lumaPos(), pos, plevel))
2762
0
        {
2763
0
          isAvailable[2] = true;
2764
0
          mi[2] = cuNeigh->getMotionInfo(pos);
2765
0
          break;
2766
0
        }
2767
0
      }
2768
2769
      // control point: RB
2770
0
      if (slice.picHeader->enableTMVP)
2771
0
      {
2772
        //>> MTK colocated-RightBottom
2773
        // offset the pos to be sure to "point" to the same position the uiAbsPartIdx would've pointed to
2774
0
        Position posRB = cu.Y().bottomRight().offset(-3, -3);
2775
2776
0
        const PreCalcValues& pcv = *cs.pcv;
2777
0
        Position posC0;
2778
0
        bool C0Avail = false;
2779
2780
0
        bool boundaryCond = ((posRB.x + pcv.minCUSize) < pcv.lumaWidth) && ((posRB.y + pcv.minCUSize) < pcv.lumaHeight);
2781
0
        const SubPic& curSubPic = cu.cs->slice->pps->getSubPicFromPos(cu.lumaPos());
2782
0
        if (curSubPic.treatedAsPic)
2783
0
        {
2784
0
          boundaryCond = ((posRB.x + pcv.minCUSize) <= curSubPic.subPicRight &&
2785
0
            (posRB.y + pcv.minCUSize) <= curSubPic.subPicBottom);
2786
0
        }
2787
0
        if (boundaryCond)
2788
0
        {
2789
0
          int posYInCtu = posRB.y & pcv.maxCUSizeMask;
2790
0
          if (posYInCtu + 4 < pcv.maxCUSize)
2791
0
          {
2792
0
            posC0 = posRB.offset(4, 4);
2793
0
            C0Avail = true;
2794
0
          }
2795
0
        }
2796
2797
0
        Mv        cColMv;
2798
0
        int       refIdx = 0;
2799
0
        bool      bExistMV = C0Avail && getColocatedMVP(cu, REF_PIC_LIST_0, posC0, cColMv, refIdx);
2800
0
        if (bExistMV)
2801
0
        {
2802
0
          mi[3].mv[0]       = cColMv;
2803
0
          mi[3].miRefIdx[0] = refIdx;
2804
0
          isAvailable[3] = true;
2805
0
        }
2806
2807
0
        if (slice.isInterB())
2808
0
        {
2809
0
          bExistMV = C0Avail && getColocatedMVP(cu, REF_PIC_LIST_1, posC0, cColMv, refIdx);
2810
0
          if (bExistMV)
2811
0
          {
2812
0
            mi[3].mv[1]       = cColMv;
2813
0
            mi[3].miRefIdx[1] = refIdx;
2814
0
            isAvailable[3] = true;
2815
0
          }
2816
0
        }
2817
0
      }
2818
2819
      //-------------------  insert model  -------------------//
2820
0
      int order[6] = { 0, 1, 2, 3, 4, 5 };
2821
0
      int modelNum = 6;
2822
0
      int model[6][4] = {
2823
0
        { 0, 1, 2 },          // 0:  LT, RT, LB
2824
0
        { 0, 1, 3 },          // 1:  LT, RT, RB
2825
0
        { 0, 2, 3 },          // 2:  LT, LB, RB
2826
0
        { 1, 2, 3 },          // 3:  RT, LB, RB
2827
0
        { 0, 1 },             // 4:  LT, RT
2828
0
        { 0, 2 },             // 5:  LT, LB
2829
0
      };
2830
2831
0
      int verNum[6] = { 3, 3, 3, 3, 2, 2 };
2832
0
      int startIdx = cu.cs->sps->AffineType ? 0 : 4;
2833
0
      for (int idx = startIdx; idx < modelNum; idx++)
2834
0
      {
2835
0
        int modelIdx = order[idx];
2836
0
        getAffineControlPointCand(cu, mi, isAvailable, model[modelIdx], ((modelIdx == 3) ? neighBcw[1] : neighBcw[0]), modelIdx, verNum[modelIdx], affMrgCtx);
2837
0
        if (affMrgCtx.numValidMergeCand != 0 && affMrgCtx.numValidMergeCand - 1 == mrgCandIdx)
2838
0
        {
2839
0
          return;
2840
0
        }
2841
2842
        // early termination
2843
0
        if (affMrgCtx.numValidMergeCand == maxNumAffineMergeCand)
2844
0
        {
2845
0
          return;
2846
0
        }
2847
0
      }
2848
0
    }
2849
    ///> End: Constructed affine candidates
2850
0
  }
2851
2852
  ///> zero padding
2853
0
  int cnt = affMrgCtx.numValidMergeCand;
2854
0
  while (cnt < maxNumAffineMergeCand)
2855
0
  {
2856
0
    for (int mvNum = 0; mvNum < 3; mvNum++)
2857
0
    {
2858
0
      affMrgCtx.mvFieldNeighbours[cnt][0][mvNum].setMvField(Mv(0, 0), 0);
2859
0
    }
2860
0
    affMrgCtx.interDirNeighbours[cnt] = 1;
2861
2862
0
    if (slice.isInterB())
2863
0
    {
2864
0
      for (int mvNum = 0; mvNum < 3; mvNum++)
2865
0
      {
2866
0
        affMrgCtx.mvFieldNeighbours[cnt][1][mvNum].setMvField(Mv(0, 0), 0);
2867
0
      }
2868
0
      affMrgCtx.interDirNeighbours[cnt] = 3;
2869
0
    }
2870
0
    affMrgCtx.affineType[cnt] = AFFINEMODEL_4PARAM;
2871
2872
0
    if (cnt == mrgCandIdx)
2873
0
    {
2874
0
      return;
2875
0
    }
2876
0
    cnt++;
2877
0
    affMrgCtx.numValidMergeCand++;
2878
0
  }
2879
0
}
2880
2881
void CU::setAllAffineMvField(CodingUnit& cu, const MvField *mvField, RefPicList eRefList)
2882
0
{
2883
  // Set Mv
2884
0
  Mv mv[3];
2885
0
  for (int i = 0; i < 3; i++)
2886
0
  {
2887
0
    mv[i] = mvField[i].mv;
2888
0
  }
2889
0
  setAllAffineMv( cu, mv[ 0 ], mv[ 1 ], mv[ 2 ], eRefList );
2890
  
2891
  // Set RefIdx
2892
0
  CHECK(mvField[0].refIdx != mvField[1].refIdx || mvField[0].refIdx != mvField[2].refIdx, "Affine mv corners don't have the same refIdx.");
2893
0
  cu.refIdx[eRefList] = mvField[0].refIdx;
2894
0
}
2895
2896
void CU::setAllAffineMv(CodingUnit& cu, Mv affLT, Mv affRT, Mv affLB, RefPicList eRefList, bool clipCPMVs)
2897
0
{
2898
0
  int width = cu.Y().width;
2899
0
  int shift = MAX_CU_DEPTH;
2900
0
  bool SameMV = false;
2901
0
  if (affLT == affRT)
2902
0
  {
2903
0
    if (affRT == affLB)
2904
0
    {
2905
0
      SameMV = true;
2906
0
    }
2907
0
  }
2908
0
  if (clipCPMVs)
2909
0
  {
2910
0
    affLT.mvCliptoStorageBitDepth();
2911
0
    affRT.mvCliptoStorageBitDepth();
2912
0
    if (cu.affineType == AFFINEMODEL_6PARAM)
2913
0
    {
2914
0
      affLB.mvCliptoStorageBitDepth();
2915
0
    }
2916
0
  }
2917
2918
0
  int deltaMvHorX = 0;
2919
0
  int deltaMvHorY = 0;
2920
0
  int deltaMvVerX = 0;
2921
0
  int deltaMvVerY = 0;
2922
0
  if (!SameMV)
2923
0
  {
2924
0
    deltaMvHorX = (affRT - affLT).hor * (1<< (shift - Log2(width)));
2925
0
    deltaMvHorY = (affRT - affLT).ver * (1<< (shift - Log2(width)));
2926
0
    int height = cu.Y().height;
2927
0
    if (cu.affineType == AFFINEMODEL_6PARAM)
2928
0
    {
2929
0
      deltaMvVerX = (affLB - affLT).hor * (1<< (shift - Log2(height)));
2930
0
      deltaMvVerY = (affLB - affLT).ver * (1<< (shift - Log2(height)));
2931
0
    }
2932
0
    else
2933
0
    {
2934
0
      deltaMvVerX = -deltaMvHorY;
2935
0
      deltaMvVerY = deltaMvHorX;
2936
0
    }
2937
0
  }
2938
2939
0
  int mvScaleHor = affLT.hor * (1<< shift);
2940
0
  int mvScaleVer = affLT.ver * (1<< shift);
2941
0
  int blockWidth = AFFINE_MIN_BLOCK_SIZE;
2942
0
  int blockHeight = AFFINE_MIN_BLOCK_SIZE;
2943
0
  const int halfBW = blockWidth >> 1;
2944
0
  const int halfBH = blockHeight >> 1;
2945
0
  MotionBuf mb = cu.getMotionBuf();
2946
0
  int mvScaleTmpHor, mvScaleTmpVer;
2947
0
  const bool subblkMVSpreadOverLimit = InterPredInterpolation::isSubblockVectorSpreadOverLimit(deltaMvHorX, deltaMvHorY, deltaMvVerX, deltaMvVerY, cu.interDir);
2948
2949
0
  int h = cu.Y().height / blockHeight;
2950
0
  int w = cu.Y().width / blockWidth;
2951
0
  for (int y = 0; y < h; y++)
2952
0
  {
2953
0
    for (int x = 0; x < w; x++)
2954
0
    {
2955
0
      if (SameMV)
2956
0
      {
2957
0
        mvScaleTmpHor = mvScaleHor;
2958
0
        mvScaleTmpVer = mvScaleVer;
2959
0
      }
2960
0
      else
2961
0
      {
2962
0
        if (!subblkMVSpreadOverLimit)
2963
0
        {
2964
0
          mvScaleTmpHor = mvScaleHor + deltaMvHorX * (halfBW + x*blockWidth) + deltaMvVerX * (halfBH + y*blockHeight);
2965
0
          mvScaleTmpVer = mvScaleVer + deltaMvHorY * (halfBW + x*blockWidth) + deltaMvVerY * (halfBH + y*blockHeight);
2966
2967
0
        }
2968
0
        else
2969
0
        {
2970
0
          mvScaleTmpHor = mvScaleHor + deltaMvHorX * (cu.Y().width >> 1) + deltaMvVerX * (cu.Y().height >> 1);
2971
0
          mvScaleTmpVer = mvScaleVer + deltaMvHorY * (cu.Y().width >> 1) + deltaMvVerY * (cu.Y().height >> 1);
2972
0
        }
2973
0
      }
2974
0
      roundAffineMv(mvScaleTmpHor, mvScaleTmpVer, shift);
2975
0
      Mv curMv(mvScaleTmpHor, mvScaleTmpVer);
2976
0
      curMv.clipToStorageBitDepth();
2977
2978
0
      mb.at(x, y).mv[eRefList] = curMv;
2979
0
    }
2980
0
  }
2981
2982
0
  cu.mv[eRefList][0] = affLT;
2983
0
  cu.mv[eRefList][1] = affRT;
2984
0
  cu.mv[eRefList][2] = affLB;
2985
0
}
2986
2987
void clipColPos(int& posX, int& posY, const CodingUnit& cu)
2988
0
{
2989
0
  Position puPos = cu.lumaPos();
2990
0
  int log2CtuSize = cu.cs->pcv->maxCUSizeLog2;
2991
0
  int ctuX = ((puPos.x >> log2CtuSize) << log2CtuSize);
2992
0
  int ctuY = ((puPos.y >> log2CtuSize) << log2CtuSize);
2993
0
  int horMax;
2994
0
  const SubPic& curSubPic = cu.slice->pps->getSubPicFromPos(puPos);
2995
0
  if (curSubPic.treatedAsPic)
2996
0
  {
2997
0
    horMax = std::min((int)curSubPic.subPicRight, ctuX + (int)cu.cs->sps->CTUSize + 3);
2998
0
  }
2999
0
  else
3000
0
  {
3001
0
    horMax = std::min((int)cu.cs->pps->picWidthInLumaSamples - 1, ctuX + (int)cu.cs->sps->CTUSize + 3);
3002
0
  }
3003
0
  int horMin = std::max((int)0, ctuX);
3004
0
  int verMax = std::min((int)cu.cs->pps->picHeightInLumaSamples - 1, ctuY + (int)cu.cs->sps->CTUSize - 1);
3005
0
  int verMin = std::max((int)0, ctuY);
3006
3007
0
  posX = std::min(horMax, std::max(horMin, posX));
3008
0
  posY = std::min(verMax, std::max(verMin, posY));
3009
0
}
3010
3011
3012
void CU::spanMotionInfo( CodingUnit& cu, const AffineMergeCtx *mrgCtx )
3013
20.6k
{
3014
20.6k
  MotionBuf mb = cu.getMotionBuf();
3015
3016
20.6k
  if( !cu.mergeFlag || cu.mergeType == MRG_TYPE_DEFAULT_N || cu.mergeType == MRG_TYPE_IBC )
3017
20.6k
  {
3018
20.6k
    bool isIBC   = CU::isIBC( cu );
3019
20.6k
    bool isInter = !CU::isIntra( cu ) && !isIBC;
3020
3021
20.6k
    if( isInter || isIBC )
3022
20.6k
    {
3023
20.6k
      MotionInfo mi;
3024
3025
61.8k
      for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ )
3026
41.2k
      {
3027
41.2k
        mi.mv[i]       = cu.mv[i][0];
3028
41.2k
        mi.miRefIdx[i] = isIBC ? MI_NOT_VALID : cu.refIdx[i];
3029
41.2k
      }
3030
3031
20.6k
      if( cu.affine )
3032
0
      {
3033
0
        for( int y = 0; y < mb.height; y++ )
3034
0
        {
3035
0
          for( int x = 0; x < mb.width; x++ )
3036
0
          {
3037
0
            MotionInfo& dest = mb.at( x, y );
3038
3039
0
            for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ )
3040
0
            {
3041
0
              if( mi.miRefIdx[i] == MI_NOT_VALID )
3042
0
              {
3043
0
                dest.mv[i] = Mv();
3044
0
              }
3045
0
              dest.miRefIdx[i] = mi.miRefIdx[i];
3046
0
            }
3047
0
          }
3048
0
        }
3049
0
        return;
3050
0
      }
3051
20.6k
      else
3052
20.6k
      {
3053
20.6k
      }
3054
3055
20.6k
      mb.fill( mi );
3056
20.6k
    }
3057
20.6k
  }
3058
0
  else if( cu.mergeType == MRG_TYPE_SUBPU_ATMVP )
3059
0
  {
3060
0
    CHECK( !mrgCtx || mrgCtx->subPuMvpMiBuf.area() == 0 || !mrgCtx->subPuMvpMiBuf.buf, "Buffer not initialized" );
3061
0
    mb.copyFrom( mrgCtx->subPuMvpMiBuf );
3062
0
  }
3063
20.6k
}
3064
3065
bool CU::isBiPredFromDifferentDirEqDistPoc(const CodingUnit& cu)
3066
0
{
3067
0
  if( cu.refIdx[0] >= 0 && cu.refIdx[1] >= 0 )
3068
0
  {
3069
0
    if( cu.slice->getRefPic( REF_PIC_LIST_0, cu.refIdx[0] )->isLongTerm
3070
0
     || cu.slice->getRefPic( REF_PIC_LIST_1, cu.refIdx[1] )->isLongTerm )
3071
0
    {
3072
0
      return false;
3073
0
    }
3074
3075
0
    const int poc0 = cu.slice->getRefPOC( REF_PIC_LIST_0, cu.refIdx[0] );
3076
0
    const int poc1 = cu.slice->getRefPOC( REF_PIC_LIST_1, cu.refIdx[1] );
3077
0
    const int poc  = cu.slice->poc;
3078
3079
0
    return ( poc - poc0 ) == ( poc1 - poc );
3080
0
  }
3081
3082
0
  return false;
3083
0
}
3084
3085
void CU::restrictBiPredMergeCandsOne( CodingUnit &cu )
3086
138k
{
3087
138k
  if( CU::isBipredRestriction( cu ) )
3088
0
  {
3089
0
    if( cu.interDir == 3 )
3090
0
    {
3091
0
      cu.interDir  =  1;
3092
0
      cu.refIdx[1] = -1;
3093
0
      cu.mv[1][0]  = Mv( 0, 0 );
3094
0
      cu.BcwIdx    = BCW_DEFAULT;
3095
0
    }
3096
0
  }
3097
138k
}
3098
3099
void CU::getGeoMergeCandidates( const CodingUnit &cu, MergeCtx &geoMrgCtx )
3100
0
{
3101
0
  MergeCtx tmpMergeCtx;
3102
3103
0
  const Slice &  slice           = *cu.cs->slice;
3104
0
  const uint32_t maxNumMergeCand = slice.sps->maxNumMergeCand;
3105
3106
0
  geoMrgCtx.numValidMergeCand = 0;
3107
3108
0
  for( int32_t i = 0; i < GEO_MAX_NUM_UNI_CANDS; i++ )
3109
0
  {
3110
0
    geoMrgCtx.BcwIdx            [i]           = BCW_DEFAULT;
3111
0
    geoMrgCtx.interDirNeighbours[i]           = 0;
3112
0
    geoMrgCtx.mrgTypeNeighbours [i]           = MRG_TYPE_DEFAULT_N;
3113
0
    geoMrgCtx.mvFieldNeighbours [i][0].refIdx = NOT_VALID;
3114
0
    geoMrgCtx.mvFieldNeighbours [i][1].refIdx = NOT_VALID;
3115
0
    geoMrgCtx.mvFieldNeighbours [i][0].mv     = Mv();
3116
0
    geoMrgCtx.mvFieldNeighbours [i][1].mv     = Mv();
3117
0
    geoMrgCtx.useAltHpelIf      [i]           = false;
3118
0
  }
3119
3120
0
  CU::getInterMergeCandidates( cu, tmpMergeCtx, 0 );
3121
3122
0
  for( int32_t i = 0; i < maxNumMergeCand; i++ )
3123
0
  {
3124
0
    int parity = i & 1;
3125
3126
0
    if( tmpMergeCtx.interDirNeighbours[i] & ( 0x01 + parity ) )
3127
0
    {
3128
0
      geoMrgCtx.interDirNeighbours[geoMrgCtx.numValidMergeCand]                 = 1 + parity;
3129
0
      geoMrgCtx.mrgTypeNeighbours [geoMrgCtx.numValidMergeCand]                 = MRG_TYPE_DEFAULT_N;
3130
0
      geoMrgCtx.mvFieldNeighbours [geoMrgCtx.numValidMergeCand][!parity].mv     = Mv(0, 0);
3131
0
      geoMrgCtx.mvFieldNeighbours [geoMrgCtx.numValidMergeCand][ parity].mv     = tmpMergeCtx.mvFieldNeighbours[i][parity].mv;
3132
0
      geoMrgCtx.mvFieldNeighbours [geoMrgCtx.numValidMergeCand][!parity].refIdx = -1;
3133
0
      geoMrgCtx.mvFieldNeighbours [geoMrgCtx.numValidMergeCand][ parity].refIdx = tmpMergeCtx.mvFieldNeighbours[i][parity].refIdx;
3134
0
      geoMrgCtx.numValidMergeCand++;
3135
3136
0
      if (geoMrgCtx.numValidMergeCand == GEO_MAX_NUM_UNI_CANDS)
3137
0
      {
3138
0
        return;
3139
0
      }
3140
0
      continue;
3141
0
    }
3142
3143
0
    if( tmpMergeCtx.interDirNeighbours[i] & ( 0x02 - parity ) )
3144
0
    {
3145
0
      geoMrgCtx.interDirNeighbours[geoMrgCtx.numValidMergeCand]                 = 2 - parity;
3146
0
      geoMrgCtx.mrgTypeNeighbours [geoMrgCtx.numValidMergeCand]                 = MRG_TYPE_DEFAULT_N;
3147
0
      geoMrgCtx.mvFieldNeighbours [geoMrgCtx.numValidMergeCand][!parity].mv     = tmpMergeCtx.mvFieldNeighbours[i][!parity].mv;
3148
0
      geoMrgCtx.mvFieldNeighbours [geoMrgCtx.numValidMergeCand][ parity].mv     = Mv(0, 0);
3149
0
      geoMrgCtx.mvFieldNeighbours [geoMrgCtx.numValidMergeCand][!parity].refIdx = tmpMergeCtx.mvFieldNeighbours[i][!parity].refIdx;
3150
0
      geoMrgCtx.mvFieldNeighbours [geoMrgCtx.numValidMergeCand][ parity].refIdx = -1;
3151
0
      geoMrgCtx.numValidMergeCand++;
3152
3153
0
      if( geoMrgCtx.numValidMergeCand == GEO_MAX_NUM_UNI_CANDS )
3154
0
      {
3155
0
        return;
3156
0
      }
3157
0
    }
3158
0
  }
3159
0
}
3160
3161
void CU::spanGeoMotionInfo( CodingUnit &cu, const MergeCtx &geoMrgCtx, const uint8_t splitDir, const uint8_t candIdx0, const uint8_t candIdx1 )
3162
0
{
3163
0
  cu.geoSplitDir    = splitDir;
3164
0
  cu.geoMergeIdx[0] = candIdx0;
3165
0
  cu.geoMergeIdx[1] = candIdx1;
3166
0
  MotionBuf mb      = cu.getMotionBuf();
3167
3168
0
  MotionInfo biMv;
3169
3170
0
  if( geoMrgCtx.interDirNeighbours[ candIdx0 ] == 1 && geoMrgCtx.interDirNeighbours[ candIdx1 ] == 2 )
3171
0
  {
3172
0
    biMv.mv[0]       = geoMrgCtx.mvFieldNeighbours[candIdx0][0].mv;
3173
0
    biMv.mv[1]       = geoMrgCtx.mvFieldNeighbours[candIdx1][1].mv;
3174
0
    biMv.miRefIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx0][0].refIdx;
3175
0
    biMv.miRefIdx[1] = geoMrgCtx.mvFieldNeighbours[candIdx1][1].refIdx;
3176
0
  }
3177
0
  else if( geoMrgCtx.interDirNeighbours[ candIdx0 ] == 2 && geoMrgCtx.interDirNeighbours[ candIdx1 ] == 1 )
3178
0
  {
3179
0
    biMv.mv[0]       = geoMrgCtx.mvFieldNeighbours[candIdx1][0].mv;
3180
0
    biMv.mv[1]       = geoMrgCtx.mvFieldNeighbours[candIdx0][1].mv;
3181
0
    biMv.miRefIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1][0].refIdx;
3182
0
    biMv.miRefIdx[1] = geoMrgCtx.mvFieldNeighbours[candIdx0][1].refIdx;
3183
0
  }
3184
0
  else if( geoMrgCtx.interDirNeighbours[ candIdx0 ] == 1 && geoMrgCtx.interDirNeighbours[ candIdx1 ] == 1 )
3185
0
  {
3186
0
    biMv.mv[0]       = geoMrgCtx.mvFieldNeighbours[candIdx1][0].mv;
3187
0
    biMv.mv[1]       = Mv(0, 0);
3188
0
    biMv.miRefIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1][0].refIdx;
3189
0
    biMv.miRefIdx[1] = MI_NOT_VALID;
3190
0
  }
3191
0
  else if( geoMrgCtx.interDirNeighbours[ candIdx0 ] == 2 && geoMrgCtx.interDirNeighbours[ candIdx1 ] == 2 )
3192
0
  {
3193
0
    biMv.mv[0]       = Mv(0, 0);
3194
0
    biMv.mv[1]       = geoMrgCtx.mvFieldNeighbours[candIdx1][1].mv;
3195
0
    biMv.miRefIdx[0] = MI_NOT_VALID;
3196
0
    biMv.miRefIdx[1] = geoMrgCtx.mvFieldNeighbours[candIdx1][1].refIdx;
3197
0
  }
3198
3199
0
  int16_t angle       = g_GeoParams[splitDir][0];
3200
0
  int     tpmMask     = 0;
3201
0
  int     lookUpY     = 0, motionIdx = 0;
3202
0
  bool    isFlip      = angle >= 13 && angle <= 27;
3203
0
  int     distanceIdx = g_GeoParams[splitDir][1];
3204
0
  int     distanceX   = angle;
3205
0
  int     distanceY   = (distanceX + (GEO_NUM_ANGLES >> 2)) % GEO_NUM_ANGLES;
3206
0
  int     offsetX     = (-(int) cu.lwidth()) >> 1;
3207
0
  int     offsetY     = (-(int) cu.lheight()) >> 1;
3208
3209
0
  if( distanceIdx > 0 )
3210
0
  {
3211
0
    if( angle % 16 == 8 || ( angle % 16 != 0 && cu.lheight() >= cu.lwidth() ) )
3212
0
      offsetY += angle < 16 ? ( ( distanceIdx * cu.lheight() ) >> 3 ) : -( int ) ( ( distanceIdx * cu.lheight() ) >> 3 );
3213
0
    else
3214
0
      offsetX += angle < 16 ? ( ( distanceIdx * cu.lwidth() ) >> 3 ) : -( int ) ( ( distanceIdx * cu.lwidth() ) >> 3 );
3215
0
  }
3216
0
  for (int y = 0; y < mb.height; y++)
3217
0
  {
3218
0
    lookUpY = (2 * (4 * y + offsetY) + 5) * g_Dis[distanceY];
3219
0
    for (int x = 0; x < mb.width; x++)
3220
0
    {
3221
0
      motionIdx = (2 * (4 * x + offsetX) + 5) * g_Dis[distanceX] + lookUpY;
3222
0
      tpmMask   = abs(motionIdx) < 32 ? 2 : (motionIdx <= 0 ? (1 - isFlip) : isFlip);
3223
0
      if (tpmMask == 2)
3224
0
      {
3225
0
        mb.at( x, y ) = biMv;
3226
0
      }
3227
0
      else if (tpmMask == 0)
3228
0
      {
3229
0
        mb.at(x, y).miRefIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx0][0].refIdx;
3230
0
        mb.at(x, y).miRefIdx[1] = geoMrgCtx.mvFieldNeighbours[candIdx0][1].refIdx;
3231
0
        mb.at(x, y).mv[0]       = geoMrgCtx.mvFieldNeighbours[candIdx0][0].mv;
3232
0
        mb.at(x, y).mv[1]       = geoMrgCtx.mvFieldNeighbours[candIdx0][1].mv;
3233
0
      }
3234
0
      else
3235
0
      {
3236
0
        mb.at(x, y).miRefIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1][0].refIdx;
3237
0
        mb.at(x, y).miRefIdx[1] = geoMrgCtx.mvFieldNeighbours[candIdx1][1].refIdx;
3238
0
        mb.at(x, y).mv[0]       = geoMrgCtx.mvFieldNeighbours[candIdx1][0].mv;
3239
0
        mb.at(x, y).mv[1]       = geoMrgCtx.mvFieldNeighbours[candIdx1][1].mv;
3240
0
      }
3241
0
    }
3242
0
  }
3243
0
}
3244
3245
void CU::resetMVDandMV2Int( CodingUnit& cu )
3246
0
{
3247
0
  if( !cu.mergeFlag )
3248
0
  {
3249
0
    if( cu.interDir != 2 /* PRED_L1 */ )
3250
0
    {
3251
0
      Mv mv        = cu.mv[0][0];
3252
0
      Mv mvPred;
3253
0
      AMVPInfo amvpInfo;
3254
0
      CU::fillMvpCand(cu, REF_PIC_LIST_0, cu.refIdx[0], amvpInfo);
3255
0
      cu.mvpNum[0] = amvpInfo.numCand;
3256
3257
0
      mvPred       = amvpInfo.mvCand[cu.mvpIdx[0]];
3258
0
      mv.roundTransPrecInternal2Amvr(cu.imv);
3259
0
      cu.mv[0][0]  = mv;
3260
0
      Mv mvDiff    = mv - mvPred;
3261
0
      cu.mvd[0][0] = mvDiff;
3262
0
    }
3263
0
    if( cu.interDir != 1 /* PRED_L0 */ )
3264
0
    {
3265
0
      Mv mv        = cu.mv[1][0];
3266
0
      Mv mvPred;
3267
0
      AMVPInfo amvpInfo;
3268
0
      CU::fillMvpCand(cu, REF_PIC_LIST_1, cu.refIdx[1], amvpInfo);
3269
0
      cu.mvpNum[1] = amvpInfo.numCand;
3270
3271
0
      mvPred       = amvpInfo.mvCand[cu.mvpIdx[1]];
3272
0
      mv.roundTransPrecInternal2Amvr(cu.imv);
3273
0
      Mv mvDiff    = mv - mvPred;
3274
3275
0
      if( cu.cs->slice->picHeader->mvdL1Zero && cu.interDir == 3 /* PRED_BI */ )
3276
0
      {
3277
0
        cu.mvd[1][0] = Mv();
3278
0
        mv = mvPred;
3279
0
      }
3280
0
      else
3281
0
      {
3282
0
        cu.mvd[1][0] = mvDiff;
3283
0
      }
3284
0
      cu.mv[1][0] = mv;
3285
0
    }
3286
3287
0
  }
3288
0
  else
3289
0
  {
3290
0
    MergeCtx mrgCtx;
3291
3292
0
    CU::getInterMergeCandidates ( cu, mrgCtx, 0 );
3293
0
    mrgCtx.setMergeInfo( cu, cu.mergeIdx );
3294
0
  }
3295
3296
0
  CU::spanMotionInfo( cu );
3297
0
}
3298
3299
bool CU::hasSubCUNonZeroMVd( const CodingUnit& cu )
3300
20.6k
{
3301
20.6k
  bool bNonZeroMvd = false;
3302
3303
20.6k
  if( ( !cu.mergeFlag ) && ( !cu.skip ) )
3304
20.6k
  {
3305
20.6k
    if( cu.interDir != 2 /* PRED_L1 */ )
3306
20.6k
    {
3307
20.6k
      bNonZeroMvd |= cu.mvd[REF_PIC_LIST_0][0].hor != 0;
3308
20.6k
      bNonZeroMvd |= cu.mvd[REF_PIC_LIST_0][0].ver != 0;
3309
20.6k
    }
3310
20.6k
    if( cu.interDir != 1 /* PRED_L0 */ )
3311
0
    {
3312
0
      if( !cu.cs->slice->picHeader->mvdL1Zero || cu.interDir != 3 /* PRED_BI */ )
3313
0
      {
3314
0
        bNonZeroMvd |= cu.mvd[REF_PIC_LIST_1][0].hor != 0;
3315
0
        bNonZeroMvd |= cu.mvd[REF_PIC_LIST_1][0].ver != 0;
3316
0
      }
3317
0
    }
3318
20.6k
  }
3319
3320
20.6k
  return bNonZeroMvd;
3321
20.6k
}
3322
3323
bool CU::hasSubCUNonZeroAffineMVd( const CodingUnit& cu )
3324
0
{
3325
0
  bool nonZeroAffineMvd = false;
3326
3327
0
  if ( !cu.affine || cu.mergeFlag )
3328
0
  {
3329
0
    return false;
3330
0
  }
3331
3332
0
  if ( ( !cu.mergeFlag ) && ( !cu.skip ) )
3333
0
  {
3334
0
    if ( cu.interDir != 2 /* PRED_L1 */ )
3335
0
    {
3336
0
      for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
3337
0
      {
3338
0
        nonZeroAffineMvd |= cu.mvd[REF_PIC_LIST_0][i].hor != 0;
3339
0
        nonZeroAffineMvd |= cu.mvd[REF_PIC_LIST_0][i].ver != 0;
3340
0
      }
3341
0
    }
3342
3343
0
    if ( cu.interDir != 1 /* PRED_L0 */ )
3344
0
    {
3345
0
      if ( !cu.cs->slice->picHeader->mvdL1Zero || cu.interDir != 3 /* PRED_BI */ )
3346
0
      {
3347
0
        for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
3348
0
        {
3349
0
          nonZeroAffineMvd |= cu.mvd[REF_PIC_LIST_1][i].hor != 0;
3350
0
          nonZeroAffineMvd |= cu.mvd[REF_PIC_LIST_1][i].ver != 0;
3351
0
        }
3352
0
      }
3353
0
    }
3354
0
  }
3355
3356
0
  return nonZeroAffineMvd;
3357
0
}
3358
3359
uint8_t CU::numSbtModeRdo( uint8_t sbtAllowed )
3360
0
{
3361
0
  uint8_t num = 0;
3362
0
  uint8_t sum = 0;
3363
0
  num = targetSbtAllowed( SBT_VER_HALF, sbtAllowed ) + targetSbtAllowed( SBT_HOR_HALF, sbtAllowed );
3364
0
  sum += std::min( SBT_NUM_RDO, ( num << 1 ) );
3365
0
  num = targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) + targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed );
3366
0
  sum += std::min( SBT_NUM_RDO, ( num << 1 ) );
3367
0
  return sum;
3368
0
}
3369
3370
bool CU::isSbtMode( const uint8_t sbtInfo )
3371
0
{
3372
0
  uint8_t sbtIdx = getSbtIdx( sbtInfo );
3373
0
  return sbtIdx >= SBT_VER_HALF && sbtIdx <= SBT_HOR_QUAD;
3374
0
}
3375
3376
bool CU::isSameSbtSize( const uint8_t sbtInfo1, const uint8_t sbtInfo2 )
3377
0
{
3378
0
  uint8_t sbtIdx1 = getSbtIdxFromSbtMode( sbtInfo1 );
3379
0
  uint8_t sbtIdx2 = getSbtIdxFromSbtMode( sbtInfo2 );
3380
0
  if( sbtIdx1 == SBT_HOR_HALF || sbtIdx1 == SBT_VER_HALF )
3381
0
    return sbtIdx2 == SBT_HOR_HALF || sbtIdx2 == SBT_VER_HALF;
3382
0
  else if( sbtIdx1 == SBT_HOR_QUAD || sbtIdx1 == SBT_VER_QUAD )
3383
0
    return sbtIdx2 == SBT_HOR_QUAD || sbtIdx2 == SBT_VER_QUAD;
3384
0
  else
3385
0
    return false;
3386
0
}
3387
3388
PartSplit CU::getSbtTuSplit( const uint8_t sbtInfo ) 
3389
0
{
3390
0
  uint8_t sbtTuSplitType = CU::getSbtPos( sbtInfo );
3391
0
  switch( CU::getSbtIdx( sbtInfo ) )
3392
0
  {
3393
0
  case SBT_VER_HALF: sbtTuSplitType += SBT_VER_HALF_POS0_SPLIT; break;
3394
0
  case SBT_HOR_HALF: sbtTuSplitType += SBT_HOR_HALF_POS0_SPLIT; break;
3395
0
  case SBT_VER_QUAD: sbtTuSplitType += SBT_VER_QUAD_POS0_SPLIT; break;
3396
0
  case SBT_HOR_QUAD: sbtTuSplitType += SBT_HOR_QUAD_POS0_SPLIT; break;
3397
0
  default: assert( 0 );  break;
3398
0
  }
3399
3400
0
  assert( sbtTuSplitType <= SBT_HOR_QUAD_POS1_SPLIT && sbtTuSplitType >= SBT_VER_HALF_POS0_SPLIT );
3401
0
  return PartSplit(sbtTuSplitType);
3402
0
}
3403
3404
bool CU::isPredRegDiffFromTB(const CodingUnit &cu)
3405
177k
{
3406
177k
  return (cu.ispMode == VER_INTRA_SUBPARTITIONS && ((cu.blocks[0].width == 4 )|| ((cu.blocks[0].width == 8) && (cu.blocks[0].height > 4))));
3407
177k
}
3408
3409
bool CU::isFirstTBInPredReg(const CodingUnit& cu, const CompArea& area)
3410
18.4k
{
3411
18.4k
  return ((area.topLeft().x - cu.Y().topLeft().x) % PRED_REG_MIN_WIDTH == 0);
3412
18.4k
}
3413
3414
void CU::adjustPredArea(CompArea& area)
3415
0
{
3416
0
  area.width = std::max<int>(PRED_REG_MIN_WIDTH, area.width);
3417
0
}
3418
3419
bool CU::isBcwIdxCoded( const CodingUnit &cu )
3420
20.6k
{
3421
20.6k
  if( ! cu.cs->sps->BCW )
3422
20.6k
  {
3423
20.6k
    CHECK(cu.BcwIdx != BCW_DEFAULT, "Error: cu.BcwIdx != BCW_DEFAULT");
3424
20.6k
    return false;
3425
20.6k
  }
3426
3427
0
  if( cu.predMode == MODE_IBC || cu.predMode == MODE_INTRA || cu.slice->isInterP() || cu.interDir != 3 )
3428
0
  {
3429
0
    return false;
3430
0
  }
3431
3432
0
  if( cu.lwidth() * cu.lheight() < BCW_SIZE_CONSTRAINT )
3433
0
  {
3434
0
    return false;
3435
0
  }
3436
3437
0
  if( !cu.mergeFlag )
3438
0
  {
3439
0
    if( cu.interDir == 3 )
3440
0
    {
3441
0
      WPScalingParam *wp0;
3442
0
      WPScalingParam *wp1;
3443
0
      int refIdx0 = cu.refIdx[REF_PIC_LIST_0];
3444
0
      int refIdx1 = cu.refIdx[REF_PIC_LIST_1];
3445
3446
0
      cu.cs->slice->getWpScaling(REF_PIC_LIST_0, refIdx0, wp0);
3447
0
      cu.cs->slice->getWpScaling(REF_PIC_LIST_1, refIdx1, wp1);
3448
0
      if ((wp0[COMP_Y].presentFlag || wp0[COMP_Cb].presentFlag || wp0[COMP_Cr].presentFlag
3449
0
        || wp1[COMP_Y].presentFlag || wp1[COMP_Cb].presentFlag || wp1[COMP_Cr].presentFlag))
3450
0
      {
3451
0
        return false;
3452
0
      }
3453
0
      return true;
3454
0
    }
3455
0
  }
3456
3457
0
  return false;
3458
0
}
3459
3460
uint8_t CU::getValidBcwIdx( const CodingUnit &cu )
3461
0
{
3462
0
  if( cu.interDir == 3 && !cu.mergeFlag )
3463
0
  {
3464
0
    return cu.BcwIdx;
3465
0
  }
3466
0
  else if( cu.interDir == 3 && cu.mergeFlag && cu.mergeType == MRG_TYPE_DEFAULT_N )
3467
0
  {
3468
    // This is intended to do nothing here.
3469
0
  }
3470
0
  else
3471
0
  {
3472
0
    CHECK(cu.BcwIdx != BCW_DEFAULT, " cu.BcwIdx != BCW_DEFAULT ");
3473
0
  }
3474
3475
0
  return BCW_DEFAULT;
3476
0
}
3477
3478
void CU::setBcwIdx( CodingUnit &cu, uint8_t uh )
3479
0
{
3480
0
  int8_t uhCnt = 0;
3481
3482
0
  if( cu.interDir == 3 && !cu.mergeFlag )
3483
0
  {
3484
0
    cu.BcwIdx = uh;
3485
0
    ++uhCnt;
3486
0
  }
3487
0
  else if( cu.interDir == 3 && cu.mergeFlag && cu.mergeType == MRG_TYPE_DEFAULT_N )
3488
0
  {
3489
    // This is intended to do nothing here.
3490
0
  }
3491
0
  else
3492
0
  {
3493
0
    cu.BcwIdx = BCW_DEFAULT;
3494
0
  }
3495
3496
0
  CHECK(uhCnt <= 0, " uhCnt <= 0 ");
3497
0
}
3498
3499
bool CU::bdpcmAllowed( const CodingUnit& cu, const ComponentID compID )
3500
649k
{
3501
649k
  SizeType transformSkipMaxSize = 1 << cu.cs->sps->log2MaxTransformSkipBlockSize;
3502
3503
649k
  const Size& blkSize = isLuma(compID) ? cu.lumaSize() : cu.chromaSize();
3504
649k
  bool bdpcmAllowed = cu.cs->sps->BDPCM;
3505
649k
       bdpcmAllowed &= CU::isIntra( cu );
3506
649k
       bdpcmAllowed &= (blkSize.width <= transformSkipMaxSize && blkSize.height <= transformSkipMaxSize);
3507
649k
  return bdpcmAllowed;
3508
649k
}
3509
3510
bool CU::isMTSAllowed(const CodingUnit &cu, const ComponentID compID)
3511
184k
{
3512
184k
  SizeType tsMaxSize = 1 << cu.cs->sps->log2MaxTransformSkipBlockSize;
3513
184k
  const int maxSize  = CU::isIntra( cu ) ? MTS_INTRA_MAX_CU_SIZE : MTS_INTER_MAX_CU_SIZE;
3514
184k
  const int cuWidth  = cu.blocks[0].lumaSize().width;
3515
184k
  const int cuHeight = cu.blocks[0].lumaSize().height;
3516
184k
  bool mtsAllowed    = cu.chType == CH_L && compID == COMP_Y;
3517
3518
184k
  mtsAllowed &= CU::isIntra( cu ) ? cu.cs->sps->MTSIntra : cu.cs->sps->MTSInter && CU::isInter( cu );
3519
184k
  mtsAllowed &= cuWidth <= maxSize && cuHeight <= maxSize;
3520
184k
  mtsAllowed &= !cu.ispMode;
3521
184k
  mtsAllowed &= !cu.sbtInfo;
3522
184k
  mtsAllowed &= !(cu.bdpcmM[CH_L] && cuWidth <= tsMaxSize && cuHeight <= tsMaxSize);
3523
184k
  return mtsAllowed;
3524
184k
}
3525
3526
bool CU::isMvInRangeFPP( const int yB, const int nH, const int yMv, const int ifpLines, const PreCalcValues& pcv, const int chromaShift, const int mvPrecShift )
3527
0
{
3528
  //const int dctifMarginVerBot = 4 >> yCompScale;
3529
0
  const int ctuLogScale = pcv.maxCUSizeLog2 - chromaShift;
3530
0
  const int yBMax       = ( pcv.heightInCtus - 1 - ifpLines ) << ctuLogScale;
3531
0
  const int yRefMax     = ( ( ( yB >> ctuLogScale ) + ifpLines + 1 ) << ctuLogScale ) - 1;
3532
0
  if( yB < yBMax && ( yB + nH + ( 4 >> chromaShift ) + (yMv >> (mvPrecShift + chromaShift) ) - 1 > yRefMax ) )
3533
0
    return false;
3534
0
  return true;
3535
0
}
3536
3537
bool CU::isMotionBufInRangeFPP( const CodingUnit &cu, const int ifpLines )
3538
0
{
3539
0
  const CMotionBuf mb = cu.getMotionBuf();
3540
0
  const ComponentID compID = COMP_Y;
3541
0
  const int mvPrecShift = MV_FRACTIONAL_BITS_INTERNAL;
3542
3543
0
  const int yCompScale = getComponentScaleY(compID, cu.chromaFormat);
3544
0
  const int maxCUSizeShift = cu.cs->pcv->maxCUSizeLog2 - yCompScale;
3545
0
  const int dctifMarginVerBot = 4 >> yCompScale;
3546
0
  const int curCtuRow = cu.block(compID).y >> maxCUSizeShift;
3547
0
  const int cuBottom = cu.block(compID).y + cu.block(compID).height - 1;
3548
3549
  // checking only bottom line of motion buffer
3550
0
  for( int y =  0; y < mb.height; y++ )
3551
0
  {
3552
0
    for( int x = 0; x < mb.width; x++ )
3553
0
    {
3554
0
      const MotionInfo& mi = mb.at( x, y );
3555
0
      for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ )
3556
0
      {
3557
0
        if( mi.miRefIdx[i] != MI_NOT_VALID )
3558
0
        {
3559
0
          const Mv& mv = mi.mv[i];
3560
0
          const int refMaxPosY = cuBottom + dctifMarginVerBot + (mv.ver >> mvPrecShift);
3561
0
          const int refCtuRow = std::min( (int)((refMaxPosY > 0) ? refMaxPosY >> maxCUSizeShift: -1), (int)(cu.cs->pcv->heightInCtus - 1));
3562
0
          if( refCtuRow > ( curCtuRow + ifpLines ) )
3563
0
            return false;
3564
0
        }
3565
0
      }
3566
0
    }
3567
0
  }
3568
0
  return true;
3569
0
}
3570
3571
// TU tools
3572
3573
bool TU::getCbf( const TransformUnit& tu, const ComponentID compID )
3574
7.86M
{
3575
7.86M
  return getCbfAtDepth( tu, compID, tu.depth );
3576
7.86M
}
3577
3578
bool TU::getCbfAtDepth(const TransformUnit& tu, const ComponentID compID, const unsigned depth)
3579
10.4M
{
3580
10.4M
  if( !tu.blocks[compID].valid() )
3581
10.4M
    CHECK( tu.cbf[compID] != 0, "cbf must be 0 if the component is not available" );
3582
10.4M
  return ((tu.cbf[compID] >> depth) & 1) == 1;
3583
10.4M
}
3584
3585
void TU::setCbfAtDepth(TransformUnit& tu, const ComponentID compID, const unsigned depth, const bool cbf)
3586
2.30M
{
3587
  // first clear the CBF at the depth
3588
2.30M
  tu.cbf[compID] &= ~(1  << depth);
3589
  // then set the CBF
3590
2.30M
  tu.cbf[compID] |= ((cbf ? 1 : 0) << depth);
3591
2.30M
}
3592
3593
bool TU::isTSAllowed(const TransformUnit &tu, const ComponentID compID)
3594
2.50M
{
3595
2.50M
  const int maxSize = tu.cs->sps->log2MaxTransformSkipBlockSize;
3596
3597
2.50M
  bool tsAllowed = tu.cs->sps->transformSkip;
3598
2.50M
  tsAllowed &= ( !tu.cu->ispMode || !isLuma(compID) );
3599
2.50M
  SizeType transformSkipMaxSize = 1 << maxSize;
3600
2.50M
  tsAllowed &= !(tu.cu->bdpcmM[toChannelType(compID)]);
3601
2.50M
  tsAllowed &= tu.blocks[compID].width <= transformSkipMaxSize && tu.blocks[compID].height <= transformSkipMaxSize;
3602
2.50M
  tsAllowed &= !tu.cu->sbtInfo;
3603
3604
2.50M
  return tsAllowed;
3605
2.50M
}
3606
3607
int TU::getICTMode( const TransformUnit& tu, int jointCbCr )
3608
7.06M
{
3609
7.06M
  if( jointCbCr < 0 )
3610
6.09M
  {
3611
6.09M
    jointCbCr = tu.jointCbCr;
3612
6.09M
  }
3613
7.06M
  return g_ictModes[ tu.cs->picHeader->jointCbCrSign ][ jointCbCr ];
3614
7.06M
}
3615
3616
bool TU::needsSqrt2Scale( const TransformUnit& tu, const ComponentID compID )
3617
2.65M
{
3618
2.65M
  const Size& size=tu.blocks[compID];
3619
2.65M
  const bool isTransformSkip = tu.mtsIdx[compID] == MTS_SKIP;
3620
2.65M
  return (!isTransformSkip) && (((Log2(size.width * size.height)) & 1) == 1);
3621
2.65M
}
3622
3623
TransformUnit* TU::getPrevTU( const TransformUnit& tu, const ComponentID compID )
3624
24.2k
{
3625
24.2k
  TransformUnit* prevTU = tu.prev;
3626
3627
24.2k
  if( prevTU != nullptr && ( prevTU->cu != tu.cu || !prevTU->blocks[compID].valid() ) )
3628
0
  {
3629
0
    prevTU = nullptr;
3630
0
  }
3631
3632
24.2k
  return prevTU;
3633
24.2k
}
3634
3635
bool TU::getPrevTuCbfAtDepth( const TransformUnit& currentTu, const ComponentID compID, const int trDepth )
3636
24.2k
{
3637
24.2k
  const TransformUnit* prevTU = getPrevTU( currentTu, compID );
3638
24.2k
  return ( prevTU != nullptr ) ? TU::getCbfAtDepth( *prevTU, compID, trDepth ) : false;
3639
24.2k
}
3640
3641
3642
// other tools
3643
3644
uint32_t getCtuAddr( const Position& pos, const PreCalcValues& pcv )
3645
379k
{
3646
379k
  return ( pos.x >> pcv.maxCUSizeLog2 ) + ( pos.y >> pcv.maxCUSizeLog2 ) * pcv.widthInCtus;
3647
379k
}
3648
3649
uint32_t getCtuAddrFromCtuSize( const Position& pos, const unsigned maxCUSizeLog2, const unsigned widthInCtus )
3650
0
{
3651
0
  return ( pos.x >> maxCUSizeLog2 ) + ( pos.y >> maxCUSizeLog2 ) * widthInCtus;
3652
0
}
3653
3654
int getNumModesMip(const Size& block)
3655
290k
{
3656
290k
  switch( getMipSizeId(block) )
3657
290k
  {
3658
0
  case 0: return 16;
3659
6.31k
  case 1: return  8;
3660
283k
  case 2: return  6;
3661
0
  default: THROW( "Invalid mipSizeId" );
3662
290k
  }
3663
290k
}
3664
3665
int getMipSizeId(const Size& block)
3666
329k
{
3667
329k
  if( block.width == 4 && block.height == 4 )
3668
0
  {
3669
0
    return 0;
3670
0
  }
3671
329k
  else if( block.width == 4 || block.height == 4 || (block.width == 8 && block.height == 8) )
3672
6.66k
  {
3673
6.66k
    return 1;
3674
6.66k
  }
3675
322k
  else
3676
322k
  {
3677
322k
    return 2;
3678
322k
  }
3679
329k
}
3680
3681
bool allowLfnstWithMip(const Size& block)
3682
50.5k
{
3683
50.5k
  if (block.width >= 16 && block.height >= 16)
3684
46.6k
  {
3685
46.6k
    return true;
3686
46.6k
  }
3687
3.85k
  return false;
3688
50.5k
}
3689
3690
bool refPicCtuLineReady( const Slice& slice, const int refCtuRow, const PreCalcValues& pcv )
3691
0
{
3692
0
  const int checkRow = std::min( refCtuRow, (int)( pcv.heightInCtus ) - 1  );
3693
0
  for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
3694
0
  {
3695
0
    int numOfActiveRef = slice.numRefIdx[refList];
3696
0
    for (int i = 0; i < numOfActiveRef; i++)
3697
0
    {
3698
      // NOTE: one additional tile column signals finished CTU row
3699
0
      if (slice.refPicList[refList][i]->m_tileColsDone->at( checkRow ) < (slice.pps->numTileCols + 1) )
3700
0
      {
3701
0
        return false;
3702
0
      }
3703
0
    }
3704
0
  }
3705
0
  return true;
3706
0
}
3707
3708
} // namespace vvenc
3709
3710
//! \}
3711