Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vvdec/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) 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     DecCu.cpp
44
    \brief    CU decoder class
45
*/
46
47
#include "DecCu.h"
48
49
#include "CommonLib/InterPrediction.h"
50
#include "CommonLib/IntraPrediction.h"
51
#include "CommonLib/UnitTools.h"
52
#include "CommonLib/TimeProfiler.h"
53
54
#include "CommonLib/dtrace_buffer.h"
55
56
namespace vvdec
57
{
58
59
//! \ingroup DecoderLib
60
//! \{
61
62
void DecCu::TaskDeriveCtuMotionInfo( CodingStructure &cs, const int ctuRsAddr, const UnitArea &ctuArea, MotionHist& hist )
63
0
{
64
0
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_CONTROL_PARSE_DERIVE_LL, cs, CH_L );
65
66
0
  const unsigned  ctuXPosInCtus  = ctuRsAddr % cs.pcv->widthInCtus;
67
0
  const unsigned  tileColIdx     = cs.pps->ctuToTileCol( ctuXPosInCtus );
68
0
  const unsigned  tileXPosInCtus = cs.pps->getTileColumnBd( tileColIdx );
69
70
0
  if( ctuXPosInCtus == tileXPosInCtus )
71
0
  {
72
0
    hist.motionLut.   resize(0);
73
0
    hist.motionLutIbc.resize(0);
74
0
  }
75
  
76
0
  for( auto &currCU : cs.traverseCUs( ctuRsAddr ) )
77
0
  {
78
0
    CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ),
79
0
           "Traversing CU at (" << currCU.blocks[currCU.chType()].x << "," << currCU.blocks[currCU.chType()].y
80
0
           << ") outside of the CTU at (" << ctuArea.blocks[currCU.chType()].x << "," << ctuArea.blocks[currCU.chType()].y << ")!"
81
0
    );
82
83
#if JVET_O1170_CHECK_BV_AT_DECODER
84
    if( currCU.Y().valid() && currCU.sps->getIBCFlag() )
85
    {
86
      const int vSize = cs.sps->getMaxCUHeight() > 64 ? 64 : cs.sps->getMaxCUHeight();
87
      if( ( currCU.Y().x % vSize ) == 0 && ( currCU.Y().y % vSize ) == 0 )
88
      {
89
        m_pcInterPred->resetVPDUforIBC( cs.pcv->chrFormat, cs.sps->getMaxCUHeight(), vSize, currCU.Y().x  + g_IBCBufferSize / cs.sps->getMaxCUHeight() / 2, currCU.Y().y );
90
      }
91
    }
92
#endif
93
94
0
    if( !CU::isIntra( currCU ) )
95
0
    {
96
0
      xDeriveCUMV( currCU, hist );
97
0
    }
98
0
    else
99
0
    {
100
0
      MotionBuf mb = currCU.getMotionBuf();
101
0
      mb.memset( MI_NOT_VALID );
102
0
    }
103
0
  }
104
0
}
105
106
void DecCu::TaskTrafoCtu( CodingStructure &cs, const int ctuRsAddr, const UnitArea &ctuArea )
107
0
{
108
0
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_ITRANS_REC, cs, CH_L );
109
110
0
  for( auto &currCU : cs.traverseCUs( ctuRsAddr ) )
111
0
  {
112
0
    CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ), "Should never happen!" );
113
114
0
    if( currCU.rootCbf() )
115
0
    {
116
0
      reconstructResi( currCU );
117
0
    }
118
0
  }
119
0
}
120
121
void DecCu::TaskInterCtu( CodingStructure &cs, const int ctuRsAddr, const UnitArea &ctuArea )
122
0
{
123
0
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_CONTROL_PARSE_DERIVE_LL, cs, CH_L );
124
125
0
  for( auto &currCU: cs.traverseCUs( ctuRsAddr ) )
126
0
  {
127
0
    CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ), "Should never happen!" );
128
129
0
    if( !CU::isIntra( currCU ) && !CU::isIBC( currCU ) )
130
0
    {
131
0
      predAndReco( currCU, false );
132
0
    }
133
0
  }
134
0
}
135
136
void DecCu::TaskCriticalIntraKernel( CodingStructure &cs, const int ctuRsAddr, const UnitArea &ctuArea )
137
0
{
138
0
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_CONTROL_PARSE_DERIVE_LL, cs, CH_L );
139
0
  const CtuData &ctuData = cs.getCtuData( ctuRsAddr );
140
141
0
  for( auto &currCU : cs.traverseCUs( ctuRsAddr ) )
142
0
  {
143
0
    CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ), "Should never happen!" );
144
145
0
    if( CU::isIntra( currCU ) || currCU.ciipFlag() || CU::isIBC( currCU ) )
146
0
    {
147
0
      predAndReco( currCU, true );
148
0
    }
149
0
    else if( currCU.rootCbf() )
150
0
    {
151
0
      finishLMCSAndReco( currCU );
152
0
    }
