Coverage Report

Created: 2026-07-25 07:06

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