Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vvenc/source/Lib/DecoderLib/DecCu.cpp
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
The copyright in this software is being made available under the Clear BSD
3
License, included below. No patent rights, trademark rights and/or 
4
other Intellectual Property Rights other than the copyrights concerning 
5
the Software are granted under this license.
6
7
The Clear BSD License
8
9
Copyright (c) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors.
10
All rights reserved.
11
12
Redistribution and use in source and binary forms, with or without modification,
13
are permitted (subject to the limitations in the disclaimer below) provided that
14
the following conditions are met:
15
16
     * Redistributions of source code must retain the above copyright notice,
17
     this list of conditions and the following disclaimer.
18
19
     * Redistributions in binary form must reproduce the above copyright
20
     notice, this list of conditions and the following disclaimer in the
21
     documentation and/or other materials provided with the distribution.
22
23
     * Neither the name of the copyright holder nor the names of its
24
     contributors may be used to endorse or promote products derived from this
25
     software without specific prior written permission.
26
27
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
28
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
32
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
40
41
------------------------------------------------------------------------------------------- */
42
43
44
/** \file     DecCu.cpp
45
    \brief    CU decoder class
46
*/
47
48
#include "DecCu.h"
49
50
#include "CommonLib/InterPrediction.h"
51
#include "CommonLib/IntraPrediction.h"
52
#include "CommonLib/Picture.h"
53
#include "CommonLib/UnitTools.h"
54
#include "CommonLib/LoopFilter.h"
55
#include "CommonLib/Reshape.h"
56
#include "CommonLib/dtrace_buffer.h"
57
58
//! \ingroup DecoderLib
59
//! \{
60
61
namespace vvenc {
62
63
// ====================================================================================================================
64
// Constructor / destructor / create / destroy
65
// ====================================================================================================================
66
67
DecCu::DecCu()
68
0
{
69
0
}
70
71
DecCu::~DecCu()
72
0
{
73
0
  m_TmpBuffer.destroy();
74
0
  m_PredBuffer.destroy();
75
0
}
76
77
void DecCu::init( TrQuant* pcTrQuant, IntraPrediction* pcIntra, InterPrediction* pcInter, ChromaFormat chrFormat)
78
0
{
79
0
  m_pcTrQuant       = pcTrQuant;
80
0
  m_pcIntraPred     = pcIntra;
81
0
  m_pcInterPred     = pcInter;
82
0
  m_TmpBuffer.destroy();
83
0
  m_TmpBuffer.create( chrFormat, Area( 0,0, MAX_TB_SIZEY, MAX_TB_SIZEY ));
84
0
  m_PredBuffer.destroy();
85
0
  m_PredBuffer.create( chrFormat, Area( 0,0, MAX_CU_SIZE, MAX_CU_SIZE ));
86
0
}
87
88
// ====================================================================================================================
89
// Protected member functions
90
// ====================================================================================================================
91
92
void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID )
93
0
{
94
0
  if( !tu.blocks[ compID ].valid() )
95
0
  {
96
0
    return;
97
0
  }
98
99
0
        CodingStructure &cs     = *tu.cs;
100
0
  const CompArea& area          = tu.blocks[compID];
101
0
  const ChannelType chType      = toChannelType( compID );
102
0
  PelBuf piPred                 = tu.cu->ispMode && isLuma( compID ) ? cs.getPredBuf( area ) : m_PredBuffer.getCompactBuf( area );
103
0
  const CodingUnit& cu          = *tu.cu;
104
0
  const uint32_t uiChFinalMode  = CU::getFinalIntraMode( cu, chType );
105
0
  PelBuf pReco                  = cs.getRecoBuf( area );
106
107
  //===== init availability pattern =====
108
0
  CompArea areaPredReg(COMP_Y, tu.chromaFormat, area);
109
0
  bool predRegDiffFromTB = isLuma( compID ) && CU::isPredRegDiffFromTB( *tu.cu );
110
0
  bool firstTBInPredReg  = isLuma( compID ) && CU::isFirstTBInPredReg ( *tu.cu, area );
111
112
0
  if( tu.cu->ispMode && isLuma( compID ) )
113
0
  {
114
0
    if( predRegDiffFromTB )
115
0
    {
116
0
      if( firstTBInPredReg )
117
0
      {
118
0
        CU::adjustPredArea( areaPredReg );
119
0
        m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, areaPredReg, pReco );
120
0
      }
121
0
    }
122
0
    else
123
0
    {
124
0
      m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, area, pReco );
125
0
    }