153
154
0
    if( cs.sps->getIBCFlag() && cs.hasIbcBlock[ctuData.lineIdx] )
155
0
    {
156
0
      cs.fillIBCbuffer( currCU, ctuData.lineIdx );
157
0
    }
158
0
  }
159
0
}
160
161
void DecCu::TaskFinishMotionInfo( CodingStructure &cs, const int ctuRsAddr, const int col, const int row )
162
0
{
163
0
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_CONTROL_PARSE_DERIVE_LL, cs, CH_L );
164
165
  // first, finish DMVR motion
166
167
0
  UnitArea    ctuArea = getCtuArea( cs, col, row, true );
168
0
  MotionBuf   mb      = cs.getMotionBuf( ctuArea.Y() );
169
0
  MotionInfo* orgPtr  = mb.buf;
170
171
0
  for( CodingUnit &cu : cs.traverseCUs( ctuRsAddr ) )
172
0
  {
173
0
    CHECKD( !ctuArea.blocks[cu.chType()].contains( cu.blocks[cu.chType()] ), "Should never happen!" );
174
    
175
0
    if( isLuma( cu.chType() ) && cu.dmvrCondition() )
176
0
    {
177
0
      const int dy = std::min<int>( cu.lumaSize().height, DMVR_SUBCU_HEIGHT );
178
0
      const int dx = std::min<int>( cu.lumaSize().width,  DMVR_SUBCU_WIDTH );
179
      
180
0
      static constexpr unsigned scale = 4 * AMVP_DECIMATION_FACTOR;
181
0
      static constexpr unsigned mask  = scale - 1;
182
183
0
      const Position puPos = cu.lumaPos();
184
0
      const Mv mv0 = cu.mv[0][0];
185
0
      const Mv mv1 = cu.mv[1][0];
186
187
0
      for( int y = puPos.y, num = 0; y < ( puPos.y + cu.lumaSize().height ); y = y + dy )
188
0
      {
189
0
        for( int x = puPos.x; x < ( puPos.x + cu.lumaSize().width ); x = x + dx, num++ )
190
0
        {
191
0
          const Mv subPuMv0 = mv0 + cs.m_dmvrMvCache[cu.mvdL0SubPuOff + num];
192
0
          const Mv subPuMv1 = mv1 - cs.m_dmvrMvCache[cu.mvdL0SubPuOff + num];
193
194
0
          int y2 = ( ( y - 1 ) & ~mask ) + scale;
195
196
0
          for( ; y2 < y + dy; y2 += scale )
197
0
          {
198
0
            int x2 = ( ( x - 1 ) & ~mask ) + scale;
199
200
0
            for( ; x2 < x + dx; x2 += scale )
201
0
            {
202
0
              mb.buf = orgPtr + cs.inCtuPos( Position{ x2, y2 }, CH_L );
203
204
0
              MotionInfo& mi = *mb.buf;
205
206
0
              mi.mv[0] = subPuMv0;
207
0
              mi.mv[1] = subPuMv1;
208
0
            }
209
0
          }
210
0
        }
211
0
      }
212
0
    }
213
0
  }
214
215
0
  CtuData &ctuData = cs.getCtuData( ctuRsAddr );
216
217
0
  const int size4x4 = (int)cs.get4x4MapStride();
218
219
0
  const MotionInfo          *src = ctuData.motion;
220
0
        ColocatedMotionInfo *dst = ctuData.colMotion;
221
222
  // ctuDta.colMotion should already be set to '0'
223
  //memset( dst, 0, sizeof( ctuData.colMotion ) );
224
225
  // skip every second source line
226
0
  for( int y = 0; y < size4x4; y += 2, src += size4x4 )
227
0
  {
228
0
    for( int x = 0; x < size4x4; x += 2, src += 2, dst++ )
229
0
    {
230
      //if( src->isInter() )
231
0
      {
232
0
        *dst = *src;
233
0
      }
234
0
    }
235
0
  }
236
0
}
237
// ====================================================================================================================
238
// Constructor / destructor / create / destroy
239
// ====================================================================================================================
240
241
DecCu::DecCu()
242
0
{
243
0
  create();
244
0
}
245
246
DecCu::~DecCu()
247
0
{
248
0
  destroy();
249
0
}
250
251
void DecCu::init( IntraPrediction* pcIntra, InterPrediction* pcInter, Reshape *pcReshape, TrQuant *pcTrQuant )
252
0
{
253
0
  m_pcIntraPred  = pcIntra;
254
0
  m_pcInterPred  = pcInter;
255
0
  m_pcTrQuant    = pcTrQuant;
256
0
  m_pcReshape    = pcReshape;
257
0
}
258
259
void DecCu::create()
260
0
{
261
0
}
262
263
void DecCu::destroy()
264
0
{
265
0
}
266
267
// ====================================================================================================================
268
// Public member functions
269
// ====================================================================================================================
270
271
void DecCu::predAndReco( CodingUnit& cu, bool doCiipIntra )
272
0
{
273
0
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_ITRANS_REC, *cu.cs, CH_L );
274
0
  CodingStructure &cs = *cu.cs;
