Coverage Report

Created: 2026-10-17 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/vvenc/source/Lib/CommonLib/CodingStructure.cpp
Line
Count
Source
1
/* -----------------------------------------------------------------------------
2
The copyright in this software is being made available under the Clear BSD
3
License, included below. No patent rights, trademark rights and/or 
4
other Intellectual Property Rights other than the copyrights concerning 
5
the Software are granted under this license.
6
7
The Clear BSD License
8
9
Copyright (c) 2019-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVenC Authors.
10
All rights reserved.
11
12
Redistribution and use in source and binary forms, with or without modification,
13
are permitted (subject to the limitations in the disclaimer below) provided that
14
the following conditions are met:
15
16
     * Redistributions of source code must retain the above copyright notice,
17
     this list of conditions and the following disclaimer.
18
19
     * Redistributions in binary form must reproduce the above copyright
20
     notice, this list of conditions and the following disclaimer in the
21
     documentation and/or other materials provided with the distribution.
22
23
     * Neither the name of the copyright holder nor the names of its
24
     contributors may be used to endorse or promote products derived from this
25
     software without specific prior written permission.
26
27
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
28
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
29
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
31
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
32
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
35
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
36
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38
POSSIBILITY OF SUCH DAMAGE.
39
40
41
------------------------------------------------------------------------------------------- */
42
43
44
/** \file     CodingStructure.h
45
 *  \brief    A class managing the coding information for a specific image part
46
 */