126
0
  }
127
0
  else
128
0
  {
129
0
    m_pcIntraPred->initIntraPatternChType( *tu.cu, area );
130
0
  }
131
132
  //===== get prediction signal =====
133
0
  if( compID != COMP_Y && CU::isLMCMode( uiChFinalMode ) )
134
0
  {
135
0
    const CodingUnit& cu = *tu.cu;
136
0
    m_pcIntraPred->loadLMLumaRecPels( cu, area );
137
0
    m_pcIntraPred->predIntraChromaLM( compID, piPred, cu, area, uiChFinalMode );
138
0
  }
139
0
  else if( CU::isMIP( cu, chType ) )
140
0
  {
141
0
    m_pcIntraPred->initIntraMip( cu );
142
0
    m_pcIntraPred->predIntraMip( piPred, cu );
143
0
  }
144
0
  else
145
0
  {
146
0
    if (predRegDiffFromTB)
147
0
    {
148
0
      if (firstTBInPredReg)
149
0
      {
150
0
        PelBuf piPredReg = cs.getPredBuf(areaPredReg);
151
0
        m_pcIntraPred->predIntraAng(compID, piPredReg, cu);
152
0
      }
153
0
    }
154
0
    else
155
0
    {
156
0
      m_pcIntraPred->predIntraAng(compID, piPred, cu);
157
0
    }
158
0
  }
159
  //===== inverse transform =====
160
0
  const Slice& slice       = *cs.slice;
161
0
  ReshapeData& reshapeData = cs.picture->reshapeData;
162
0
  bool lmcsflag = slice.lmcsEnabled && (slice.isIntra() || (!slice.isIntra() && reshapeData.getCTUFlag()));
163
0
  if (lmcsflag && slice.picHeader->lmcsChromaResidualScale && (compID != COMP_Y) && (tu.cbf[COMP_Cb] || tu.cbf[COMP_Cr]))
164
0
  {
165
0
    const Area area = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType, CH_L, tu.blocks[tu.chType].pos()), recalcSize(tu.chromaFormat, tu.chType, CH_L, tu.blocks[tu.chType].size()));
166
0
    const CompArea& areaY = CompArea(COMP_Y, tu.chromaFormat, area);
167
0
    tu.chromaAdj = reshapeData.calculateChromaAdjVpduNei(tu, areaY, TREE_D);
168
0
  }
169
  //===== inverse transform =====
170
0
  PelBuf piResi = cs.getResiBuf( area );
171
172
0
  const QpParam cQP( tu, compID );
173
174
0
  if( tu.jointCbCr && isChroma(compID) )
175
0
  {
176
0
    if( compID == COMP_Cb )
177
0
    {
178
0
      PelBuf resiCr = cs.getResiBuf( tu.blocks[ COMP_Cr ] );
179
0
      if( tu.jointCbCr >> 1 )
180
0
      {
181
0
        m_pcTrQuant->invTransformNxN( tu, COMP_Cb, piResi, cQP );
182
0
      }
183
0
      else
184
0
      {
185
0
        const QpParam qpCr( tu, COMP_Cr );
186
0
        m_pcTrQuant->invTransformNxN( tu, COMP_Cr, resiCr, qpCr );
187
0
      }
188
0
      m_pcTrQuant->invTransformICT( tu, piResi, resiCr );
189
0
    }
190
0
  }
191
0
  else
192
0
  if( TU::getCbf( tu, compID ) )
193
0
  {
194
0
    m_pcTrQuant->invTransformNxN( tu, compID, piResi, cQP );
195
0
  }
196
0
  else
197
0
  {
198
0
    piResi.fill( 0 );
199
0
  }
200
201
  //===== reconstruction =====
202
0
  lmcsflag &= (tu.blocks[compID].width*tu.blocks[compID].height > 4) && slice.picHeader->lmcsChromaResidualScale;
203
0
  if (lmcsflag && (TU::getCbf(tu, compID) || tu.jointCbCr) && isChroma(compID) )