275
  
276
0
  if( CU::isIntra( cu ) )
277
0
  {
278
0
    if( cu.colorTransform() )
279
0
    {
280
0
      xIntraRecACT( cu );
281
0
      return;
282
0
    }
283
284
0
    for( TransformUnit &tu : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
285
0
    {
286
0
      for( const CompArea &area : tu.blocks )
287
0
      {
288
0
        if( !area.valid() )
289
0
        {
290
0
          continue;
291
0
        }
292
293
0
        const ComponentID compID = area.compID();
294
0
        const ChannelType chType = toChannelType( compID );
295
296
0
        PelBuf piPred;
297
0
        {
298
0
          PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_INTRAPRED, cs, compID );
299
300
0
          if( cu.planeCbf( compID ) )
301
0
          {
302
0
            if( chType == CHANNEL_TYPE_LUMA )
303
0
            {
304
0
              Position pos = Position( tu.Y().x - cu.lumaPos().x, tu.Y().y - cu.lumaPos().y );
305
0
              piPred = cs.getPredBuf( cu ).Y().subBuf( pos, tu.lumaSize() );
306
0
            }
307
0
            else
308
0
            {
309
0
              piPred = cs.getPredBuf( cu ).Cb().subBuf( Position( 0, 0 ), tu.chromaSize() );
310
0
            }
311
0
          }
312
0
          else
313
0
          {
314
0
            piPred = cs.getRecoBuf( area );
315
0
          }
316
317
0
          const uint32_t uiChFinalMode  = PU::getFinalIntraMode( cu, chType );
318
319
0
          if( CU::isMIP( cu, chType ) )
320
0
          {
321
0
            m_pcIntraPred->initIntraPatternChType( tu, area );
322
0
            m_pcIntraPred->initIntraMip( cu, area );
323
0
            m_pcIntraPred->predIntraMip( compID, piPred, cu );
324
0
          }
325
0
          else if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) )
326
0
          {
327
0
            m_pcIntraPred->initIntraPatternChType( tu, area );
328
0
            m_pcIntraPred->xGetLumaRecPixels( cu, area );
329
0
            m_pcIntraPred->predIntraChromaLM( compID, piPred, cu, area, uiChFinalMode );
330
0
          }
331
0
          else
332
0
          {
333
0
            const bool predRegDiffFromTB = CU::isPredRegDiffFromTB( *tu.cu, compID );
334
0
            const bool firstTBInPredReg  = CU::isFirstTBInPredReg( *tu.cu, compID, area );
335
0
            CompArea areaPredReg( COMPONENT_Y, area );
336
337
0
            const bool bUseFilteredPredictions = isLuma( compID ) && cu.ispMode() == NOT_INTRA_SUBPARTITIONS && IntraPrediction::useFilteredIntraRefSamples( compID, cu, tu );
338
339
0
            if( tu.cu->ispMode() && isLuma( compID ) )
340
0
            {
341
0
              PelBuf piReco = cs.getRecoBuf( area );
342
0
              if( predRegDiffFromTB )
343
0
              {
344
0
                if( firstTBInPredReg )
345
0
                {
346
0
                  CU::adjustPredArea( areaPredReg );
347
0
                  m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, areaPredReg, piReco );
348
0
                }
349
0
              }
350
0
              else
351
0
              {
352
0
                m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, area, piReco );
353
0
              }
354
0
            }
355
0
            else
356
0
            {
357
0
              m_pcIntraPred->initIntraPatternChType( tu, area, bUseFilteredPredictions );
358
0
            }
359
360
0
            if( predRegDiffFromTB )
361
0
            {
362
0
              if( firstTBInPredReg )
363
0
              {
364
0
                Position pos( areaPredReg.x - cu.lumaPos().x, areaPredReg.y - cu.lumaPos().y );
365
0
                piPred      = cs.getPredBuf( cu ).Y().subBuf( pos, areaPredReg.size() );
366
367
0
                m_pcIntraPred->predIntraAng( compID, piPred, cu, bUseFilteredPredictions );
368
369
0
                piPred.width = area.width;
370
0
              }
371
0
            }
372
0
            else
373
0
              m_pcIntraPred->predIntraAng( compID, piPred, cu, bUseFilteredPredictions );
374
0
          }
375
0
        }
376
377
        //===== inverse transform =====
378
0
        PelBuf piReco = cs.getRecoBuf( area );
379
0
        PelBuf piResi = cs.getRecoBuf( area );
380
381
0
        const Slice &slice      = *cu.slice;
382
0
        const bool   doChrScale = isChroma( compID )
383
0
                                  && slice.getLmcsEnabledFlag()
384
0
                                  && slice.getPicHeader()->getLmcsChromaResidualScaleFlag()
385
0
                                  && tu.blocks[compID].area() > 4
386
0
                                  && ( TU::getCbf( tu, compID ) || tu.jointCbCr )
387
0
                                  ;
388
389
0
        if( doChrScale )
