Coverage Report

Created: 2026-06-16 07:20

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
3.35k
{
64
3.35k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_CONTROL_PARSE_DERIVE_LL, cs, CH_L );
65
66
3.35k
  const unsigned  ctuXPosInCtus  = ctuRsAddr % cs.pcv->widthInCtus;
67
3.35k
  const unsigned  tileColIdx     = cs.pps->ctuToTileCol( ctuXPosInCtus );
68
3.35k
  const unsigned  tileXPosInCtus = cs.pps->getTileColumnBd( tileColIdx );
69
70
3.35k
  if( ctuXPosInCtus == tileXPosInCtus )
71
861
  {
72
861
    hist.motionLut.   resize(0);
73
861
    hist.motionLutIbc.resize(0);
74
861
  }
75
  
76
3.35k
  for( auto &currCU : cs.traverseCUs( ctuRsAddr ) )
77
106k
  {
78
106k
    CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ),
79
106k
           "Traversing CU at (" << currCU.blocks[currCU.chType()].x << "," << currCU.blocks[currCU.chType()].y
80
106k
           << ") outside of the CTU at (" << ctuArea.blocks[currCU.chType()].x << "," << ctuArea.blocks[currCU.chType()].y << ")!"
81
106k
    );
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
106k
    if( !CU::isIntra( currCU ) )
95
23.3k
    {
96
23.3k
      xDeriveCUMV( currCU, hist );
97
23.3k
    }
98
83.5k
    else
99
83.5k
    {
100
83.5k
      MotionBuf mb = currCU.getMotionBuf();
101
83.5k
      mb.memset( MI_NOT_VALID );
102
83.5k
    }
103
106k
  }
104
3.35k
}
105
106
void DecCu::TaskTrafoCtu( CodingStructure &cs, const int ctuRsAddr, const UnitArea &ctuArea )
107
3.08k
{
108
3.08k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_ITRANS_REC, cs, CH_L );
109
110
3.08k
  for( auto &currCU : cs.traverseCUs( ctuRsAddr ) )
111
97.6k
  {
112
97.6k
    CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ), "Should never happen!" );
113
114
97.6k
    if( currCU.rootCbf() )
115
65.8k
    {
116
65.8k
      reconstructResi( currCU );
117
65.8k
    }
118
97.6k
  }
119
3.08k
}
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
2.01k
{
138
2.01k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_CONTROL_PARSE_DERIVE_LL, cs, CH_L );
139
2.01k
  const CtuData &ctuData = cs.getCtuData( ctuRsAddr );
140
141
2.01k
  for( auto &currCU : cs.traverseCUs( ctuRsAddr ) )
142
45.8k
  {
143
45.8k
    CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ), "Should never happen!" );
144
145
45.8k
    if( CU::isIntra( currCU ) || currCU.ciipFlag() || CU::isIBC( currCU ) )
146
45.8k
    {
147
45.8k
      predAndReco( currCU, true );
148
45.8k
    }
149
3
    else if( currCU.rootCbf() )
150
0
    {
151
0
      finishLMCSAndReco( currCU );
152
0
    }
153
154
45.8k
    if( cs.sps->getIBCFlag() && cs.hasIbcBlock[ctuData.lineIdx] )
155
44.6k
    {
156
44.6k
      cs.fillIBCbuffer( currCU, ctuData.lineIdx );
157
44.6k
    }
158
45.8k
  }
159
2.01k
}
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
59.8k
{
243
59.8k
  create();
244
59.8k
}
245
246
DecCu::~DecCu()
247
59.8k
{
248
59.8k
  destroy();
249
59.8k
}
250
251
void DecCu::init( IntraPrediction* pcIntra, InterPrediction* pcInter, Reshape *pcReshape, TrQuant *pcTrQuant )
252
22.8k
{
253
22.8k
  m_pcIntraPred  = pcIntra;
254
22.8k
  m_pcInterPred  = pcInter;
255
22.8k
  m_pcTrQuant    = pcTrQuant;
256
22.8k
  m_pcReshape    = pcReshape;
257
22.8k
}
258
259
void DecCu::create()
260
59.8k
{
261
59.8k
}
262
263
void DecCu::destroy()
264
59.8k
{
265
59.8k
}
266
267
// ====================================================================================================================
268
// Public member functions
269
// ====================================================================================================================
270
271
void DecCu::predAndReco( CodingUnit& cu, bool doCiipIntra )
272
45.8k
{
273
45.8k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_ITRANS_REC, *cu.cs, CH_L );
274
45.8k
  CodingStructure &cs = *cu.cs;
