Coverage Report

Created: 2026-06-10 07:00

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
534k
  : area            ()
66
534k
  , picture         ( nullptr )
67
534k
  , parent          ( nullptr )
68
534k
  , lumaCS          ( nullptr )
69
534k
  , picHeader       ( nullptr )
70
534k
  , m_isTuEnc       ( false )
71
534k
  , m_cuCache       ( unitCache.cuCache )
72
534k
  , m_tuCache       ( unitCache.tuCache )
73
534k
  , m_unitCacheMutex( mutex )
74
534k
  , bestParent      ( nullptr )
75
534k
  , resetIBCBuffer  ( false )
76
534k
{
77
2.13M
  for( uint32_t i = 0; i < MAX_NUM_COMP; i++ )
78
1.60M
  {
79
1.60M
    m_coeffs[ i ] = nullptr;
80
1.60M
    m_offsets[ i ] = 0;
81
1.60M
  }
82
83
1.60M
  for( uint32_t i = 0; i < MAX_NUM_CH; i++ )
84
1.06M
  {
85
1.06M
    m_cuPtr   [ i ] = nullptr;
86
1.06M
  }
87
88
1.60M
  for( int i = 0; i < NUM_EDGE_DIR; i++ )
89
1.06M
  {
90
1.06M
    m_lfParam [ i ] = nullptr;
91
1.06M
  }
92
93
534k
  m_motionBuf = nullptr;
94
95
534k
  m_numTUs = m_numCUs = 0;
96
534k
}
97
98
void CodingStructure::destroy()
99
516k
{
100
516k
  picture   = nullptr;
101
516k
  parent    = nullptr;
102
516k
  lumaCS     = nullptr;
103
104
516k
  m_pred.destroy();
105
516k
  m_resi.destroy();
106
516k
  m_reco.destroy();
107
516k
  m_rspreco.destroy();
108
516k
  m_org = nullptr;
109
516k
  m_rsporg = nullptr;
110
111
516k
  destroyCoeffs();
112
516k
  delete[] m_motionBuf;
113
516k
  m_motionBuf = nullptr;
114
115
516k
  destroyTempBuffers();
116
117
516k
  if ( m_unitCacheMutex ) m_unitCacheMutex->lock();
118
119
516k
  m_tuCache.cache( tus );
120
516k
  m_cuCache.cache( cus );
121
122
516k
  if ( m_unitCacheMutex ) m_unitCacheMutex->unlock();
123
516k
}
124
125
void CodingStructure::releaseIntermediateData()
126
416k
{
127
416k
  clearTUs();
128
416k
  clearCUs();
129
416k
}
130
131
CodingUnit* CodingStructure::getLumaCU( const Position& pos )
132
0
{
133
0
  const ChannelType effChType = CH_L;
134
0
  const CompArea& _blk = area.blocks[effChType];
135
0
  CHECK( !_blk.contains( pos ), "must contain the pos" );
136
137
0
  return m_cuPtr[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
138
0
}
139
140
CodingUnit* CodingStructure::getCU( const Position& pos, const ChannelType effChType, const TreeType _treeType )
141
4.63M
{
142
4.63M
  CHECKD(_treeType == TREE_C && effChType == CH_L && parent == nullptr && _treeType == TREE_C && effChType == CH_L, "parent shall be valid; consider using function getLumaCU()");
143
144
4.63M
  CodingStructure* cs = _treeType == TREE_C && effChType == CH_L ? parent : this;
145
5.51M
  while (cs && !cs->area.blocks[effChType].contains(pos)) cs = cs->parent;
146
147
4.63M
  if (!cs)
148
173
  {
149
173
    return nullptr;
150
173
  }
151
4.63M
  else
152
4.63M
  {
153
4.63M
    const Area& _blk = cs->area.blocks[effChType];
154
4.63M
    return cs->m_cuPtr[effChType][rsAddr(pos, _blk.pos(), _blk.width, unitScale[effChType])];
155
4.63M
  }
156
4.63M
}
157
158
const CodingUnit* CodingStructure::getCU( const Position& pos, const ChannelType effChType, const TreeType _treeType ) const
159
2.67M
{
160
2.67M
  CHECKD(_treeType == TREE_C && effChType == CH_L && parent == nullptr && _treeType == TREE_C && effChType == CH_L, "parent shall be valid; consider using function getLumaCU()");
161
162
2.67M
  const CodingStructure* cs = _treeType == TREE_C && effChType == CH_L ? parent : this;
163
6.32M
  while (cs && !cs->area.blocks[effChType].contains(pos)) cs = cs->parent;
164
165
2.67M
  if (!cs)
166
13.5k
  {
167
13.5k
    return nullptr;
168
13.5k
  }
169
2.66M
  else
170
2.66M
  {
171
2.66M
    const Area& _blk = cs->area.blocks[effChType];
172
2.66M
    return cs->m_cuPtr[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
173
2.66M
  }
174
2.67M
}
175
176
TransformUnit* CodingStructure::getTU( const Position& pos, const ChannelType effChType, const int subTuIdx )
177
1.47M
{
178
1.47M
  const CompArea& _blk = area.blocks[effChType];
179
180
1.47M
  if( !_blk.contains( pos ) )
181
0
  {
182
0
    if( parent ) return parent->getTU( pos, effChType );
183
0
    else         return nullptr;
184
0
  }
185
1.47M
  else
186
1.47M
  {
187
1.47M
    CodingUnit* cu = m_cuPtr[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
188
1.47M
    if( !cu ) return nullptr;
189
190
1.47M
    TransformUnit* ptu = cu->firstTU;
191
192
1.49M
    while( ptu && !ptu->blocks[effChType].contains( pos ) )
193
24.5k
    {
194
24.5k
      ptu = ptu->next;
195
24.5k
    }
196
197
1.47M
    return ptu;
198
1.47M
  }
199
1.47M
}
200
201
const TransformUnit * CodingStructure::getTU( const Position& pos, const ChannelType effChType, const int subTuIdx ) const
202
148k
{
203
148k
  const CompArea& _blk = area.blocks[effChType];
204
205
148k
  if( !_blk.contains( pos ) )
206
0
  {
207
0
    if( parent ) return parent->getTU( pos, effChType );
208
0
    else         return nullptr;
209
0
  }
210
148k
  else
211
148k
  {
212
148k
    const CodingUnit* cu = m_cuPtr[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
213
148k
    if( !cu ) return nullptr;
214
215
148k
    const TransformUnit* ptu = cu->firstTU;
216
217
148k
    while( ptu && !ptu->blocks[effChType].contains( pos ) )
218
222
    {
219
222
      ptu = ptu->next;
220
222
    }
221
222
148k
    return ptu;
223
148k
  }
224
148k
}
225
226
CodingUnit& CodingStructure::addCU( const UnitArea& unit, const ChannelType chType, CodingUnit* cuInit )
227
403k
{
228
403k
  CodingUnit* cu;
229
230
403k
  if( cuInit )
231
138k
  {
232
138k
    cu = cuInit;
233
138k
  }
234
264k
  else
235
264k
  {
236
264k
    if( m_unitCacheMutex ) m_unitCacheMutex->lock();
237
238
264k
    cu = m_cuCache.get();
239
240
264k
    if( m_unitCacheMutex ) m_unitCacheMutex->unlock();
241
242
264k
    cu->UnitArea::operator=( unit );
243
264k
    cu->initData();
244
264k
    cu->slice   = nullptr;
245
264k
  }
246
  
247
403k
  cu->next      = nullptr;
248
403k
  cu->firstTU   = nullptr;
249
403k
  cu->lastTU    = nullptr;
250
403k
  cu->chType    = chType;
251
403k
  cu->cs        = this;
252
253
403k
  CodingUnit *prevCU = m_numCUs > 0 ? cus.back() : nullptr;
254
255
403k
  if( prevCU )
256
112k
  {
257
112k
    const int prevCuCtuRsAddr = getCtuAddr( recalcPosition( area.chromaFormat, prevCU->chType, CH_L, prevCU->blocks[prevCU->chType] ), *pcv );
258
112k
    const int currCuCtuRsAddr = getCtuAddr( recalcPosition( area.chromaFormat,         chType, CH_L,     cu->blocks[        chType] ), *pcv );
259
260
112k
    if( prevCuCtuRsAddr == currCuCtuRsAddr )
261
109k
    {
262
109k
      prevCU->next = cu;
263
109k
    }
264
112k
  }
265
266
403k
  cus.push_back( cu );
267
268
403k
  Mv* prevCuMvd = cuInit ? cuInit->mvdL0SubPu : nullptr;
269
  
270
403k
  cu->idx        = ++m_numCUs;
271
403k
  cu->mvdL0SubPu = nullptr;
272
273
403k
  if( isLuma( chType ) && unit.lheight() >= 8 && unit.lwidth() >= 8 && unit.Y().area() >= 128 )
274
252k
  {
275
252k
    CHECKD( m_dmvrMvCacheOffset >= m_dmvrMvCache.size(), "dmvr cache offset out of bounds" );
276
277
252k
    int mvdArrSize       = std::max<int>( 1, unit.lwidth() >> DMVR_SUBCU_SIZE_LOG2 ) * std::max<int>( 1, unit.lheight() >> DMVR_SUBCU_SIZE_LOG2 );
278
252k
    cu->mvdL0SubPu       = &m_dmvrMvCache[m_dmvrMvCacheOffset];
279
252k
    m_dmvrMvCacheOffset += mvdArrSize;
280
281
252k
    if( prevCuMvd )
282
59.3k
      memcpy( cu->mvdL0SubPu, prevCuMvd, sizeof( Mv ) * mvdArrSize );
283
252k
  }
284
285
403k
  uint32_t numCh = getNumberValidChannels( area.chromaFormat );
286
287
1.20M
  for( uint32_t i = 0; i < numCh; i++ )
288
806k
  {
289
806k
    if( !cu->blocks[i].valid() )
290
403k
    {
291
403k
      continue;
292
403k
    }
293
294
403k
    const CompArea& _selfBlk = area.blocks[i];
295
403k
    const CompArea     &_blk = cu-> blocks[i];
296
297
403k
    const UnitScale& scale = unitScale[_blk.compID];
298
403k
    const Area scaledSelf  = scale.scale( _selfBlk );
299
403k
    const Area scaledBlk   = scale.scale(     _blk );
300
403k
    CodingUnit **cuPtr     = m_cuPtr[i] + rsAddr( scaledBlk.pos(), scaledSelf.pos(), scaledSelf.width );
301
302
403k
    CHECKD( *cuPtr, "Overwriting a pre-existing value, should be '0'!" );
303
304
403k
    g_pelBufOP.fillPtrMap( ( void** ) cuPtr, scaledSelf.width, scaledBlk.width, scaledBlk.height, ( void* ) cu );
305
403k
  }
306
307
403k
  return *cu;
308
403k
}
309
310
TransformUnit& CodingStructure::addTU( const UnitArea& unit, const ChannelType chType, CodingUnit* cu, TransformUnit* tuInit )
311
475k
{
312
475k
  TransformUnit* tu;
313
314
475k
  if( tuInit )
315
162k
  {
316
162k
    tu = tuInit;
317
162k
  }
318
313k
  else
319
313k
  {
320
313k
    if( m_unitCacheMutex ) m_unitCacheMutex->lock();
321
322
313k
    tu = m_tuCache.get();
323
324
313k
    if( m_unitCacheMutex ) m_unitCacheMutex->unlock();
325
326
313k
    tu->UnitArea::operator=( unit );
327
313k
    tu->initData();
328
313k
  }
329
330
475k
  tu->next   = nullptr;
331
475k
  tu->prev   = nullptr;
332
475k
  tu->cs     = this;
333
475k
  tu->cu     = cu;
334
475k
  tu->chType = chType;
335
336
475k
  TransformUnit *prevTU = m_numTUs > 0 ? tus.back() : nullptr;
337
338
475k
  if( prevTU && prevTU->cu == tu->cu )
339
17.3k
  {
340
17.3k
    prevTU->next = tu;
341
17.3k
    tu->prev     = prevTU;
342
17.3k
  }
343
344
475k
  tus.push_back( tu );
345
346
475k
  if( tu->cu )
347
420k
  {
348
420k
    if( tu->cu->firstTU == nullptr )
349
398k
    {
350
398k
      tu->cu->firstTU = tu;
351
398k
    }
352
420k
    tu->cu->lastTU = tu;
353
420k
  }
354
355
475k
  uint32_t idx = ++m_numTUs;
356
475k
  tu->idx = idx;
357
358
475k
  TCoeffSig *coeffs[3] = { nullptr, nullptr, nullptr };
359
360
475k
  uint32_t numCh = getNumberValidComponents( area.chromaFormat );
361
362
1.90M
  for( uint32_t i = 0; i < numCh; i++ )
363
1.42M
  {
364
1.42M
    if( !tu->blocks[i].valid() )
365
747k
    {
366
747k
      continue;
367
747k
    }
368
369
678k
    coeffs[i] = m_coeffs[i] + m_offsets[i];
370
371
678k
    unsigned areaSize = tu->blocks[i].area();
372
678k
    m_offsets[i] += areaSize;
373
374
678k
    const bool cpyRsi = tuInit &&
375
240k
                      ( tuInit->cbf[i] ||
376
195k
                 ( i && tuInit->jointCbCr && numCh > 1 && ( TU::getCbf( *tuInit, COMP_Cb ) || TU::getCbf( *tuInit, COMP_Cr ) ) )
377
240k
                      );
378
379
678k
    if( cpyRsi )
380
44.6k
      memcpy( coeffs[i], tu->m_coeffs[i], areaSize * sizeof( TCoeffSig ) );
381
678k
  }
382
383
475k
  tu->init( coeffs );
384
385
475k
  return *tu;
386
475k
}
387
388
void CodingStructure::addEmptyTUs( Partitioner &partitioner, CodingUnit* cu )
389
20.4k
{
390
20.4k
  const UnitArea& area    = partitioner.currArea();
391
20.4k
  bool            split   = partitioner.canSplit(TU_MAX_TR_SPLIT, *this);
392
20.4k
  const unsigned  trDepth = partitioner.currTrDepth;
393
394
20.4k
  if( split )
395
0
  {
396
0
    partitioner.splitCurrArea( TU_MAX_TR_SPLIT, *this );
397
0
    do
398
0
    {
399
0
      addEmptyTUs( partitioner, cu );
400
0
    } while( partitioner.nextPart( *this ) );
401
402
0
    partitioner.exitCurrSplit();
403
0
  }
404
20.4k
  else
405
20.4k
  {
406
20.4k
    TransformUnit& tu = addTU(CS::getArea(*this, area, partitioner.chType, TreeType(partitioner.treeType)), partitioner.chType, cu);
407
20.4k
    tu.depth = trDepth;
408
20.4k
  }
409
20.4k
}
410
411
CUTraverser CodingStructure::traverseCUs( const UnitArea& unit, const ChannelType effChType )
412
6.92k
{
413
  //  CHECK( _treeType != treeType, "not good");
414
6.92k
  CodingUnit* firstCU = getCU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType, TREE_D );
415
6.92k
  CodingUnit* lastCU = firstCU;
416
6.92k
  if( !CS::isDualITree( *this ) ) //for a more generalized separate tree
417
0
  {
418
0
    bool bContinue = true;
419
0
    CodingUnit* currCU = firstCU;
420
0
    while( bContinue )
421
0
    {
422
0
      if( currCU == nullptr )
423
0
      {
424
0
        bContinue = false;
425
0
        lastCU = currCU;
426
0
      }
427
0
      else if( currCU->chType != effChType )
428
0
      {
429
0
        lastCU = currCU;
430
0
        currCU = currCU->next;
431
0
      }
432
0
      else
433
0
      {
434
0
        if( unit.contains( *currCU ) )
435
0
        {
436
0
          lastCU = currCU;
437
0
          currCU = currCU->next;
438
0
        }
439
0
        else
440
0
        {
441
0
          bContinue = false;
442
0
          lastCU = currCU;
443
0
        }
444
0
      }
445
0
    }
446
0
  }
447
6.92k
  else
448
6.92k
  {
449
36.1k
  do { } while( lastCU && (0 != ( lastCU = lastCU->next )) && unit.contains( *lastCU ) );
450
6.92k
  }
451
452
6.92k
  return CUTraverser( firstCU, lastCU );
453
6.92k
}
454
455
TUTraverser CodingStructure::traverseTUs( const UnitArea& unit, const ChannelType effChType )
456
0
{
457
0
  TransformUnit* firstTU = getTU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType );
458
0
  TransformUnit* lastTU  = firstTU;
459
460
0
  do { } while( lastTU && (0 != ( lastTU = lastTU->next )) && unit.contains( *lastTU ) );
461
462
0
  return TUTraverser( firstTU, lastTU );
463
0
}
464
465
cCUTraverser CodingStructure::traverseCUs( const UnitArea& unit, const ChannelType effChType ) const
466
0
{
467
0
  const CodingUnit* firstCU = getCU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType, TREE_D );
468
0
  const CodingUnit* lastCU  = firstCU;
469
470
0
  do { } while( lastCU && (0 != ( lastCU = lastCU->next )) && unit.contains( *lastCU ) );
471
472
0
  return cCUTraverser( firstCU, lastCU );
473
0
}
474
475
cTUTraverser CodingStructure::traverseTUs( const UnitArea& unit, const ChannelType effChType ) const
476
0
{
477
0
  const TransformUnit* firstTU = getTU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType );
478
0
  const TransformUnit* lastTU  = firstTU;
479
480
0
  do { } while( lastTU && (0 != ( lastTU = lastTU->next )) && unit.contains( *lastTU ) );
481
482
0
  return cTUTraverser( firstTU, lastTU );
483
0
}
484
485
486
487
LFPBuf CodingStructure::getLoopFilterParamBuf(const DeblockEdgeDir& edgeDir)
488
6.92k
{
489
6.92k
  return LFPBuf(m_lfParam[edgeDir], m_mapSize[0]);
490
6.92k
}
491
492
const CLFPBuf CodingStructure::getLoopFilterParamBuf(const DeblockEdgeDir& edgeDir) const
493
0
{
494
0
  return CLFPBuf(m_lfParam[edgeDir], m_mapSize[0]);
495
0
}
496
497
498
// coding utilities
499
500
void CodingStructure::allocateVectorsAtPicLevel()
501
1.11k
{
502
1.11k
  const int  twice = ( !pcv->ISingleTree && slice->isIRAP() && pcv->chrFormat != CHROMA_400 ) ? 2 : 1;
503
1.11k
  size_t allocSize = twice * unitScale[0].scale( area.blocks[0].size() ).area();
504
505
1.11k
  cus.reserve( allocSize );
506
1.11k
  tus.reserve( allocSize );
507
1.11k
}
508
509
510
511
void CodingStructure::createForSearch( const ChromaFormat _chromaFormat, const Area& _area )
512
515k
{
513
515k
  createInternals( UnitArea( _chromaFormat, _area ), false );
514
515
515k
  m_reco.create( area );
516
515k
  m_pred.create( area );
517
515k
  m_resi.create( area );
518
515k
  m_rspreco.create( CHROMA_400, area.Y() );
519
515k
}
520
521
void CodingStructure::createPicLevel( const UnitArea& _unit, const PreCalcValues* _pcv )
522
1.11k
{
523
1.11k
  pcv = _pcv;
524
525
1.11k
  createInternals( _unit, true );
526
1.11k
}
527
528
static constexpr int UnitScaleArray[NUM_CHROMA_FORMAT][MAX_NUM_COMP][2] =
529
{
530
  { {2,2}, {0,0}, {0,0} },  // 4:0:0
531
  { {2,2}, {1,1}, {1,1} },  // 4:2:0
532
  { {2,2}, {1,2}, {1,2} },  // 4:2:2
533
  { {2,2}, {2,2}, {2,2} }   // 4:4:4
534
};
535
536
void CodingStructure::createInternals( const UnitArea& _unit, const bool isTopLayer )
537
516k
{
538
516k
  area     = _unit;
539
516k
  _maxArea = _unit;
540
541
516k
  unitScale[COMP_Y ] = UnitScale( UnitScaleArray[area.chromaFormat][COMP_Y ][0], UnitScaleArray[area.chromaFormat][COMP_Y ][1] );
542
516k
  unitScale[COMP_Cb] = UnitScale( UnitScaleArray[area.chromaFormat][COMP_Cb][0], UnitScaleArray[area.chromaFormat][COMP_Cb][1] );
543
516k
  unitScale[COMP_Cr] = UnitScale( UnitScaleArray[area.chromaFormat][COMP_Cr][0], UnitScaleArray[area.chromaFormat][COMP_Cr][1] );
544
545
516k
  picture = nullptr;
546
516k
  parent  = nullptr;
547
516k
  lumaCS  = nullptr;
548
549
516k
  unsigned _lumaAreaScaled = g_miScaling.scale( area.lumaSize() ).area();
550
516k
  m_motionBuf = new MotionInfo[_lumaAreaScaled];
551
552
516k
  if( isTopLayer )
553
1.11k
  {
554
1.11k
    motionLutBuf.resize( pps->getNumTileLineIds() );
555
1.11k
  }
556
515k
  else
557
515k
  {
558
515k
    createCoeffs();
559
515k
    createTempBuffers( false );
560
515k
    initStructData( MAX_INT, false, nullptr );
561
515k
  }
562
516k
}
563
564
void CodingStructure::createTempBuffers( const bool isTopLayer )
565
516k
{
566
516k
  unsigned numCh = getNumberValidChannels( area.chromaFormat );
567
568
1.54M
  for( unsigned i = 0; i < numCh; i++ )
569
1.03M
  {
570
1.03M
    Size allocArea  = area.blocks[i].size();
571
1.03M
    m_mapSize[i]    = unitScale[i].scale(allocArea);
572
573
1.03M
    unsigned _area  = unitScale[i].scale( area.blocks[i].size() ).area();
574
575
1.03M
    m_cuPtr[i]      = _area > 0 ? new CodingUnit*    [_area] : nullptr;
576
1.03M
  }
577
578
516k
  clearCUs( true );
579
580
1.54M
  for( unsigned i = 0; i < NUM_EDGE_DIR; i++ )
581
1.03M
  {
582
1.03M
    m_lfParam[i] = ( isTopLayer && m_mapSize[0].area() > 0 ) ? ( LoopFilterParam* ) xMalloc( LoopFilterParam, m_mapSize[0].area() ) : nullptr;
583
1.03M
  }
584
585
516k
  unsigned _maxNumDmvrMvs = ( area.lwidth() >> 3 ) * ( area.lheight() >> 3 );
586
516k
  m_dmvrMvCache.resize( _maxNumDmvrMvs );
587
516k
}
588
589
void CodingStructure::destroyTempBuffers()
590
517k
{
591
1.55M
  for( uint32_t i = 0; i < MAX_NUM_CH; i++ )
592
1.03M
  {
593
1.03M
    delete[] m_cuPtr[i];
594
1.03M
    m_cuPtr[i] = nullptr;
595
1.03M
  }
596
597
1.55M
  for( int i = 0; i < NUM_EDGE_DIR; i++ )
598
1.03M
  {
599
1.03M
    xFree( m_lfParam[i] );
600
1.03M
    m_lfParam[i] = nullptr;
601
1.03M
  }
602
603
  // swap the contents of the vector so that memory released
604
517k
  std::vector<Mv>().swap( m_dmvrMvCache );
605
517k
  std::vector<CodingUnit*>().swap( cus );
606
517k
  std::vector<TransformUnit*>().swap( tus );
607
517k
}
608
609
void CodingStructure::addMiToLut( static_vector<HPMVInfo, MAX_NUM_HMVP_CANDS>& lut, const HPMVInfo& mi )
610
0
{
611
0
  size_t currCnt = lut.size();
612
613
0
  bool pruned      = false;
614
0
  int  sameCandIdx = 0;
615
616
0
  for( int idx = 0; idx < currCnt; idx++ )
617
0
  {
618
0
    if( lut[idx] == mi )
619
0
    {
620
0
      sameCandIdx = idx;
621
0
      pruned = true;
622
0
      break;
623
0
    }
624
0
  }
625
626
0
  if( pruned || currCnt == lut.capacity() )
627
0
  {
628
0
    lut.erase( lut.begin() + sameCandIdx );
629
0
  }
630
631
0
  lut.push_back(mi);
632
0
}
633
634
void CodingStructure::rebindPicBufs()
635
2.22k
{
636
2.22k
  CHECK( parent, "rebindPicBufs can only be used for the top level CodingStructure" );
637
638
2.22k
  if( !picture->m_picBufs[ PIC_RECONSTRUCTION ].bufs.empty() ) m_reco.createFromBuf( picture->m_picBufs[ PIC_RECONSTRUCTION ] );
639
0
  else                                                         m_reco.destroy();
640
2.22k
  if( !picture->m_picBufs[ PIC_PREDICTION     ].bufs.empty() ) m_pred.createFromBuf( picture->m_picBufs[ PIC_PREDICTION ] );
641
2.22k
  else                                                         m_pred.destroy();
642
2.22k
  if( !picture->m_picBufs[ PIC_RESIDUAL       ].bufs.empty() ) m_resi.createFromBuf( picture->m_picBufs[ PIC_RESIDUAL ] );
643
2.22k
  else                                                         m_resi.destroy();
644
2.22k
}
645
646
void CodingStructure::createCoeffs()
647
516k
{
648
516k
  const unsigned numComp = getNumberValidComponents( area.chromaFormat );
649
2.06M
  for( unsigned i = 0; i < numComp; i++ )
650
1.54M
  {
651
1.54M
    unsigned _area = area.blocks[i].area();
652
1.54M
    m_coeffs[i] = _area > 0 ? ( TCoeffSig* ) xMalloc( TCoeffSig, _area ) : nullptr;
653
1.54M
  }
654
655
2.06M
  for( unsigned i = 0; i < numComp; i++ )
656
1.54M
  {
657
1.54M
    m_offsets[i] = 0;
658
1.54M
  }
659
516k
}
660
661
void CodingStructure::destroyCoeffs()
662
517k
{
663
2.07M
  for( uint32_t i = 0; i < MAX_NUM_COMP; i++ )
664
1.55M
  {
665
1.55M
    if( m_coeffs[i] ) { xFree( m_coeffs[i] ); m_coeffs[i] = nullptr; }
666
1.55M
  }
667
517k
}
668
669
void CodingStructure::initSubStructure( CodingStructure& subStruct, const ChannelType _chType, const UnitArea& subArea, const bool isTuEnc, PelStorage* pOrgBuffer, PelStorage* pRspBuffer )
670
344k
{
671
344k
  CHECK( this == &subStruct, "Trying to init self as sub-structure" );
672
673
344k
  subStruct.parent = this;
674
675
344k
  if( pOrgBuffer ) pOrgBuffer->compactResize( subArea );
676
344k
  UnitArea subAreaLuma = subArea;
677
344k
  subAreaLuma.blocks.resize( 1 );
678
344k
  if( pRspBuffer ) pRspBuffer->compactResize( subAreaLuma );
679
680
344k
  subStruct.m_org    = (pOrgBuffer) ? pOrgBuffer : m_org;
681
344k
  subStruct.m_rsporg = (pRspBuffer) ? pRspBuffer : m_rsporg;
682
683
344k
  subStruct.compactResize( subArea );
684
685
344k
  subStruct.costDbOffset = 0;
686
687
344k
  if( parent )
688
330k
  {
689
    // allow this to be false at the top level (need for edge CTU's)
690
330k
    CHECKD( !area.contains( subArea ), "Trying to init sub-structure not contained in the parent" );
691
330k
  }
692
693
344k
  subStruct.parent    = this;
694
344k
  subStruct.picture   = picture;
695
344k
  subStruct.lumaCS    = picture->cs;
696
697
344k
  subStruct.sps       = sps;
698
344k
  subStruct.vps       = vps;
699
344k
  subStruct.pps       = pps;
700
344k
  subStruct.picHeader = picHeader;
701
702
344k
  memcpy(subStruct.alfAps, alfAps, sizeof(alfAps));
703
704
344k
  subStruct.lmcsAps   = lmcsAps;
705
706
344k
  subStruct.slice     = slice;
707
344k
  subStruct.baseQP    = baseQP;
708
344k
  subStruct.prevQP[_chType]
709
344k
                      = prevQP[_chType];
710
344k
  subStruct.pcv       = pcv;
711
712
344k
  subStruct.m_isTuEnc = isTuEnc;
713
714
344k
  if( nullptr == parent )
715
13.8k
  {
716
13.8k
    const int ctuPosX = subArea.lx() >> pcv->maxCUSizeLog2;
717
13.8k
    const int ctuPosY = subArea.ly() >> pcv->maxCUSizeLog2;
718
13.8k
    subStruct.motionLut = motionLutBuf[pps->getTileLineId( ctuPosX, ctuPosY )];
719
13.8k
  }
720
330k
  else
721
330k
  {
722
330k
    subStruct.motionLut = motionLut;
723
330k
  }
724
725
344k
  subStruct.initStructData( currQP[_chType] );
726
727
344k
  if( isTuEnc )
728
106k
  {
729
106k
    CHECKD( area != subStruct.area, "Trying to init sub-structure for TU-encoding of incompatible size" );
730
731
106k
    for( const auto &pcu : cus )
732
106k
    {
733
106k
      CodingUnit &cu = subStruct.addCU( *pcu, _chType );
734
735
106k
      cu = *pcu;
736
106k
    }
737
106k
  }
738
344k
}
739
740
void CodingStructure::useSubStructure( CodingStructure& subStruct, const ChannelType chType, const TreeType _treeType, const UnitArea& subArea, const bool cpyRecoToPic )
741
142k
{
742
142k
  UnitArea clippedArea = clipArea( subArea, *picture );
743
744
142k
  CPelUnitBuf subRecoBuf = subStruct.getRecoBuf( clippedArea );
745
746
142k
  if( parent )
747
135k
  {
748
    // copy data to picture
749
135k
    getRecoBuf( clippedArea ).copyFrom( subRecoBuf );
750
135k
  }
751
752
142k
  if( cpyRecoToPic )
753
112k
  {
754
112k
    picture->getRecoBuf( clippedArea ).copyFrom( subRecoBuf );
755
112k
  }
756
757
142k
  if( !subStruct.m_isTuEnc && ( ( !slice->isIntra() || slice->sps->IBC ) && chType != CH_C ) )
758
47.4k
  {
759
    // copy motion buffer
760
47.4k
    MotionBuf ownMB  = getMotionBuf          ( clippedArea );
761
47.4k
    CMotionBuf subMB = subStruct.getMotionBuf( clippedArea );
762
763
47.4k
    ownMB.copyFrom( subMB );
764
765
47.4k
    if( nullptr == parent )
766
3.46k
    {
767
3.46k
      const int ctuPosX = subStruct.area.lx() >> pcv->maxCUSizeLog2;
768
3.46k
      const int ctuPosY = subStruct.area.ly() >> pcv->maxCUSizeLog2;
769
3.46k
      motionLutBuf[pps->getTileLineId( ctuPosX, ctuPosY )] = subStruct.motionLut;
770
3.46k
    }
771
43.9k
    else
772
43.9k
    {
773
43.9k
      motionLut = subStruct.motionLut;
774
43.9k
    }
775
47.4k
  }
776
777
142k
  fracBits += subStruct.fracBits;
778
142k
  dist     += subStruct.dist;
779
142k
  cost     += subStruct.cost;
780
142k
  costDbOffset += subStruct.costDbOffset;
781
782
142k
  if( parent )
783
135k
  {
784
    // allow this to be false at the top level
785
135k
    CHECKD( !area.contains( subArea ), "Trying to use a sub-structure not contained in self" );
786
135k
  }
787
788
  // copy the CUs over
789
142k
  if( subStruct.m_isTuEnc )
790
23.1k
  {
791
    // don't copy if the substruct was created for encoding of the TUs
792
23.1k
  }
793
119k
  else
794
119k
  {
795
119k
    if( &m_cuCache == &subStruct.m_cuCache )
796
112k
    {
797
      // copy the CUs over with taking ownership
798
112k
      for( const auto& pcu : subStruct.cus )
799
138k
      {
800
        // add an analogue CU into own CU store
801
138k
        const UnitArea& cuPatch = *pcu;
802
138k
        addCU( cuPatch, pcu->chType, pcu );
803
138k
      }
804
805
112k
      subStruct.cus.resize( 0 );
806
112k
    }
807
6.92k
    else
808
6.92k
    {
809
      // copy the CUs over
810
6.92k
      for( const auto& pcu : subStruct.cus )
811
36.2k
      {
812
        // add an analogue CU into own CU store
813
36.2k
        const UnitArea& cuPatch = *pcu;
814
815
36.2k
        CodingUnit& cu = addCU( cuPatch, pcu->chType );
816
817
        // copy the CU info from subPatch
818
36.2k
        cu = *pcu;
819
36.2k
      }
820
6.92k
    }
821
119k
  }
822
823
142k
  if( &m_tuCache == &subStruct.m_tuCache )
824
135k
  {
825
    // copy the TUs over with taking ownership
826
135k
    for( const auto& ptu : subStruct.tus )
827
162k
    {
828
      // add an analogue TU into own TU store
829
162k
      const UnitArea& tuPatch = *ptu;
830
162k
      addTU( tuPatch, ptu->chType, getCU( tuPatch.blocks[ptu->chType].pos(), ptu->chType, _treeType ), ptu );
831
162k
    }
832
833
135k
    subStruct.tus.resize( 0 );
834
135k
  }
835
6.92k
  else
836
6.92k
  {
837
    // copy the TUs over
838
6.92k
    for( const auto& ptu : subStruct.tus )
839
36.2k
    {
840
      // add an analogue TU into own TU store
841
36.2k
      const UnitArea& tuPatch = *ptu;
842
843
36.2k
      TransformUnit& tu = addTU( tuPatch, ptu->chType, getCU( tuPatch.blocks[ptu->chType], ptu->chType, _treeType ) );
844
845
      // copy the TU info from subPatch
846
36.2k
      tu = *ptu;
847
36.2k
    }
848
6.92k
  }
849
142k
}
850
851
void CodingStructure::copyStructure( const CodingStructure& other, const ChannelType chType, const TreeType _treeType, const bool copyTUs, const bool copyRecoBuf )
852
0
{
853
0
  fracBits      = other.fracBits;
854
0
  dist          = other.dist;
855
0
  cost          = other.cost;
856
0
  costDbOffset  = other.costDbOffset;
857
0
  CHECKD( area != other.area, "Incompatible sizes" );
858
859
0
  const UnitArea dualITreeArea = CS::getArea( *this, area, chType, _treeType );
860
861
  // copy the CUs over
862
0
  for (const auto &pcu : other.cus)
863
0
  {
864
0
    if( !dualITreeArea.contains( *pcu ) )
865
0
    {
866
0
      continue;
867
0
    }
868
    // add an analogue CU into own CU store
869
0
    const UnitArea& cuPatch = *pcu;
870
871
0
    CodingUnit &cu = addCU(cuPatch, pcu->chType);
872
873
    // copy the CU info from subPatch
874
0
    cu = *pcu;
875
0
  }
876
877
0
  if (!other.slice->isIntra() || other.slice->sps->IBC)
878
0
  {
879
    // copy motion buffer
880
0
    MotionBuf  ownMB = getMotionBuf();
881
0
    CMotionBuf subMB = other.getMotionBuf();
882
883
0
    ownMB.copyFrom( subMB );
884
885
0
    motionLut = other.motionLut;
886
0
  }
887
888
0
  if( copyTUs )
889
0
  {
890
    // copy the TUs over
891
0
    for( const auto &ptu : other.tus )
892
0
    {
893
0
      if( !dualITreeArea.contains( *ptu ) )
894
0
      {
895
0
        continue;
896
0
      }
897
      // add an analogue TU into own TU store
898
0
      const UnitArea& tuPatch = *ptu;
899
900
0
      TransformUnit& tu = addTU( tuPatch, ptu->chType, getCU( tuPatch.blocks[ptu->chType], ptu->chType, _treeType) );
901
902
      // copy the TU info from subPatch
903
0
      tu = *ptu;
904
0
    }
905
0
  }
906
907
0
  if( copyRecoBuf )
908
0
  {
909
0
    CPelUnitBuf recoBuf = other.getRecoBuf( area );
910
911
0
    if( parent )
912
0
    {
913
      // copy data to self for neighbors
914
0
      getRecoBuf( area ).copyFrom( recoBuf );
915
0
    }
916
917
    // copy data to picture
918
0
    picture->getRecoBuf( area ).copyFrom( recoBuf );
919
0
  }
920
0
}
921
922
void CodingStructure::compactResize( const UnitArea& _area )
923
391k
{
924
391k
  UnitArea areaLuma = _area;
925
391k
  areaLuma.blocks.resize( 1 );
926
927
391k
  m_pred   .compactResize( _area );
928
391k
  m_reco   .compactResize( _area );
929
391k
  m_resi   .compactResize( _area );
930
391k
  m_rspreco.compactResize( areaLuma );
931
932
1.56M
  for( uint32_t i = 0; i < _area.blocks.size(); i++ )
933
1.17M
  {
934
1.17M
    CHECK( _maxArea.blocks[i].area() < _area.blocks[i].area(), "Trying to init sub-structure of incompatible size" );
935
1.17M
  }
936
937
391k
  area = _area;
938
391k
}
939
940
void CodingStructure::initStructData( const int QP, const bool skipMotBuf, const UnitArea* _area )
941
1.27M
{
942
1.27M
  clearTUs( false );
943
1.27M
  clearCUs( false );
944
945
1.27M
  if( _area ) compactResize( *_area );
946
947
1.27M
  if( QP < MAX_INT )
948
653k
  {
949
653k
    currQP[0] = currQP[1] = QP;
950
653k
  }
951
952
1.27M
  if( !skipMotBuf && ( !parent || ( ( !slice->isIntra() || slice->sps->IBC ) && !m_isTuEnc ) ) )
953
591k
  {
954
591k
    getMotionBuf().memset( -1 );
955
591k
  }
956
957
1.27M
  m_dmvrMvCacheOffset = 0;
958
959
1.27M
  fracBits      = 0;
960
1.27M
  dist          = 0;
961
1.27M
  cost          = MAX_DOUBLE;
962
1.27M
  lumaCost      = MAX_DOUBLE;
963
1.27M
  costDbOffset  = 0;
964
1.27M
  interHad      = MAX_DISTORTION;
965
1.27M
}
966
967
968
void CodingStructure::clearTUs( bool force )
969
1.76M
{
970
#if CLEAR_AND_CHECK_TUIDX
971
  if( !m_numTUs && !force ) return;
972
973
#endif
974
1.76M
  memset( m_offsets, 0, sizeof( m_offsets ) );
975
976
1.76M
  for( auto &pcu : cus )
977
278k
  {
978
278k
    pcu->firstTU = pcu->lastTU = nullptr;
979
278k
  }
980
981
1.76M
  if ( m_unitCacheMutex ) m_unitCacheMutex->lock();
982
1.76M
  m_tuCache.cache( tus );
983
1.76M
  if ( m_unitCacheMutex ) m_unitCacheMutex->unlock();
984
985
1.76M
  m_numTUs = 0;
986
1.76M
}
987
988
void CodingStructure::clearCUs( bool force )
989
2.20M
{
990
2.20M
  if( !m_numCUs && !force ) return;
991
992
805k
  int numCh = getNumberValidChannels( area.chromaFormat );
993
2.41M
  for( int i = 0; i < numCh; i++ )
994
1.61M
  {
995
1.61M
    memset( m_cuPtr[i], 0, sizeof( *m_cuPtr[0] ) * unitScale[i].scaleArea( area.blocks[i].area() ) );
996
1.61M
  }
997
998
805k
  if ( m_unitCacheMutex ) m_unitCacheMutex->lock();
999
805k
  m_cuCache.cache( cus );
1000
805k
  if ( m_unitCacheMutex ) m_unitCacheMutex->unlock();
1001
1002
805k
  m_numCUs = 0;
1003
805k
}
1004
1005
MotionBuf CodingStructure::getMotionBuf( const Area& _area )
1006
710k
{
1007
710k
  const CompArea& _luma = area.Y();
1008
1009
710k
  CHECKD( !_luma.contains( _area ), "Trying to access motion information outside of this coding structure" );
1010
1011
710k
  const Area miArea   = g_miScaling.scale( _area );
1012
710k
  const Area selfArea = g_miScaling.scale( _luma );
1013
1014
710k
  return MotionBuf( m_motionBuf + rsAddr( miArea.pos(), selfArea.pos(), selfArea.width ), selfArea.width, miArea.size() );
1015
710k
}
1016
1017
const CMotionBuf CodingStructure::getMotionBuf( const Area& _area ) const
1018
0
{
1019
0
  const CompArea& _luma = area.Y();
1020
1021
0
  CHECKD( !_luma.contains( _area ), "Trying to access motion information outside of this coding structure" );
1022
1023
0
  const Area miArea   = g_miScaling.scale( _area );
1024
0
  const Area selfArea = g_miScaling.scale( _luma );
1025
1026
0
  return MotionBuf( m_motionBuf + rsAddr( miArea.pos(), selfArea.pos(), selfArea.width ), selfArea.width, miArea.size() );
1027
0
}
1028
1029
MotionInfo& CodingStructure::getMotionInfo( const Position& pos )
1030
0
{
1031
0
  CHECKD( !area.Y().contains( pos ), "Trying to access motion information outside of this coding structure" );
1032
1033
  // bypass the motion buf calling and get the value directly
1034
0
  const unsigned stride = g_miScaling.scaleHor( area.lumaSize().width );
1035
0
  const Position miPos  = g_miScaling.scale( pos - area.lumaPos() );
1036
1037
0
  return *( m_motionBuf + miPos.y * stride + miPos.x );
1038
0
}
1039
1040
const MotionInfo& CodingStructure::getMotionInfo( const Position& pos ) const
1041
0
{
1042
0
  CHECKD( !area.Y().contains( pos ), "Trying to access motion information outside of this coding structure" );
1043
1044
  // bypass the motion buf calling and get the value directly
1045
0
  const unsigned stride = g_miScaling.scaleHor( area.lumaSize().width );
1046
0
  const Position miPos  = g_miScaling.scale( pos - area.lumaPos() );
1047
1048
0
  return *( m_motionBuf + miPos.y * stride + miPos.x );
1049
0
}
1050
1051
PelBuf CodingStructure::getBuf( const CompArea& blk, const PictureType type )
1052
17.2M
{
1053
17.2M
  if (!blk.valid())
1054
461k
  {
1055
461k
    return PelBuf();
1056
461k
  }
1057
1058
16.7M
  const ComponentID compID = blk.compID;
1059
1060
16.7M
  PelStorage* buf = type == PIC_PREDICTION ? &m_pred : ( type == PIC_RESIDUAL ? &m_resi : ( type == PIC_RECONSTRUCTION ? &m_reco : nullptr ) );
1061
16.7M
  if (type == PIC_ORIGINAL)
1062
2.16M
  {
1063
2.16M
    buf = m_org;
1064
2.16M
  }
1065
14.5M
  else if( type == PIC_ORIGINAL_RSP)
1066
0
  {
1067
0
    buf = m_rsporg;
1068
0
  }
1069
14.5M
  else if (type == PIC_ORIGINAL_RSP_REC)
1070
0
  {
1071
0
    buf = &m_rspreco;
1072
0
  }
1073
1074
16.7M
  CHECK( !buf, "Unknown buffer requested" );
1075
1076
16.7M
  CHECKD( !area.blocks[compID].contains( blk ), "Buffer not contained in self requested" );
1077
1078
16.7M
  CompArea cFinal = blk;
1079
16.7M
  cFinal.relativeTo( area.blocks[compID] );
1080
1081
16.7M
  if( !parent && ( type == PIC_RESIDUAL || type == PIC_PREDICTION ) )
1082
34.1k
  {
1083
34.1k
    cFinal.x &= ( pcv->maxCUSizeMask >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
1084
34.1k
    cFinal.y &= ( pcv->maxCUSizeMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
1085
34.1k
  }
1086
1087
16.7M
  return buf->getBuf( cFinal );
1088
16.7M
}
1089
1090
const CPelBuf CodingStructure::getBuf( const CompArea& blk, const PictureType type ) const
1091
25.4k
{
1092
25.4k
  if (!blk.valid())
1093
0
  {
1094
0
    return PelBuf();
1095
0
  }
1096
1097
25.4k
  const ComponentID compID = blk.compID;
1098
1099
25.4k
  const PelStorage* buf = type == PIC_PREDICTION ? &m_pred : ( type == PIC_RESIDUAL ? &m_resi : ( type == PIC_RECONSTRUCTION ? &m_reco : nullptr ) );
1100
25.4k
  if (type == PIC_ORIGINAL)
1101
25.4k
  {
1102
25.4k
    buf = m_org;
1103
25.4k
  }
1104
0
  else if( type == PIC_ORIGINAL_RSP)
1105
0
  {
1106
0
    buf = m_rsporg;
1107
0
  }
1108
0
  else if (type == PIC_ORIGINAL_RSP_REC)
1109
0
  {
1110
0
    buf = &m_rspreco;
1111
0
  }
1112
1113
25.4k
  CHECK( !buf, "Unknown buffer requested" );
1114
1115
25.4k
  CHECKD( !area.blocks[compID].contains( blk ), "Buffer not contained in self requested" );
1116
1117
25.4k
  CompArea cFinal = blk;
1118
25.4k
  cFinal.relativeTo( area.blocks[compID] );
1119
1120
25.4k
  if( !parent && ( type == PIC_RESIDUAL || type == PIC_PREDICTION ) )
1121
0
  {
1122
0
    cFinal.x &= ( pcv->maxCUSizeMask >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
1123
0
    cFinal.y &= ( pcv->maxCUSizeMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
1124
0
  }
1125
1126
25.4k
  return buf->getBuf( cFinal );
1127
25.4k
}
1128
1129
PelUnitBuf CodingStructure::getBuf( const UnitArea& unit, const PictureType type )
1130
436k
{
1131
  // no parent fetching for buffers
1132
436k
  if( area.chromaFormat == CHROMA_400 )
1133
0
  {
1134
0
    return PelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ) );
1135
0
  }
1136
436k
  else
1137
436k
  {
1138
436k
    return PelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ), getBuf( unit.Cb(), type ), getBuf( unit.Cr(), type ) );
1139
436k
  }
1140
436k
}
1141
1142
const CPelUnitBuf CodingStructure::getBuf( const UnitArea& unit, const PictureType type ) const
1143
0
{
1144
  // no parent fetching for buffers
1145
0
  if( area.chromaFormat == CHROMA_400 )
1146
0
  {
1147
0
    return CPelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ) );
