Coverage Report

Created: 2026-07-25 07:06

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.32k
{
64
3.32k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_CONTROL_PARSE_DERIVE_LL, cs, CH_L );
65
66
3.32k
  const unsigned  ctuXPosInCtus  = ctuRsAddr % cs.pcv->widthInCtus;
67
3.32k
  const unsigned  tileColIdx     = cs.pps->ctuToTileCol( ctuXPosInCtus );
68
3.32k
  const unsigned  tileXPosInCtus = cs.pps->getTileColumnBd( tileColIdx );
69
70
3.32k
  if( ctuXPosInCtus == tileXPosInCtus )
71
860
  {
72
860
    hist.motionLut.   resize(0);
73
860
    hist.motionLutIbc.resize(0);
74
860
  }
75
  
76
3.32k
  for( auto &currCU : cs.traverseCUs( ctuRsAddr ) )
77
105k
  {
78
105k
    CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ),
79
105k
           "Traversing CU at (" << currCU.blocks[currCU.chType()].x << "," << currCU.blocks[currCU.chType()].y
80
105k
           << ") outside of the CTU at (" << ctuArea.blocks[currCU.chType()].x << "," << ctuArea.blocks[currCU.chType()].y << ")!"
81
105k
    );
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
105k
    if( !CU::isIntra( currCU ) )
95
23.1k
    {
96
23.1k
      xDeriveCUMV( currCU, hist );
97
23.1k
    }
98
81.9k
    else
99
81.9k
    {
100
81.9k
      MotionBuf mb = currCU.getMotionBuf();
101
81.9k
      mb.memset( MI_NOT_VALID );
102
81.9k
    }
103
105k
  }
104
3.32k
}
105
106
void DecCu::TaskTrafoCtu( CodingStructure &cs, const int ctuRsAddr, const UnitArea &ctuArea )
107
3.01k
{
108
3.01k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_ITRANS_REC, cs, CH_L );
109
110
3.01k
  for( auto &currCU : cs.traverseCUs( ctuRsAddr ) )
111
95.4k
  {
112
95.4k
    CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ), "Should never happen!" );
113
114
95.4k
    if( currCU.rootCbf() )
115
64.4k
    {
116
64.4k
      reconstructResi( currCU );
117
64.4k
    }
118
95.4k
  }
119
3.01k
}
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
1.98k
{
138
1.98k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_CONTROL_PARSE_DERIVE_LL, cs, CH_L );
139
1.98k
  const CtuData &ctuData = cs.getCtuData( ctuRsAddr );
140
141
1.98k
  for( auto &currCU : cs.traverseCUs( ctuRsAddr ) )
142
45.0k
  {
143
45.0k
    CHECK( !ctuArea.blocks[currCU.chType()].contains( currCU.blocks[currCU.chType()] ), "Should never happen!" );
144
145
45.0k
    if( CU::isIntra( currCU ) || currCU.ciipFlag() || CU::isIBC( currCU ) )
146
45.0k
    {
147
45.0k
      predAndReco( currCU, true );
148
45.0k
    }
149
4
    else if( currCU.rootCbf() )
150
0
    {
151
0
      finishLMCSAndReco( currCU );
152
0
    }
153
154
45.0k
    if( cs.sps->getIBCFlag() && cs.hasIbcBlock[ctuData.lineIdx] )
155
43.9k
    {
156
43.9k
      cs.fillIBCbuffer( currCU, ctuData.lineIdx );
157
43.9k
    }
158
45.0k
  }
159
1.98k
}
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.0k
{
273
45.0k
  PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_ITRANS_REC, *cu.cs, CH_L );
274
45.0k
  CodingStructure &cs = *cu.cs;
275
  
276
45.0k
  if( CU::isIntra( cu ) )