275
  
276
45.8k
  if( CU::isIntra( cu ) )
277
33.3k
  {
278
33.3k
    if( cu.colorTransform() )
279
0
    {
280
0
      xIntraRecACT( cu );
281
0
      return;
282
0
    }
283
284
33.3k
    for( TransformUnit &tu : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
285
37.5k
    {
286
37.5k
      for( const CompArea &area : tu.blocks )
287
112k
      {
288
112k
        if( !area.valid() )
289
58.8k
        {
290
58.8k
          continue;
291
58.8k
        }
292
293
53.9k
        const ComponentID compID = area.compID();
294
53.9k
        const ChannelType chType = toChannelType( compID );
295
296
53.9k
        PelBuf piPred;
297
53.9k
        {
298
53.9k
          PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_INTRAPRED, cs, compID );
299
300
53.9k
          if( cu.planeCbf( compID ) )
301
36.7k
          {
302
36.7k
            if( chType == CHANNEL_TYPE_LUMA )
303
18.0k
            {
304
18.0k
              Position pos = Position( tu.Y().x - cu.lumaPos().x, tu.Y().y - cu.lumaPos().y );
305
18.0k
              piPred = cs.getPredBuf( cu ).Y().subBuf( pos, tu.lumaSize() );
306
18.0k
            }
307
18.6k
            else
308
18.6k
            {
309
18.6k
              piPred = cs.getPredBuf( cu ).Cb().subBuf( Position( 0, 0 ), tu.chromaSize() );
310
18.6k
            }
311
36.7k
          }
312
17.2k
          else
313
17.2k
          {
314
17.2k
            piPred = cs.getRecoBuf( area );
315
17.2k
          }
316
317
53.9k
          const uint32_t uiChFinalMode  = PU::getFinalIntraMode( cu, chType );
318
319
53.9k
          if( CU::isMIP( cu, chType ) )
320
2.77k
          {
321
2.77k
            m_pcIntraPred->initIntraPatternChType( tu, area );
322
2.77k
            m_pcIntraPred->initIntraMip( cu, area );
323
2.77k
            m_pcIntraPred->predIntraMip( compID, piPred, cu );
324
2.77k
          }
325
51.1k
          else if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) )
326
12.4k
          {
327
12.4k
            m_pcIntraPred->initIntraPatternChType( tu, area );
328
12.4k
            m_pcIntraPred->xGetLumaRecPixels( cu, area );
329
12.4k
            m_pcIntraPred->predIntraChromaLM( compID, piPred, cu, area, uiChFinalMode );
330
12.4k
          }
331
38.7k
          else
332
38.7k
          {
333
38.7k
            const bool predRegDiffFromTB = CU::isPredRegDiffFromTB( *tu.cu, compID );
334
38.7k
            const bool firstTBInPredReg  = CU::isFirstTBInPredReg( *tu.cu, compID, area );
335
38.7k
            CompArea areaPredReg( COMPONENT_Y, area );
336
337
38.7k
            const bool bUseFilteredPredictions = isLuma( compID ) && cu.ispMode() == NOT_INTRA_SUBPARTITIONS && IntraPrediction::useFilteredIntraRefSamples( compID, cu, tu );
338
339
38.7k
            if( tu.cu->ispMode() && isLuma( compID ) )
340
5.73k
            {
341
5.73k
              PelBuf piReco = cs.getRecoBuf( area );
342
5.73k
              if( predRegDiffFromTB )
343
930
              {
344
930
                if( firstTBInPredReg )
345
430
                {
346
430
                  CU::adjustPredArea( areaPredReg );
347
430
                  m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, areaPredReg, piReco );
348
430
                }
349
930
              }
350
4.80k
              else
351
4.80k
              {
352
4.80k
                m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, area, piReco );
353
4.80k
              }
354
5.73k
            }
355
33.0k
            else
356
33.0k
            {
357
33.0k
              m_pcIntraPred->initIntraPatternChType( tu, area, bUseFilteredPredictions );
358
33.0k
            }
359
360
38.7k
            if( predRegDiffFromTB )
361
930
            {
362
930
              if( firstTBInPredReg )
363
430
              {
364
430
                Position pos( areaPredReg.x - cu.lumaPos().x, areaPredReg.y - cu.lumaPos().y );
365
430
                piPred      = cs.getPredBuf( cu ).Y().subBuf( pos, areaPredReg.size() );
366
367
430
                m_pcIntraPred->predIntraAng( compID, piPred, cu, bUseFilteredPredictions );
368
369
430
                piPred.width = area.width;
370
430
              }
371
930
            }
372
37.8k
            else
373
37.8k
              m_pcIntraPred->predIntraAng( compID, piPred, cu, bUseFilteredPredictions );
374
38.7k
          }
