Coverage Report

Created: 2026-04-01 07:49

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
0
{
68
0
#if GDR_ADJ
69
0
  return slice.isIntra() && slice.getSPS()->getUseDualITree();
70
#else
71
  return slice.isIRAP() && slice.getSPS()->getUseDualITree();
72
#endif
73
0
}
74
75
76
bool CU::isDualITree( const CodingUnit &cu )
77
0
{
78
0
#if GDR_ADJ
79
0
  return cu.slice->isIntra() && cu.sps->getUseDualITree();
80
#else
81
  return cu.slice->isIRAP() && cu.sps->getUseDualITree();
82
#endif
83
0
}
84
85
UnitArea getArea( const Slice &slice, const UnitArea &area, const ChannelType chType, const TreeType treeType )
86
0
{
87
0
  return isDualITree( slice ) || treeType != TREE_D ? area.singleChan( chType ) : area;
88
0
}
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
0
{
226
0
  return cu.slice->getIndependentSliceIdx() == cu2.slice->getIndependentSliceIdx();
227
0
}
228
229
bool CU::isSameTile(const CodingUnit& cu, const CodingUnit& cu2)
230
0
{
231
0
  return cu.tileIdx == cu2.tileIdx;
232
0
}
233
234
bool CU::isSameSliceAndTile(const CodingUnit& cu, const CodingUnit& cu2)
235
0
{
236
0
  return isSameSlice(cu, cu2) && isSameTile(cu, cu2);
237
0
}
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
0
{
246
0
  uint32_t ctuSizeBit = getLog2(cu.sps->getMaxCUWidth());
247
248
0
  Position pos1Ctu(cu.lumaPos().x  >> ctuSizeBit, cu.lumaPos().y  >> ctuSizeBit);
249
0
  Position pos2Ctu(cu2.lumaPos().x >> ctuSizeBit, cu2.lumaPos().y >> ctuSizeBit);
250
251
0
  return pos1Ctu.x == pos2Ctu.x && pos1Ctu.y == pos2Ctu.y;
252
0
}
253
254
bool CU::isAvailable( const CodingUnit& cu, const CodingUnit& cu2, const bool bEnforceSliceRestriction, const bool bEnforceTileRestriction, const bool bEnforceSubPicRestriction )
255
0
{
256
0
  return ( !bEnforceSliceRestriction || CU::isSameSlice( cu, cu2 ) )
257
0
         && ( !bEnforceTileRestriction || CU::isSameTile( cu, cu2 ) )
258
0
         && ( !bEnforceSubPicRestriction || CU::isSameSubPic( cu, cu2 ) );
259
0
}
260
261
uint32_t CU::getCtuAddr( const CodingUnit &cu )
262
0
{
263
0
  return getCtuAddr( cu.blocks[cu.chType()].lumaPos( cu.chromaFormat ), *cu.cs->pcv );
264
0
}
265
266
int CU::predictQP( const CodingUnit& cu, const int prevQP )
267
0
{
268
0
  const ChannelType      chType  = cu.chType();
269
0
  const CodingStructure& cs      = *cu.cs;
270
0
  const CodingUnit*      cuAbove = cs.getCU( cu.blocks[chType].pos().offset( 0, -1 ), chType );
271
0
  const CodingUnit*      cuLeft  = cs.getCU( cu.blocks[chType].pos().offset( -1, 0 ), chType );
272
273
0
  uint32_t  ctuRsAddr       = getCtuAddr( cu );
274
0
  uint32_t  ctuXPosInCtus   = ctuRsAddr % cs.pcv->widthInCtus;
275
0
  uint32_t  tileColIdx      = cu.pps->ctuToTileCol( ctuXPosInCtus );
276
0
  uint32_t  tileXPosInCtus  = cu.pps->getTileColumnBd( tileColIdx );
277
0
  if( ctuXPosInCtus == tileXPosInCtus &&
278
0
      !( cu.blocks[chType].x & ( cs.pcv->maxCUWidthMask  >> getChannelTypeScaleX( chType, cu.chromaFormat ) ) ) &&
279
0
      !( cu.blocks[chType].y & ( cs.pcv->maxCUHeightMask >> getChannelTypeScaleY( chType, cu.chromaFormat ) ) ) &&
280
0
       cuAbove != nullptr && CU::isSameSliceAndTile( *cuAbove, cu ) )
281
0
  {
282
0
    return cuAbove->qp;
283
0
  }
284
0
  else
285
0
  {
286
0
    const int a = ( cu.blocks[chType].y & ( cs.pcv->maxCUHeightMask >> getChannelTypeScaleY( chType, cu.chromaFormat ) ) ) ? cuAbove->qp : prevQP;
287
0
    const int b = ( cu.blocks[chType].x & ( cs.pcv->maxCUWidthMask  >> getChannelTypeScaleX( chType, cu.chromaFormat ) ) ) ? cuLeft->qp  : prevQP;
288
289
0
    return ( a + b + 1 ) >> 1;
290
0
  }
291
0
}
292
293
bool CU::divideTuInRows( const CodingUnit &cu )
294
0
{
295
0
  CHECK( cu.ispMode() != HOR_INTRA_SUBPARTITIONS && cu.ispMode() != VER_INTRA_SUBPARTITIONS, "Intra Subpartitions type not recognized!" );
296
0
  return cu.ispMode() == HOR_INTRA_SUBPARTITIONS ? true : false;
297
0
}
298
299
PartSplit CU::getISPType( const CodingUnit &cu, const ComponentID compID )
300
0
{
301
0
  if( cu.ispMode() && isLuma( compID ) )
302
0
  {
303
0
    const bool tuIsDividedInRows = CU::divideTuInRows( cu );
304
305
0
    return tuIsDividedInRows ? TU_1D_HORZ_SPLIT : TU_1D_VERT_SPLIT;
306
0
  }
307
0
  return TU_NO_ISP;
308
0
}
309
310
ISPType CU::canUseISPSplit( const CodingUnit &cu, const ComponentID compID )
311
0
{
312
0
  const int width     = cu.blocks[compID].width;
313
0
  const int height    = cu.blocks[compID].height;
314
0
  const int maxTrSize = cu.sps->getMaxTbSize();
315
316
0
  return CU::canUseISPSplit( width, height, maxTrSize );
317
0
}
318
319
bool CU::canUseLfnstWithISP( const CompArea& cuArea, const ISPType ispSplitType )
320
0
{
321
0
  if( ispSplitType == NOT_INTRA_SUBPARTITIONS )
322
0
  {
323
0
    return false;
324
0
  }
325
326
0
  const Size tuSize = ( ispSplitType == HOR_INTRA_SUBPARTITIONS )
327
0
    ? Size( cuArea.width, CU::getISPSplitDim( cuArea.width, cuArea.height, TU_1D_HORZ_SPLIT ) )
328
0
    : Size( CU::getISPSplitDim( cuArea.width, cuArea.height, TU_1D_VERT_SPLIT ), cuArea.height );
329
330
0
  if( !( tuSize.width >= MIN_TB_SIZEY && tuSize.height >= MIN_TB_SIZEY ) )
331
0
  {
332
0
    return false;
333
0
  }
334
0
  return true;
335
0
}
336
337
bool CU::canUseLfnstWithISP( const CodingUnit& cu, const ChannelType chType )
338
0
{
339
0
  CHECK( !isLuma( chType ), "Wrong ISP mode!" );
340
0
  return CU::canUseLfnstWithISP( cu.blocks[chType == CHANNEL_TYPE_LUMA ? 0 : 1], (ISPType)cu.ispMode() );
341
0
}
342
343
ISPType CU::canUseISPSplit( const int width, const int height, const int maxTrSize )
344
0
{
345
0
  const uint32_t minTuSizeForISP  = MIN_TB_SIZEY;
346
0
  bool  notEnoughSamplesToSplit   = ( getLog2( width ) + getLog2( height ) <= ( getLog2( minTuSizeForISP ) << 1 ) );
347
0
  bool  cuSizeLargerThanMaxTrSize = width  > maxTrSize || height > maxTrSize;
348
349
0
  int   widthCanBeUsed  = ( !cuSizeLargerThanMaxTrSize && !notEnoughSamplesToSplit ) ? 4 : 2;
350
0
  int   heightCanBeUsed = ( !cuSizeLargerThanMaxTrSize && !notEnoughSamplesToSplit ) ? 0 : 2;
351
352
0
  return ISPType( widthCanBeUsed >> heightCanBeUsed );
353
354
  //  widthCanBeUsed &&  heightCanBeUsed -> 4
355
  // !widthCanBeUsed &&  heightCanBeUsed -> 2
356
  //  widthCanBeUsed && !heightCanBeUsed -> 1
357
  // !widthCanBeUsed && !heightCanBeUsed -> 0
358
0
}
359
360
uint32_t CU::getISPSplitDim( const int width, const int height, const PartSplit ispType )
361
0
{
362
0
  bool divideTuInRows = ispType == TU_1D_HORZ_SPLIT;
363
0
  uint32_t splitDimensionSize, nonSplitDimensionSize, partitionSize, divShift = 2;
364
365
0
  if( divideTuInRows )
366
0
  {
367
0
    splitDimensionSize    = height;
368
0
    nonSplitDimensionSize = width;
369
0
  }
370
0
  else
371
0
  {
372
0
    splitDimensionSize    = width;
373
0
    nonSplitDimensionSize = height;
374
0
  }
375
376
0
  const int minNumberOfSamplesPerCu = 1 << ( ( getLog2(MIN_TB_SIZEY) << 1 ) );
377
0
  const int factorToMinSamples = nonSplitDimensionSize < minNumberOfSamplesPerCu ? minNumberOfSamplesPerCu >> getLog2(nonSplitDimensionSize) : 1;
378
0
  partitionSize = ( splitDimensionSize >> divShift ) < factorToMinSamples ? factorToMinSamples : ( splitDimensionSize >> divShift );
379
380
0
  CHECK( getLog2(partitionSize) + getLog2(nonSplitDimensionSize) < getLog2(minNumberOfSamplesPerCu), "A partition has less than the minimum amount of samples!" );
381
0
  return partitionSize;
382
0
}
383
384
// PU tools
385
386
int PU::getIntraMPMs( const CodingUnit &cu, unsigned* mpm, const ChannelType &channelType /*= CHANNEL_TYPE_LUMA*/ )
387
0
{
388
0
  const int numMPMs = NUM_MOST_PROBABLE_MODES;
389
0
  {
390
0
    CHECK(channelType != CHANNEL_TYPE_LUMA, "Not harmonized yet");
391
0
    int numCand      = -1;
392
0
    int leftIntraDir = PLANAR_IDX, aboveIntraDir = PLANAR_IDX;
393
394
0
    const CompArea &area = cu.block(getFirstComponentOfChannel(channelType));
395
0
    const Position posRT = area.topRight();
396
0
    const Position posLB = area.bottomLeft();
397
398
    // Get intra direction of left PU
399
0
    const CodingUnit *cuLeft = cu.cs->getCURestricted(posLB.offset(-1, 0), cu, channelType, cu.left);
400
0
    if( cuLeft && CU::isIntra( *cuLeft ) )
401
0
    {
402
0
      leftIntraDir = PU::getIntraDirLuma( *cuLeft );
403
0
    }
404
405
    // Get intra direction of above PU
406
0
    const CodingUnit *cuAbove = cu.cs->getCURestricted(posRT.offset(0, -1), cu, channelType, cu.above);
407
0
    if( cuAbove && CU::isIntra( *cuAbove ) && CU::isSameCtu( cu, *cuAbove ) )
408
0
    {
409
0
      aboveIntraDir = PU::getIntraDirLuma( *cuAbove );
410
0
    }
411
412
0
    CHECK(2 >= numMPMs, "Invalid number of most probable modes");
413
414
0
    const int offset = (int)NUM_LUMA_MODE - 6;
415
0
    const int mod = offset + 3;
416
417
0
    {
418
0
      mpm[0] = PLANAR_IDX;
419
0
      mpm[1] = DC_IDX;
420
0
      mpm[2] = VER_IDX;
421
0
      mpm[3] = HOR_IDX;
422
0
      mpm[4] = VER_IDX - 4;
423
0
      mpm[5] = VER_IDX + 4;
424
425
0
      if (leftIntraDir == aboveIntraDir)
426
0
      {
427
0
        numCand = 1;
428
0
        if (leftIntraDir > DC_IDX)
429
0
        {
430
0
          mpm[0] = PLANAR_IDX;
431
0
          mpm[1] = leftIntraDir;
432
0
          mpm[2] = ((leftIntraDir + offset) % mod) + 2;
433
0
          mpm[3] = ((leftIntraDir - 1) % mod) + 2;
434
0
          mpm[4] = ((leftIntraDir + offset - 1) % mod) + 2;
435
0
          mpm[5] = ( leftIntraDir               % mod) + 2;
436
0
        }
437
0
      }
438
0
      else //L!=A
439
0
      {
440
0
        numCand = 2;
441
0
        int  maxCandModeIdx = mpm[0] > mpm[1] ? 0 : 1;
442
443
0
        if ((leftIntraDir > DC_IDX) && (aboveIntraDir > DC_IDX))
444
0
        {
445
0
          mpm[0] = PLANAR_IDX;
446
0
          mpm[1] = leftIntraDir;
447
0
          mpm[2] = aboveIntraDir;
448
0
          maxCandModeIdx = mpm[1] > mpm[2] ? 1 : 2;
449
0
          int minCandModeIdx = mpm[1] > mpm[2] ? 2 : 1;
450
0
          if (mpm[maxCandModeIdx] - mpm[minCandModeIdx] == 1)
451
0
          {
452
0
            mpm[3] = ((mpm[minCandModeIdx] + offset)     % mod) + 2;
453
0
            mpm[4] = ((mpm[maxCandModeIdx] - 1)          % mod) + 2;
454
0
            mpm[5] = ((mpm[minCandModeIdx] + offset - 1) % mod) + 2;
455
0
          }
456
0
          else if (mpm[maxCandModeIdx] - mpm[minCandModeIdx] >= 62)
457
0
          {
458
0
            mpm[3] = ((mpm[minCandModeIdx] - 1)      % mod) + 2;
459
0
            mpm[4] = ((mpm[maxCandModeIdx] + offset) % mod) + 2;
460
0
            mpm[5] = ( mpm[minCandModeIdx]           % mod) + 2;
461
0
          }
462
0
          else if (mpm[maxCandModeIdx] - mpm[minCandModeIdx] == 2)
463
0
          {
464
0
            mpm[3] = ((mpm[minCandModeIdx] - 1)      % mod) + 2;
465
0
            mpm[4] = ((mpm[minCandModeIdx] + offset) % mod) + 2;
466
0
            mpm[5] = ((mpm[maxCandModeIdx] - 1)      % mod) + 2;
467
0
          }
468
0
          else
469
0
          {
470
0
            mpm[3] = ((mpm[minCandModeIdx] + offset) % mod) + 2;
471
0
            mpm[4] = ((mpm[minCandModeIdx] - 1)      % mod) + 2;
472
0
            mpm[5] = ((mpm[maxCandModeIdx] + offset) % mod) + 2;
473
0
          }
474
0
        }
475
0
        else if (leftIntraDir + aboveIntraDir >= 2)
476
0
        {
477
0
          mpm[0] = PLANAR_IDX;
478
0
          mpm[1] = (leftIntraDir < aboveIntraDir) ? aboveIntraDir : leftIntraDir;
479
0
          maxCandModeIdx = 1;
480
0
          mpm[2] = ((mpm[maxCandModeIdx] + offset)     % mod) + 2;
481
0
          mpm[3] = ((mpm[maxCandModeIdx] - 1)          % mod) + 2;
482
0
          mpm[4] = ((mpm[maxCandModeIdx] + offset - 1) % mod) + 2;
483
0
          mpm[5] = ( mpm[maxCandModeIdx]               % mod) + 2;
484
0
        }
485
0
      }
486
0
    }
487
0
    for (int i = 0; i < numMPMs; i++)
488
0
    {
489
0
      CHECK(mpm[i] >= NUM_LUMA_MODE, "Invalid MPM");
490
0
    }
491
0
    CHECK(numCand == 0, "No candidates found");
492
0
    return numCand;
493
0
  }
494
0
}
495
496
bool CU::isMIP( const CodingUnit &cu, const ChannelType &chType )
497
0
{
498
0
  if( chType == CHANNEL_TYPE_LUMA )
499
0
  {
500
    // Default case if chType is omitted.
501
0
    return cu.mipFlag();
502
0
  }
503
0
  else
504
0
  {
505
0
    return PU::isDMChromaMIP(cu) && (cu.intraDir[CHANNEL_TYPE_CHROMA] == DM_CHROMA_IDX);
506
0
  }
507
0
}
508
509
bool PU::isDMChromaMIP(const CodingUnit &cu)
510
0
{
511
0
  return !CU::isSepTree( cu ) && (cu.chromaFormat == CHROMA_444) && getCoLocatedLumaPU(cu).mipFlag();
512
0
}
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
0
{
533
0
  if( CU::isMIP( cu ) )
534
0
  {
535
0
    return PLANAR_IDX;
536
0
  }
537
0
  else
538
0
  {
539
0
    return cu.intraDir[CHANNEL_TYPE_LUMA];
540
0
  }
541
0
}
542
543
544
void PU::getIntraChromaCandModes( const CodingUnit &cu, unsigned modeList[NUM_CHROMA_MODE] )
545
0
{
546
0
  modeList[0] = PLANAR_IDX;
547
0
  modeList[1] = VER_IDX;
548
0
  modeList[2] = HOR_IDX;
549
0
  modeList[3] = DC_IDX;
550
0
  modeList[4] = LM_CHROMA_IDX;
551
0
  modeList[5] = MDLM_L_IDX;
552
0
  modeList[6] = MDLM_T_IDX;
553
0
  modeList[7] = DM_CHROMA_IDX;
554
555
  // If Direct Mode is MIP, mode cannot be already in the list.
556
0
  if( isDMChromaMIP(cu) )
557
0
  {
558
0
    return;
559
0
  }
560
561
0
  const uint32_t lumaMode = getCoLocatedIntraLumaMode( cu );
562
0
  for( int i = 0; i < 4; i++ )
563
0
  {
564
0
    if( lumaMode == modeList[i] )
565
0
    {
566
0
      modeList[i] = VDIA_IDX;
567
0
      break;
568
0
    }
569
0
  }
570
0
}
571
572
573
bool PU::isLMCMode(unsigned mode)
574
0
{
575
0
  return mode >= LM_CHROMA_IDX && mode <= MDLM_T_IDX;
576
0
}
577
578
int PU::getLMSymbolList( const CodingUnit &cu, int *pModeList )
579
0
{
580
0
  pModeList[0] = LM_CHROMA_IDX;
581
0
  pModeList[1] = MDLM_L_IDX;
582
0
  pModeList[2] = MDLM_T_IDX;
583
584
0
  return 3;
585
0
}
586
587
uint32_t PU::getFinalIntraMode( const CodingUnit &cu, const ChannelType &chType )
588
0
{
589
0
  uint32_t uiIntraMode = cu.intraDir[chType];
590
591
0
  if( uiIntraMode == DM_CHROMA_IDX && !isLuma( chType ) )
592
0
  {
593
0
    uiIntraMode = getCoLocatedIntraLumaMode( cu );
594
0
  }
595
0
  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
0
  return uiIntraMode;
600
0
}
601
602
const CodingUnit &PU::getCoLocatedLumaPU( const CodingUnit &cu )
603
0
{
604
0
  Position              topLeftPos = cu.blocks[cu.chType()].lumaPos ( cu.chromaFormat );
605
0
  Position refPos     = topLeftPos.offset( cu.blocks[cu.chType()].lumaSize( cu.chromaFormat ).width >> 1, cu.blocks[cu.chType()].lumaSize( cu.chromaFormat ).height >> 1 );
606
607
0
  const CodingUnit &lumaPU = CU::isSepTree( cu ) ? *cu.cs->getCU( refPos, CHANNEL_TYPE_LUMA ) : cu;
608
609
0
  return lumaPU;
610
0
}
611
612
uint32_t PU::getCoLocatedIntraLumaMode( const CodingUnit &cu )
613
0
{
614
0
  return PU::getIntraDirLuma( PU::getCoLocatedLumaPU(cu) );
615
0
}
616
617
int PU::getWideAngIntraMode( const TransformUnit &tu, const uint32_t dirMode, const ComponentID compID )
618
0
{
619
0
  if( dirMode < 2 )
620
0
  {
621
0
    return ( int ) dirMode;
622
0
  }
623
0
  const CompArea&  area         = tu.cu->ispMode() && isLuma(compID) ? tu.cu->blocks[compID] : tu.blocks[ compID ];
624
0
  int              width        = int( area.width );
625
0
  int              height       = int( area.height );
626
0
  static const int modeShift[ ] = { 0, 6, 10, 12, 14, 15 };
627
0
  int              deltaSize    = abs( getLog2( width ) - getLog2( height ) );
628
0
  int              predMode     = dirMode;
629
630
0
  if( width > height && dirMode < 2 + modeShift[ deltaSize ] )
631
0
  {
632
0
    predMode += ( VDIA_IDX - 1 );
633
0
  }
634
0
  else if( height > width && predMode > VDIA_IDX - modeShift[ deltaSize ] )
635
0
  {
636
0
    predMode -= ( VDIA_IDX + 1 );
637
0
  }
638
639
0
  return predMode;
640
0
}
641
642
bool PU::xCheckSimilarMotion(const int mergeCandIndex, const int prevCnt, const MergeCtx& mergeCandList, bool hasPruned[MRG_MAX_NUM_CANDS])
643
0
{
644
0
  for (uint32_t ui = 0; ui < prevCnt; ui++)
645
0
  {
646
0
    if (hasPruned[ui])
647
0
    {
648
0
      continue;
649
0
    }
650
0
    if (mergeCandList.interDirNeighbours[ui] == mergeCandList.interDirNeighbours[mergeCandIndex])
651
0
    {
652
0
      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
0
      else
667
0
      {
668
0
        int offset0 = (ui             * 2) + mergeCandList.interDirNeighbours[ui] - 1;
669
0
        int offset1 = (mergeCandIndex * 2) + mergeCandList.interDirNeighbours[ui] - 1;
670
0
        if (mergeCandList.mvFieldNeighbours[offset0].mfRefIdx == mergeCandList.mvFieldNeighbours[offset1].mfRefIdx &&
671
0
            mergeCandList.mvFieldNeighbours[offset0].mv       == mergeCandList.mvFieldNeighbours[offset1].mv
672
0
          )
673
0
        {
674
0
          hasPruned[ui] = true;
675
0
          return true;
676
0
        }
677
0
      }
678
0
    }
679
0
  }
680
681
0
  return false;
682
0
}
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
0
{
687
0
  bool hasPruned[MRG_MAX_NUM_CANDS];
688
0
  memset(hasPruned, 0, MRG_MAX_NUM_CANDS * sizeof(bool));
689
0
  if (isAvailableSubPu)
690
0
  {
691
0
    hasPruned[subPuMvpPos] = true;
692
0
  }
693
0
  auto &lut = ibcFlag ? hist.motionLutIbc : hist.motionLut;
694
0
  int num_avai_candInLUT = (int) lut.size();
695
696
0
  for (int mrgIdx = 1; mrgIdx <= num_avai_candInLUT; mrgIdx++)
697
0
  {
698
0
    const HPMVInfo &miNeighbor = lut[(num_avai_candInLUT - mrgIdx)];
699
0
    mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir();
700
0
    mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.mhRefIdx[0]);
701
0
    mrgCtx.useAltHpelIf[cnt] = !ibcFlag && miNeighbor.useAltHpelIf;
702
0
    if (isInterB)
703
0
    {
704
0
      mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.mhRefIdx[1]);
705
0
    }