277
32.5k
  {
278
32.5k
    if( cu.colorTransform() )
279
0
    {
280
0
      xIntraRecACT( cu );
281
0
      return;
282
0
    }
283
284
32.5k
    for( TransformUnit &tu : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
285
36.6k
    {
286
36.6k
      for( const CompArea &area : tu.blocks )
287
110k
      {
288
110k
        if( !area.valid() )
289
57.3k
        {
290
57.3k
          continue;
291
57.3k
        }
292
293
52.6k
        const ComponentID compID = area.compID();
294
52.6k
        const ChannelType chType = toChannelType( compID );
295
296
52.6k
        PelBuf piPred;
297
52.6k
        {
298
52.6k
          PROFILER_SCOPE_AND_STAGE_EXT( 1, g_timeProfiler, P_INTRAPRED, cs, compID );
299
300
52.6k
          if( cu.planeCbf( compID ) )
301
35.9k
          {
302
35.9k
            if( chType == CHANNEL_TYPE_LUMA )
303
17.6k
            {
304
17.6k
              Position pos = Position( tu.Y().x - cu.lumaPos().x, tu.Y().y - cu.lumaPos().y );
305
17.6k
              piPred = cs.getPredBuf( cu ).Y().subBuf( pos, tu.lumaSize() );
306
17.6k
            }
307
18.2k
            else
308
18.2k
            {
309
18.2k
              piPred = cs.getPredBuf( cu ).Cb().subBuf( Position( 0, 0 ), tu.chromaSize() );
310
18.2k
            }
311
35.9k
          }
312
16.6k
          else
313
16.6k
          {
314
16.6k
            piPred = cs.getRecoBuf( area );
315
16.6k
          }
316
317
52.6k
          const uint32_t uiChFinalMode  = PU::getFinalIntraMode( cu, chType );
318
319
52.6k
          if( CU::isMIP( cu, chType ) )
320
2.68k
          {
321
2.68k
            m_pcIntraPred->initIntraPatternChType( tu, area );
322
2.68k
            m_pcIntraPred->initIntraMip( cu, area );
323
2.68k
            m_pcIntraPred->predIntraMip( compID, piPred, cu );
324
2.68k
          }
325
49.9k
          else if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) )
326
12.0k
          {
327
12.0k
            m_pcIntraPred->initIntraPatternChType( tu, area );
328
12.0k
            m_pcIntraPred->xGetLumaRecPixels( cu, area );
329
12.0k
            m_pcIntraPred->predIntraChromaLM( compID, piPred, cu, area, uiChFinalMode );
330
12.0k
          }
331
37.9k
          else
332
37.9k
          {
333
37.9k
            const bool predRegDiffFromTB = CU::isPredRegDiffFromTB( *tu.cu, compID );
334
37.9k
            const bool firstTBInPredReg  = CU::isFirstTBInPredReg( *tu.cu, compID, area );
335
37.9k
            CompArea areaPredReg( COMPONENT_Y, area );
336
337
37.9k
            const bool bUseFilteredPredictions = isLuma( compID ) && cu.ispMode() == NOT_INTRA_SUBPARTITIONS && IntraPrediction::useFilteredIntraRefSamples( compID, cu, tu );
338
339
37.9k
            if( tu.cu->ispMode() && isLuma( compID ) )
340
5.61k
            {
341
5.61k
              PelBuf piReco = cs.getRecoBuf( area );
342
5.61k
              if( predRegDiffFromTB )
343
922
              {
344
922
                if( firstTBInPredReg )
345
425
                {
346
425
                  CU::adjustPredArea( areaPredReg );
347
425
                  m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, areaPredReg, piReco );
348
425
                }
349
922
              }
350
4.69k
              else
351
4.69k
              {
352
4.69k
                m_pcIntraPred->initIntraPatternChTypeISP( *tu.cu, area, piReco );
353
4.69k
              }
354
5.61k
            }
355
32.3k
            else
356
32.3k
            {
357
32.3k
              m_pcIntraPred->initIntraPatternChType( tu, area, bUseFilteredPredictions );
358
32.3k
            }
359
360
37.9k
            if( predRegDiffFromTB )
361
922
            {
362
922
              if( firstTBInPredReg )
363
425
              {
364
425
                Position pos( areaPredReg.x - cu.lumaPos().x, areaPredReg.y - cu.lumaPos().y );
365
425
                piPred      = cs.getPredBuf( cu ).Y().subBuf( pos, areaPredReg.size() );
366
367
425
                m_pcIntraPred->predIntraAng( compID, piPred, cu, bUseFilteredPredictions );
368
369
425
                piPred.width = area.width;
370
425
              }
371
922
            }
372
37.0k
            else
373
37.0k
              m_pcIntraPred->predIntraAng( compID, piPred, cu, bUseFilteredPredictions );
374
37.9k
          }
375
52.6k
        }
376
377
        //===== inverse transform =====
378
52.6k
        PelBuf piReco = cs.getRecoBuf( area );
379
52.6k
        PelBuf piResi = cs.getRecoBuf( area );
380
381
52.6k
        const Slice &slice      = *cu.slice;
382
52.6k
        const bool   doChrScale = isChroma( compID )
383
31.9k
                                  && slice.getLmcsEnabledFlag()
384
0
                                  && slice.getPicHeader()->getLmcsChromaResidualScaleFlag()
385
0
                                  && tu.blocks[compID].area() > 4
386
0
                                  && ( TU::getCbf( tu, compID ) || tu.jointCbCr )
387
52.6k
                                  ;
388
389
52.6k
        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
52.6k
        if( TU::getCbf( tu, compID ) || ( isChroma( compID ) && tu.jointCbCr ) )
397
33.7k
        {
398
33.7k
          piReco.reconstruct( piPred, piResi, slice.clpRng( compID ) );
399
33.7k
        }
400
18.9k
        else if( cu.planeCbf( compID ) )
401
2.23k
        {
402
2.23k
          piReco.copyFrom( piPred );
403
2.23k
        }
404
52.6k
      }