390
0
        {
391
0
          const Area area       = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType(), CHANNEL_TYPE_LUMA, tu.blocks[tu.chType()].pos()), recalcSize(tu.chromaFormat, tu.chType(), CHANNEL_TYPE_LUMA, tu.blocks[tu.chType()].size()));
392
0
          int chromaResScaleInv = m_pcReshape->calculateChromaAdjVpduNei( tu, area.pos() );
393
0
          piReco.scaleSignal( chromaResScaleInv, slice.clpRng( compID ) );
394
0
        }
395
396
0
        if( TU::getCbf( tu, compID ) || ( isChroma( compID ) && tu.jointCbCr ) )
397
0
        {
398
0
          piReco.reconstruct( piPred, piResi, slice.clpRng( compID ) );
399
0
        }
400
0
        else if( cu.planeCbf( compID ) )
401
0
        {
402
0
          piReco.copyFrom( piPred );
403
0
        }
404
0
      }
405
0
    }
406
0
  }
407
0
  else
408
0
  {
409
0
    const UnitArea& cuArea = cu;
410
411
0
    PelUnitBuf predBuf = cu.rootCbf() ? cs.getPredBuf( cu ) : cs.getRecoBuf( cuArea );
412
0
    PelUnitBuf recoBuf = cs.getRecoBuf( cuArea );
413
414
    // CBF in at least one channel, but no TU split
415
0
    if( cu.rootCbf() )
416
0
    {
417
0
      for( const auto &blk : cu.blocks )
418
0
      {
419
0
        if( blk.valid() && !cu.planeCbf( blk.compID() ) )
420
0
        {
421
0
          predBuf.bufs[blk.compID()] = recoBuf.bufs[blk.compID()];
422
0
        }
423
0
      }
424
0
    }
425
426
0
    if( cu.geoFlag() )
427
0
    {
428
0
      m_pcInterPred->motionCompensationGeo( cu, predBuf );
429
0
    }
430
0
    else
431
0
    {
432
      // inter prediction
433
0
      CHECK( CU::isIBC( cu ) && cu.ciipFlag(),       "IBC and CIIP cannot be used together"   );
434
0
      CHECK( CU::isIBC( cu ) && cu.affineFlag(),     "IBC and AFFINE cannot be used together" );
435
0
      CHECK( CU::isIBC( cu ) && cu.geoFlag(),        "IBC and GEO cannot be used together"    );
436
0
      CHECK( CU::isIBC( cu ) && cu.mmvdFlag(),       "IBC and MMVD cannot be used together"     );
437
438
0
      if( !CU::isIBC( cu ) && !doCiipIntra )
439
0
      {
440
0
        m_pcInterPred->motionCompensation( cu, predBuf );
441
0
      }
442
0
      else if( CU::isIBC( cu ) )
443
0
      {
444
0
        const bool luma   = cu.Y ().valid();
445
0
        const bool chroma = isChromaEnabled(cu.chromaFormat) && cu.Cb().valid();
446
0
        m_pcInterPred->motionCompensation( cu, predBuf, luma, chroma );
447
0
      }
448
0
    }
449
450
0
    if( cu.ciipFlag() && doCiipIntra )
451
0
    {
452
0
      m_pcIntraPred->predBlendIntraCiip( predBuf, cu );
453
0
    }
454
455
0
    DTRACE    ( g_trace_ctx, D_TMP, "pred " );
456
0
    DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, predBuf, &cu.Y() );
457
458
0
    if( cu.rootCbf() )
459
0
    {
460
0
      if( cu.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag( *cu.slice ) && !doCiipIntra )
461
0
      {
462
0
         m_pcReshape->rspBufFwd( predBuf.Y() );
463
0
      }
464
465
0
      if( ( cu.ciipFlag() && doCiipIntra ) || CU::isIBC( cu ) )
466
0
      {
467
0
        finishLMCSAndReco( cu );
468
0
      }
469
0
    }
470
0
    else
471
0
    {
472
0
      if( cu.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag( *cu.slice ) && !CU::isIBC( cu ) )
473
0
      {
474
0
        m_pcReshape->rspBufFwd( predBuf.Y() );
475
0
      }
476
0
    }
477
478
0
    DTRACE    ( g_trace_ctx, D_TMP, "reco " );
479
0
    DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, cu.cs->getRecoBuf( cuArea ), &cu.Y() );
480
0
  }
481
0
}
482
483
void DecCu::finishLMCSAndReco( CodingUnit &cu )
484
0
{
485
0
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_ITRANS_REC, *cu.cs, CH_L );
486
0
  CodingStructure &cs = *cu.cs;
487
488
0
  const uint32_t uiNumVaildComp = getNumberValidComponents( cu.chromaFormat );
489
0
  const bool     doCS           = cs.picHeader->getLmcsEnabledFlag() && cs.picHeader->getLmcsChromaResidualScaleFlag() && cu.slice->getLmcsEnabledFlag();
490
0
  const PelUnitBuf predUnitBuf  = cs.getPredBuf( cu );