706
0
    if (mrgIdx > 2 || ((mrgIdx > 1 || !isGt4x4) && ibcFlag) || !xCheckSimilarMotion(cnt, prevCnt, mrgCtx, hasPruned))
707
0
    {
708
0
      mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? miNeighbor.BcwIdx : BCW_DEFAULT;
709
0
      if (mrgCandIdx == cnt && canFastExit)
710
0
      {
711
0
        return true;
712
0
      }
713
0
      cnt ++;
714
0
      if (cnt  == maxNumMergeCandMin1)
715
0
      {
716
0
        break;
717
0
      }
718
0
    }
719
0
  }
720
0
  if (cnt < maxNumMergeCandMin1)
721
0
  {
722
0
    mrgCtx.useAltHpelIf[cnt] = false;
723
0
  }
724
0
  return false;
725
0
}
726
727
void PU::getIBCMergeCandidates(const CodingUnit &cu, MergeCtx& mrgCtx, MotionHist& hist, const int& mrgCandIdx)
728
0
{
729
0
  const CodingStructure &cs = *cu.cs;
730
0
  const Slice &slice = *cu.slice;
731
0
  const uint32_t maxNumMergeCand = slice.getPicHeader()->getMaxNumIBCMergeCand();
732
0
  const bool canFastExit = true; // TODO: remove this
733
734
0
  for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui)