405
36.6k
    }
406
32.5k
  }
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.00k
    {
417
9.00k
      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.00k
    }
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.0k
}
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
64.4k
{
538
64.4k
  CodingStructure &cs = *cu.cs;
539
540
64.4k
  for( TransformUnit &tu : TUTraverser( &cu.firstTU, cu.lastTU->next ) )
541
74.4k
  {
542
74.4k
    for( const auto &area : tu.blocks )
543
222k
    {
544
222k
      if( !area.valid() )
545
128k
      {
546
128k
        continue;
547
128k
      }
548
549
94.6k
      const ComponentID compID = area.compID();
550
551
      //===== inverse transform =====
552
94.6k
      PelBuf piResi = cs.getRecoBuf( area );
553
554
94.6k
      if( tu.jointCbCr && isChroma( compID ) )
555
14.1k
      {
556
14.1k
        if( compID == COMPONENT_Cb )
557
7.05k
        {
558
7.05k
          PelBuf resiCr = cs.getRecoBuf( tu.blocks[ COMPONENT_Cr ] );
559
7.05k
          if( tu.jointCbCr >> 1 )
560
5.87k
          {
561
5.87k
            QpParam qpCb( tu, compID );
562
5.87k
            m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cb, piResi, qpCb );
563
5.87k
          }
564
1.18k
          else
565
1.18k
          {
566
1.18k
            QpParam qpCr( tu, COMPONENT_Cr );
567
1.18k
            m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cr, resiCr, qpCr );
568
1.18k
          }
569
7.05k
          m_pcTrQuant->invTransformICT( tu, piResi, resiCr );
570
7.05k
        }
571
14.1k
      }
572
80.5k
      else if( TU::getCbf( tu, compID ) )
573
70.9k
      {
574
70.9k
        QpParam cQP( tu, compID );
575
70.9k
        m_pcTrQuant->invTransformNxN( tu, compID, piResi, cQP );
576
70.9k
      }
577
94.6k
    }