491
492
0
  for( auto& currTU : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
493
0
  {
494
0
    int chromaResScaleInv = 0;
495
496
0
    for( uint32_t ch = 0; ch < uiNumVaildComp; ch++ )
497
0
    {
498
0
      const ComponentID compID = ComponentID( ch );
499
        
500
0
      if( doCS )
501
0
      {
502
0
        if( isLuma( compID ) )
503
0
        {
504
0
          chromaResScaleInv = m_pcReshape->calculateChromaAdjVpduNei( currTU, currTU.blocks[COMPONENT_Y] );
505
0
        }
506
0
        else if( ( TU::getCbf( currTU, compID ) || currTU.jointCbCr ) && currTU.blocks[compID].area() > 4 )
507
0
        {
508
0
          const CompArea &area = currTU.blocks[compID];
509
0
          PelBuf resiBuf       = cs.getRecoBuf( area );
510
0
          resiBuf.scaleSignal( chromaResScaleInv, cu.slice->clpRng( compID ) );
511
0
        }
512
0
      }
513
514
0
      if( currTU.blocks[compID].valid() )
515
0
      {
516
0
        CPelBuf predBuf = predUnitBuf.bufs[compID];
517
0
        OFFSET( predBuf.buf, predBuf.stride, currTU.blocks[compID].x - cu.blocks[compID].x, currTU.blocks[compID].y - cu.blocks[compID].y );
518
        //CPelBuf resiBuf = cs.getRecoBuf( currTU.blocks[compID] );
519
0
         PelBuf recoBuf = cs.getRecoBuf( currTU.blocks[compID] );
520
0
         predBuf.width  = recoBuf.width;
521
0
         predBuf.height = recoBuf.height;
522
523
0
        if( TU::getCbf( currTU, compID ) || ( isChroma( compID ) && currTU.jointCbCr ) )
524
0
        {
525
0
          recoBuf.reconstruct( predBuf, recoBuf, cu.slice->clpRngs() );
526
0
        }
527
0
        else if( cu.planeCbf( compID ) )
528
0
        {
529
0
          recoBuf.copyFrom( predBuf );
530
0
        }
531
0
      }
532
0
    }
533
0
  }
534
0
}
535
536
void DecCu::reconstructResi( CodingUnit &cu )
537
0
{
538
0
  CodingStructure &cs = *cu.cs;
539
540
0
  for( TransformUnit &tu : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
541
0
  {
542
0
    for( const auto &area : tu.blocks )
543
0
    {
544
0
      if( !area.valid() )
545
0
      {
546
0
        continue;
547
0
      }
548
549
0
      const ComponentID compID = area.compID();
550
551
      //===== inverse transform =====
552
0
      PelBuf piResi = cs.getRecoBuf( area );
553
554
0
      if( tu.jointCbCr && isChroma( compID ) )
555
0
      {
556
0
        if( compID == COMPONENT_Cb )
557
0
        {
558
0
          PelBuf resiCr = cs.getRecoBuf( tu.blocks[ COMPONENT_Cr ] );
559
0
          if( tu.jointCbCr >> 1 )
560
0
          {
561
0
            QpParam qpCb( tu, compID );
562
0
            m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cb, piResi, qpCb );
563
0
          }
564
0
          else
565
0
          {
566
0
            QpParam qpCr( tu, COMPONENT_Cr );
567
0
            m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cr, resiCr, qpCr );
568
0
          }
569
0
          m_pcTrQuant->invTransformICT( tu, piResi, resiCr );
570
0
        }
571
0
      }
572
0
      else if( TU::getCbf( tu, compID ) )
573
0
      {
574
0
        QpParam cQP( tu, compID );
575
0
        m_pcTrQuant->invTransformNxN( tu, compID, piResi, cQP );
576
0
      }
577
0
    }
578
0
  }
