Coverage Report

Created: 2026-09-01 06:57

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