578
74.4k
  }
579
64.4k
}
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.1k
{
722
23.1k
  if( cu.mergeFlag() )
723
10.8k
  {
724
10.8k
    MergeCtx mrgCtx;
725
726
10.8k
    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
10.8k
    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
10.8k
    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
10.8k
    else
784
10.8k
    {
785
10.8k
      if( CU::isIBC( cu ) )
786
10.8k
        PU::getIBCMergeCandidates  ( cu, mrgCtx, hist, cu.mergeIdx() );
787
0
      else
788
0
        PU::getInterMergeCandidates( cu, mrgCtx, hist, cu.mergeIdx() );
789
790
10.8k
      mrgCtx.setMergeInfo         ( cu, cu.mergeIdx() );
791
792
10.8k
      PU::spanMotionInfo          ( cu );
793
10.8k
    }
794
10.8k
  }
795
12.2k
  else
796
12.2k
  {
797
12.2k
    if( cu.imv() && !cu.affineFlag() )
798
9.95k
    {
799
9.95k
      PU::applyImv      ( cu, hist );
800
9.95k
      PU::spanMotionInfo( cu );
801
9.95k
    }
802
2.26k
    else
803
2.26k
    {
804
2.26k
      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.26k
      else if( CU::isIBC( cu ) && cu.interDir() == 1 )
851
2.26k
      {
852
2.26k
        AMVPInfo amvpInfo;
853
2.26k
        PU::fillIBCMvpCand( cu, amvpInfo, hist );
854
2.26k
        Mv mvd = cu.mv[REF_PIC_LIST_0][0];
855
2.26k
        mvd <<= 4;
856
2.26k
        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.26k
        cu.mv[REF_PIC_LIST_0][0] = amvpInfo.mvCand[cu.mvpIdx[REF_PIC_LIST_0]] + mvd;
861
2.26k
        cu.mv[REF_PIC_LIST_0][0] . mvCliptoStorageBitDepth();
862
2.26k
      }
863
18.4E
      else
864
18.4E
      {
865
18.4E
        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
18.4E
      }
880
2.26k
      PU::spanMotionInfo( cu );
881
2.26k
    }
882
12.2k
  }
883
884
23.1k
  bool isIbcSmallBlk = CU::isIBC( cu ) && ( cu.lwidth() * cu.lheight() <= 16 );
885
23.1k
  if( !cu.affineFlag() && !cu.geoFlag() && !isIbcSmallBlk )
886
22.6k
  {
887
22.6k
    const unsigned log2ParallelMergeLevel = (cu.sps->getLog2ParallelMergeLevelMinus2() + 2);
888
22.6k
    const unsigned xBr = cu.Y().width  + cu.Y().x;
889
22.6k
    const unsigned yBr = cu.Y().height + cu.Y().y;
890
22.6k
    bool enableHmvp      = ((xBr >> log2ParallelMergeLevel) > (cu.Y().x >> log2ParallelMergeLevel)) && ((yBr >> log2ParallelMergeLevel) > (cu.Y().y >> log2ParallelMergeLevel));
891
22.6k
    bool isIbc           = CU::isIBC( cu );
892
22.6k
    bool enableInsertion = isIbc || enableHmvp;
893
894
22.6k
    if( enableInsertion )
895
22.6k
    {
896
22.6k
      HPMVInfo mi( cu.getMotionInfo(), cu.interDir() == 3 ? cu.BcwIdx() : BCW_DEFAULT, cu.imv() == IMV_HPEL );
897
22.6k
      if( isIbc ) mi.mhRefIdx[0] = MH_NOT_VALID + 1;
898
22.6k
      MotionHist::addMiToLut( isIbc ? hist.motionLutIbc : hist.motionLut, mi );
899
22.6k
    }
900
22.6k
  }
901
23.1k
}
902
903
}