579
0
}
580
581
// ====================================================================================================================
582
// Protected member functions
583
// ====================================================================================================================
584
585
/** Function for deriving reconstructed luma/chroma samples of a PCM mode CU.
586
* \param pcCU pointer to current CU
587
* \param uiPartIdx part index
588
* \param piPCM pointer to PCM code arrays
589
* \param piReco pointer to reconstructed sample arrays
590
* \param uiStride stride of reconstructed sample arrays
591
* \param uiWidth CU width
592
* \param uiHeight CU height
593
* \param compID colour component ID
594
* \returns void
595
*/
596
597
void DecCu::xIntraRecACT( CodingUnit &cu )
598
0
{
599
0
  CodingStructure &cs  = *cu.cs;
600
0
  const Slice &slice   = *cu.slice;
601
602
0
  for( TransformUnit &tu : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
603
0
  {
604
0
    cs.getRecoBuf( tu ).colorSpaceConvert( cs.getRecoBuf( tu ), slice.clpRng( COMPONENT_Y ) );
605
606
0
    for( const CompArea &area : tu.blocks )
607
0
    {
608
0
      const ComponentID compID = area.compID();
609
610
0
      if( compID == COMPONENT_Y )
611
0
      {
612
0
        continue;
613
0
      }
614
      //===== inverse transform =====
615
0
      PelBuf piReco = cs.getRecoBuf( area );
616
617
0
      const bool   doChrScale = isChroma( compID )
618
0
                                && slice.getLmcsEnabledFlag() 
619
0
                                && slice.getPicHeader()->getLmcsChromaResidualScaleFlag()
620
0
                                && tu.blocks[compID].area() > 4
621
0
                                && ( TU::getCbf( tu, compID ) || tu.jointCbCr )
622
0
                                ;
623
624
0
      if( doChrScale )
625
0
      {
626
0
        const Area area       = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType(), CHANNEL_TYPE_LUMA, tu.blocks[tu.chType()].pos()), recalcSize(tu.chromaFormat, tu.chType(), CHANNEL_TYPE_LUMA, tu.blocks[tu.chType()].size()));
627
0
        int chromaResScaleInv = m_pcReshape->calculateChromaAdjVpduNei( tu, area.pos() );
628
0
        piReco.scaleSignal( chromaResScaleInv, slice.clpRng( compID ) );
629
0
      }
630
0
    }
631
632
0
    for( const CompArea &area : tu.blocks )
633
0
    {
634
0
      if( !area.valid() )
635
0
      {
636
0
        continue;
637
0
      }
638
639
0
      const ComponentID compID = area.compID();
640
0
      const ChannelType chType = toChannelType( compID );
641
642
0
      PelBuf piPred;
643
0
      if( chType == CHANNEL_TYPE_LUMA )
644
0
      {
645
0
        Position pos = Position( tu.Y().x - cu.lumaPos().x, tu.Y().y - cu.lumaPos().y );
646
0
        piPred = cs.getPredBuf( cu ).Y().subBuf( pos, tu.lumaSize() );
647
0
      }
648
0
      else
649
0
      {
650
0
        piPred = cs.getPredBuf( cu ).Cb().subBuf( Position( 0, 0 ), tu.chromaSize() );
651
0
      }
652
653
0
      const uint32_t uiChFinalMode  = PU::getFinalIntraMode( cu, chType );
654
655
0
      bool predRegDiffFromTB = CU::isPredRegDiffFromTB( *tu.cu, compID );
656
0
      bool firstTBInPredReg  = CU::isFirstTBInPredReg( *tu.cu, compID, area );
657
0
      CompArea areaPredReg   ( COMPONENT_Y, area );
658
659
0
      if( CU::isMIP( cu, chType ) )
660
0
      {
661
0
        m_pcIntraPred->initIntraPatternChType( tu, area );
662
0
        m_pcIntraPred->initIntraMip( cu, area );
663
0
        m_pcIntraPred->predIntraMip( compID, piPred, cu );
664
0
      }
665
0
      else
666
0
      {
667
0
        const bool bUseFilteredPredictions = isLuma( chType ) && cu.ispMode() == NOT_INTRA_SUBPARTITIONS && IntraPrediction::useFilteredIntraRefSamples( compID, cu, tu );
668
        
669
0
        if( tu.cu->ispMode() && isLuma( compID ) )
670
0
        {
671
0
          PelBuf piReco = cs.getRecoBuf( area );
672
0
          if( predRegDiffFromTB )
673
0
          {
674
0
            if( firstTBInPredReg )
675
0
            {
676
0
              CU::adjustPredArea( areaPredReg );
677
0
              m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, areaPredReg, piReco );
678
0
            }
679
0
          }
680
0
          else
681
0
          {
682
0
            m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, area, piReco );
683
0
          }
684
0
        }
685
0
        else
686
0
        {
687
0
          m_pcIntraPred->initIntraPatternChType( tu, area, bUseFilteredPredictions );
688
0
        }
689
690
0
        if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) )
691
0
        {
692
0
          m_pcIntraPred->xGetLumaRecPixels( cu, area );
693
0
          m_pcIntraPred->predIntraChromaLM( compID, piPred, cu, area, uiChFinalMode );
694
0
        }
695
0
        else
696
0
        {
697
0
          if( predRegDiffFromTB )
698
0
          {
699
0
            if( firstTBInPredReg )
700
0
            {
701
0
              Position pos( areaPredReg.x - cu.lumaPos().x, areaPredReg.y - cu.lumaPos().y );
702
0
              piPred      = cs.getPredBuf( cu ).Y().subBuf( pos, areaPredReg.size() );
703
704
0
              m_pcIntraPred->predIntraAng( compID, piPred, cu, bUseFilteredPredictions );
705
0
            }
706
0
          }
707
0
          else
708
0
            m_pcIntraPred->predIntraAng( compID, piPred, cu, bUseFilteredPredictions );
709
0
        }
710
0
      }
711
712
0
      PelBuf piReco = cs.getRecoBuf( area );
713
0
      PelBuf piResi = cs.getRecoBuf( area );
