Coverage Report

Created: 2026-06-16 07:20

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