735
0
  {
736
0
    mrgCtx.BcwIdx[ui] = BCW_DEFAULT;
737
0
    mrgCtx.interDirNeighbours[ui] = 0;
738
0
    mrgCtx.mrgTypeNeighbours[ui] = MRG_TYPE_IBC;
739
0
    mrgCtx.mvFieldNeighbours[ui * 2].mfRefIdx = MF_NOT_VALID;
740
0
    mrgCtx.mvFieldNeighbours[ui * 2 + 1].mfRefIdx = MF_NOT_VALID;
741
0
    mrgCtx.useAltHpelIf[ui] = false;
742
0
  }
743
744
0
  mrgCtx.numValidMergeCand = maxNumMergeCand;
745
  // compute the location of the current PU
746
747
0
  int cnt = 0;
748
749
0
  const Position posRT = cu.Y().topRight();
750
0
  const Position posLB = cu.Y().bottomLeft();
751
752
0
  MotionInfo miAbove, miLeft, miAboveLeft, miAboveRight, miBelowLeft;
753
754
  //left
755
0
  const CodingUnit* cuLeft = cs.getCURestricted(posLB.offset(-1, 0), cu, CH_L, cu.left);
756
0
  const bool isAvailableA1 = cuLeft && CU::isIBC(*cuLeft);
757
0
  bool isGt4x4 = cu.lwidth() * cu.lheight() > 16;
758
0
  if (isGt4x4 && isAvailableA1)
759
0
  {
760
0
    miLeft             = cuLeft->getMotionInfo(posLB.offset(-1, 0));
761
0
    miLeft.miRefIdx[0] = MI_NOT_VALID + 1;
762
763
    // get Inter Dir
764
0
    mrgCtx.interDirNeighbours[cnt] = miLeft.interDir();
765
    // get Mv from Left
766
0
    mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miLeft.mv[0], 0 );
767
0
    if (mrgCandIdx == cnt && canFastExit)
768
0
    {
769
0
      return;
770
0
    }
771
0
    cnt++;
772
0
  }
773
774
  // early termination
775
0
  if (cnt == maxNumMergeCand)
776
0
  {
777
0
    return;
778
0
  }
779
780
781
  // above
782
0
  const CodingUnit *cuAbove = cs.getCURestricted(posRT.offset(0, -1), cu, CH_L, cu.above);
783
0
  bool isAvailableB1 = cuAbove && CU::isIBC(*cuAbove);
784
0
  if (isGt4x4 && isAvailableB1)
785
0
  {
786
0
    miAbove             = cuAbove->getMotionInfo(posRT.offset(0, -1));
787
0
    miAbove.miRefIdx[0] = MI_NOT_VALID + 1;
788
789
0
    if (!isAvailableA1 || cuAbove->slice->getIndependentSliceIdx() != cuLeft->slice->getIndependentSliceIdx() || miAbove != miLeft)
790
0
    {
791
      // get Inter Dir
792
0
      mrgCtx.interDirNeighbours[cnt] = miAbove.interDir();
793
      // get Mv from Above
794
0
      mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAbove.mv[0], 0 );
795
0
      if (mrgCandIdx == cnt && canFastExit)
796
0
      {
797
0
        return;
798
0
      }
799
800
0
      cnt++;
801
0
    }
802
0
  }
803
804
  // early termination
805
0
  if (cnt == maxNumMergeCand)
806
0
  {
807
0
    return;
808
0
  }
809
810
0
  int spatialCandPos = cnt;
811
812
813
0
  int maxNumMergeCandMin1 = maxNumMergeCand;
814
0
  if( cnt != maxNumMergeCandMin1 )
815
0
  {
816
0
    bool isAvailableSubPu = false;
817
0
    unsigned subPuMvpPos = 0;
818
819
0
    bool bFound = addMergeHMVPCand( cs, mrgCtx, hist, canFastExit, mrgCandIdx, maxNumMergeCandMin1, cnt, spatialCandPos, isAvailableSubPu, subPuMvpPos, true, isGt4x4, cu.slice->isInterB() );
820
0
    if( bFound )
821
0
    {
822
0
      return;
823
0
    }
824
0
  }
825
826
0
  while( cnt < maxNumMergeCand )
827
0
  {
828
0
    mrgCtx.mvFieldNeighbours [cnt * 2].setMvField( Mv( 0, 0 ), NOT_VALID );
829
0
    mrgCtx.interDirNeighbours[cnt] = 1;
830
0
    cnt++;
831
0
    if( mrgCandIdx == cnt && canFastExit )
832
0
    {
833
0
      return;
834
0
    }
835
0
  }