375
53.9k
        }
376
377
        //===== inverse transform =====
378
53.9k
        PelBuf piReco = cs.getRecoBuf( area );
379
53.9k
        PelBuf piResi = cs.getRecoBuf( area );
380
381
53.9k
        const Slice &slice      = *cu.slice;
382
53.9k
        const bool   doChrScale = isChroma( compID )
383
32.7k
                                  && slice.getLmcsEnabledFlag()
384
0
                                  && slice.getPicHeader()->getLmcsChromaResidualScaleFlag()
385
0
                                  && tu.blocks[compID].area() > 4
386
0
                                  && ( TU::getCbf( tu, compID ) || tu.jointCbCr )
387
53.9k
                                  ;
388
389
53.9k
        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
53.9k
        if( TU::getCbf( tu, compID ) || ( isChroma( compID ) && tu.jointCbCr ) )
397
34.3k
        {
398
34.3k
          piReco.reconstruct( piPred, piResi, slice.clpRng( compID ) );
399
34.3k
        }
400
19.5k
        else if( cu.planeCbf( compID ) )
401
2.30k
        {
402
2.30k
          piReco.copyFrom( piPred );
403
2.30k
        }
404
53.9k
      }
405
37.5k
    }
406
33.3k
  }
407
12.5k
  else
408
12.5k
  {
409
12.5k
    const UnitArea& cuArea = cu;
410
411
12.5k
    PelUnitBuf predBuf = cu.rootCbf() ? cs.getPredBuf( cu ) : cs.getRecoBuf( cuArea );
412
12.5k
    PelUnitBuf recoBuf = cs.getRecoBuf( cuArea );
413
414
    // CBF in at least one channel, but no TU split
415
12.5k
    if( cu.rootCbf() )
416
9.01k
    {
417
9.01k
      for( const auto &blk : cu.blocks )
418
27.0k
      {
419
27.0k
        if( blk.valid() && !cu.planeCbf( blk.compID() ) )
420
0
        {
421
0
          predBuf.bufs[blk.compID()] = recoBuf.bufs[blk.compID()];
422
0
        }
423
27.0k
      }
424
9.01k
    }
425
426
12.5k
    if( cu.geoFlag() )
427
0
    {
428
0
      m_pcInterPred->motionCompensationGeo( cu, predBuf );
429
0
    }
430
12.5k
    else
431
12.5k
    {
432
      // inter prediction
433
12.5k
      CHECK( CU::isIBC( cu ) && cu.ciipFlag(),       "IBC and CIIP cannot be used together"   );
434
12.5k
      CHECK( CU::isIBC( cu ) && cu.affineFlag(),     "IBC and AFFINE cannot be used together" );
435
12.5k
      CHECK( CU::isIBC( cu ) && cu.geoFlag(),        "IBC and GEO cannot be used together"    );
436
12.5k
      CHECK( CU::isIBC( cu ) && cu.mmvdFlag(),       "IBC and MMVD cannot be used together"     );
437
438
12.5k
      if( !CU::isIBC( cu ) && !doCiipIntra )
439
0
      {
440
0
        m_pcInterPred->motionCompensation( cu, predBuf );
441
0
      }
442
12.5k
      else if( CU::isIBC( cu ) )
443
12.5k
      {
444
12.5k
        const bool luma   = cu.Y ().valid();
445
12.5k
        const bool chroma = isChromaEnabled(cu.chromaFormat) && cu.Cb().valid();
446
12.5k
        m_pcInterPred->motionCompensation( cu, predBuf, luma, chroma );
447
12.5k
      }
448
12.5k
    }
449
450
12.5k
    if( cu.ciipFlag() && doCiipIntra )
451
0
    {
452
0
      m_pcIntraPred->predBlendIntraCiip( predBuf, cu );
453
0
    }
454
455
12.5k
    DTRACE    ( g_trace_ctx, D_TMP, "pred " );
456
12.5k
    DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, predBuf, &cu.Y() );