47
48
#include "CodingStructure.h"
49
#include "Unit.h"
50
#include "Slice.h"
51
#include "Picture.h"
52
#include "UnitTools.h"
53
#include "UnitPartitioner.h"
54
55
//! \ingroup CommonLib
56
//! \{
57
58
namespace vvenc {
59
60
// ---------------------------------------------------------------------------
61
// coding structure method definitions
62
// ---------------------------------------------------------------------------
63
64
CodingStructure::CodingStructure( XUCache& unitCache, std::mutex* mutex )
65
139k
  : area            ()
66
139k
  , picture         ( nullptr )
67
139k
  , parent          ( nullptr )
68
139k
  , lumaCS          ( nullptr )
69
139k
  , picHeader       ( nullptr )
70
139k
  , m_isTuEnc       ( false )
71
139k
  , m_cuCache       ( unitCache.cuCache )
72
139k
  , m_tuCache       ( unitCache.tuCache )
73
139k
  , m_unitCacheMutex( mutex )
74
139k
  , bestParent      ( nullptr )
75
139k
  , resetIBCBuffer  ( false )
76
139k
{
77
559k
  for( uint32_t i = 0; i < MAX_NUM_COMP; i++ )
78
419k
  {
79
419k
    m_coeffs[ i ] = nullptr;
80
419k
    m_offsets[ i ] = 0;
81
419k
  }
82
83
419k
  for( uint32_t i = 0; i < MAX_NUM_CH; i++ )
84
279k
  {
85
279k
    m_cuPtr   [ i ] = nullptr;
86
279k
  }
87
88
419k
  for( int i = 0; i < NUM_EDGE_DIR; i++ )
89
279k
  {
90
279k
    m_lfParam [ i ] = nullptr;
91
279k
  }
92
93
139k
  m_motionBuf             = nullptr;
94
139k
  m_colocatedMotion       = nullptr;
95
139k
  m_colocatedMotionStride = 0;
96
97
139k
  m_numTUs = m_numCUs = 0;
98
139k
}
99
100
void CodingStructure::destroy()
101
135k
{
102
135k
  picture   = nullptr;
103
135k
  parent    = nullptr;
104
135k
  lumaCS     = nullptr;
105
106
135k
  m_pred.destroy();
107
135k
  m_resi.destroy();
108
135k
  m_reco.destroy();
109
135k
  m_org = nullptr;
110
111
135k
  destroyCoeffs();
112
135k
  destroyMotionBuf();
113
114
135k
  destroyTempBuffers();
115
116
135k
  if ( m_unitCacheMutex ) m_unitCacheMutex->lock();
117
118
135k
  m_tuCache.cache( tus );
119
135k
  m_cuCache.cache( cus );
120
121
135k
  if ( m_unitCacheMutex ) m_unitCacheMutex->unlock();
122
135k
}
123
124
void CodingStructure::releaseIntermediateData()
125
430k
{
126
430k
  clearTUs();
127
430k
  clearCUs();
128
430k
}
129
130
CodingUnit* CodingStructure::getLumaCU( const Position& pos )
131
0
{
132
0
  const ChannelType effChType = CH_L;
133
0
  const CompArea& _blk = area.blocks[effChType];
134
0
  CHECK( !_blk.contains( pos ), "must contain the pos" );
135
136
0
  return m_cuPtr[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
137
0
}
138
139
CodingUnit* CodingStructure::getCU( const Position& pos, const ChannelType effChType, const TreeType _treeType )
140
4.83M
{
141
4.83M
  CHECKD(_treeType == TREE_C && effChType == CH_L && parent == nullptr && _treeType == TREE_C && effChType == CH_L, "parent shall be valid; consider using function getLumaCU()");
142
143
4.83M
  CodingStructure* cs = _treeType == TREE_C && effChType == CH_L ? parent : this;
144
5.88M
  while (cs && !cs->area.blocks[effChType].contains(pos)) cs = cs->parent;
145
146
4.83M
  if (!cs)
147
225
  {
148
225
    return nullptr;
149
225
  }
150
4.83M
  else
151
4.83M
  {
152
4.83M
    const Area& _blk = cs->area.blocks[effChType];
153
4.83M
    return cs->m_cuPtr[effChType][rsAddr(pos, _blk.pos(), _blk.width, unitScale[effChType])];
154
4.83M
  }
155
4.83M
}
156
157
const CodingUnit* CodingStructure::getCU( const Position& pos, const ChannelType effChType, const TreeType _treeType ) const
158
2.73M
{
159
2.73M
  CHECKD(_treeType == TREE_C && effChType == CH_L && parent == nullptr && _treeType == TREE_C && effChType == CH_L, "parent shall be valid; consider using function getLumaCU()");
160
161
2.73M
  const CodingStructure* cs = _treeType == TREE_C && effChType == CH_L ? parent : this;
162
6.46M
  while (cs && !cs->area.blocks[effChType].contains(pos)) cs = cs->parent;
163
164
2.73M
  if (!cs)
165
13.2k
  {
166
13.2k
    return nullptr;
167
13.2k
  }
168
2.72M
  else
169
2.72M
  {
170
2.72M
    const Area& _blk = cs->area.blocks[effChType];
171
2.72M
    return cs->m_cuPtr[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
172
2.72M
  }
173
2.73M
}
174
175
TransformUnit* CodingStructure::getTU( const Position& pos, const ChannelType effChType, const int subTuIdx )
176
1.52M
{
177
1.52M
  const CompArea& _blk = area.blocks[effChType];
178
179
1.52M
  if( !_blk.contains( pos ) )
180
0
  {
181
0
    if( parent ) return parent->getTU( pos, effChType );
182
0
    else         return nullptr;
183
0
  }
184
1.52M
  else
185
1.52M
  {
186
1.52M
    CodingUnit* cu = m_cuPtr[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
187
1.52M
    if( !cu ) return nullptr;
188
189
1.52M
    TransformUnit* ptu = cu->firstTU;
190
191
1.55M
    while( ptu && !ptu->blocks[effChType].contains( pos ) )
192
25.7k
    {
193
25.7k
      ptu = ptu->next;
194
25.7k
    }
195
196
1.52M
    return ptu;
197
1.52M
  }
198
1.52M
}
199
200
const TransformUnit * CodingStructure::getTU( const Position& pos, const ChannelType effChType, const int subTuIdx ) const
201
152k
{
202
152k
  const CompArea& _blk = area.blocks[effChType];
203
204
152k
  if( !_blk.contains( pos ) )
205
0
  {
206
0
    if( parent ) return parent->getTU( pos, effChType );
207
0
    else         return nullptr;
208
0
  }
209
152k
  else
210
152k
  {
211
152k
    const CodingUnit* cu = m_cuPtr[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
212
152k
    if( !cu ) return nullptr;
213
214
152k
    const TransformUnit* ptu = cu->firstTU;
215
216
152k
    while( ptu && !ptu->blocks[effChType].contains( pos ) )
217
246
    {
218
246
      ptu = ptu->next;
219
246
    }
220
221
152k
    return ptu;
222
152k
  }
223
152k
}
224
225
CodingUnit& CodingStructure::addCU( const UnitArea& unit, const ChannelType chType, CodingUnit* cuInit )
226
415k
{
227
415k
  CodingUnit* cu;
228
229
415k
  if( cuInit )
230
143k
  {
231
143k
    cu = cuInit;
232
143k
  }
233
271k
  else
234
271k
  {
235
271k
    if( m_unitCacheMutex ) m_unitCacheMutex->lock();
236
237
271k
    cu = m_cuCache.get();
238
239
271k
    if( m_unitCacheMutex ) m_unitCacheMutex->unlock();
240
241
271k
    cu->UnitArea::operator=( unit );
242
271k
    cu->initData();
243
271k
    cu->slice   = nullptr;
244
271k
  }
245
  
246
415k
  cu->next      = nullptr;
247
415k
  cu->firstTU   = nullptr;
248
415k
  cu->lastTU    = nullptr;
249
415k
  cu->chType    = chType;
250
415k
  cu->cs        = this;
251
252
415k
  CodingUnit *prevCU = m_numCUs > 0 ? cus.back() : nullptr;
253
254
415k
  if( prevCU )
255
116k
  {
256
116k
    const int prevCuCtuRsAddr = getCtuAddr( recalcPosition( area.chromaFormat, prevCU->chType, CH_L, prevCU->blocks[prevCU->chType] ), *pcv );
257
116k
    const int currCuCtuRsAddr = getCtuAddr( recalcPosition( area.chromaFormat,         chType, CH_L,     cu->blocks[        chType] ), *pcv );
258
259
116k
    if( prevCuCtuRsAddr == currCuCtuRsAddr )
260
113k
    {
261
113k
      prevCU->next = cu;
262
113k
    }
263
116k
  }
264
265
415k
  cus.push_back( cu );
266
267
415k
  Mv* prevCuMvd = cuInit ? cuInit->mvdL0SubPu : nullptr;
268
  
269
415k
  cu->idx        = ++m_numCUs;
270
415k
  cu->mvdL0SubPu = nullptr;
271
272
415k
  if( isLuma( chType ) && unit.lheight() >= 8 && unit.lwidth() >= 8 && unit.Y().area() >= 128 )
273
259k
  {
274
259k
    CHECKD( m_dmvrMvCacheOffset >= m_dmvrMvCache.size(), "dmvr cache offset out of bounds" );
275
276
259k
    int mvdArrSize       = std::max<int>( 1, unit.lwidth() >> DMVR_SUBCU_SIZE_LOG2 ) * std::max<int>( 1, unit.lheight() >> DMVR_SUBCU_SIZE_LOG2 );
277
259k
    cu->mvdL0SubPu       = &m_dmvrMvCache[m_dmvrMvCacheOffset];
278
259k
    m_dmvrMvCacheOffset += mvdArrSize;
279
280
259k
    if( prevCuMvd )
281
61.2k
      memcpy( cu->mvdL0SubPu, prevCuMvd, sizeof( Mv ) * mvdArrSize );
282
259k
  }
283
284
415k
  uint32_t numCh = getNumberValidChannels( area.chromaFormat );
285
286
1.24M
  for( uint32_t i = 0; i < numCh; i++ )
287
831k
  {
288
831k
    if( !cu->blocks[i].valid() )
289
415k
    {
290
415k
      continue;
291
415k
    }
292
293
415k
    const CompArea& _selfBlk = area.blocks[i];
294
415k
    const CompArea     &_blk = cu-> blocks[i];
295
296
415k
    const UnitScale& scale = unitScale[_blk.compID];
297
415k
    const Area scaledSelf  = scale.scale( _selfBlk );
298
415k
    const Area scaledBlk   = scale.scale(     _blk );
299
415k
    CodingUnit **cuPtr     = m_cuPtr[i] + rsAddr( scaledBlk.pos(), scaledSelf.pos(), scaledSelf.width );
300
301
415k
    CHECKD( *cuPtr, "Overwriting a pre-existing value, should be '0'!" );
302
303
415k
    g_pelBufOP.fillPtrMap( ( void** ) cuPtr, scaledSelf.width, scaledBlk.width, scaledBlk.height, ( void* ) cu );
304
415k
  }
305
306
415k
  return *cu;
307
415k
}
308
309
TransformUnit& CodingStructure::addTU( const UnitArea& unit, const ChannelType chType, CodingUnit* cu, TransformUnit* tuInit )
310
490k
{
311
490k
  TransformUnit* tu;
312
313
490k
  if( tuInit )
314
167k
  {
315
167k
    tu = tuInit;
316
167k
  }
317
322k
  else
318
322k
  {
319
322k
    if( m_unitCacheMutex ) m_unitCacheMutex->lock();
320
321
322k
    tu = m_tuCache.get();
322
323
322k
    if( m_unitCacheMutex ) m_unitCacheMutex->unlock();
324
325
322k
    tu->UnitArea::operator=( unit );
326
322k
    tu->initData();
327
322k
  }
328
329
490k
  tu->next   = nullptr;
330
490k
  tu->prev   = nullptr;
331
490k
  tu->cs     = this;
332
490k
  tu->cu     = cu;
333
490k
  tu->chType = chType;
334
335
490k
  TransformUnit *prevTU = m_numTUs > 0 ? tus.back() : nullptr;
336
337
490k
  if( prevTU && prevTU->cu == tu->cu )
338
18.1k
  {
339
18.1k
    prevTU->next = tu;
340
18.1k
    tu->prev     = prevTU;
341
18.1k
  }
342
343
490k
  tus.push_back( tu );
344
345
490k
  if( tu->cu )
346
433k
  {
347
433k
    if( tu->cu->firstTU == nullptr )
348
410k
    {
349
410k
      tu->cu->firstTU = tu;
350
410k
    }
351
433k
    tu->cu->lastTU = tu;
352
433k
  }
353
354
490k
  uint32_t idx = ++m_numTUs;
355
490k
  tu->idx = idx;
356
357
490k
  TCoeffSig *coeffs[3] = { nullptr, nullptr, nullptr };
358
359
490k
  uint32_t numCh = getNumberValidComponents( area.chromaFormat );
360
361
1.96M
  for( uint32_t i = 0; i < numCh; i++ )
362
1.47M
  {
363
1.47M
    if( !tu->blocks[i].valid() )
364
771k
    {
365
771k
      continue;
366
771k
    }
367
368
700k
    coeffs[i] = m_coeffs[i] + m_offsets[i];
369
370
700k
    unsigned areaSize = tu->blocks[i].area();
371
700k
    m_offsets[i] += areaSize;
372
373
700k
    const bool cpyRsi = tuInit &&
374
248k
                      ( tuInit->cbf[i] ||
375
202k
                 ( i && tuInit->jointCbCr && numCh > 1 && ( TU::getCbf( *tuInit, COMP_Cb ) || TU::getCbf( *tuInit, COMP_Cr ) ) )
376
248k
                      );
377
378
700k
    if( cpyRsi )
379
46.6k
      memcpy( coeffs[i], tu->m_coeffs[i], areaSize * sizeof( TCoeffSig ) );
380
700k
  }
381
382
490k
  tu->init( coeffs );
383
384
490k
  return *tu;
385
490k
}
386
387
void CodingStructure::addEmptyTUs( Partitioner &partitioner, CodingUnit* cu )
388
21.0k
{
389
21.0k
  const UnitArea& area    = partitioner.currArea();
390
21.0k
  bool            split   = partitioner.canSplit(TU_MAX_TR_SPLIT, *this);
391
21.0k
  const unsigned  trDepth = partitioner.currTrDepth;
392
393
21.0k
  if( split )
394
0
  {
395
0
    partitioner.splitCurrArea( TU_MAX_TR_SPLIT, *this );
396
0
    do
397
0
    {
398
0
      addEmptyTUs( partitioner, cu );
399
0
    } while( partitioner.nextPart( *this ) );
400
401
0
    partitioner.exitCurrSplit();
402
0
  }
403
21.0k
  else
404
21.0k
  {
405
21.0k
    TransformUnit& tu = addTU(CS::getArea(*this, area, partitioner.chType, TreeType(partitioner.treeType)), partitioner.chType, cu);
406
21.0k
    tu.depth = trDepth;
407
21.0k
  }
408
21.0k
}
409
410
CUTraverser CodingStructure::traverseCUs( const UnitArea& unit, const ChannelType effChType )
411
7.00k
{
412
  //  CHECK( _treeType != treeType, "not good");
413
7.00k
  CodingUnit* firstCU = getCU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType, TREE_D );
414
7.00k
  CodingUnit* lastCU = firstCU;
415
7.00k
  if( !CS::isDualITree( *this ) ) //for a more generalized separate tree
416
0
  {
417
0
    bool bContinue = true;
418
0
    CodingUnit* currCU = firstCU;
419
0
    while( bContinue )
420
0
    {
421
0
      if( currCU == nullptr )
422
0
      {
423
0
        bContinue = false;
424
0
        lastCU = currCU;
425
0
      }
426
0
      else if( currCU->chType != effChType )
427
0
      {
428
0
        lastCU = currCU;
429
0
        currCU = currCU->next;
430
0
      }
431
0
      else
432
0
      {
433
0
        if( unit.contains( *currCU ) )
434
0
        {
435
0
          lastCU = currCU;
436
0
          currCU = currCU->next;
437
0
        }
438
0
        else
439
0
        {
440
0
          bContinue = false;
441
0
          lastCU = currCU;
442
0
        }
443
0
      }
444
0
    }
445
0
  }
446
7.00k
  else
447
7.00k
  {
448
36.9k
  do { } while( lastCU && (0 != ( lastCU = lastCU->next )) && unit.contains( *lastCU ) );
449
7.00k
  }
450
451
7.00k
  return CUTraverser( firstCU, lastCU );
452
7.00k
}
453
454
TUTraverser CodingStructure::traverseTUs( const UnitArea& unit, const ChannelType effChType )
455
0
{
456
0
  TransformUnit* firstTU = getTU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType );
457
0
  TransformUnit* lastTU  = firstTU;
458
459
0
  do { } while( lastTU && (0 != ( lastTU = lastTU->next )) && unit.contains( *lastTU ) );
460
461
0
  return TUTraverser( firstTU, lastTU );
462
0
}
463
464
cCUTraverser CodingStructure::traverseCUs( const UnitArea& unit, const ChannelType effChType ) const
465
0
{
466
0
  const CodingUnit* firstCU = getCU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType, TREE_D );
467
0
  const CodingUnit* lastCU  = firstCU;
468
469
0
  do { } while( lastCU && (0 != ( lastCU = lastCU->next )) && unit.contains( *lastCU ) );
470
471
0
  return cCUTraverser( firstCU, lastCU );
472
0
}
473
474
cTUTraverser CodingStructure::traverseTUs( const UnitArea& unit, const ChannelType effChType ) const
475
0
{
476
0
  const TransformUnit* firstTU = getTU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType );
477
0
  const TransformUnit* lastTU  = firstTU;
478
479
0
  do { } while( lastTU && (0 != ( lastTU = lastTU->next )) && unit.contains( *lastTU ) );
480
481
0
  return cTUTraverser( firstTU, lastTU );
482
0
}
483
484
485
486
LFPBuf CodingStructure::getLoopFilterParamBuf(const DeblockEdgeDir& edgeDir)
487
6.99k
{
488
6.99k
  return LFPBuf(m_lfParam[edgeDir], m_mapSize[0]);
489
6.99k
}
490
491
const CLFPBuf CodingStructure::getLoopFilterParamBuf(const DeblockEdgeDir& edgeDir) const
492
0
{
493
0
  return CLFPBuf(m_lfParam[edgeDir], m_mapSize[0]);
494
0
}
495
496
497
// coding utilities
498
499
void CodingStructure::allocateVectorsAtPicLevel()
500
1.15k
{
501
1.15k
  const int  twice = ( !pcv->ISingleTree && slice->isIRAP() && pcv->chrFormat != CHROMA_400 ) ? 2 : 1;
502
1.15k
  size_t allocSize = twice * unitScale[0].scale( area.blocks[0].size() ).area();
503
504
1.15k
  cus.reserve( allocSize );
505
1.15k
  tus.reserve( allocSize );
506
1.15k
}
507
508
void CodingStructure::releaseVectorsAtPicLevel()
509
1.15k
{
510
1.15k
  CHECKD( !cus.empty() || !tus.empty(), "Clearing non-empty CU/TU vectors, risking a memory leak!" );
511
512
  // clear() keeps the capacity, which is one pointer per 4x4 block of the picture, so swap the
513
  // lists with empty ones to return it.
514
1.15k
  std::vector<CodingUnit*>().swap( cus );
515
1.15k
  std::vector<TransformUnit*>().swap( tus );
516
1.15k
}
517
518
519
520
void CodingStructure::createForSearch( const ChromaFormat _chromaFormat, const Area& _area )
521
134k
{
522
134k
  createInternals( UnitArea( _chromaFormat, _area ), false );
523
524
134k
  m_reco.create( area );
525
134k
  m_pred.create( area );
526
134k
  m_resi.create( area );
527
134k
}
528
529
void CodingStructure::createPicLevel( const UnitArea& _unit, const PreCalcValues* _pcv )
530
1.15k
{
531
1.15k
  pcv = _pcv;
532
533
1.15k
  createInternals( _unit, true );
534
1.15k
}
535
536
static constexpr int UnitScaleArray[NUM_CHROMA_FORMAT][MAX_NUM_COMP][2] =
537
{
538
  { {2,2}, {0,0}, {0,0} },  // 4:0:0
539
  { {2,2}, {1,1}, {1,1} },  // 4:2:0
540
  { {2,2}, {1,2}, {1,2} },  // 4:2:2
541
  { {2,2}, {2,2}, {2,2} }   // 4:4:4
542
};
543
544
void CodingStructure::createInternals( const UnitArea& _unit, const bool isTopLayer )
545
135k
{
546
135k
  area     = _unit;
547
135k
  _maxArea = _unit;
548
549
135k
  unitScale[COMP_Y ] = UnitScale( UnitScaleArray[area.chromaFormat][COMP_Y ][0], UnitScaleArray[area.chromaFormat][COMP_Y ][1] );
550
135k
  unitScale[COMP_Cb] = UnitScale( UnitScaleArray[area.chromaFormat][COMP_Cb][0], UnitScaleArray[area.chromaFormat][COMP_Cb][1] );
551
135k
  unitScale[COMP_Cr] = UnitScale( UnitScaleArray[area.chromaFormat][COMP_Cr][0], UnitScaleArray[area.chromaFormat][COMP_Cr][1] );
552
553
135k
  picture = nullptr;
554
135k
  parent  = nullptr;
555
135k
  lumaCS  = nullptr;
556
557
  // The picture-level structure gets its motion field when the picture's encoding starts (see
558
  // Picture::createEncodingBuffers), so pictures that wait in the GOP queue do not hold one.
559
135k
  if( isTopLayer )
560
1.15k
  {
561
1.15k
    motionLutBuf.resize( pps->getNumTileLineIds() );
562
1.15k
  }
563
134k
  else
564
134k
  {
565
134k
    createMotionBuf();
566
134k
    createCoeffs();
567
134k
    createTempBuffers( false );
568
134k
    initStructData( MAX_INT, false, nullptr );
569
134k
  }
570
135k
}
571
572
void CodingStructure::createTempBuffers( const bool isTopLayer )
573
135k
{
574
135k
  unsigned numCh = getNumberValidChannels( area.chromaFormat );
575
576
405k
  for( unsigned i = 0; i < numCh; i++ )
577
270k
  {
578
270k
    Size allocArea  = area.blocks[i].size();
579
270k
    m_mapSize[i]    = unitScale[i].scale(allocArea);
580
581
270k
    unsigned _area  = unitScale[i].scale( area.blocks[i].size() ).area();
582
583
270k
    m_cuPtr[i]      = _area > 0 ? new CodingUnit*    [_area] : nullptr;
584
270k
  }
585
586
135k
  clearCUs( true );
587
588
405k
  for( unsigned i = 0; i < NUM_EDGE_DIR; i++ )
589
270k
  {
590
270k
    m_lfParam[i] = ( isTopLayer && m_mapSize[0].area() > 0 ) ? ( LoopFilterParam* ) xMalloc( LoopFilterParam, m_mapSize[0].area() ) : nullptr;
591
270k
  }
592
593
135k
  unsigned _maxNumDmvrMvs = ( area.lwidth() >> 3 ) * ( area.lheight() >> 3 );
594
135k
  m_dmvrMvCache.resize( _maxNumDmvrMvs );
595
135k
}
596
597
void CodingStructure::destroyTempBuffers()
598
136k
{
599
409k
  for( uint32_t i = 0; i < MAX_NUM_CH; i++ )
600
272k
  {
601
272k
    delete[] m_cuPtr[i];
602
272k
    m_cuPtr[i] = nullptr;
603
272k
  }
604
605
409k
  for( int i = 0; i < NUM_EDGE_DIR; i++ )
606
272k
  {
607
272k
    xFree( m_lfParam[i] );
608
272k
    m_lfParam[i] = nullptr;
609
272k
  }
610
611
  // swap the contents of the vector so that memory released
612
136k
  std::vector<Mv>().swap( m_dmvrMvCache );
613
136k
  std::vector<CodingUnit*>().swap( cus );
614
136k
  std::vector<TransformUnit*>().swap( tus );
615
136k
}
616
617
void CodingStructure::addMiToLut( static_vector<HPMVInfo, MAX_NUM_HMVP_CANDS>& lut, const HPMVInfo& mi )
618
0
{
619
0
  size_t currCnt = lut.size();
620
621
0
  bool pruned      = false;
622
0
  int  sameCandIdx = 0;
623
624
0
  for( int idx = 0; idx < currCnt; idx++ )
625
0
  {
626
0
    if( lut[idx] == mi )
627
0
    {
628
0
      sameCandIdx = idx;
629
0
      pruned = true;
630
0
      break;
631
0
    }
632
0
  }
633
634
0
  if( pruned || currCnt == lut.capacity() )
635
0
  {
636
0
    lut.erase( lut.begin() + sameCandIdx );
637
0
  }
638
639
0
  lut.push_back(mi);
640
0
}
641
642
void CodingStructure::rebindPicBufs()
643
2.31k
{
644
2.31k
  CHECK( parent, "rebindPicBufs can only be used for the top level CodingStructure" );
645
646
2.31k
  if( !picture->m_picBufs[ PIC_RECONSTRUCTION ].bufs.empty() ) m_reco.createFromBuf( picture->m_picBufs[ PIC_RECONSTRUCTION ] );
647
1.15k
  else                                                         m_reco.destroy();
648
2.31k
  if( !picture->m_picBufs[ PIC_PREDICTION     ].bufs.empty() ) m_pred.createFromBuf( picture->m_picBufs[ PIC_PREDICTION ] );
649
2.31k
  else                                                         m_pred.destroy();
650
2.31k
  if( !picture->m_picBufs[ PIC_RESIDUAL       ].bufs.empty() ) m_resi.createFromBuf( picture->m_picBufs[ PIC_RESIDUAL ] );
651
2.31k
  else                                                         m_resi.destroy();
652
2.31k
}
653
654
void CodingStructure::createCoeffs()
655
135k
{
656
135k
  const unsigned numComp = getNumberValidComponents( area.chromaFormat );
657
541k
  for( unsigned i = 0; i < numComp; i++ )
658
405k
  {
659
405k
    unsigned _area = area.blocks[i].area();
660
405k
    m_coeffs[i] = _area > 0 ? ( TCoeffSig* ) xMalloc( TCoeffSig, _area ) : nullptr;
661
405k
  }
662
663
541k
  for( unsigned i = 0; i < numComp; i++ )
664
405k
  {
665
405k
    m_offsets[i] = 0;
666
405k
  }
667
135k
}
668
669
void CodingStructure::createMotionBuf()
670
135k
{
671
135k
  if( !m_motionBuf )
672
135k
  {
673
135k
    m_motionBuf = new MotionInfo[g_miScaling.scale( area.lumaSize() ).area()];
674
135k
  }
675
135k
}
676
677
void CodingStructure::destroyMotionBuf()
678
136k
{
679
136k
  destroyFullMotionBuf();
680
136k
  delete[] m_colocatedMotion;
681
136k
  m_colocatedMotion = nullptr;
682
136k
}
683
684
// Temporal motion vector prediction reads the motion of other pictures on this grid (see
685
// CU::getColocatedMVP), so the colocated field holds one motion per grid cell.
686
static constexpr int COL_MOTION_GRID_LOG2 = 3;
687
static constexpr int COL_MOTION_GRID      = 1 << COL_MOTION_GRID_LOG2;
688
static_assert( COL_MOTION_GRID == 4 * std::max<int>( 1, 4 * AMVP_DECIMATION_FACTOR / 4 ), "The grid must match CU::getColocatedMVP" );
689
690
void CodingStructure::createColocatedMotionBuf()
691
1.15k
{
692
1.15k
  CHECK( parent, "Only the picture-level coding structure has a colocated motion field" );
693
694
1.15k
  m_colocatedMotionStride = ( area.lwidth() + COL_MOTION_GRID - 1 ) >> COL_MOTION_GRID_LOG2;
695
1.15k
  if( !m_colocatedMotion )
696
1.15k
  {
697
1.15k
    const int heightOnGrid = ( area.lheight() + COL_MOTION_GRID - 1 ) >> COL_MOTION_GRID_LOG2;
698
1.15k
    m_colocatedMotion = new MotionInfo[m_colocatedMotionStride * heightOnGrid];
699
1.15k
  }
700
1.15k
}
701
702
MotionInfo& CodingStructure::colocatedMotionInfo( const Position& pos )
703
415k
{
704
415k
  CHECKD( ( pos.x | pos.y ) & ( COL_MOTION_GRID - 1 ), "Colocated motion lies on the grid only" );
705
415k
  return m_colocatedMotion[( pos.y >> COL_MOTION_GRID_LOG2 ) * m_colocatedMotionStride + ( pos.x >> COL_MOTION_GRID_LOG2 )];
706
415k
}
707
708
const MotionInfo& CodingStructure::getColocatedMotionInfo( const Position& pos ) const
709
0
{
710
0
  CHECKD( parent, "Colocated motion is read through the picture-level coding structure only" );
711
0
  CHECKD( ( pos.x | pos.y ) & ( COL_MOTION_GRID - 1 ), "Colocated motion is read on the grid only" );
712
0
  CHECKD( !m_colocatedMotion, "Colocated motion is read only when temporal motion vector prediction is enabled" );
713
0
  return m_colocatedMotion[( pos.y >> COL_MOTION_GRID_LOG2 ) * m_colocatedMotionStride + ( pos.x >> COL_MOTION_GRID_LOG2 )];
714
0
}
715
716
void CodingStructure::destroyCoeffs()
717
136k
{
718
545k
  for( uint32_t i = 0; i < MAX_NUM_COMP; i++ )
719
409k
  {
720
409k
    if( m_coeffs[i] ) { xFree( m_coeffs[i] ); m_coeffs[i] = nullptr; }
721
409k
  }
722
136k
}
723
724
void CodingStructure::initSubStructure( CodingStructure& subStruct, const ChannelType _chType, const UnitArea& subArea, const bool isTuEnc, PelStorage* pOrgBuffer )
725
355k
{
726
355k
  CHECK( this == &subStruct, "Trying to init self as sub-structure" );
727
728
355k
  subStruct.parent = this;
729
730
355k
  if( pOrgBuffer ) pOrgBuffer->compactResize( subArea );
731
732
355k
  subStruct.m_org    = (pOrgBuffer) ? pOrgBuffer : m_org;
733
355k
  subStruct.compactResize( subArea );
734
735
355k
  subStruct.costDbOffset = 0;
736
737
355k
  if( parent )
738
341k
  {
739
    // allow this to be false at the top level (need for edge CTU's)
740
341k
    CHECKD( !area.contains( subArea ), "Trying to init sub-structure not contained in the parent" );
741
341k
  }
742
743
355k
  subStruct.parent    = this;
744
355k
  subStruct.picture   = picture;
745
355k
  subStruct.lumaCS    = picture->cs;
746
747
355k
  subStruct.sps       = sps;
748
355k
  subStruct.vps       = vps;
749
355k
  subStruct.pps       = pps;
750
355k
  subStruct.picHeader = picHeader;
751
752
355k
  memcpy(subStruct.alfAps, alfAps, sizeof(alfAps));
753
754
355k
  subStruct.slice     = slice;
755
355k
  subStruct.baseQP    = baseQP;
756
355k
  subStruct.prevQP[_chType]
757
355k
                      = prevQP[_chType];
758
355k
  subStruct.pcv       = pcv;
759
760
355k
  subStruct.m_isTuEnc = isTuEnc;
761
762
355k
  if( nullptr == parent )
763
14.0k
  {
764
14.0k
    const int ctuPosX = subArea.lx() >> pcv->maxCUSizeLog2;
765
14.0k
    const int ctuPosY = subArea.ly() >> pcv->maxCUSizeLog2;
766
14.0k
    subStruct.motionLut = motionLutBuf[pps->getTileLineId( ctuPosX, ctuPosY )];
767
14.0k
  }
768
341k
  else
769
341k
  {
770
341k
    subStruct.motionLut = motionLut;
771
341k
  }
772
773
355k
  subStruct.initStructData( currQP[_chType] );
774
775
355k
  if( isTuEnc )
776
109k
  {
777
109k
    CHECKD( area != subStruct.area, "Trying to init sub-structure for TU-encoding of incompatible size" );
778
779
109k
    for( const auto &pcu : cus )
780
109k
    {
781
109k
      CodingUnit &cu = subStruct.addCU( *pcu, _chType );
782
783
109k
      cu = *pcu;
784
109k
    }
785
109k
  }
786
355k
}
787
788
void CodingStructure::useSubStructure( CodingStructure& subStruct, const ChannelType chType, const TreeType _treeType, const UnitArea& subArea, const bool cpyRecoToPic )
789
146k
{
790
146k
  UnitArea clippedArea = clipArea( subArea, *picture );
791
792
146k
  CPelUnitBuf subRecoBuf = subStruct.getRecoBuf( clippedArea );
793
794
146k
  if( parent )
795
139k
  {
796
    // copy data to picture
797
139k
    getRecoBuf( clippedArea ).copyFrom( subRecoBuf );
798
139k
  }
799
800
146k
  if( cpyRecoToPic )
801
116k
  {
802
116k
    picture->getRecoBuf( clippedArea ).copyFrom( subRecoBuf );
803
116k
  }
804
805
146k
  if( !subStruct.m_isTuEnc && ( ( !slice->isIntra() || slice->sps->IBC ) && chType != CH_C ) )
806
48.8k
  {
807
    // copy motion buffer
808
48.8k
    MotionBuf ownMB  = getMotionBuf          ( clippedArea );
809
48.8k
    CMotionBuf subMB = subStruct.getMotionBuf( clippedArea );
810
811
48.8k
    ownMB.copyFrom( subMB );
812
813
48.8k
    if( nullptr == parent )
814
3.50k
    {
815
3.50k
      const int ctuPosX = subStruct.area.lx() >> pcv->maxCUSizeLog2;
816
3.50k
      const int ctuPosY = subStruct.area.ly() >> pcv->maxCUSizeLog2;
817
3.50k
      motionLutBuf[pps->getTileLineId( ctuPosX, ctuPosY )] = subStruct.motionLut;
818
3.50k
    }
819
45.3k
    else
820
45.3k
    {
821
45.3k
      motionLut = subStruct.motionLut;
822
45.3k
    }
823
48.8k
  }
824
825
146k
  fracBits += subStruct.fracBits;
826
146k
  dist     += subStruct.dist;
827
146k
  cost     += subStruct.cost;
828
146k
  costDbOffset += subStruct.costDbOffset;
829
830
146k
  if( parent )
831
139k
  {
832
    // allow this to be false at the top level
833
139k
    CHECKD( !area.contains( subArea ), "Trying to use a sub-structure not contained in self" );
834
139k
  }
835
836
  // copy the CUs over
837
146k
  if( subStruct.m_isTuEnc )
838
23.7k
  {
839
    // don't copy if the substruct was created for encoding of the TUs
840
23.7k
  }
841
123k
  else
842
123k
  {
843
123k
    if( &m_cuCache == &subStruct.m_cuCache )
844
116k
    {
845
      // copy the CUs over with taking ownership
846
116k
      for( const auto& pcu : subStruct.cus )
847
143k
      {
848
        // add an analogue CU into own CU store
849
143k
        const UnitArea& cuPatch = *pcu;
850
143k
        addCU( cuPatch, pcu->chType, pcu );
851
143k
      }
852
853
116k
      subStruct.cus.resize( 0 );
854
116k
    }
855
7.00k
    else
856
7.00k
    {
857
      // copy the CUs over
858
7.00k
      for( const auto& pcu : subStruct.cus )
859
37.1k
      {
860
        // add an analogue CU into own CU store
861
37.1k
        const UnitArea& cuPatch = *pcu;
862
863
37.1k
        CodingUnit& cu = addCU( cuPatch, pcu->chType );
864
865
        // copy the CU info from subPatch
866
37.1k
        cu = *pcu;
867
37.1k
      }
868
7.00k
    }
869
123k
  }
870
871
146k
  if( &m_tuCache == &subStruct.m_tuCache )
872
139k
  {
873
    // copy the TUs over with taking ownership
874
139k
    for( const auto& ptu : subStruct.tus )
875
167k
    {
876
      // add an analogue TU into own TU store
877
167k
      const UnitArea& tuPatch = *ptu;
878
167k
      addTU( tuPatch, ptu->chType, getCU( tuPatch.blocks[ptu->chType].pos(), ptu->chType, _treeType ), ptu );
879
167k
    }
880
881
139k
    subStruct.tus.resize( 0 );
882
139k
  }
883
7.00k
  else
884
7.00k
  {
885
    // copy the TUs over
886
7.00k
    for( const auto& ptu : subStruct.tus )
887
37.1k
    {
888
      // add an analogue TU into own TU store
889
37.1k
      const UnitArea& tuPatch = *ptu;
890
891
37.1k
      TransformUnit& tu = addTU( tuPatch, ptu->chType, getCU( tuPatch.blocks[ptu->chType], ptu->chType, _treeType ) );
892
893
      // copy the TU info from subPatch
894
37.1k
      tu = *ptu;
895
37.1k
    }
896
7.00k
  }
897
146k
}
898
899
void CodingStructure::copyStructure( const CodingStructure& other, const ChannelType chType, const TreeType _treeType, const bool copyTUs, const bool copyRecoBuf )
900
0
{
901
0
  fracBits      = other.fracBits;
902
0
  dist          = other.dist;
903
0
  cost          = other.cost;
904
0
  costDbOffset  = other.costDbOffset;
905
0
  CHECKD( area != other.area, "Incompatible sizes" );
906
907
0
  const UnitArea dualITreeArea = CS::getArea( *this, area, chType, _treeType );
908
909
  // copy the CUs over
910
0
  for (const auto &pcu : other.cus)
911
0
  {
912
0
    if( !dualITreeArea.contains( *pcu ) )
913
0
    {
914
0
      continue;
915
0
    }
916
    // add an analogue CU into own CU store
917
0
    const UnitArea& cuPatch = *pcu;
918
919
0
    CodingUnit &cu = addCU(cuPatch, pcu->chType);
920
921
    // copy the CU info from subPatch
922
0
    cu = *pcu;
923
0
  }
924
925
0
  if (!other.slice->isIntra() || other.slice->sps->IBC)
926
0
  {
927
    // copy motion buffer
928
0
    MotionBuf  ownMB = getMotionBuf();
929
0
    CMotionBuf subMB = other.getMotionBuf();
930
931
0
    ownMB.copyFrom( subMB );
932
933
0
    motionLut = other.motionLut;
934
0
  }
935
936
0
  if( copyTUs )
937
0
  {
938
    // copy the TUs over
939
0
    for( const auto &ptu : other.tus )
940
0
    {
941
0
      if( !dualITreeArea.contains( *ptu ) )
942
0
      {
943
0
        continue;
944
0
      }
945
      // add an analogue TU into own TU store
946
0
      const UnitArea& tuPatch = *ptu;
947
948
0
      TransformUnit& tu = addTU( tuPatch, ptu->chType, getCU( tuPatch.blocks[ptu->chType], ptu->chType, _treeType) );
949
950
      // copy the TU info from subPatch
951
0
      tu = *ptu;
952
0
    }
953
0
  }
954
955
0
  if( copyRecoBuf )
956
0
  {
957
0
    CPelUnitBuf recoBuf = other.getRecoBuf( area );
958
959
0
    if( parent )
960
0
    {
961
      // copy data to self for neighbors
962
0
      getRecoBuf( area ).copyFrom( recoBuf );
963
0
    }
964
965
    // copy data to picture
966
0
    picture->getRecoBuf( area ).copyFrom( recoBuf );
967
0
  }
968
0
}
969
970
void CodingStructure::compactResize( const UnitArea& _area )
971
403k
{
972
403k
  m_pred   .compactResize( _area );
973
403k
  m_reco   .compactResize( _area );
974
403k
  m_resi   .compactResize( _area );
975
976
1.61M
  for( uint32_t i = 0; i < _area.blocks.size(); i++ )
977
1.20M
  {
978
1.20M
    CHECK( _maxArea.blocks[i].area() < _area.blocks[i].area(), "Trying to init sub-structure of incompatible size" );
979
1.20M
  }
980
981
403k
  area = _area;
982
403k
}
983
984
void CodingStructure::initStructData( const int QP, const bool skipMotBuf, const UnitArea* _area )
985
870k
{
986
870k
  clearTUs( false );
987
870k
  clearCUs( false );
988
989
870k
  if( _area ) compactResize( *_area );
990
991
870k
  if( QP < MAX_INT )
992
674k
  {
993
674k
    currQP[0] = currQP[1] = QP;
994
674k
  }
995
996
870k
  if( !skipMotBuf && ( !parent || ( ( !slice->isIntra() || slice->sps->IBC ) && !m_isTuEnc ) ) )
997
213k
  {
998
213k
    getMotionBuf().memset( -1 );
999
213k
  }
1000
1001
870k
  m_dmvrMvCacheOffset = 0;
1002
1003
870k
  fracBits      = 0;
1004
870k
  dist          = 0;
1005
870k
  cost          = MAX_DOUBLE;
1006
870k
  lumaCost      = MAX_DOUBLE;
1007
870k
  costDbOffset  = 0;
1008
870k
  interHad      = MAX_DISTORTION;
1009
870k
}
1010
1011
1012
void CodingStructure::clearTUs( bool force )
1013
1.38M
{
1014
#if CLEAR_AND_CHECK_TUIDX
1015
  if( !m_numTUs && !force ) return;
1016
1017
#endif
1018
1.38M
  memset( m_offsets, 0, sizeof( m_offsets ) );
1019
1020
1.38M
  for( auto &pcu : cus )
1021
286k
  {
1022
286k
    pcu->firstTU = pcu->lastTU = nullptr;
1023
286k
  }
1024
1025
1.38M
  if ( m_unitCacheMutex ) m_unitCacheMutex->lock();
1026
1.38M
  m_tuCache.cache( tus );
1027
1.38M
  if ( m_unitCacheMutex ) m_unitCacheMutex->unlock();
1028
1029
1.38M
  m_numTUs = 0;
1030
1.38M
}
1031
1032
void CodingStructure::clearCUs( bool force )
1033
1.43M
{
1034
1.43M
  if( !m_numCUs && !force ) return;
1035
1036
433k
  int numCh = getNumberValidChannels( area.chromaFormat );
1037
1.30M
  for( int i = 0; i < numCh; i++ )
1038
866k
  {
1039
866k
    memset( m_cuPtr[i], 0, sizeof( *m_cuPtr[0] ) * unitScale[i].scaleArea( area.blocks[i].area() ) );
1040
866k
  }
1041
1042
433k
  if ( m_unitCacheMutex ) m_unitCacheMutex->lock();
1043
433k
  m_cuCache.cache( cus );
1044
433k
  if ( m_unitCacheMutex ) m_unitCacheMutex->unlock();
1045
1046
433k
  m_numCUs = 0;
1047
433k
}
1048
1049
MotionBuf CodingStructure::getMotionBuf( const Area& _area )
1050
331k
{
1051
331k
  const CompArea& _luma = area.Y();
1052
1053
331k
  CHECKD( !_luma.contains( _area ), "Trying to access motion information outside of this coding structure" );
1054
1055
331k
  const Area miArea   = g_miScaling.scale( _area );
1056
331k
  const Area selfArea = g_miScaling.scale( _luma );
1057
1058
331k
  return MotionBuf( m_motionBuf + rsAddr( miArea.pos(), selfArea.pos(), selfArea.width ), selfArea.width, miArea.size() );
1059
331k
}
1060
1061
const CMotionBuf CodingStructure::getMotionBuf( const Area& _area ) const
1062
0
{
1063
0
  const CompArea& _luma = area.Y();
1064
1065
0
  CHECKD( !_luma.contains( _area ), "Trying to access motion information outside of this coding structure" );
1066
1067
0
  const Area miArea   = g_miScaling.scale( _area );
1068
0
  const Area selfArea = g_miScaling.scale( _luma );
1069
1070
0
  return MotionBuf( m_motionBuf + rsAddr( miArea.pos(), selfArea.pos(), selfArea.width ), selfArea.width, miArea.size() );
1071
0
}
1072
1073
MotionInfo& CodingStructure::getMotionInfo( const Position& pos )
1074
415k
{
1075
415k
  CHECKD( !area.Y().contains( pos ), "Trying to access motion information outside of this coding structure" );
1076
1077
  // bypass the motion buf calling and get the value directly
1078
415k
  const unsigned stride = g_miScaling.scaleHor( area.lumaSize().width );
1079
415k
  const Position miPos  = g_miScaling.scale( pos - area.lumaPos() );
1080
1081
415k
  return *( m_motionBuf + miPos.y * stride + miPos.x );
1082
415k
}
1083
1084
const MotionInfo& CodingStructure::getMotionInfo( const Position& pos ) const
1085
0
{
1086
0
  CHECKD( !area.Y().contains( pos ), "Trying to access motion information outside of this coding structure" );
1087
1088
  // bypass the motion buf calling and get the value directly
1089
0
  const unsigned stride = g_miScaling.scaleHor( area.lumaSize().width );
1090
0
  const Position miPos  = g_miScaling.scale( pos - area.lumaPos() );
1091
1092
0
  return *( m_motionBuf + miPos.y * stride + miPos.x );
1093
0
}
1094
1095
PelBuf CodingStructure::getBuf( const CompArea& blk, const PictureType type )
1096
17.8M
{
1097
17.8M
  if (!blk.valid())
1098
475k
  {
1099
475k
    return PelBuf();
1100
475k
  }
1101
1102
17.3M
  const ComponentID compID = blk.compID;
1103
1104
17.3M
  PelStorage* buf = type == PIC_PREDICTION ? &m_pred : ( type == PIC_RESIDUAL ? &m_resi : ( type == PIC_RECONSTRUCTION ? &m_reco : nullptr ) );
1105
17.3M
  if (type == PIC_ORIGINAL)
1106
2.24M
  {
1107
2.24M
    buf = m_org;
1108
2.24M
  }
1109
1110
17.3M
  CHECK( !buf, "Unknown buffer requested" );
1111
1112
17.3M
  CHECKD( !area.blocks[compID].contains( blk ), "Buffer not contained in self requested" );
1113
1114
17.3M
  CompArea cFinal = blk;
1115
17.3M
  cFinal.relativeTo( area.blocks[compID] );
1116
1117
17.3M
  if( !parent && ( type == PIC_RESIDUAL || type == PIC_PREDICTION ) )
1118
35.2k
  {
1119
35.2k
    cFinal.x &= ( pcv->maxCUSizeMask >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
1120
35.2k
    cFinal.y &= ( pcv->maxCUSizeMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
1121
35.2k
  }
1122
1123
17.3M
  return buf->getBuf( cFinal );
1124
17.3M
}
1125
1126
const CPelBuf CodingStructure::getBuf( const CompArea& blk, const PictureType type ) const
1127
25.5k
{
1128
25.5k
  if (!blk.valid())
1129
0
  {
1130
0
    return PelBuf();
1131
0
  }
1132
1133
25.5k
  const ComponentID compID = blk.compID;
1134
1135
25.5k
  const PelStorage* buf = type == PIC_PREDICTION ? &m_pred : ( type == PIC_RESIDUAL ? &m_resi : ( type == PIC_RECONSTRUCTION ? &m_reco : nullptr ) );
1136
25.5k
  if (type == PIC_ORIGINAL)
1137
25.5k
  {
1138
25.5k
    buf = m_org;
1139
25.5k
  }
1140
1141
25.5k
  CHECK( !buf, "Unknown buffer requested" );
1142
1143
25.5k
  CHECKD( !area.blocks[compID].contains( blk ), "Buffer not contained in self requested" );
1144
1145
25.5k
  CompArea cFinal = blk;
1146
25.5k
  cFinal.relativeTo( area.blocks[compID] );
1147
1148
25.5k
  if( !parent && ( type == PIC_RESIDUAL || type == PIC_PREDICTION ) )
1149
0
  {
1150
0
    cFinal.x &= ( pcv->maxCUSizeMask >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
1151
0
    cFinal.y &= ( pcv->maxCUSizeMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
1152
0
  }
1153
1154
25.5k
  return buf->getBuf( cFinal );
1155
25.5k
}
1156
1157
PelUnitBuf CodingStructure::getBuf( const UnitArea& unit, const PictureType type )
1158
451k
{
1159
  // no parent fetching for buffers
1160
451k
  if( area.chromaFormat == CHROMA_400 )
1161
0
  {
1162
0
    return PelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ) );
1163
0
  }
1164
451k
  else
1165
451k
  {
1166
451k
    return PelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ), getBuf( unit.Cb(), type ), getBuf( unit.Cr(), type ) );
1167
451k
  }
1168
451k
}
1169
1170
const CPelUnitBuf CodingStructure::getBuf( const UnitArea& unit, const PictureType type ) const
1171
0
{
1172
  // no parent fetching for buffers
1173
0
  if( area.chromaFormat == CHROMA_400 )
1174
0
  {
1175
0
    return CPelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ) );
1176
0
  }