204
0
  {
205
0
    piResi.scaleSignal(tu.chromaAdj, 0, tu.cu->cs->slice->clpRngs[compID]);
206
0
  }
207
208
209
0
  piPred.reconstruct( piPred, piResi, tu.cu->cs->slice->clpRngs[ compID ] );
210
0
  pReco.copyFrom( piPred );
211
212
0
  if( true/*isEncoder*/ )
213
0
  {
214
0
    cs.picture->getRecoBuf( area ).copyFrom( pReco );
215
0
  }
216
0
}
217
218
void DecCu::xReconIntraQT( CodingUnit &cu )
219
0
{
220
0
  const uint32_t numChType = getNumberValidChannels( cu.chromaFormat );
221
222
0
  for( uint32_t chType = CH_L; chType < numChType; chType++ )
223
0
  {
224
0
    if( cu.blocks[chType].valid() )
225
0
    {
226
0
      xIntraRecQT( cu, ChannelType( chType ) );
227
0
    }
228
0
  }
229
0
}
230
231
/** Function for deriving reconstructed PU/CU chroma samples with QTree structure
232
* \param pcRecoYuv pointer to reconstructed sample arrays
233
* \param pcPredYuv pointer to prediction sample arrays
234
* \param pcResiYuv pointer to residue sample arrays
235
* \param chType    texture channel type (luma/chroma)
236
* \param rTu       reference to transform data
237
*
238
\ This function derives reconstructed PU/CU chroma samples with QTree recursive structure
239
*/
240
241
void DecCu::xIntraRecQT(CodingUnit &cu, const ChannelType chType)
242
0
{
243
0
  for( auto &currTU : CU::traverseTUs( cu ) )
244
0
  {
245
0
    if( isLuma( chType ) )
246
0
    {
247
0
      xIntraRecBlk( currTU, COMP_Y );
248
0
    }
249
0
    else
250
0
    {
251
0
      const uint32_t numValidComp = getNumberValidComponents( cu.chromaFormat );
252
253
0
      for( uint32_t compID = COMP_Cb; compID < numValidComp; compID++ )
254
0
      {
255
0
        xIntraRecBlk( currTU, ComponentID( compID ) );
256
0
      }
257
0
    }
258
0
  }
259
0
}
260
261
262
void DecCu::xReconInter( CodingUnit &cu )
263
0
{
264
0
  CodingStructure &cs = *cu.cs;
265
266
0
  PelUnitBuf predBuf = m_PredBuffer.getCompactBuf( cu ); 
267
0
  const ReshapeData& reshapeData = cs.picture->reshapeData;
268
0
  if (cu.geo)
269
0
  {
270
0
    m_pcInterPred->motionCompensationGeo(cu, predBuf, m_geoMrgCtx);
271
0
    CU::spanGeoMotionInfo(cu, m_geoMrgCtx, cu.geoSplitDir, cu.geoMergeIdx[0], cu.geoMergeIdx[1]);
272
0
  }
273
0
  else
274
0
  {
275
0
    CHECK(CU::isIBC(cu) && cu.ciip, "IBC and Ciip cannot be used together");
276
0
    CHECK(CU::isIBC(cu) && cu.affine, "IBC and Affine cannot be used together");
277
0
    CHECK(CU::isIBC(cu) && cu.geo, "IBC and geo cannot be used together");
278
0
    CHECK(CU::isIBC(cu) && cu.mmvdMergeFlag, "IBC and MMVD cannot be used together");
279
0
    const bool luma   = cu.Y().valid();
280
0
    const bool chroma = isChromaEnabled( cu.chromaFormat ) && cu.Cb().valid();
281
282
0
    if( luma && ( chroma || !isChromaEnabled( cu.chromaFormat ) ) )
283
0
    {
284
0
      cu.mvRefine = true;
285
0
      m_pcInterPred->motionCompensation(cu, predBuf);
286
0
      cu.mvRefine = false;
287
0
    }
288
0
    else
289
0
    {
290
0
      cu.mcControl  = luma   ? 0 : 4;
291
0
      cu.mcControl |= chroma ? 0 : 2;
292
0
      m_pcInterPred->motionCompensationIBC(cu, predBuf);
293
0
      cu.mcControl  = 0;
294
0
    }
295
0
    if( cu.Y().valid() )
296
0
    {
297
0
      bool isIbcSmallBlk = CU::isIBC( cu ) && ( cu.lwidth() * cu.lheight() <= 16 );
298
      //CU::saveMotionInHMVP(cu, isIbcSmallBlk);
299
0
      if( !cu.affine && !cu.geo && !isIbcSmallBlk )
300
0
      {
301
0
        const MotionInfo &mi = cu.getMotionInfo();
302
0
        HPMVInfo hMi( mi, ( mi.interDir() == 3 ) ? cu.BcwIdx : BCW_DEFAULT, cu.imv == IMV_HPEL, CU::isIBC( cu ) );
303
0
        cs.addMiToLut( CU::isIBC( cu ) ? cu.cs->motionLut.lutIbc : cu.cs->motionLut.lut, hMi );
304
0
      }
305
0
    }
306
307
0
    if (cu.ciip)
308
0
    {
309
0
      PelBuf ciipBuf = m_TmpBuffer.getCompactBuf( cu.Y() );
310
311
0
      m_pcIntraPred->initIntraPatternChType(cu, cu.Y());
312
0
      m_pcIntraPred->predIntraAng(COMP_Y, ciipBuf, cu);
313
314
0
      if( cs.picHeader->lmcsEnabled && reshapeData.getCTUFlag() )
315
0
      {
316
0
        predBuf.Y().rspSignal( reshapeData.getFwdLUT());
317
0
      }
318
0
      const int numCiipIntra = m_pcIntraPred->getNumIntraCiip( cu );
319
0
      predBuf.Y().weightCiip( ciipBuf, numCiipIntra);
320
321
0
      if (isChromaEnabled(cu.chromaFormat) && cu.chromaSize().width > 2)
322
0
      {
323
0
        PelBuf ciipBufC = m_TmpBuffer.getCompactBuf( cu.Cb() );
324
0
        m_pcIntraPred->initIntraPatternChType(cu, cu.Cb());
325
0
        m_pcIntraPred->predIntraAng(COMP_Cb, ciipBufC, cu);
326
0
        predBuf.Cb().weightCiip( ciipBufC, numCiipIntra);
327
328
0
        m_pcIntraPred->initIntraPatternChType(cu, cu.Cr());
329
0
        m_pcIntraPred->predIntraAng(COMP_Cr, ciipBufC, cu);
330
0
        predBuf.Cr().weightCiip( ciipBufC, numCiipIntra);
331
0
      }
332
0
    }
333
0
  }
334
335
0
  if (cs.slice->lmcsEnabled && reshapeData.getCTUFlag() && !cu.ciip && !CU::isIBC(cu) )
336
0
  {
337
0
    predBuf.Y().rspSignal(reshapeData.getFwdLUT());
338
0
  }
339
340
  // inter recon
341
0
  xDecodeInterTexture(cu);
342
343
0
  bool LumaOnly = ((predBuf.bufs.size() > 1) && (predBuf.bufs[1].stride != 0 && predBuf.bufs[2].stride != 0) ) ? false : true;
344
0
  if (cu.rootCbf)
345
0
  {
346
0
    if (LumaOnly)
347
0
    {
348
0
      cs.getResiBuf(cu.Y()).reconstruct(predBuf.Y(), cs.getResiBuf(cu.Y()), cs.slice->clpRngs[COMP_Y]);
349
0
      cs.getRecoBuf(cu.Y()).copyFrom(cs.getResiBuf(cu.Y()));
350
0
    }
351
0
    else
352
0
    {
353
0
      cs.getResiBuf(cu).reconstruct(predBuf, cs.getResiBuf(cu), cs.slice->clpRngs);
354
0
      cs.getRecoBuf(cu).copyFrom(cs.getResiBuf(cu));
355
0
    }
356
0
  }
357
0
  else
358
0
  {
359
0
    if (LumaOnly)
360
0
    {
361
0
      cs.getRecoBuf(cu.Y()).copyClip(predBuf.Y(), cs.slice->clpRngs[COMP_Y]);
362
0
    }
363
0
    else
364
0
    {
365
0
      cs.getRecoBuf(cu).copyClip(predBuf, cs.slice->clpRngs);
366
0
    }
367
0
  }
368
0
}
369
370
void DecCu::xDecodeInterTU( TransformUnit&  currTU, const ComponentID compID )
371
0
{
372
0
  if( !currTU.blocks[compID].valid() ) return;
373
374
0
  const CompArea& area = currTU.blocks[compID];
375
376
0
  CodingStructure& cs = *currTU.cs;
377
378
  //===== inverse transform =====
379
0
  PelBuf resiBuf  = cs.getResiBuf(area);
380
381
0
  const QpParam cQP(currTU, compID);
382
383
0
  if( currTU.jointCbCr && isChroma(compID) )
384
0
  {
385
0
    if( compID == COMP_Cb )
386
0
    {
387
0
      PelBuf resiCr = cs.getResiBuf( currTU.blocks[ COMP_Cr ] );
388
0
      if( currTU.jointCbCr >> 1 )
389
0
      {
390
0
        m_pcTrQuant->invTransformNxN( currTU, COMP_Cb, resiBuf, cQP );
391
0
      }
392
0
      else
393
0
      {
394
0
        const QpParam qpCr( currTU, COMP_Cr );
395
0
        m_pcTrQuant->invTransformNxN( currTU, COMP_Cr, resiCr, qpCr );
396
0
      }
397
0
      m_pcTrQuant->invTransformICT( currTU, resiBuf, resiCr );
398
0
    }
399
0
  }
400
0
  else
401
0
  if( TU::getCbf( currTU, compID ) )
402
0
  {
403
0
    m_pcTrQuant->invTransformNxN( currTU, compID, resiBuf, cQP );
404
0
  }
405
0
  else
406
0
  {
407
0
    resiBuf.fill( 0 );
408
0
  }
409
410
0
  const Slice& slice = *currTU.cu->slice;
411
0
  const ReshapeData& reshapeData = cs.picture->reshapeData;
412
0
  if( slice.lmcsEnabled && reshapeData.getCTUFlag() && isChroma(compID) && (TU::getCbf(currTU, compID) || currTU.jointCbCr)
413
0
   && slice.picHeader->lmcsChromaResidualScale && currTU.blocks[compID].width * currTU.blocks[compID].height > 4)
414
0
  {
415
0
    resiBuf.scaleSignal(currTU.chromaAdj, 0, slice.clpRngs[compID]);
416
0
  }
417
0
}
418
419
void DecCu::xDecodeInterTexture(CodingUnit &cu)
420
0
{
421
0
  if( !cu.rootCbf )
422
0
  {
423
0
    return;
424
0
  }
425
426
0
  const uint32_t uiNumVaildComp = getNumberValidComponents(cu.chromaFormat);
427
0
  ReshapeData& reshapeData = cu.cs->picture->reshapeData;
428
0
  const bool chromaAdj = cu.slice->lmcsEnabled && reshapeData.getCTUFlag() && cu.slice->picHeader->lmcsChromaResidualScale;
429
0
  for (uint32_t ch = 0; ch < uiNumVaildComp; ch++)
430
0
  {
431
0
    const ComponentID compID = ComponentID(ch);
432
433
0
    for( auto& currTU : CU::traverseTUs( cu ) )
434
0
    {
435
0
      if( chromaAdj && (compID == COMP_Y) && (currTU.cbf[COMP_Cb] || currTU.cbf[COMP_Cr]))
436
0
      {
437
0
        currTU.chromaAdj = reshapeData.calculateChromaAdjVpduNei(currTU, currTU.blocks[COMP_Y], TREE_D);
438
0
      }
439
440
0
      xDecodeInterTU( currTU, compID );
441
0
    }
442
0
  }
443
0
}
444
445
void DecCu::xDeriveCUMV( CodingUnit &cu )
446
0
{
447
0
  if( cu.mergeFlag )
448
0
  {
449
0
    MergeCtx mrgCtx;
450
451
0
    if (cu.mmvdMergeFlag || cu.mmvdSkip)
452
0
    {
453
0
      CHECK( cu.ciip, "invalid CIIP" );
454
0
      CU::getInterMergeCandidates    ( cu, mrgCtx, 1,  cu.mmvdMergeIdx.pos.baseIdx + 1 );
455
0
      CU::getInterMMVDMergeCandidates( cu, mrgCtx );
456
0
      mrgCtx.setMmvdMergeCandiInfo   ( cu, cu.mmvdMergeIdx );
457
0
      CU::spanMotionInfo             ( cu );
458
0
    }
459
0
    else
460
0
    {
461
0
      if (cu.geo)
462
0
      {
463
0
        CU::getGeoMergeCandidates(cu, m_geoMrgCtx);
464
0
      }
465
0
      else
466
0
      {
467
0
        AffineMergeCtx affineMergeCtx;
468
0
        if (cu.affine)
469
0
        {
470
0
          if (cu.cs->sps->SbtMvp)
471
0
          {
472
0
            Size bufSize                  = g_miScaling.scale(cu.lumaSize());
473
0
            affineMergeCtx.subPuMvpMiBuf  = MotionBuf(m_subPuMiBuf, bufSize);
474
0
          }
475
0
          CU::getAffineMergeCand(cu, affineMergeCtx, cu.mergeIdx);
476
0
          cu.interDir           =    affineMergeCtx.interDirNeighbours[cu.mergeIdx];
477
0
          cu.affineType         =    affineMergeCtx.affineType        [cu.mergeIdx];
478
0
          cu.BcwIdx             =    affineMergeCtx.BcwIdx            [cu.mergeIdx];
479
0
          cu.mergeType          =    affineMergeCtx.mergeType         [cu.mergeIdx];
480
481
0
          if (cu.mergeType == MRG_TYPE_SUBPU_ATMVP)
482
0
          {
483
0
            cu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[cu.mergeIdx][0][0].refIdx;
484
0
            cu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[cu.mergeIdx][1][0].refIdx;
485
0
          }
486
0
          else
487
0
          {
488
0
            for (int i = 0; i < 2; ++i)
489
0
            {
490
0
              if (cu.cs->slice->numRefIdx[RefPicList(i)] > 0)
491
0
              {
492
0
                MvField *mvField = affineMergeCtx.mvFieldNeighbours[cu.mergeIdx][i];
493
0
                cu.mvpIdx[i]     = 0;
494
0
                cu.mvpNum[i]     = 0;
495
0
                cu.mvd[i][0]     = Mv();
496
0
                CU::setAllAffineMvField(cu, mvField, RefPicList(i));
497
0
              }
498
0
            }
499
0
          }
500
0
        }
501
0
        else
502
0
        {
503
0
          if (CU::isIBC(cu))
504
0
          {
505
0
            CU::getIBCMergeCandidates(cu, mrgCtx, cu.mergeIdx);
506
0
          }
507
0
          else
508
0
          {
509
0
            CU::getInterMergeCandidates(cu, mrgCtx, 0, cu.mergeIdx);
510
0
          }
511
0
          mrgCtx.setMergeInfo(cu, cu.mergeIdx);
512
0
        }
513
514
0
        CU::spanMotionInfo(cu, &affineMergeCtx);
515
0
      }
516
0
    }
517
0
  } 
518
0
  else
519
0
  {
520
0
    if (cu.affine)
521
0
    {
522
0
      for (uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++)
523
0
      {
524
0
        RefPicList eRefList = RefPicList(uiRefListIdx);
525
0
        if (cu.cs->slice->numRefIdx[eRefList] > 0 && (cu.interDir & (1 << uiRefListIdx)))
526
0
        {
527
0
          AffineAMVPInfo affineAMVPInfo;
528
0
          CU::fillAffineMvpCand(cu, eRefList, cu.refIdx[eRefList], affineAMVPInfo);
529
530
0
          const unsigned mvp_idx = cu.mvpIdx[eRefList];
531
532
0
          cu.mvpNum[eRefList] = affineAMVPInfo.numCand;
533
534
          //    Mv mv[3];
535
0
          CHECK(cu.refIdx[eRefList] < 0, "Unexpected negative refIdx.");
536
0
          if (!true/*isEncoder*/)
537
0
          {
538
0
            cu.mvd[eRefList][0].changeAffinePrecAmvr2Internal(cu.imv);
539
0
            cu.mvd[eRefList][1].changeAffinePrecAmvr2Internal(cu.imv);
540
0
            if (cu.affineType == AFFINEMODEL_6PARAM)
541
0
            {
542
0
              cu.mvd[eRefList][2].changeAffinePrecAmvr2Internal(cu.imv);
543
0
            }
544
0
          }
545
546
0
          Mv mvLT = affineAMVPInfo.mvCandLT[mvp_idx] + cu.mvd[eRefList][0];
547
0
          Mv mvRT = affineAMVPInfo.mvCandRT[mvp_idx] + cu.mvd[eRefList][1];
548
0
          mvRT += cu.mvd[eRefList][0];
549
550
0
          Mv mvLB;
551
0
          if (cu.affineType == AFFINEMODEL_6PARAM)
552
0
          {
553
0
            mvLB = affineAMVPInfo.mvCandLB[mvp_idx] + cu.mvd[eRefList][2];
554
0
            mvLB += cu.mvd[eRefList][0];
555
0
          }
556
0
          CU::setAllAffineMv(cu, mvLT, mvRT, mvLB, eRefList, true);
557
0
        }
558
0
      }
559
0
    }
560
0
    else if (CU::isIBC(cu) && cu.interDir == 1)
561
0
    {
562
0
      AMVPInfo amvpInfo;
563
0
      CU::fillIBCMvpCand(cu, amvpInfo);
564
0
      cu.mvpNum[REF_PIC_LIST_0] = amvpInfo.numCand;
565
0
      Mv mvd = cu.mvd[REF_PIC_LIST_0][0];
566
0
      if (!true/*isEncoder*/)
567
0
      {
568
0
        mvd.changeIbcPrecAmvr2Internal(cu.imv);
569
0
      }
570
0
      if (cu.cs->sps->maxNumIBCMergeCand == 1)
571
0
      {
572
0
        CHECK(cu.mvpIdx[REF_PIC_LIST_0], "mvpIdx for IBC mode should be 0");
573
0
      }
574
0
      cu.mv[REF_PIC_LIST_0][0] = amvpInfo.mvCand[cu.mvpIdx[REF_PIC_LIST_0]] + mvd;
575
0
      cu.mv[REF_PIC_LIST_0][0].mvCliptoStorageBitDepth();
576
0
    }
577
0
    else
578
0
    {
579
0
      for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
580
0
      {
581
0
        RefPicList eRefList = RefPicList( uiRefListIdx );
582
0
        if ((cu.cs->slice->numRefIdx[eRefList] > 0 || (eRefList == REF_PIC_LIST_0 && CU::isIBC(cu))) && (cu.interDir & (1 << uiRefListIdx)))
583
0
        {
584
0
          AMVPInfo amvpInfo;
585
0
          CU::fillMvpCand(cu, eRefList, cu.refIdx[eRefList], amvpInfo);
586
0
          cu.mvpNum [eRefList] = amvpInfo.numCand;
587
0
          if (!true/*isEncoder*/)
588
0
          {
589
0
            cu.mvd[eRefList][0].changeTransPrecAmvr2Internal(cu.imv);
590
0
          }
591
0
          cu.mv[eRefList][0] = amvpInfo.mvCand[cu.mvpIdx[eRefList]] + cu.mvd[eRefList][0];
592
0
          cu.mv[eRefList][0].mvCliptoStorageBitDepth();
593
0
        }
594
0
      }
595
0
    }
596
0
    CU::spanMotionInfo( cu );
597
0
  }
598
0
  if (CU::isIBC(cu)) //only check
599
0
  {
600
0
    const int cuPelX = cu.Y().x;
601
0
    const int cuPelY = cu.Y().y;
602
0
    int roiWidth = cu.lwidth();
603
0
    int roiHeight = cu.lheight();
604
0
    const unsigned int  lcuWidth = cu.cs->slice->sps->CTUSize;
605
0
    int xPred = cu.mv[0][0].hor >> MV_FRACTIONAL_BITS_INTERNAL;
606
0
    int yPred = cu.mv[0][0].ver >> MV_FRACTIONAL_BITS_INTERNAL;
607
0
    CHECK(!m_pcInterPred->isLumaBvValidIBC(lcuWidth, cuPelX, cuPelY, roiWidth, roiHeight, xPred, yPred), "invalid block vector for IBC detected.");
608
0
  }
609
0
}
610
611
} // namespace vvenc
612
613
//! \}
614