457
458
12.5k
    if( cu.rootCbf() )
459
8.80k
    {
460
8.80k
      if( cu.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag( *cu.slice ) && !doCiipIntra )
461
0
      {
462
0
         m_pcReshape->rspBufFwd( predBuf.Y() );
463
0
      }
464
465
8.80k
      if( ( cu.ciipFlag() && doCiipIntra ) || CU::isIBC( cu ) )
466
8.80k
      {
467
8.80k
        finishLMCSAndReco( cu );
468
8.80k
      }
469
8.80k
    }
470
3.75k
    else
471
3.75k
    {
472
3.75k
      if( cu.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag( *cu.slice ) && !CU::isIBC( cu ) )
473
0
      {
474
0
        m_pcReshape->rspBufFwd( predBuf.Y() );
475
0
      }
476
3.75k
    }
477
478
12.5k
    DTRACE    ( g_trace_ctx, D_TMP, "reco " );
479
12.5k
    DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, cu.cs->getRecoBuf( cuArea ), &cu.Y() );
480
12.5k
  }
481
45.8k
}
482
483
void DecCu::finishLMCSAndReco( CodingUnit &cu )
484
8.80k
{
485
8.80k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_ITRANS_REC, *cu.cs, CH_L );
486
8.80k
  CodingStructure &cs = *cu.cs;
487
488
8.80k
  const uint32_t uiNumVaildComp = getNumberValidComponents( cu.chromaFormat );
489
8.80k
  const bool     doCS           = cs.picHeader->getLmcsEnabledFlag() && cs.picHeader->getLmcsChromaResidualScaleFlag() && cu.slice->getLmcsEnabledFlag();
490
8.80k
  const PelUnitBuf predUnitBuf  = cs.getPredBuf( cu );
491
492
8.80k
  for( auto& currTU : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
493
8.80k
  {
494
8.80k
    int chromaResScaleInv = 0;
495
496
35.2k
    for( uint32_t ch = 0; ch < uiNumVaildComp; ch++ )
497
26.4k
    {
498
26.4k
      const ComponentID compID = ComponentID( ch );
499
        
500
26.4k
      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
26.4k
      if( currTU.blocks[compID].valid() )
515
8.80k
      {
516
8.80k
        CPelBuf predBuf = predUnitBuf.bufs[compID];
517
8.80k
        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
8.80k
         PelBuf recoBuf = cs.getRecoBuf( currTU.blocks[compID] );
520
8.80k
         predBuf.width  = recoBuf.width;
521
8.80k
         predBuf.height = recoBuf.height;
522
523
8.80k
        if( TU::getCbf( currTU, compID ) || ( isChroma( compID ) && currTU.jointCbCr ) )
524
8.80k
        {
525
8.80k
          recoBuf.reconstruct( predBuf, recoBuf, cu.slice->clpRngs() );
526
8.80k
        }
527
0
        else if( cu.planeCbf( compID ) )
528
0
        {
529
0
          recoBuf.copyFrom( predBuf );
530
0
        }
531
8.80k
      }
532
26.4k
    }
533
8.80k
  }
534
8.80k
}
535
536
void DecCu::reconstructResi( CodingUnit &cu )
537
65.8k
{
538
65.8k
  CodingStructure &cs = *cu.cs;
539
540
65.8k
  for( TransformUnit &tu : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
541
76.0k
  {
542
76.0k
    for( const auto &area : tu.blocks )
543
227k
    {
544
227k
      if( !area.valid() )
545
130k
      {
546
130k
        continue;
547
130k
      }
548
549
96.6k
      const ComponentID compID = area.compID();
550
551
      //===== inverse transform =====
552
96.6k
      PelBuf piResi = cs.getRecoBuf( area );
553
554
96.6k
      if( tu.jointCbCr && isChroma( compID ) )
555
14.5k
      {
556
14.5k
        if( compID == COMPONENT_Cb )
557
7.25k
        {
558
7.25k
          PelBuf resiCr = cs.getRecoBuf( tu.blocks[ COMPONENT_Cr ] );
559
7.25k
          if( tu.jointCbCr >> 1 )
560
6.06k
          {
561
6.06k
            QpParam qpCb( tu, compID );
562
6.06k
            m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cb, piResi, qpCb );
563
6.06k
          }
564
1.19k
          else
565
1.19k
          {
566
1.19k
            QpParam qpCr( tu, COMPONENT_Cr );
567
1.19k
            m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cr, resiCr, qpCr );
568
1.19k
          }
569
7.25k
          m_pcTrQuant->invTransformICT( tu, piResi, resiCr );
570
7.25k
        }
571
14.5k
      }
572
82.1k
      else if( TU::getCbf( tu, compID ) )
573
72.3k
      {
574
72.3k
        QpParam cQP( tu, compID );
575
72.3k
        m_pcTrQuant->invTransformNxN( tu, compID, piResi, cQP );
576
72.3k
      }
577
96.6k
    }
578
76.0k
  }