714
715
0
      piReco.reconstruct( piPred, piResi, slice.clpRng( compID ) );
716
0
    }
717
0
  }
718
0
}
719
720
void DecCu::xDeriveCUMV( CodingUnit &cu, MotionHist& hist )
721
0
{
722
0
  if( cu.mergeFlag() )
723
0
  {
724
0
    MergeCtx mrgCtx;
725
726
0
    if( cu.mmvdFlag() )
727
0
    {
728
0
      int fPosBaseIdx = cu.mmvdIdx / MMVD_MAX_REFINE_NUM;
729
730
0
      PU::getInterMergeCandidates     ( cu, mrgCtx, hist, fPosBaseIdx + 1 );
731
0
      PU::getInterMMVDMergeCandidates ( cu, mrgCtx,       cu.mmvdIdx );
732
0
      mrgCtx.setMmvdMergeCandiInfo    ( cu, cu.mmvdIdx );
733
734
0
      PU::spanMotionInfo              ( cu );
735
0
    }
736
0
    else if( cu.geoFlag() )
737
0
    {
738
0
      PU::getGeoMergeCandidates( cu, m_geoMrgCtx, hist );
739
740
0
      const uint8_t splitDir = cu.geoSplitDir;
741
0
      const uint8_t candIdx0 = cu.geoMergeIdx0();
742
0
      const uint8_t candIdx1 = cu.geoMergeIdx1();
743
744
0
      PU::spanGeoMotionInfo( cu, m_geoMrgCtx, splitDir, candIdx0, candIdx1 );
745
0
    }
746
0
    else if( cu.affineFlag() )
747
0
    {
748
0
      AffineMergeCtx affineMergeCtx;
749
750
0
      if( cu.sps->getSBTMVPEnabledFlag() )
751
0
      {
752
0
        affineMergeCtx.subPuMvpMiBuf = cu.getMotionBuf();
753
0
      }
754
755
0
      int mergeIdx = cu.mergeIdx();
756
0
      PU::getAffineMergeCand( cu, affineMergeCtx, mergeIdx );
757
758
0
      cu.setInterDir        ( affineMergeCtx.interDirNeighbours[mergeIdx] );
759
0
      cu.setAffineType      ( affineMergeCtx.affineType        [mergeIdx] );
760
0
      cu.setBcwIdx          ( affineMergeCtx.BcwIdx            [mergeIdx] );
761
0
      cu.setMergeType       ( affineMergeCtx.mergeType         [mergeIdx] );
762
763
0
      if( cu.mergeType() == MRG_TYPE_SUBPU_ATMVP )
764
0
      {
765
0
        cu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[( cu.mergeIdx() << 1 ) + 0][0].mfRefIdx;
766
0
        cu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[( cu.mergeIdx() << 1 ) + 1][0].mfRefIdx;
767
0
      }
768
0
      else
769
0
      {
770
0
        for( int i = 0; i < 2; ++i )
771
0
        {
772
0
          if( cu.slice->getNumRefIdx( RefPicList( i ) ) > 0 )
773
0
          {
774
0
            MvField* mvField = affineMergeCtx.mvFieldNeighbours[( cu.mergeIdx() << 1 ) + i];
775
776
0
            PU::setAllAffineMvField( cu, mvField, RefPicList( i ) );
777
0
          }
778
0
        }
779
0
      }
780
781
0
      PU::spanMotionInfo( cu );
782
0
    }
783
0
    else
784
0
    {
785
0
      if( CU::isIBC( cu ) )
786
0
        PU::getIBCMergeCandidates  ( cu, mrgCtx, hist, cu.mergeIdx() );
787
0
      else
788
0
        PU::getInterMergeCandidates( cu, mrgCtx, hist, cu.mergeIdx() );
789
790
0
      mrgCtx.setMergeInfo         ( cu, cu.mergeIdx() );
791
792
0
      PU::spanMotionInfo          ( cu );
793
0
    }
794
0
  }
795
0
  else
796
0
  {
797
0
    if( cu.imv() && !cu.affineFlag() )
798
0
    {
799
0
      PU::applyImv      ( cu, hist );
800
0
      PU::spanMotionInfo( cu );
801
0
    }
802
0
    else
803
0
    {
804
0
      if( cu.affineFlag() )
805
0
      {
806
0
        for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
807
0
        {
808
0
          RefPicList eRefList = RefPicList( uiRefListIdx );
809
0
          if( cu.slice->getNumRefIdx( eRefList ) > 0 && ( cu.interDir() & ( 1 << uiRefListIdx ) ) )
810
0
          {
811
0
            AffineAMVPInfo affineAMVPInfo;
812
0
            PU::fillAffineMvpCand( cu, eRefList, cu.refIdx[eRefList], affineAMVPInfo );
813
814
0
            const unsigned mvp_idx = cu.mvpIdx[eRefList];
815
816
            //    Mv mv[3];
817
0
            CHECK( cu.refIdx[eRefList] < 0, "Unexpected negative refIdx." );
818
0
            const int imvShift = cu.imv() == 2 ? MV_FRACTIONAL_BITS_DIFF : 0;
819
0
            Mv mv0 = cu.mv[eRefList][0];
820
0
            Mv mv1 = cu.mv[eRefList][1];
821
822
0
            mv0 <<= imvShift;
823
0
            mv1 <<= imvShift;
824
825
0
            Mv mvLT = affineAMVPInfo.mvCandLT[mvp_idx] + mv0;
826
0
            Mv mvRT = affineAMVPInfo.mvCandRT[mvp_idx] + mv1;
827
0
            mvRT   += mv0;
828
0
            if( cu.imv() != 1 )
829
0
            {
830
0
              mvLT.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
831
0
              mvRT.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
832
0
            }
833
834
0
            Mv mvLB;
835
0
            if( cu.affineType() == AFFINEMODEL_6PARAM )
836
0
            {
837
0
              Mv mv2 = cu.mv[eRefList][2];
838
0
              mv2 <<= imvShift;
839
0
              mvLB = affineAMVPInfo.mvCandLB[mvp_idx] + mv2;
840
0
              mvLB += mv0;
841
0
              if ( cu.imv() != 1 )
842
0
              {
843
0
                mvLB.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL );
844
0
              }
845
0
            }
846
0
            PU::setAllAffineMv( cu, mvLT, mvRT, mvLB, eRefList, true );
847
0
          }
848
0
        }
849
0
      }
850
0
      else if( CU::isIBC( cu ) && cu.interDir() == 1 )
851
0
      {
852
0
        AMVPInfo amvpInfo;
853
0
        PU::fillIBCMvpCand( cu, amvpInfo, hist );
854
0
        Mv mvd = cu.mv[REF_PIC_LIST_0][0];
855
0
        mvd <<= 4;
856
0
        if( cu.slice->getPicHeader()->getMaxNumIBCMergeCand() == 1 )
857
0
        {
858
0
          CHECK( cu.mvpIdx[REF_PIC_LIST_0], "mvpIdx for IBC mode should be 0" );
859
0
        }
860
0
        cu.mv[REF_PIC_LIST_0][0] = amvpInfo.mvCand[cu.mvpIdx[REF_PIC_LIST_0]] + mvd;
861
0
        cu.mv[REF_PIC_LIST_0][0] . mvCliptoStorageBitDepth();
862
0
      }
863
0
      else
864
0
      {
865
0
        for( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
866
0
        {
867
0
          RefPicList eRefList = RefPicList( uiRefListIdx );
868
0
          if( ( cu.slice->getNumRefIdx( eRefList ) > 0 || ( eRefList == REF_PIC_LIST_0 && CU::isIBC( cu ) ) ) && ( cu.interDir() & ( 1 << uiRefListIdx ) ) )
869
0
          {
870
0
            AMVPInfo amvpInfo;
871
0
            PU::fillMvpCand( cu, eRefList, cu.refIdx[eRefList], amvpInfo, hist );
872
873
0
            Mv mvd              = cu.mv[eRefList][0];
874
0
            mvd                 . changePrecisionAmvr( cu.imv(), MV_PRECISION_INTERNAL);
875
0
            cu.mv [eRefList][0] = amvpInfo.mvCand[cu.mvpIdx[eRefList]] + mvd;
876
0
            cu.mv [eRefList][0] . mvCliptoStorageBitDepth();
877
0
          }
878
0
        }
879
0
      }
880
0
      PU::spanMotionInfo( cu );
881
0
    }
882
0
  }
883
884
0
  bool isIbcSmallBlk = CU::isIBC( cu ) && ( cu.lwidth() * cu.lheight() <= 16 );
885
0
  if( !cu.affineFlag() && !cu.geoFlag() && !isIbcSmallBlk )
886
0
  {
887
0
    const unsigned log2ParallelMergeLevel = (cu.sps->getLog2ParallelMergeLevelMinus2() + 2);
888
0
    const unsigned xBr = cu.Y().width  + cu.Y().x;
889
0
    const unsigned yBr = cu.Y().height + cu.Y().y;
890
0
    bool enableHmvp      = ((xBr >> log2ParallelMergeLevel) > (cu.Y().x >> log2ParallelMergeLevel)) && ((yBr >> log2ParallelMergeLevel) > (cu.Y().y >> log2ParallelMergeLevel));
891
0
    bool isIbc           = CU::isIBC( cu );
892
0
    bool enableInsertion = isIbc || enableHmvp;
893
894
0
    if( enableInsertion )
895
0
    {
896
0
      HPMVInfo mi( cu.getMotionInfo(), cu.interDir() == 3 ? cu.BcwIdx() : BCW_DEFAULT, cu.imv() == IMV_HPEL );
897
0
      if( isIbc ) mi.mhRefIdx[0] = MH_NOT_VALID + 1;
898
0
      MotionHist::addMiToLut( isIbc ? hist.motionLutIbc : hist.motionLut, mi );
899
0
    }
900
0
  }
901
0
}
902
903
}