836
837
0
  mrgCtx.numValidMergeCand = cnt;
838
0
}
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
0
{
1538
1539
0
  AMVPInfo *pInfo = &amvpInfo;
1540
1541
0
  pInfo->numCand = 0;
1542
1543
0
  MergeCtx mergeCtx;
1544
0
  PU::getIBCMergeCandidates(cu, mergeCtx, hist, AMVP_MAX_NUM_CANDS - 1);
1545
0
  int candIdx = 0;
1546
0
  while (pInfo->numCand < AMVP_MAX_NUM_CANDS)
1547
0
  {
1548
0
    pInfo->mvCand[pInfo->numCand] = mergeCtx.mvFieldNeighbours[(candIdx << 1) + 0].mv;;
1549
0
    pInfo->numCand++;
1550
0
    candIdx++;
1551
0
  }
1552
1553
0
  for (Mv &mv : pInfo->mvCand)
1554
0
  {
1555
0
    mv.roundToPrecision( MV_PRECISION_INTERNAL, cu.imv() == 2 ? MV_PRECISION_4PEL : MV_PRECISION_INT );
1556
0
  }
1557
0
}
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
0
{
2177
0
  const SizeType w = cu.lwidth(), h = cu.lheight();
2178
  /* disable bi-prediction for 4x8/8x4 */
2179
0
  return ( w + h <= 12 );
2180
0
}
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
2931
0
  if( true )
2932
0
  {
2933
0
    int xOff = (puWidth >> 1) + tempX;
2934
0
    int yOff = (puHeight >> 1) + tempY;
2935
2936
0
    MotionBuf& mb = mrgCtx.subPuMvpMiBuf;
2937
2938
0
    const bool isBiPred = isBipredRestriction(cu);
2939
2940
0
    MotionInfo mi;
2941
2942
0
    MotionInfo* miPtr = mb.buf;
2943
2944
0
    for( int y = puPos.y; y < puPos.y + puSize.height; y += puHeight, miPtr += g_miScaling.scaleVer( puHeight ) * mb.stride )
2945
0
    {
2946
0
      MotionInfo* miLinePtr = miPtr;
2947
0
      for( int x = puPos.x; x < puPos.x + puSize.width; x += puWidth, miLinePtr += g_miScaling.scaleHor( puWidth ) )
2948
0
      {
2949
0
        mi.miRefIdx[0] = mi.miRefIdx[1] = MI_NOT_VALID;
2950
0
        memset( NO_WARNING_class_memaccess( mi.mv ), 0, sizeof( mi.mv ) );
2951
2952
0
        Position colPos{ x + xOff, y + yOff };
2953
2954
0
        clipColPos( colPos.x, colPos.y, cu );
2955
2956
0
        const Slice* pColSlice;
2957
0
        const ColocatedMotionInfo&
2958
0
                     colMi = pColPic->cs->getColInfo( colPos, pColSlice );
2959
0
        bool found = false;
2960
2961
0
        if (colMi.isInter())
2962
0
        {
2963
0
          for (unsigned currRefListId = 0; currRefListId < (!isBiPred && bBSlice ? 2 : 1); currRefListId++)
2964
0
          {
2965
0
            RefPicList currRefPicList = RefPicList(currRefListId);
2966
0
            if( getColocatedMVP( cu, currRefPicList, colPos, cColMv, 0, true ) )
2967
0
            {
2968
0
              mi.miRefIdx[currRefListId] = 0;
2969
0
              mi.mv[currRefListId] = cColMv;
2970
0
              found = true;
2971
0
            }
2972
0
          }
2973
0
        }
2974
        
2975
0
        if( !found )
2976
0
        {
2977
          // intra coded, in this case, no motion vector is available for list 0 or list 1, so use default
2978
0
          mi.mv[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0][0].mv;
2979
0
          mi.mv[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1][0].mv;
2980
0
          mi.miRefIdx[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0][0].mfRefIdx;
2981
0
          mi.miRefIdx[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1][0].mfRefIdx;
2982
0
        }
2983
2984
0
        if( isBiPred && mi.interDir() == 3 )
2985
0
        {
2986
0
          mi.mv[1]      = Mv();
2987
0
          mi.miRefIdx[1]  = MI_NOT_VALID;
2988
0
        }
2989
2990
0
        *  miLinePtr                   = mi;
2991
0
        *( miLinePtr             + 1 ) = mi;
2992
0
        *( miLinePtr + mb.stride     ) = mi;
2993
0
        *( miLinePtr + mb.stride + 1 ) = mi;
2994
0
      }
2995
0
    }
2996
0
  }
2997
0
  return true;
2998
0
}
2999
3000
void PU::spanMotionInfo( CodingUnit &cu )
3001
0
{
3002
0
  MotionBuf mb = cu.getMotionBuf();
3003
3004
0
  if( !cu.mergeFlag() || cu.mergeType() == MRG_TYPE_DEFAULT_N || cu.mergeType() == MRG_TYPE_IBC )
3005
0
  {
3006
0
    MotionInfo mi;
3007
3008
0
    bool isIbc = CU::isIBC( cu );
3009
3010
0
    for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ )
3011
0
    {
3012
0
      mi.mv[i]       = cu.mv[i][0];
3013
0
      mi.miRefIdx[i] = isIbc ? MI_NOT_VALID : cu.refIdx[i];
3014
0
    }
3015
3016
0
    if( cu.affineFlag() )
3017
0
    {
3018
0
      for( int y = 0; y < mb.height; y++ )
3019
0
      {
3020
0
        for( int x = 0; x < mb.width; x++ )
3021
0
        {
3022
0
          MotionInfo &dest  = mb.at( x, y );
3023
3024
0
          for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ )
3025
0
          {
3026
0
            if( isMotionInvalid( mi.miRefIdx[i], MI_NOT_VALID ) )
3027
0
            {
3028
0
              dest.mv[i] = Mv();
3029
0
            }
3030
0
            dest.miRefIdx[i] = mi.miRefIdx[i];
3031
0
          }
3032
0
        }
3033
0
      }
3034
0
    }
3035
0
    else
3036
0
    {
3037
0
      mb.fill( mi );
3038
0
    }
3039
0
  }
3040
0
  else
3041
0
  {
3042
    // cu.mergeType() == MRG_TYPE_SUBPU_ATMVP
3043
    // already done
3044
0
  }
3045
0
}
3046
3047
void PU::applyImv( CodingUnit& cu, MotionHist& hist )
3048
0
{
3049
0
  CHECKD( cu.mergeFlag(), "IMV should never be applied to merge!" );
3050
3051
0
  Mv mvd;
3052
3053
0
  if( cu.interDir() != 2 /* PRED_L1 */ )
3054
0
  {
3055
0
    mvd = cu.mv[0][0];
3056
0
    mvd.changePrecisionAmvr( cu.imv(), MV_PRECISION_INTERNAL );
3057
0
    unsigned mvp_idx = cu.mvpIdx[0];
3058
0
    AMVPInfo amvpInfo;
3059
3060
0
    if( CU::isIBC( cu ) )
3061
0
      PU::fillIBCMvpCand( cu, amvpInfo, hist );
3062
0
    else
3063
0
      PU::fillMvpCand( cu, REF_PIC_LIST_0, cu.refIdx[0], amvpInfo, hist );
3064
3065
0
    cu.mvpIdx[0]    = mvp_idx;
3066
0
    cu.mv    [0][0] = amvpInfo.mvCand[mvp_idx] + mvd;
3067
0
    cu.mv    [0][0] . mvCliptoStorageBitDepth();
3068
0
  }
3069
3070
0
  if( cu.interDir() != 1 /* PRED_L0 */ )
3071
0
  {
3072
0
    mvd = cu.mv[1][0];
3073
3074
0
    if( !( cu.cs->picHeader->getMvdL1ZeroFlag() && cu.interDir() == 3 ) && cu.imv() )/* PRED_BI */
3075
0
    {
3076
0
      mvd.changePrecisionAmvr( cu.imv(), MV_PRECISION_INTERNAL );
3077
0
    }
3078
3079
0
    unsigned mvp_idx = cu.mvpIdx[1];
3080
0
    AMVPInfo amvpInfo;
3081
0
    PU::fillMvpCand( cu, REF_PIC_LIST_1, cu.refIdx[1], amvpInfo, hist );
3082
0
    cu.mvpIdx[1]    = mvp_idx;
3083
0
    cu.mv    [1][0] = amvpInfo.mvCand[mvp_idx] + mvd;
3084
0
    cu.mv    [1][0] . mvCliptoStorageBitDepth();
3085
0
  }
3086
0
}
3087
3088
3089
bool PU::isBiPredFromDifferentDirEqDistPoc( const CodingUnit& cu )
3090
0
{
3091
0
  if( cu.refIdx[0] >= 0 && cu.refIdx[1] >= 0 )
3092
0
  {
3093
0
    if( cu.slice->getIsUsedAsLongTerm( REF_PIC_LIST_0, cu.refIdx[0] ) || cu.slice->getIsUsedAsLongTerm( REF_PIC_LIST_1, cu.refIdx[1] ) )
3094
0
    {
3095
0
      return false;
3096
0
    }
3097
0
    const int poc0 = cu.slice->getRefPOC( REF_PIC_LIST_0, cu.refIdx[0] );
3098
0
    const int poc1 = cu.slice->getRefPOC( REF_PIC_LIST_1, cu.refIdx[1] );
3099
0
    const int poc  = cu.slice->getPOC();
3100
3101
0
    return ( poc - poc0 ) == ( poc1 - poc );
3102
0
  }
3103
0
  return false;
3104
0
}
3105
3106
void PU::restrictBiPredMergeCandsOne( CodingUnit &cu )
3107
0
{
3108
0
  if( PU::isBipredRestriction( cu ) )
3109
0
  {
3110
0
    if( cu.interDir() == 3 )
3111
0
    {
3112
0
      cu.setInterDir(  1 );
3113
0
      cu.refIdx[1]  = -1;
3114
0
      cu.mv[1][0]   = Mv( 0, 0 );
3115
0
      cu.setBcwIdx  ( BCW_DEFAULT );
3116
0
    }
3117
0
  }
3118
0
}
3119
3120
void PU::getGeoMergeCandidates( const CodingUnit &cu, MergeCtx& geoMrgCtx, MotionHist& hist )
3121
0
{
3122
0
  MergeCtx tmpMergeCtx;
3123
3124
0
  const Slice &slice = *cu.slice;
3125
0
  const uint32_t maxNumMergeCand = slice.getSPS()->getMaxNumMergeCand();
3126
3127
0
  geoMrgCtx.numValidMergeCand = 0;
3128
3129
0
  for (int32_t i = 0; i < GEO_MAX_NUM_UNI_CANDS; i++)
3130
0
  {
3131
0
    geoMrgCtx.BcwIdx[i] = BCW_DEFAULT;
3132
0
    geoMrgCtx.interDirNeighbours[i] = 0;
3133
0
    geoMrgCtx.mrgTypeNeighbours[i] = MRG_TYPE_DEFAULT_N;
3134
0
    geoMrgCtx.mvFieldNeighbours[(i << 1)].mfRefIdx = MF_NOT_VALID;
3135
0
    geoMrgCtx.mvFieldNeighbours[(i << 1) + 1].mfRefIdx = MF_NOT_VALID;
3136
0
    geoMrgCtx.mvFieldNeighbours[(i << 1)].mv = Mv();
3137
0
    geoMrgCtx.mvFieldNeighbours[(i << 1) + 1].mv = Mv();
3138
0
    geoMrgCtx.useAltHpelIf[i] = false;
3139
0
  }
3140
3141
0
  PU::getInterMergeCandidates(cu, tmpMergeCtx, hist);
3142
3143
0
  for (int32_t i = 0; i < maxNumMergeCand; i++)
3144
0
  {
3145
0
    int parity = i & 1;
3146
0
    if( tmpMergeCtx.interDirNeighbours[i] & (0x01 + parity) )
3147
0
    {
3148
0
      geoMrgCtx.interDirNeighbours[geoMrgCtx.numValidMergeCand] = 1 + parity;
3149
0
      geoMrgCtx.mrgTypeNeighbours[geoMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
3150
0
      geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].mv = Mv(0, 0);
3151
0
      geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].mv;
3152
0
      geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].mfRefIdx = -1;
3153
0
      geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].mfRefIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].mfRefIdx;