1148
0
  }
1149
0
  else
1150
0
  {
1151
0
    return CPelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ), getBuf( unit.Cb(), type ), getBuf( unit.Cr(), type ) );
1152
0
  }
1153
0
}
1154
1155
const CodingUnit* CodingStructure::getCURestricted( const Position& pos, const CodingUnit& curCu, const ChannelType _chType ) const
1156
1.85M
{
1157
1.85M
  const int csx    = getChannelTypeScaleX( _chType, area.chromaFormat );
1158
1.85M
  const int csy    = getChannelTypeScaleY( _chType, area.chromaFormat );
1159
1.85M
  const int xshift = pcv->maxCUSizeLog2 - csx;
1160
1.85M
  const int yshift = pcv->maxCUSizeLog2 - csy;
1161
1.85M
  const int ydiff  = ( pos.y >> yshift ) - ( curCu.blocks[_chType].y >> yshift );
1162
1.85M
  const int xdiff  = ( pos.x >> xshift ) - ( curCu.blocks[_chType].x >> xshift );
1163
1164
1.85M
  if( !xdiff && !ydiff )
1165
797k
  {
1166
797k
    const CodingUnit* cu = getCU( pos, _chType, curCu.treeType );
1167
1168
797k
    return ( cu && ( cu->cs != curCu.cs || cu->idx <= curCu.idx ) ) ? cu : nullptr;
1169
797k
  }
1170
1171
1.05M
  if( ydiff > 0 || ( ydiff == 0 && xdiff > 0 ) || ( ydiff == -1 && xdiff > ( sps->entropyCodingSyncEnabled ? 0 : 1 ) ) )
1172
27.6k
    return nullptr;
1173
1174
1.02M
  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;
1175
1176
239k
  const CodingUnit* cu = getCU( pos, _chType, curCu.treeType );
1177
1178
239k
  return ( cu && CU::isSameSlice( *cu, curCu ) ) ? cu : nullptr;
1179
1.02M
}
1180
1181
const CodingUnit *CodingStructure::getCURestricted( const Position &pos, const Position curPos, const unsigned curSliceIdx, const unsigned curTileIdx, const ChannelType _chType, const TreeType _treeType ) const
1182
2.28M
{
1183
2.28M
  const int csx    = getChannelTypeScaleX( _chType, area.chromaFormat );
1184
2.28M
  const int csy    = getChannelTypeScaleY( _chType, area.chromaFormat );
1185
2.28M
  const int xshift = pcv->maxCUSizeLog2 - csx;
1186
2.28M
  const int yshift = pcv->maxCUSizeLog2 - csy;
1187
2.28M
  const int ydiff  = ( pos.y >> yshift ) - ( curPos.y >> yshift );
1188
2.28M
  const int xdiff  = ( pos.x >> xshift ) - ( curPos.x >> xshift );
1189
1190
2.28M
  if( !xdiff && !ydiff )
1191
724k
  {
1192
724k
    return getCU( pos, _chType, _treeType );
1193
724k
  }
1194
1195
1.56M
  if( ydiff > 0 || ( ydiff == 0 && xdiff > 0 ) || ( ydiff == -1 && xdiff > ( sps->entropyCodingSyncEnabled ? 0 : 1 ) ) )
1196
30.1k
    return nullptr;
1197
1198
1.53M
  if( pos.x < 0 || pos.y < 0 || ( pos.x << csx ) >= pcv->lumaWidth || pps->getTileIdx( pos.x >> xshift, pos.y >> yshift ) != curTileIdx ) return nullptr;
1199
1200
601k
  const CodingUnit* cu = getCU( pos, _chType, _treeType );
1201
1202
601k
  return ( cu && cu->slice->independentSliceIdx == curSliceIdx && cu->tileIdx == curTileIdx ) ? cu : nullptr;
1203
1.53M
}
1204
1205
const TransformUnit* CodingStructure::getTURestricted( const Position& pos, const TransformUnit& curTu, const ChannelType _chType ) const
1206
0
{
1207
0
  if( sps->entropyCodingSyncEnabled )
1208
0
  {
1209
0
    const int xshift = pcv->maxCUSizeLog2 - getChannelTypeScaleX( _chType, curTu.chromaFormat );
1210
0
    const int yshift = pcv->maxCUSizeLog2 - getChannelTypeScaleY( _chType, curTu.chromaFormat );
1211
0
    if( (pos.x >> xshift) > (curTu.blocks[_chType].x >> xshift) || (pos.y >> yshift) > (curTu.blocks[_chType].y >> yshift) )
1212
0
      return nullptr;
1213
0
  }
1214
0
  const TransformUnit* tu = getTU( pos, _chType );
1215
0
  return ( tu && CU::isSameSliceAndTile( *tu->cu, *curTu.cu ) && ( tu->cs != curTu.cs || tu->idx <= curTu.idx ) ) ? tu : nullptr;
1216
0
}
1217
1218
} // namespace vvenc
1219
1220
//! \}
1221