579
65.8k
}
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
23.3k
{
722
23.3k
  if( cu.mergeFlag() )
723
11.0k
  {
724
11.0k
    MergeCtx mrgCtx;
725
726
11.0k
    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
11.0k
    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
11.0k
    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
11.0k
    else
784
11.0k
    {
785
11.0k
      if( CU::isIBC( cu ) )
786
11.0k
        PU::getIBCMergeCandidates  ( cu, mrgCtx, hist, cu.mergeIdx() );
787
0
      else
788
0
        PU::getInterMergeCandidates( cu, mrgCtx, hist, cu.mergeIdx() );
789
790
11.0k
      mrgCtx.setMergeInfo         ( cu, cu.mergeIdx() );
791
792
11.0k
      PU::spanMotionInfo          ( cu );
793
11.0k
    }
794
11.0k
  }
795
12.3k
  else
796
12.3k
  {
797
12.3k
    if( cu.imv() && !cu.affineFlag() )
798
10.0k
    {
799
10.0k
      PU::applyImv      ( cu, hist );
800
10.0k
      PU::spanMotionInfo( cu );
801
10.0k
    }
802
2.28k
    else
803
2.28k
    {
804
2.28k
      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
2.28k
      else if( CU::isIBC( cu ) && cu.interDir() == 1 )
851
2.28k
      {
852
2.28k
        AMVPInfo amvpInfo;
853
2.28k
        PU::fillIBCMvpCand( cu, amvpInfo, hist );
854
2.28k
        Mv mvd = cu.mv[REF_PIC_LIST_0][0];
855
2.28k
        mvd <<= 4;
856
2.28k
        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
2.28k
        cu.mv[REF_PIC_LIST_0][0] = amvpInfo.mvCand[cu.mvpIdx[REF_PIC_LIST_0]] + mvd;
861
2.28k
        cu.mv[REF_PIC_LIST_0][0] . mvCliptoStorageBitDepth();
862
2.28k
      }
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
2.28k
      PU::spanMotionInfo( cu );
881
2.28k
    }
882
12.3k
  }
883
884
23.3k
  bool isIbcSmallBlk = CU::isIBC( cu ) && ( cu.lwidth() * cu.lheight() <= 16 );
885
23.3k
  if( !cu.affineFlag() && !cu.geoFlag() && !isIbcSmallBlk )
886
22.9k
  {
887
22.9k
    const unsigned log2ParallelMergeLevel = (cu.sps->getLog2ParallelMergeLevelMinus2() + 2);
888
22.9k
    const unsigned xBr = cu.Y().width  + cu.Y().x;
889
22.9k
    const unsigned yBr = cu.Y().height + cu.Y().y;
890
22.9k
    bool enableHmvp      = ((xBr >> log2ParallelMergeLevel) > (cu.Y().x >> log2ParallelMergeLevel)) && ((yBr >> log2ParallelMergeLevel) > (cu.Y().y >> log2ParallelMergeLevel));
891
22.9k
    bool isIbc           = CU::isIBC( cu );
892
22.9k
    bool enableInsertion = isIbc || enableHmvp;
893
894
22.9k
    if( enableInsertion )
895
22.9k
    {
896
22.9k
      HPMVInfo mi( cu.getMotionInfo(), cu.interDir() == 3 ? cu.BcwIdx() : BCW_DEFAULT, cu.imv() == IMV_HPEL );
897
22.9k
      if( isIbc ) mi.mhRefIdx[0] = MH_NOT_VALID + 1;
898
22.9k
      MotionHist::addMiToLut( isIbc ? hist.motionLutIbc : hist.motionLut, mi );
899
22.9k
    }
900
22.9k
  }
901
23.3k
}
902
903
}