1177
0
  else
1178
0
  {
1179
0
    return CPelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ), getBuf( unit.Cb(), type ), getBuf( unit.Cr(), type ) );
1180
0
  }
1181
0
}
1182
1183
const CodingUnit* CodingStructure::getCURestricted( const Position& pos, const CodingUnit& curCu, const ChannelType _chType ) const
1184
1.92M
{
1185
1.92M
  const int csx    = getChannelTypeScaleX( _chType, area.chromaFormat );
1186
1.92M
  const int csy    = getChannelTypeScaleY( _chType, area.chromaFormat );
1187
1.92M
  const int xshift = pcv->maxCUSizeLog2 - csx;
1188
1.92M
  const int yshift = pcv->maxCUSizeLog2 - csy;
1189
1.92M
  const int ydiff  = ( pos.y >> yshift ) - ( curCu.blocks[_chType].y >> yshift );
1190
1.92M
  const int xdiff  = ( pos.x >> xshift ) - ( curCu.blocks[_chType].x >> xshift );
1191
1192
1.92M
  if( !xdiff && !ydiff )
1193
822k
  {
1194
822k
    const CodingUnit* cu = getCU( pos, _chType, curCu.treeType );
1195
1196
822k
    return ( cu && ( cu->cs != curCu.cs || cu->idx <= curCu.idx ) ) ? cu : nullptr;
1197
822k
  }
1198
1199
1.10M
  if( ydiff > 0 || ( ydiff == 0 && xdiff > 0 ) || ( ydiff == -1 && xdiff > ( sps->entropyCodingSyncEnabled ? 0 : 1 ) ) )
1200
27.2k
    return nullptr;
1201
1202
1.07M
  if( pos.x < 0 || pos.y < 0 || ( pos.x * ( 1 << csx ) ) >= pcv->lumaWidth || pps->getTileIdx( pos.x >> xshift, pos.y >> yshift ) != curCu.tileIdx ) return nullptr;
1203
1204
242k
  const CodingUnit* cu = getCU( pos, _chType, curCu.treeType );
1205
1206
242k
  return ( cu && CU::isSameSlice( *cu, curCu ) ) ? cu : nullptr;
1207
1.07M
}
1208
1209
const CodingUnit *CodingStructure::getCURestricted( const Position &pos, const Position curPos, const unsigned curSliceIdx, const unsigned curTileIdx, const ChannelType _chType, const TreeType _treeType ) const
1210
2.33M
{
1211
2.33M
  const int csx    = getChannelTypeScaleX( _chType, area.chromaFormat );
1212
2.33M
  const int csy    = getChannelTypeScaleY( _chType, area.chromaFormat );
1213
2.33M
  const int xshift = pcv->maxCUSizeLog2 - csx;
1214
2.33M
  const int yshift = pcv->maxCUSizeLog2 - csy;
1215
2.33M
  const int ydiff  = ( pos.y >> yshift ) - ( curPos.y >> yshift );
1216
2.33M
  const int xdiff  = ( pos.x >> xshift ) - ( curPos.x >> xshift );
1217
1218
2.33M
  if( !xdiff && !ydiff )
1219
754k
  {
1220
754k
    return getCU( pos, _chType, _treeType );
1221
754k
  }
1222
1223
1.58M
  if( ydiff > 0 || ( ydiff == 0 && xdiff > 0 ) || ( ydiff == -1 && xdiff > ( sps->entropyCodingSyncEnabled ? 0 : 1 ) ) )
1224
30.7k
    return nullptr;
1225
1226
1.55M
  if( pos.x < 0 || pos.y < 0 || ( pos.x << csx ) >= pcv->lumaWidth || pps->getTileIdx( pos.x >> xshift, pos.y >> yshift ) != curTileIdx ) return nullptr;
1227
1228
592k
  const CodingUnit* cu = getCU( pos, _chType, _treeType );
1229
1230
592k
  return ( cu && cu->slice->independentSliceIdx == curSliceIdx && cu->tileIdx == curTileIdx ) ? cu : nullptr;
1231
1.55M
}
1232
1233
const TransformUnit* CodingStructure::getTURestricted( const Position& pos, const TransformUnit& curTu, const ChannelType _chType ) const
1234
0
{
1235
0
  if( sps->entropyCodingSyncEnabled )
1236
0
  {
1237
0
    const int xshift = pcv->maxCUSizeLog2 - getChannelTypeScaleX( _chType, curTu.chromaFormat );
1238
0
    const int yshift = pcv->maxCUSizeLog2 - getChannelTypeScaleY( _chType, curTu.chromaFormat );
1239
0
    if( (pos.x >> xshift) > (curTu.blocks[_chType].x >> xshift) || (pos.y >> yshift) > (curTu.blocks[_chType].y >> yshift) )
1240
0
      return nullptr;
1241
0
  }
1242
0
  const TransformUnit* tu = getTU( pos, _chType );
1243
0
  return ( tu && CU::isSameSliceAndTile( *tu->cu, *curTu.cu ) && ( tu->cs != curTu.cs || tu->idx <= curTu.idx ) ) ? tu : nullptr;
1244
0
}
1245
1246
} // namespace vvenc
1247
1248
//! \}
1249