3154
0
      geoMrgCtx.numValidMergeCand++;
3155
0
      if (geoMrgCtx.numValidMergeCand == GEO_MAX_NUM_UNI_CANDS)
3156
0
      {
3157
0
        return;
3158
0
      }
3159
0
      continue;
3160
0
    }
3161
3162
0
    if (tmpMergeCtx.interDirNeighbours[i] & (0x02 - parity))
3163
0
    {
3164
0
      geoMrgCtx.interDirNeighbours[geoMrgCtx.numValidMergeCand] = 2 - parity;
3165
0
      geoMrgCtx.mrgTypeNeighbours[geoMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
3166
0
      geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].mv;
3167
0
      geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].mv = Mv(0, 0);
3168
0
      geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].mfRefIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].mfRefIdx;
3169
0
      geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].mfRefIdx = -1;
3170
0
      geoMrgCtx.numValidMergeCand++;
3171
0
      if (geoMrgCtx.numValidMergeCand == GEO_MAX_NUM_UNI_CANDS)
3172
0
      {
3173
0
        return;
3174
0
      }
3175
0
    }
3176
0
  }
3177
0
}
3178
3179
void PU::spanGeoMotionInfo( CodingUnit &cu, MergeCtx &geoMrgCtx, const uint8_t splitDir, const uint8_t candIdx0, const uint8_t candIdx1)
3180
0
{
3181
0
  uint8_t off0 = geoMrgCtx.interDirNeighbours[candIdx0] == 1 ? 0 : 1;
3182
0
  uint8_t off1 = geoMrgCtx.interDirNeighbours[candIdx1] == 1 ? 0 : 1;
3183
3184
0
  cu.mv[0][1] = geoMrgCtx.mvFieldNeighbours[( candIdx0 << 1 ) + off0].mv;
3185
0
  cu.mv[1][1] = geoMrgCtx.mvFieldNeighbours[( candIdx1 << 1 ) + off1].mv;
3186
3187
0
  uint8_t val0 = geoMrgCtx.interDirNeighbours[candIdx0];
3188
0
  uint8_t val1 = geoMrgCtx.interDirNeighbours[candIdx1];
3189
0
  val0 <<= 4;
3190
0
  val1 <<= 4;
3191
0
  val0 += geoMrgCtx.mvFieldNeighbours[( candIdx0 << 1 ) + off0].mfRefIdx;
3192
0
  val1 += geoMrgCtx.mvFieldNeighbours[( candIdx1 << 1 ) + off1].mfRefIdx;
3193
3194
0
  cu.setInterDirrefIdxGeo0( val0 );
3195
0
  cu.setInterDirrefIdxGeo1( val1 );
3196
3197
0
  MotionBuf mb = cu.getMotionBuf();
3198
3199
0
  MotionInfo biMv;
3200
3201
0
  if( geoMrgCtx.interDirNeighbours[candIdx0] == 1 && geoMrgCtx.interDirNeighbours[candIdx1] == 2 )
3202
0
  {
3203
0
    biMv.mv[0]     = geoMrgCtx.mvFieldNeighbours[ candIdx0 << 1     ].mv;
3204
0
    biMv.mv[1]     = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
3205
0
    biMv.miRefIdx[0] = geoMrgCtx.mvFieldNeighbours[ candIdx0 << 1     ].mfRefIdx;
3206
0
    biMv.miRefIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mfRefIdx;
3207
0
  }
3208
0
  else if( geoMrgCtx.interDirNeighbours[candIdx0] == 2 && geoMrgCtx.interDirNeighbours[candIdx1] == 1 )
3209
0
  {
3210
0
    biMv.mv[0]     = geoMrgCtx.mvFieldNeighbours[ candIdx1 << 1     ].mv;
3211
0
    biMv.mv[1]     = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
3212
0
    biMv.miRefIdx[0] = geoMrgCtx.mvFieldNeighbours[ candIdx1 << 1     ].mfRefIdx;
3213
0
    biMv.miRefIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mfRefIdx;
3214
0
  }
3215
0
  else if( geoMrgCtx.interDirNeighbours[candIdx0] == 1 && geoMrgCtx.interDirNeighbours[candIdx1] == 1 )
3216
0
  {
3217
0
    biMv.mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv;
3218
0
    biMv.mv[1] = Mv(0, 0);
3219
0
    biMv.miRefIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].mfRefIdx;
3220
0
    biMv.miRefIdx[1] = MI_NOT_VALID;
3221
0
  }
3222
0
  else if( geoMrgCtx.interDirNeighbours[candIdx0] == 2 && geoMrgCtx.interDirNeighbours[candIdx1] == 2 )
3223
0
  {
3224
0
    biMv.mv[0] = Mv(0, 0);
3225
0
    biMv.mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
3226
0
    biMv.miRefIdx[0] = MI_NOT_VALID;
3227
0
    biMv.miRefIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mfRefIdx;
3228
0
  }
3229
3230
0
  int16_t angle = g_GeoParams[splitDir][0];
3231
0
  int tpmMask = 0;
3232
0
  int lookUpY = 0, motionIdx = 0;
3233
0
  bool isFlip = angle >= 13 && angle <= 27;
3234
0
  int distanceIdx = g_GeoParams[splitDir][1];
3235
0
  int distanceX = angle;
3236
0
  int distanceY = (distanceX + (GEO_NUM_ANGLES >> 2)) % GEO_NUM_ANGLES;
3237
0
  int offsetX = (-(int)cu.lwidth()) >> 1;
3238
0
  int offsetY = (-(int)cu.lheight()) >> 1;
3239
0
  if (distanceIdx > 0)
3240
0
  {
3241
0
    if (angle % 16 == 8 || (angle % 16 != 0 && cu.lheight() >= cu.lwidth()))
3242
0
      offsetY += angle < 16 ? ((distanceIdx * cu.lheight()) >> 3) : -(int)((distanceIdx * cu.lheight()) >> 3);
3243
0
    else
3244
0
      offsetX += angle < 16 ? ((distanceIdx * cu.lwidth()) >> 3) : -(int)((distanceIdx * cu.lwidth()) >> 3);
3245
0
  }
3246
0
  for (int y = 0; y < mb.height; y++)
3247
0
  {
3248
0
    lookUpY = (((4 * y + offsetY) *2) + 5) * g_Dis[distanceY];
3249
0
    for (int x = 0; x < mb.width; x++)
3250
0
    {
3251
0
      motionIdx = (((4 * x + offsetX) *2) + 5) * g_Dis[distanceX] + lookUpY;
3252
0
      tpmMask = abs(motionIdx) < 32 ? 2 : (motionIdx <= 0 ? (1 - isFlip) : isFlip);
3253
0
      if (tpmMask == 2)
3254
0
      {
3255
0
        mb.at(x, y) = biMv;
3256
0
      }
3257
0
      else if (tpmMask == 0)
3258
0
      {
3259
0
        mb.at(x, y).miRefIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx0 << 1].mfRefIdx;
3260
0
        mb.at(x, y).miRefIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mfRefIdx;
3261
0
        mb.at(x, y).mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx0 << 1].mv;
3262
0
        mb.at(x, y).mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
3263
0
      }
3264
0
      else
3265
0
      {
3266
0
        mb.at(x, y).miRefIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].mfRefIdx;
3267
0
        mb.at(x, y).miRefIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mfRefIdx;
3268
0
        mb.at(x, y).mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv;
3269
0
        mb.at(x, y).mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
3270
0
      }
3271
0
    }
3272
0
  }
