Coverage Report

Created: 2026-09-13 06:34

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