Coverage Report

Created: 2026-09-02 06:43

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