3273
0
}
3274
3275
// CU
3276
3277
bool CU::hasSubCUNonZeroMVd( const CodingUnit& cu )
3278
0
{
3279
0
  bool bNonZeroMvd = false;
3280
3281
0
  if( cu.interDir() != 2 /* PRED_L1 */ )
3282
0
  {
3283
0
    bNonZeroMvd |= cu.mv[REF_PIC_LIST_0][0].getHor() != 0;
3284
0
    bNonZeroMvd |= cu.mv[REF_PIC_LIST_0][0].getVer() != 0;
3285
0
  }
3286
0
  if( cu.interDir() != 1 /* PRED_L0 */ )
3287
0
  {
3288
0
    if( !cu.cs->picHeader->getMvdL1ZeroFlag() || cu.interDir() != 3 /* PRED_BI */ )
3289
0
    {
3290
0
      bNonZeroMvd |= cu.mv[REF_PIC_LIST_1][0].getHor() != 0;
3291
0
      bNonZeroMvd |= cu.mv[REF_PIC_LIST_1][0].getVer() != 0;
3292
0
    }
3293
0
  }
3294
3295
0
  return bNonZeroMvd;
3296
0
}
3297
3298
bool CU::hasSubCUNonZeroAffineMVd( const CodingUnit& cu )
3299
0
{
3300
0
  bool nonZeroAffineMvd = false;
3301
3302
0
  if( cu.interDir() != 2 /* PRED_L1 */ )
3303
0
  {
3304
0
    for( int i = 0; !nonZeroAffineMvd && i < ( cu.affineType() == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
3305
0
    {
3306
0
      nonZeroAffineMvd |= cu.mv[REF_PIC_LIST_0][i].getHor() != 0;
3307
0
      nonZeroAffineMvd |= cu.mv[REF_PIC_LIST_0][i].getVer() != 0;
3308
0
    }
3309
0
  }
3310
3311
0
  if( !nonZeroAffineMvd && cu.interDir() != 1 /* PRED_L0 */ )
3312
0
  {
3313
0
    if ( !cu.cs->picHeader->getMvdL1ZeroFlag() || cu.interDir() != 3 /* PRED_BI */ )
3314
0
    {
3315
0
      for( int i = 0; !nonZeroAffineMvd && i < ( cu.affineType() == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
3316
0
      {
3317
0
        nonZeroAffineMvd |= cu.mv[REF_PIC_LIST_1][i].getHor() != 0;
3318
0
        nonZeroAffineMvd |= cu.mv[REF_PIC_LIST_1][i].getVer() != 0;
3319
0
      }
3320
0
    }
3321
0
  }
3322
3323
0
  return nonZeroAffineMvd;
3324
0
}
3325
3326
uint8_t CU::getSbtIdx( const uint8_t sbtInfo )
3327
0
{
3328
0
  return ( sbtInfo >> 0 ) & 0xf;
3329
0
}
3330
3331
uint8_t CU::getSbtPos( const uint8_t sbtInfo )
3332
0
{
3333
0
  return ( sbtInfo >> 4 ) & 0x3;
3334
0
}
3335
3336
uint8_t CU::targetSbtAllowed( uint8_t sbtIdx, uint8_t sbtAllowed )
3337
0
{
3338
0
  return ( sbtAllowed >> sbtIdx ) & 0x1;
3339
0
}
3340
3341
0
uint8_t CU::getSbtIdx( const CodingUnit& cu )              { CHECKD( ( ( cu.sbtInfo() >> 0 ) & 0xf ) >= NUMBER_SBT_IDX, "wrong" ); return ( cu.sbtInfo() >> 0 ) & 0xf; }
3342
0
uint8_t CU::getSbtPos( const CodingUnit& cu )              { return ( cu.sbtInfo() >> 4 ) & 0x3; }
3343
0
void    CU::setSbtIdx(       CodingUnit& cu, uint8_t idx ) { CHECKD( idx >= NUMBER_SBT_IDX, "sbt_idx wrong" ); cu.setSbtInfo( ( idx << 0 ) + ( cu.sbtInfo() & 0xf0 ) ); }
3344
0
void    CU::setSbtPos(       CodingUnit& cu, uint8_t pos ) { CHECKD( pos >= 4, "sbt_pos wrong" ); cu.setSbtInfo( ( pos << 4 ) + ( cu.sbtInfo() & 0xcf ) ); }
3345
3346
uint8_t CU::checkAllowedSbt( const CodingUnit& cu )
3347
0
{
3348
  //check on prediction mode
3349
0
  if( !cu.slice->getSPS()->getUseSBT() || cu.predMode() != MODE_INTER || cu.ciipFlag() ) //intra or IBC or triangle
3350
0
  {
3351
0
    return 0;
3352
0
  }
3353
3354
0
  uint8_t sbtAllowed = 0;
3355
0
  int cuWidth  = cu.lwidth();
3356
0
  int cuHeight = cu.lheight();
3357
3358
  //parameter
3359
0
  const int maxSbtCUSize = cu.sps->getMaxTbSize();
3360
3361
  //check on size
3362
0
  if( cuWidth > maxSbtCUSize || cuHeight > maxSbtCUSize )
3363
0
  {
3364
0
    return 0;
3365
0
  }
3366
3367
0
  const int minSbtCUSize = 1 << ( MIN_CU_LOG2 + 1 );
3368
3369
0
  sbtAllowed |= ( cuWidth   >= minSbtCUSize )          << SBT_VER_HALF;
3370
0
  sbtAllowed |= ( cuHeight  >= minSbtCUSize )          << SBT_HOR_HALF;
3371
0
  sbtAllowed |= ( cuWidth   >= ( minSbtCUSize << 1 ) ) << SBT_VER_QUAD;
3372
0
  sbtAllowed |= ( cuHeight  >= ( minSbtCUSize << 1 ) ) << SBT_HOR_QUAD;
3373
3374
0
  return sbtAllowed;
3375
0
}
3376
3377
uint8_t CU::getSbtTuSplit( const CodingUnit& cu )
3378
0
{
3379
0
  uint8_t sbtTuSplitType = 0;
3380
3381
0
  switch( getSbtIdx( cu ) )
3382
0
  {
3383
0
  case SBT_VER_HALF: sbtTuSplitType = ( getSbtPos( cu ) == SBT_POS0 ? 0 : 1 ) + SBT_VER_HALF_POS0_SPLIT; break;
3384
0
  case SBT_HOR_HALF: sbtTuSplitType = ( getSbtPos( cu ) == SBT_POS0 ? 0 : 1 ) + SBT_HOR_HALF_POS0_SPLIT; break;
3385
0
  case SBT_VER_QUAD: sbtTuSplitType = ( getSbtPos( cu ) == SBT_POS0 ? 0 : 1 ) + SBT_VER_QUAD_POS0_SPLIT; break;
3386
0
  case SBT_HOR_QUAD: sbtTuSplitType = ( getSbtPos( cu ) == SBT_POS0 ? 0 : 1 ) + SBT_HOR_QUAD_POS0_SPLIT; break;
3387
0
  default: CHECK( true, "wrong split" );  break;
3388
0
  }
3389
3390
0
  CHECK( !( sbtTuSplitType <= SBT_HOR_QUAD_POS1_SPLIT && sbtTuSplitType >= SBT_VER_HALF_POS0_SPLIT ), "wrong split type" );
3391
0
  return sbtTuSplitType;
3392
0
}
3393
3394
static bool isMinWidthPredEnabledForBlkSize( const int w, const int h )
3395
0
{
3396
0
  return ( ( w == 8 && h > 4 ) || w == 4 );
3397
0
}
3398
3399
bool CU::isPredRegDiffFromTB( const CodingUnit &cu, const ComponentID compID )
3400
0
{
3401
0
  return isLuma( compID ) && cu.ispMode() == VER_INTRA_SUBPARTITIONS && isMinWidthPredEnabledForBlkSize( cu.blocks[compID].width, cu.blocks[compID].height );
3402
0
}
3403
3404
bool CU::isFirstTBInPredReg( const CodingUnit& cu, const ComponentID compID, const CompArea &area )
3405
0
{
3406
0
  return isLuma( compID ) && cu.ispMode() && ( ( area.topLeft().x - cu.Y().topLeft().x ) % PRED_REG_MIN_WIDTH == 0 );
3407
0
}
3408
3409
void CU::adjustPredArea(CompArea &area)
3410
0
{
3411
0
  area.width = std::max<int>( PRED_REG_MIN_WIDTH, area.width );
3412
0
}
3413
3414
PartSplit CU::getSplitAtDepth( const CodingUnit& cu, const unsigned depth )
3415
0
{
3416
0
  CHECK( depth >= 3, "Only works up to the split depth of '3'" );
3417
3418
0
  if( depth >= cu.depth ) return CU_DONT_SPLIT;
3419
3420
0
  const PartSplit cuSplitType = PartSplit( ( cu.splitSeries >> ( depth * SPLIT_DMULT ) ) & SPLIT_MASK );
3421
3422
0
  if     ( cuSplitType == CU_QUAD_SPLIT    ) return CU_QUAD_SPLIT;
3423
3424
0
  else if( cuSplitType == CU_HORZ_SPLIT    ) return CU_HORZ_SPLIT;
3425
3426
0
  else if( cuSplitType == CU_VERT_SPLIT    ) return CU_VERT_SPLIT;
3427
3428
0
  else if( cuSplitType == CU_TRIH_SPLIT    ) return CU_TRIH_SPLIT;
3429
0
  else if( cuSplitType == CU_TRIV_SPLIT    ) return CU_TRIV_SPLIT;
3430
3431
0
  THROW_RECOVERABLE( "Unknown split mode" );
3432
0
}
3433
3434
bool CU::checkCCLMAllowed( const CodingUnit& cu )
3435
0
{
3436
0
  bool allowCCLM = false;
3437
3438
0
  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)
3439
0
  {
3440
0
    allowCCLM = true;
3441
0
  }
3442
0
  else if( cu.sps->getCTUSize() <= 32 ) //dual tree, CTUsize < 64
3443
0
  {
3444
0
    allowCCLM = true;
3445
0
  }
3446
0
  else //dual tree, CTU size 64 or 128
3447
0
  {
3448
0
    const int       depthFor64x64Node = cu.sps->getCTUSize() == 128 ? 1 : 0;
3449
0
    const PartSplit cuSplitTypeDepth1 = CU::getSplitAtDepth( cu, depthFor64x64Node );
3450
0
    const PartSplit cuSplitTypeDepth2 = CU::getSplitAtDepth( cu, depthFor64x64Node + 1 );
3451
3452
    //allow CCLM if 64x64 chroma tree node uses QT split or HBT+VBT split combination
3453
0
    if( cuSplitTypeDepth1 == CU_QUAD_SPLIT || ( cuSplitTypeDepth1 == CU_HORZ_SPLIT && cuSplitTypeDepth2 == CU_VERT_SPLIT ) )
3454
0
    {
3455
0
      allowCCLM = true;
3456
0
    }
3457
    //allow CCLM if 64x64 chroma tree node uses NS (No Split) and becomes a chroma CU containing 32x32 chroma blocks
3458
0
    else if( cuSplitTypeDepth1 == CU_DONT_SPLIT )
3459
0
    {
3460
0
      allowCCLM = true;
3461
0
    }
3462
    //allow CCLM if 64x32 chroma tree node uses NS and becomes a chroma CU containing 32x16 chroma blocks
3463
0
    else if( cuSplitTypeDepth1 == CU_HORZ_SPLIT && cuSplitTypeDepth2 == CU_DONT_SPLIT )
3464
0
    {
3465
0
      allowCCLM = true;
3466
0
    }
3467
3468
    //further check luma conditions
3469
0
    if( allowCCLM )
3470
0
    {
3471
      //disallow CCLM if luma 64x64 block uses BT or TT or NS with ISP
3472
0
      const Position lumaRefPos( cu.chromaPos().x << getComponentScaleX( COMPONENT_Cb, cu.chromaFormat ), cu.chromaPos().y << getComponentScaleY( COMPONENT_Cb, cu.chromaFormat ) );
3473
0
      const CodingUnit* colLumaCu = cu.cs->getCU( lumaRefPos, CHANNEL_TYPE_LUMA );
3474
3475
0
      if( colLumaCu->depth > depthFor64x64Node && colLumaCu->qtDepth == depthFor64x64Node ) //further split at 64x64 luma node
3476
0
      {
3477
0
        allowCCLM = false;
3478
0
      }
3479
0
      else if( colLumaCu->depth == depthFor64x64Node && colLumaCu->ispMode() ) //not split at 64x64 luma node and use ISP mode
3480
0
      {
3481
0
        allowCCLM = false;
3482
0
      }
3483
0
    }
3484
0
  }
3485
3486
0
  return allowCCLM;
3487
0
}
3488
3489
bool CU::isBcwIdxCoded( const CodingUnit &cu )
3490
0
{
3491
0
  if( cu.sps->getUseBcw() == false )
3492
0
  {
3493
0
    CHECK( cu.BcwIdx() != BCW_DEFAULT, "Error: cu.BcwIdx != BCW_DEFAULT" );
3494
0
    return false;
3495
0
  }
3496
3497
0
  if( cu.predMode() == MODE_IBC || cu.predMode() == MODE_INTRA || cu.slice->isInterP() || cu.interDir() != 3 )
3498
0
  {
3499
0
    return false;
3500
0
  }
3501
3502
0
  if( cu.lwidth() * cu.lheight() < BCW_SIZE_CONSTRAINT )
3503
0
  {
3504
0
    return false;
3505
0
  }
3506
3507
0
  const WPScalingParam* wp0 = nullptr;
3508
0
  const WPScalingParam* wp1 = nullptr;
3509
0
  int refIdx0 = cu.refIdx[REF_PIC_LIST_0];
3510
0
  int refIdx1 = cu.refIdx[REF_PIC_LIST_1];
3511
3512
0
  cu.slice->getWpScaling(REF_PIC_LIST_0, refIdx0, wp0);
3513
0
  cu.slice->getWpScaling(REF_PIC_LIST_1, refIdx1, wp1);
3514
3515
0
  if ((wp0[COMPONENT_Y].bPresentFlag || wp0[COMPONENT_Cb].bPresentFlag || wp0[COMPONENT_Cr].bPresentFlag
3516
0
    || wp1[COMPONENT_Y].bPresentFlag || wp1[COMPONENT_Cb].bPresentFlag || wp1[COMPONENT_Cr].bPresentFlag))
3517
0
  {
3518
0
    return false;
3519
0
  }
3520
0
  return true;
3521
0
}
3522
3523
void CU::setBcwIdx( CodingUnit &cu, uint8_t uh )
3524
0
{
3525
0
  int8_t uhCnt = 0;
3526
3527
0
  if( cu.interDir() == 3 && !cu.mergeFlag() )
3528
0
  {
3529
0
    cu.setBcwIdx( uh );
3530
0
    ++uhCnt;
3531
0
  }
3532
0
  else if( cu.interDir()== 3 && cu.mergeFlag() && cu.mergeType() == MRG_TYPE_DEFAULT_N )
3533
0
  {
3534
    // This is intended to do nothing here.
3535
0
  }
3536
0
  else if( cu.mergeFlag() && cu.mergeType() == MRG_TYPE_SUBPU_ATMVP )
3537
0
  {
3538
0
    cu.setBcwIdx( BCW_DEFAULT );
3539
0
  }
3540
0
  else
3541
0
  {
3542
0
    cu.setBcwIdx( BCW_DEFAULT );
3543
0
  }
3544
3545
0
  CHECK(uhCnt <= 0, " uhCnt <= 0 ");
3546
0
}
3547
3548
3549
bool CU::bdpcmAllowed( const CodingUnit& cu, const ComponentID compID )
3550
0
{
3551
0
  const SizeType transformSkipMaxSize = 1 << cu.sps->getLog2MaxTransformSkipBlockSize();
3552
0
  const Size&    blkSize              = cu.blocks[compID].size();
3553
3554
0
  bool bdpcmAllowed = cu.sps->getBDPCMEnabledFlag() &&
3555
0
                    ( isLuma( compID ) || !cu.colorTransform() ) &&
3556
0
                      blkSize.width <= transformSkipMaxSize &&
3557
0
                      blkSize.height <= transformSkipMaxSize;
3558
3559
0
  return bdpcmAllowed;
3560
0
}
3561
3562
bool CU::isMTSAllowed(const CodingUnit &cu, const ComponentID compID)
3563
0
{
3564
0
  SizeType tsMaxSize = 1 << cu.sps->getLog2MaxTransformSkipBlockSize();
3565
0
  const int maxSize  = CU::isIntra( cu ) ? MTS_INTRA_MAX_CU_SIZE : MTS_INTER_MAX_CU_SIZE;
3566
0
  const int cuWidth  = cu.lumaSize().width;
3567
0
  const int cuHeight = cu.lumaSize().height;
3568
0
  bool mtsAllowed    = cu.chType() == CHANNEL_TYPE_LUMA && compID == COMPONENT_Y;
3569
3570
0
  mtsAllowed &= CU::isIntra( cu ) ? cu.sps->getUseIntraMTS() : cu.sps->getUseInterMTS() && CU::isInter( cu );
3571
0
  mtsAllowed &= cuWidth <= maxSize && cuHeight <= maxSize;
3572
0
  mtsAllowed &= !cu.ispMode();
3573
0
  mtsAllowed &= !cu.sbtInfo();
3574
0
  mtsAllowed &= !(cu.bdpcmMode() && cuWidth <= tsMaxSize && cuHeight <= tsMaxSize);
3575
0
  return mtsAllowed;
3576
0
}
3577
3578
// TU tools
3579
3580
bool TU::getCbf( const TransformUnit &tu, const ComponentID &compID )
3581
0
{
3582
0
  return ( tu.cbf >> compID ) & 1;
3583
0
}
3584
3585
void TU::setCbf(TransformUnit &tu, const ComponentID &compID, const bool &cbf)
3586
0
{
3587
  // first clear the CBF at the depth
3588
0
  tu.cbf &= ~(1  << compID);
3589
  // then set the CBF
3590
0
  tu.cbf |= ((cbf ? 1 : 0) << compID);
3591
0
}
3592
3593
bool TU::isTSAllowed(const TransformUnit &tu, const ComponentID compID)
3594
0
{
3595
0
  const int maxSize = tu.cu->sps->getLog2MaxTransformSkipBlockSize();
3596
0
  bool tsAllowed = tu.cu->sps->getTransformSkipEnabledFlag();
3597
0
  tsAllowed &= ( !tu.cu->ispMode() || !isLuma( compID ) );
3598
0
  SizeType transformSkipMaxSize = 1 << maxSize;
3599
0
  tsAllowed &= !(tu.cu->bdpcmMode() && isLuma(compID));
3600
0
  tsAllowed &= !(tu.cu->bdpcmModeChroma() && isChroma(compID));
3601
0
  tsAllowed &= tu.blocks[compID].width <= transformSkipMaxSize && tu.blocks[compID].height <= transformSkipMaxSize;
3602
0
  tsAllowed &= !tu.cu->sbtInfo();
3603
3604
0
  return tsAllowed;
3605
0
}
3606
3607
3608
int TU::getICTMode( const TransformUnit& tu, bool sign )
3609
0
{
3610
0
  return g_ictModes[ sign ][ tu.jointCbCr ];
3611
0
}
3612
3613
3614
3615
bool TU::needsSqrt2Scale( const TransformUnit &tu, const ComponentID &compID )
3616
0
{
3617
0
  const Size &size            = tu.blocks[compID];
3618
0
  const bool  isTransformSkip = tu.mtsIdx( compID ) == 1;
3619
0
  return !isTransformSkip && ( ( getLog2( size.width ) + getLog2( size.height ) ) & 1 ) == 1;
3620
0
}
3621
3622
bool TU::needsBlockSizeTrafoScale( const TransformUnit &tu, const ComponentID &compID )
3623
0
{
3624
0
  return needsSqrt2Scale( tu, compID );
3625
0
}
3626
3627
const TransformUnit* TU::getPrevTU( const TransformUnit &tu, const ComponentID compID )
3628
0
{
3629
0
  const TransformUnit* prevTU = nullptr;
3630
3631
0
  for( auto &currTu : cTUTraverser( &tu.cu->firstTU, &tu ) )
3632
0
  {
3633
0
    if( &tu == &currTu ) break;
3634
0
    prevTU = &currTu;
3635
0
  }
3636
3637
0
  if( prevTU != nullptr && ( prevTU->cu != tu.cu || !prevTU->blocks[compID].valid() ) )
3638
0
  {
3639
0
    prevTU = nullptr;
3640
0
  }
3641
3642
0
  return prevTU;
3643
0
}
3644
3645
bool TU::getPrevTUCbf( const TransformUnit &currentTu, const ComponentID compID )
3646
0
{
3647
0
  const TransformUnit* prevTU = getPrevTU( currentTu, compID );
3648
0
  return ( prevTU != nullptr ) ? TU::getCbf( *prevTU, compID ) : false;
3649
0
}
3650
3651
3652
bool TU::checkTuNoResidual( TransformUnit &tu, unsigned idx )
3653
0
{
3654
0
  if( CU::getSbtIdx( tu.cu->sbtInfo() ) == SBT_OFF_DCT )
3655
0
  {
3656
0
    return false;
3657
0
  }
3658
3659
0
  if( ( CU::getSbtPos( tu.cu->sbtInfo() ) == SBT_POS0 && idx == 1 ) || ( CU::getSbtPos( tu.cu->sbtInfo() ) == SBT_POS1 && idx == 0 ) )
3660
0
  {
3661
0
    return true;
3662
0
  }
3663
3664
0
  return false;
3665
0
}
3666
3667
3668
int TU::getTbAreaAfterCoefZeroOut(const TransformUnit &tu, const ComponentID compID)
3669
0
{
3670
0
  int tbZeroOutWidth  = tu.blocks[compID].width;
3671
0
  int tbZeroOutHeight = tu.blocks[compID].height;
3672
3673
0
  if( compID == COMPONENT_Y && ( tu.mtsIdx( compID ) > MTS_SKIP || ( tu.cu->sps->getUseMTS() && tu.cu->sbtInfo() != 0 && tbZeroOutWidth <= 32 && tbZeroOutHeight <= 32 ) ) )
3674
0
  {
3675
0
    tbZeroOutWidth  = (tbZeroOutWidth  == 32) ? 16 : tbZeroOutWidth;
3676
0
    tbZeroOutHeight = (tbZeroOutHeight == 32) ? 16 : tbZeroOutHeight;
3677
0
  }
3678
3679
0
  tbZeroOutWidth  = std::min<int>( JVET_C0024_ZERO_OUT_TH, tbZeroOutWidth );
3680
0
  tbZeroOutHeight = std::min<int>( JVET_C0024_ZERO_OUT_TH, tbZeroOutHeight );
3681
0
  return tbZeroOutWidth * tbZeroOutHeight;
3682
0
}
3683
3684
3685
// other tools
3686
3687
uint32_t getCtuAddr( const Position& pos, const PreCalcValues& pcv )
3688
0
{
3689
0
  return ( pos.x >> pcv.maxCUWidthLog2 ) + ( pos.y >> pcv.maxCUHeightLog2 ) * pcv.widthInCtus;
3690
0
}
3691
3692
3693
UnitArea getLineArea(const CodingStructure & cs, unsigned line, bool clipToPic)
3694
0
{
3695
0
  const unsigned widthInCtus = cs.pcv->widthInCtus;
3696
0
  const unsigned maxCUWidth  = cs.pcv->maxCUWidth;
3697
0
  const unsigned maxCUHeight = cs.pcv->maxCUHeight;
3698
3699
0
  if( !clipToPic )
3700
0
  {
3701
0
    return UnitArea( cs.area.chromaFormat, Area( 0, line * maxCUHeight, maxCUWidth * widthInCtus, maxCUHeight ) );
3702
0
  }
3703
3704
0
  const unsigned width  = cs.pcv->lumaWidth;
3705
0
  const unsigned height = std::min( cs.pcv->lumaHeight - line * maxCUHeight, maxCUHeight );
3706
3707
0
  return UnitArea( cs.area.chromaFormat, Area( 0, line * maxCUHeight, width, height ) );
3708
0
}
3709
3710
UnitArea getCtuArea(const CodingStructure & cs, unsigned col, unsigned line, bool clipToPic)
3711
0
{
3712
0
  const unsigned maxCUWidth  = cs.pcv->maxCUWidth;
3713
0
  const unsigned maxCUHeight = cs.pcv->maxCUHeight;
3714
0
  const int      xPos        = col  * maxCUWidth;
3715
0
  const int      yPos        = line * maxCUHeight;
3716
3717
0
  if( !clipToPic )
3718
0
  {
3719
0
    return UnitArea( cs.area.chromaFormat, Area( xPos, yPos, maxCUWidth, maxCUHeight ) );
3720
0
  }
3721
3722
0
  CHECKD( (unsigned)xPos > cs.pcv->lumaWidth,  "Block start lies outside of the picture!" );
3723
0
  CHECKD( (unsigned)yPos > cs.pcv->lumaHeight, "Block start lies outside of the picture!" );
3724
3725
0
  const unsigned width  = std::min( cs.pcv->lumaWidth  - xPos, maxCUWidth );
3726
0
  const unsigned height = std::min( cs.pcv->lumaHeight - yPos, maxCUHeight );
3727
3728
0
  return UnitArea( cs.area.chromaFormat, Area( xPos, yPos, width, height ) );
3729
0
}
3730
3731
int getNumModesMip( const Size& block )
3732
0
{
3733
0
  switch( getMipSizeId(block) )
3734
0
  {
3735
0
    case 0: return 16;
3736
0
    case 1: return  8;
3737
0
    case 2: return  6;
3738
0
    default: THROW_FATAL( "Invalid mipSizeId" );
3739
0
  }
3740
0
}
3741
3742
3743
int getMipSizeId(const Size& block)
3744
0
{
3745
0
  if( block.width == 4 && block.height == 4 )
3746
0
  {
3747
0
    return 0;
3748
0
  }
3749
0
  else if( block.width == 4 || block.height == 4 || (block.width == 8 && block.height == 8) )
3750
0
  {
3751
0
    return 1;
3752
0
  }
3753
0
  else
3754
0
  {
3755
0
    return 2;
3756
0
  }
3757
3758
0
}
3759
3760
bool allowLfnstWithMip( const Size& block )
3761
0
{
3762
0
  return block.width >= 16 && block.height >= 16;
3763
0
}
3764
3765
bool PU::isRefPicSameSize( const CodingUnit& cu )
3766
0
{
3767
0
  bool samePicSize = true;
3768
0
  int curPicWidth  = cu.pps->getPicWidthInLumaSamples();
3769
0
  int curPicHeight = cu.pps->getPicHeightInLumaSamples();
3770
3771
0
  if( cu.refIdx[0] >= 0 )
3772
0
  {
3773
0
    int refPicWidth  = cu.slice->getRefPic( REF_PIC_LIST_0, cu.refIdx[0] )->cs->pps->getPicWidthInLumaSamples();
3774
0
    int refPicHeight = cu.slice->getRefPic( REF_PIC_LIST_0, cu.refIdx[0] )->cs->pps->getPicHeightInLumaSamples();
3775
3776
0
    samePicSize = refPicWidth == curPicWidth && refPicHeight == curPicHeight;
3777
0
  }
3778
3779
0
  if( cu.refIdx[1] >= 0 )
3780
0
  {
3781
0
    int refPicWidth  = cu.slice->getRefPic( REF_PIC_LIST_1, cu.refIdx[1] )->cs->pps->getPicWidthInLumaSamples();
3782
0
    int refPicHeight = cu.slice->getRefPic( REF_PIC_LIST_1, cu.refIdx[1] )->cs->pps->getPicHeightInLumaSamples();
3783
3784
0
    samePicSize = samePicSize && ( refPicWidth == curPicWidth && refPicHeight == curPicHeight );
3785
0
  }
3786
3787
0
  return samePicSize;
3788
0
}
3789
3790
bool isCrossedByVirtualBoundaries( const PicHeader* picHeader,
3791
                                   const Area&      area,
3792
                                   int&             numHorVirBndry,
3793
                                   int&             numVerVirBndry,
3794
                                   int              horVirBndryPos[],
3795
                                   int              verVirBndryPos[] )
3796
0
{
3797
0
  numHorVirBndry = 0;
3798
0
  numVerVirBndry = 0;
3799
0
  if( !picHeader->getVirtualBoundariesPresentFlag() )
3800
0
  {
3801
0
    return false;
3802
0
  }
3803
3804
0
  for( int i = 0; i < picHeader->getNumHorVirtualBoundaries(); i++ )
3805
0
  {
3806
0
    if( area.y <= picHeader->getVirtualBoundariesPosY( i ) && picHeader->getVirtualBoundariesPosY( i ) <= area.y + area.height )
3807
0
    {
3808
0
      horVirBndryPos[numHorVirBndry++] = picHeader->getVirtualBoundariesPosY( i );
3809
0
    }
3810
0
  }
3811
0
  for( int i = 0; i < picHeader->getNumVerVirtualBoundaries(); i++ )
3812
0
  {
3813
0
    if( area.x <= picHeader->getVirtualBoundariesPosX( i ) && picHeader->getVirtualBoundariesPosX( i ) <= area.x + area.width )
3814
0
    {
3815
0
      verVirBndryPos[numVerVirBndry++] = picHeader->getVirtualBoundariesPosX( i );
3816
0
    }
3817
0
  }
3818
3819
0
  return numHorVirBndry > 0 || numVerVirBndry > 0;
3820
0
}
3821
3822
}