Coverage Report

Created: 2026-09-14 06:44

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
576k
  : area            ()
66
576k
  , picture         ( nullptr )
67
576k
  , parent          ( nullptr )
68
576k
  , lumaCS          ( nullptr )
69
576k
  , picHeader       ( nullptr )
70
576k
  , m_isTuEnc       ( false )
71
576k
  , m_cuCache       ( unitCache.cuCache )
72
576k
  , m_tuCache       ( unitCache.tuCache )
73
576k
  , m_unitCacheMutex( mutex )
74
576k
  , bestParent      ( nullptr )
75
576k
  , resetIBCBuffer  ( false )
76
576k
{
77
2.30M
  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
576k
  m_motionBuf = nullptr;
94
95
576k
  m_numTUs = m_numCUs = 0;
96
576k
}
97
98
void CodingStructure::destroy()
99
557k
{
100
557k
  picture   = nullptr;
101
557k
  parent    = nullptr;
102
557k
  lumaCS     = nullptr;
103
104
557k
  m_pred.destroy();
105
557k
  m_resi.destroy();
106
557k
  m_reco.destroy();
107
557k
  m_rspreco.destroy();
108
557k
  m_org = nullptr;
109
557k
  m_filtorg = nullptr;
110
111
557k
  destroyCoeffs();
112
557k
  delete[] m_motionBuf;
113
557k
  m_motionBuf = nullptr;
114
115
557k
  destroyTempBuffers();
116
117
557k
  if ( m_unitCacheMutex ) m_unitCacheMutex->lock();
118
119
557k
  m_tuCache.cache( tus );
120
557k
  m_cuCache.cache( cus );
121
122
557k
  if ( m_unitCacheMutex ) m_unitCacheMutex->unlock();
123
557k
}
124
125
void CodingStructure::releaseIntermediateData()
126
452k
{
127
452k
  clearTUs();
128
452k
  clearCUs();
129
452k
}
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.98M
  while (cs && !cs->area.blocks[effChType].contains(pos)) cs = cs->parent;
146
147
5.02M
  if (!cs)
148
267
  {
149
267
    return nullptr;
150
267
  }
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.94M
{
160
2.94M
  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.94M
  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.94M
  if (!cs)
166
14.8k
  {
167
14.8k
    return nullptr;
168
14.8k
  }
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.94M
}
175
176
TransformUnit* CodingStructure::getTU( const Position& pos, const ChannelType effChType, const int subTuIdx )
177
1.59M
{
178
1.59M
  const CompArea& _blk = area.blocks[effChType];
179
180
1.59M
  if( !_blk.contains( pos ) )
181
0
  {
182
0
    if( parent ) return parent->getTU( pos, effChType );
183
0
    else         return nullptr;
184
0
  }
185
1.59M
  else
186
1.59M
  {
187
1.59M
    CodingUnit* cu = m_cuPtr[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
188
1.59M
    if( !cu ) return nullptr;
189
190
1.59M
    TransformUnit* ptu = cu->firstTU;
191
192
1.62M
    while( ptu && !ptu->blocks[effChType].contains( pos ) )
193
25.0k
    {
194
25.0k
      ptu = ptu->next;
195
25.0k
    }
196
197
1.59M
    return ptu;
198
1.59M
  }
199
1.59M
}
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
437k
{
228
437k
  CodingUnit* cu;
229
230
437k
  if( cuInit )
231
150k
  {
232
150k
    cu = cuInit;
233
150k
  }
234
286k
  else
235
286k
  {
236
286k
    if( m_unitCacheMutex ) m_unitCacheMutex->lock();
237
238
286k
    cu = m_cuCache.get();
239
240
286k
    if( m_unitCacheMutex ) m_unitCacheMutex->unlock();
241
242
286k
    cu->UnitArea::operator=( unit );
243
286k
    cu->initData();
244
286k
    cu->slice   = nullptr;
245
286k
  }
246
  
247
437k
  cu->next      = nullptr;
248
437k
  cu->firstTU   = nullptr;
249
437k
  cu->lastTU    = nullptr;
250
437k
  cu->chType    = chType;
251
437k
  cu->cs        = this;
252
253
437k
  CodingUnit *prevCU = m_numCUs > 0 ? cus.back() : nullptr;
254
255
437k
  if( prevCU )
256
121k
  {
257
121k
    const int prevCuCtuRsAddr = getCtuAddr( recalcPosition( area.chromaFormat, prevCU->chType, CH_L, prevCU->blocks[prevCU->chType] ), *pcv );
258
121k
    const int currCuCtuRsAddr = getCtuAddr( recalcPosition( area.chromaFormat,         chType, CH_L,     cu->blocks[        chType] ), *pcv );
259
260
121k
    if( prevCuCtuRsAddr == currCuCtuRsAddr )
261
119k
    {
262
119k
      prevCU->next = cu;
263
119k
    }
264
121k
  }
265
266
437k
  cus.push_back( cu );
267
268
437k
  Mv* prevCuMvd = cuInit ? cuInit->mvdL0SubPu : nullptr;
269
  
270
437k
  cu->idx        = ++m_numCUs;
271
437k
  cu->mvdL0SubPu = nullptr;
272
273
437k
  if( isLuma( chType ) && unit.lheight() >= 8 && unit.lwidth() >= 8 && unit.Y().area() >= 128 )
274
274k
  {
275
274k
    CHECKD( m_dmvrMvCacheOffset >= m_dmvrMvCache.size(), "dmvr cache offset out of bounds" );
276
277
274k
    int mvdArrSize       = std::max<int>( 1, unit.lwidth() >> DMVR_SUBCU_SIZE_LOG2 ) * std::max<int>( 1, unit.lheight() >> DMVR_SUBCU_SIZE_LOG2 );
278
274k
    cu->mvdL0SubPu       = &m_dmvrMvCache[m_dmvrMvCacheOffset];
279
274k
    m_dmvrMvCacheOffset += mvdArrSize;
280
281
274k
    if( prevCuMvd )
282
64.5k
      memcpy( cu->mvdL0SubPu, prevCuMvd, sizeof( Mv ) * mvdArrSize );
283
274k
  }
284
285
437k
  uint32_t numCh = getNumberValidChannels( area.chromaFormat );
286
287
1.31M
  for( uint32_t i = 0; i < numCh; i++ )
288
874k
  {
289
874k
    if( !cu->blocks[i].valid() )
290
437k
    {
291
437k
      continue;
292
437k
    }
293
294
437k
    const CompArea& _selfBlk = area.blocks[i];
295
437k
    const CompArea     &_blk = cu-> blocks[i];
296
297
437k
    const UnitScale& scale = unitScale[_blk.compID];
298
437k
    const Area scaledSelf  = scale.scale( _selfBlk );
299
437k
    const Area scaledBlk   = scale.scale(     _blk );
300
437k
    CodingUnit **cuPtr     = m_cuPtr[i] + rsAddr( scaledBlk.pos(), scaledSelf.pos(), scaledSelf.width );
301
302
437k
    CHECKD( *cuPtr, "Overwriting a pre-existing value, should be '0'!" );
303
304
437k
    g_pelBufOP.fillPtrMap( ( void** ) cuPtr, scaledSelf.width, scaledBlk.width, scaledBlk.height, ( void* ) cu );
305
437k
  }
306
307
437k
  return *cu;
308
437k
}
309
310
TransformUnit& CodingStructure::addTU( const UnitArea& unit, const ChannelType chType, CodingUnit* cu, TransformUnit* tuInit )
311
515k
{
312
515k
  TransformUnit* tu;
313
314
515k
  if( tuInit )
315
175k
  {
316
175k
    tu = tuInit;
317
175k
  }
318
339k
  else
319
339k
  {
320
339k
    if( m_unitCacheMutex ) m_unitCacheMutex->lock();
321
322
339k
    tu = m_tuCache.get();
323
324
339k
    if( m_unitCacheMutex ) m_unitCacheMutex->unlock();
325
326
339k
    tu->UnitArea::operator=( unit );
327
339k
    tu->initData();
328
339k
  }
329
330
515k
  tu->next   = nullptr;
331
515k
  tu->prev   = nullptr;
332
515k
  tu->cs     = this;
333
515k
  tu->cu     = cu;
334
515k
  tu->chType = chType;
335
336
515k
  TransformUnit *prevTU = m_numTUs > 0 ? tus.back() : nullptr;
337
338
515k
  if( prevTU && prevTU->cu == tu->cu )
339
18.5k
  {
340
18.5k
    prevTU->next = tu;
341
18.5k
    tu->prev     = prevTU;
342
18.5k
  }
343
344
515k
  tus.push_back( tu );
345
346
515k
  if( tu->cu )
347
455k
  {
348
455k
    if( tu->cu->firstTU == nullptr )
349
431k
    {
350
431k
      tu->cu->firstTU = tu;
351
431k
    }
352
455k
    tu->cu->lastTU = tu;
353
455k
  }
354
355
515k
  uint32_t idx = ++m_numTUs;
356
515k
  tu->idx = idx;
357
358
515k
  TCoeffSig *coeffs[3] = { nullptr, nullptr, nullptr };
359
360
515k
  uint32_t numCh = getNumberValidComponents( area.chromaFormat );
361
362
2.06M
  for( uint32_t i = 0; i < numCh; i++ )
363
1.54M
  {
364
1.54M
    if( !tu->blocks[i].valid() )
365
810k
    {
366
810k
      continue;
367
810k
    }
368
369
735k
    coeffs[i] = m_coeffs[i] + m_offsets[i];
370
371
735k
    unsigned areaSize = tu->blocks[i].area();
372
735k
    m_offsets[i] += areaSize;
373
374
735k
    const bool cpyRsi = tuInit &&
375
260k
                      ( tuInit->cbf[i] ||
376
212k
                 ( i && tuInit->jointCbCr && numCh > 1 && ( TU::getCbf( *tuInit, COMP_Cb ) || TU::getCbf( *tuInit, COMP_Cr ) ) )
377
260k
                      );
378
379
735k
    if( cpyRsi )
380
48.0k
      memcpy( coeffs[i], tu->m_coeffs[i], areaSize * sizeof( TCoeffSig ) );
381
735k
  }
382
383
515k
  tu->init( coeffs );
384
385
515k
  return *tu;
386
515k
}
387
388
void CodingStructure::addEmptyTUs( Partitioner &partitioner, CodingUnit* cu )
389
22.3k
{
390
22.3k
  const UnitArea& area    = partitioner.currArea();
391
22.3k
  bool            split   = partitioner.canSplit(TU_MAX_TR_SPLIT, *this);
392
22.3k
  const unsigned  trDepth = partitioner.currTrDepth;
393
394
22.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
22.3k
  else
405
22.3k
  {
406
22.3k
    TransformUnit& tu = addTU(CS::getArea(*this, area, partitioner.chType, TreeType(partitioner.treeType)), partitioner.chType, cu);
407
22.3k
    tu.depth = trDepth;
408
22.3k
  }
409
22.3k
}
410
411
CUTraverser CodingStructure::traverseCUs( const UnitArea& unit, const ChannelType effChType )
412
7.69k
{
413
  //  CHECK( _treeType != treeType, "not good");
414
7.69k
  CodingUnit* firstCU = getCU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType, TREE_D );
415
7.69k
  CodingUnit* lastCU = firstCU;
416
7.69k
  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.69k
  else
448
7.69k
  {
449
39.5k
  do { } while( lastCU && (0 != ( lastCU = lastCU->next )) && unit.contains( *lastCU ) );
450
7.69k
  }
451
452
7.69k
  return CUTraverser( firstCU, lastCU );
453
7.69k
}
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.69k
{
489
7.69k
  return LFPBuf(m_lfParam[edgeDir], m_mapSize[0]);
490
7.69k
}
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.19k
{
502
1.19k
  const int  twice = ( !pcv->ISingleTree && slice->isIRAP() && pcv->chrFormat != CHROMA_400 ) ? 2 : 1;
503
1.19k
  size_t allocSize = twice * unitScale[0].scale( area.blocks[0].size() ).area();
504
505
1.19k
  cus.reserve( allocSize );
506
1.19k
  tus.reserve( allocSize );
507
1.19k
}
508
509
510
511
void CodingStructure::createForSearch( const ChromaFormat _chromaFormat, const Area& _area )
512
556k
{
513
556k
  createInternals( UnitArea( _chromaFormat, _area ), false );
514
515
556k
  m_reco.create( area );
516
556k
  m_pred.create( area );
517
556k
  m_resi.create( area );
518
556k
  m_rspreco.create( CHROMA_400, area.Y() );
519
556k
}
520
521
void CodingStructure::createPicLevel( const UnitArea& _unit, const PreCalcValues* _pcv )
522
1.19k
{
523
1.19k
  pcv = _pcv;
524
525
1.19k
  createInternals( _unit, true );
526
1.19k
}
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
557k
{
538
557k
  area     = _unit;
539
557k
  _maxArea = _unit;
540
541
557k
  unitScale[COMP_Y ] = UnitScale( UnitScaleArray[area.chromaFormat][COMP_Y ][0], UnitScaleArray[area.chromaFormat][COMP_Y ][1] );
542
557k
  unitScale[COMP_Cb] = UnitScale( UnitScaleArray[area.chromaFormat][COMP_Cb][0], UnitScaleArray[area.chromaFormat][COMP_Cb][1] );
543
557k
  unitScale[COMP_Cr] = UnitScale( UnitScaleArray[area.chromaFormat][COMP_Cr][0], UnitScaleArray[area.chromaFormat][COMP_Cr][1] );
544
545
557k
  picture = nullptr;
546
557k
  parent  = nullptr;
547
557k
  lumaCS  = nullptr;
548
549
557k
  unsigned _lumaAreaScaled = g_miScaling.scale( area.lumaSize() ).area();
550
557k
  m_motionBuf = new MotionInfo[_lumaAreaScaled];
551
552
557k
  if( isTopLayer )
553
1.19k
  {
554
1.19k
    motionLutBuf.resize( pps->getNumTileLineIds() );
555
1.19k
  }
556
556k
  else
557
556k
  {
558
556k
    createCoeffs();
559
556k
    createTempBuffers( false );
560
556k
    initStructData( MAX_INT, false, nullptr );
561
556k
  }
562
557k
}
563
564
void CodingStructure::createTempBuffers( const bool isTopLayer )
565
557k
{
566
557k
  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
557k
  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
557k
  unsigned _maxNumDmvrMvs = ( area.lwidth() >> 3 ) * ( area.lheight() >> 3 );
586
557k
  m_dmvrMvCache.resize( _maxNumDmvrMvs );
587
557k
}
588
589
void CodingStructure::destroyTempBuffers()
590
558k
{
591
1.67M
  for( uint32_t i = 0; i < MAX_NUM_CH; i++ )
592
1.11M
  {
593
1.11M
    delete[] m_cuPtr[i];
594
1.11M
    m_cuPtr[i] = nullptr;
595
1.11M
  }
596
597
1.67M
  for( int i = 0; i < NUM_EDGE_DIR; i++ )
598
1.11M
  {
599
1.11M
    xFree( m_lfParam[i] );
600
1.11M
    m_lfParam[i] = nullptr;
601
1.11M
  }
602
603
  // swap the contents of the vector so that memory released
604
558k
  std::vector<Mv>().swap( m_dmvrMvCache );
605
558k
  std::vector<CodingUnit*>().swap( cus );
606
558k
  std::vector<TransformUnit*>().swap( tus );
607
558k
}
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.39k
{
636
2.39k
  CHECK( parent, "rebindPicBufs can only be used for the top level CodingStructure" );
637
638
2.39k
  if( !picture->m_picBufs[ PIC_RECONSTRUCTION ].bufs.empty() ) m_reco.createFromBuf( picture->m_picBufs[ PIC_RECONSTRUCTION ] );
639
0
  else                                                         m_reco.destroy();
640
2.39k
  if( !picture->m_picBufs[ PIC_PREDICTION     ].bufs.empty() ) m_pred.createFromBuf( picture->m_picBufs[ PIC_PREDICTION ] );
641
2.39k
  else                                                         m_pred.destroy();
642
2.39k
  if( !picture->m_picBufs[ PIC_RESIDUAL       ].bufs.empty() ) m_resi.createFromBuf( picture->m_picBufs[ PIC_RESIDUAL ] );
643
2.39k
  else                                                         m_resi.destroy();
644
2.39k
}
645
646
void CodingStructure::createCoeffs()
647
557k
{
648
557k
  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
557k
}
660
661
void CodingStructure::destroyCoeffs()
662
558k
{
663
2.23M
  for( uint32_t i = 0; i < MAX_NUM_COMP; i++ )
664
1.67M
  {
665
1.67M
    if( m_coeffs[i] ) { xFree( m_coeffs[i] ); m_coeffs[i] = nullptr; }
666
1.67M
  }
667
558k
}
668
669
void CodingStructure::initSubStructure( CodingStructure& subStruct, const ChannelType _chType, const UnitArea& subArea, const bool isTuEnc, PelStorage* pOrgBuffer, PelStorage* pFiltOrgBuffer )
670
374k
{
671
374k
  CHECK( this == &subStruct, "Trying to init self as sub-structure" );
672
673
374k
  subStruct.parent = this;
674
675
374k
  if( pOrgBuffer ) pOrgBuffer->compactResize( subArea );
676
374k
  UnitArea subAreaLuma = subArea;
677
374k
  subAreaLuma.blocks.resize( 1 );
678
374k
  if( pFiltOrgBuffer ) pFiltOrgBuffer->compactResize( subAreaLuma );
679
680
374k
  subStruct.m_org    = (pOrgBuffer) ? pOrgBuffer : m_org;
681
374k
  subStruct.m_filtorg = (pFiltOrgBuffer) ? pFiltOrgBuffer : m_filtorg;
682
374k
  subStruct.compactResize( subArea );
683
684
374k
  subStruct.costDbOffset = 0;
685
686
374k
  if( parent )
687
359k
  {
688
    // allow this to be false at the top level (need for edge CTU's)
689
359k
    CHECKD( !area.contains( subArea ), "Trying to init sub-structure not contained in the parent" );
690
359k
  }
691
692
374k
  subStruct.parent    = this;
693
374k
  subStruct.picture   = picture;
694
374k
  subStruct.lumaCS    = picture->cs;
695
696
374k
  subStruct.sps       = sps;
697
374k
  subStruct.vps       = vps;
698
374k
  subStruct.pps       = pps;
699
374k
  subStruct.picHeader = picHeader;
700
701
374k
  memcpy(subStruct.alfAps, alfAps, sizeof(alfAps));
702
703
374k
  subStruct.slice     = slice;
704
374k
  subStruct.baseQP    = baseQP;
705
374k
  subStruct.prevQP[_chType]
706
374k
                      = prevQP[_chType];
707
374k
  subStruct.pcv       = pcv;
708
709
374k
  subStruct.m_isTuEnc = isTuEnc;
710
711
374k
  if( nullptr == parent )
712
15.3k
  {
713
15.3k
    const int ctuPosX = subArea.lx() >> pcv->maxCUSizeLog2;
714
15.3k
    const int ctuPosY = subArea.ly() >> pcv->maxCUSizeLog2;
715
15.3k
    subStruct.motionLut = motionLutBuf[pps->getTileLineId( ctuPosX, ctuPosY )];
716
15.3k
  }
717
359k
  else
718
359k
  {
719
359k
    subStruct.motionLut = motionLut;
720
359k
  }
721
722
374k
  subStruct.initStructData( currQP[_chType] );
723
724
374k
  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
374k
}
736
737
void CodingStructure::useSubStructure( CodingStructure& subStruct, const ChannelType chType, const TreeType _treeType, const UnitArea& subArea, const bool cpyRecoToPic )
738
154k
{
739
154k
  UnitArea clippedArea = clipArea( subArea, *picture );
740
741
154k
  CPelUnitBuf subRecoBuf = subStruct.getRecoBuf( clippedArea );
742
743
154k
  if( parent )
744
147k
  {
745
    // copy data to picture
746
147k
    getRecoBuf( clippedArea ).copyFrom( subRecoBuf );
747
147k
  }
748
749
154k
  if( cpyRecoToPic )
750
122k
  {
751
122k
    picture->getRecoBuf( clippedArea ).copyFrom( subRecoBuf );
752
122k
  }
753
754
154k
  if( !subStruct.m_isTuEnc && ( ( !slice->isIntra() || slice->sps->IBC ) && chType != CH_C ) )
755
51.8k
  {
756
    // copy motion buffer
757
51.8k
    MotionBuf ownMB  = getMotionBuf          ( clippedArea );
758
51.8k
    CMotionBuf subMB = subStruct.getMotionBuf( clippedArea );
759
760
51.8k
    ownMB.copyFrom( subMB );
761
762
51.8k
    if( nullptr == parent )
763
3.84k
    {
764
3.84k
      const int ctuPosX = subStruct.area.lx() >> pcv->maxCUSizeLog2;
765
3.84k
      const int ctuPosY = subStruct.area.ly() >> pcv->maxCUSizeLog2;
766
3.84k
      motionLutBuf[pps->getTileLineId( ctuPosX, ctuPosY )] = subStruct.motionLut;
767
3.84k
    }
768
47.9k
    else
769
47.9k
    {
770
47.9k
      motionLut = subStruct.motionLut;
771
47.9k
    }
772
51.8k
  }
773
774
154k
  fracBits += subStruct.fracBits;
775
154k
  dist     += subStruct.dist;
776
154k
  cost     += subStruct.cost;
777
154k
  costDbOffset += subStruct.costDbOffset;
778
779
154k
  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
154k
  if( subStruct.m_isTuEnc )
787
25.1k
  {
788
    // don't copy if the substruct was created for encoding of the TUs
789
25.1k
  }
790
129k
  else
791
129k
  {
792
129k
    if( &m_cuCache == &subStruct.m_cuCache )
793
121k
    {
794
      // copy the CUs over with taking ownership
795
121k
      for( const auto& pcu : subStruct.cus )
796
150k
      {
797
        // add an analogue CU into own CU store
798
150k
        const UnitArea& cuPatch = *pcu;
799
150k
        addCU( cuPatch, pcu->chType, pcu );
800
150k
      }
801
802
121k
      subStruct.cus.resize( 0 );
803
121k
    }
804
7.70k
    else
805
7.70k
    {
806
      // copy the CUs over
807
7.70k
      for( const auto& pcu : subStruct.cus )
808
39.6k
      {
809
        // add an analogue CU into own CU store
810
39.6k
        const UnitArea& cuPatch = *pcu;
811
812
39.6k
        CodingUnit& cu = addCU( cuPatch, pcu->chType );
813
814
        // copy the CU info from subPatch
815
39.6k
        cu = *pcu;
816
39.6k
      }
817
7.70k
    }
818
129k
  }
819
820
154k
  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
175k
    {
825
      // add an analogue TU into own TU store
826
175k
      const UnitArea& tuPatch = *ptu;
827
175k
      addTU( tuPatch, ptu->chType, getCU( tuPatch.blocks[ptu->chType].pos(), ptu->chType, _treeType ), ptu );
828
175k
    }
829
830
147k
    subStruct.tus.resize( 0 );
831
147k
  }
832
7.70k
  else
833
7.70k
  {
834
    // copy the TUs over
835
7.70k
    for( const auto& ptu : subStruct.tus )
836
39.6k
    {
837
      // add an analogue TU into own TU store
838
39.6k
      const UnitArea& tuPatch = *ptu;
839
840
39.6k
      TransformUnit& tu = addTU( tuPatch, ptu->chType, getCU( tuPatch.blocks[ptu->chType], ptu->chType, _treeType ) );
841
842
      // copy the TU info from subPatch
843
39.6k
      tu = *ptu;
844
39.6k
    }
845
7.70k
  }
846
154k
}
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
424k
{
921
424k
  UnitArea areaLuma = _area;
922
424k
  areaLuma.blocks.resize( 1 );
923
924
424k
  m_pred   .compactResize( _area );
925
424k
  m_reco   .compactResize( _area );
926
424k
  m_resi   .compactResize( _area );
927
424k
  m_rspreco.compactResize( areaLuma );
928
929
1.69M
  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
424k
  area = _area;
935
424k
}
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
710k
  {
946
710k
    currQP[0] = currQP[1] = QP;
947
710k
  }
948
949
1.37M
  if( !skipMotBuf && ( !parent || ( ( !slice->isIntra() || slice->sps->IBC ) && !m_isTuEnc ) ) )
950
639k
  {
951
639k
    getMotionBuf().memset( -1 );
952
639k
  }
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
302k
  {
975
302k
    pcu->firstTU = pcu->lastTU = nullptr;
976
302k
  }
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.38M
{
987
2.38M
  if( !m_numCUs && !force ) return;
988
989
871k
  int numCh = getNumberValidChannels( area.chromaFormat );
990
2.61M
  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
871k
  if ( m_unitCacheMutex ) m_unitCacheMutex->lock();
996
871k
  m_cuCache.cache( cus );
997
871k
  if ( m_unitCacheMutex ) m_unitCacheMutex->unlock();
998
999
871k
  m_numCUs = 0;
1000
871k
}
1001
1002
MotionBuf CodingStructure::getMotionBuf( const Area& _area )
1003
769k
{
1004
769k
  const CompArea& _luma = area.Y();
1005
1006
769k
  CHECKD( !_luma.contains( _area ), "Trying to access motion information outside of this coding structure" );
1007
1008
769k
  const Area miArea   = g_miScaling.scale( _area );
1009
769k
  const Area selfArea = g_miScaling.scale( _luma );
1010
1011
769k
  return MotionBuf( m_motionBuf + rsAddr( miArea.pos(), selfArea.pos(), selfArea.width ), selfArea.width, miArea.size() );
1012
769k
}
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.6M
{
1050
18.6M
  if (!blk.valid())
1051
502k
  {
1052
502k
    return PelBuf();
1053
502k
  }
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.34M
  {
1060
2.34M
    buf = m_org;
1061
2.34M
  }
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
36.7k
  {
1076
36.7k
    cFinal.x &= ( pcv->maxCUSizeMask >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
1077
36.7k
    cFinal.y &= ( pcv->maxCUSizeMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
1078
36.7k
  }
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.2k
{
1085
28.2k
  if (!blk.valid())
1086
0
  {
1087
0
    return PelBuf();
1088
0
  }
1089
1090
28.2k
  const ComponentID compID = blk.compID;
1091
1092
28.2k
  const PelStorage* buf = type == PIC_PREDICTION ? &m_pred : ( type == PIC_RESIDUAL ? &m_resi : ( type == PIC_RECONSTRUCTION ? &m_reco : nullptr ) );
1093
28.2k
  if (type == PIC_ORIGINAL)
1094
28.2k
  {
1095
28.2k
    buf = m_org;
1096
28.2k
  }
1097
0
  else if( type == PIC_FILT_ORIGINAL)
1098
0
  {
1099
0
    buf = m_filtorg;
1100
0
  }
1101
1102
28.2k
  CHECK( !buf, "Unknown buffer requested" );
1103
1104
28.2k
  CHECKD( !area.blocks[compID].contains( blk ), "Buffer not contained in self requested" );
1105
1106
28.2k
  CompArea cFinal = blk;
1107
28.2k
  cFinal.relativeTo( area.blocks[compID] );
1108
1109
28.2k
  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.2k
  return buf->getBuf( cFinal );
1116
28.2k
}
1117
1118
PelUnitBuf CodingStructure::getBuf( const UnitArea& unit, const PictureType type )
1119
475k
{
1120
  // no parent fetching for buffers
1121
475k
  if( area.chromaFormat == CHROMA_400 )
1122
0
  {
1123
0
    return PelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ) );
1124
0
  }
1125
475k
  else
1126
475k
  {
1127
475k
    return PelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ), getBuf( unit.Cb(), type ), getBuf( unit.Cr(), type ) );
1128
475k
  }
1129
475k
}
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
863k
  {
1155
863k
    const CodingUnit* cu = getCU( pos, _chType, curCu.treeType );
1156
1157
863k
    return ( cu && ( cu->cs != curCu.cs || cu->idx <= curCu.idx ) ) ? cu : nullptr;
1158
863k
  }
1159
1160
1.15M
  if( ydiff > 0 || ( ydiff == 0 && xdiff > 0 ) || ( ydiff == -1 && xdiff > ( sps->entropyCodingSyncEnabled ? 0 : 1 ) ) )
1161
31.0k
    return nullptr;
1162
1163
1.12M
  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
270k
  const CodingUnit* cu = getCU( pos, _chType, curCu.treeType );
1166
1167
270k
  return ( cu && CU::isSameSlice( *cu, curCu ) ) ? cu : nullptr;
1168
1.12M
}
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.51M
{
1172
2.51M
  const int csx    = getChannelTypeScaleX( _chType, area.chromaFormat );
1173
2.51M
  const int csy    = getChannelTypeScaleY( _chType, area.chromaFormat );
1174
2.51M
  const int xshift = pcv->maxCUSizeLog2 - csx;
1175
2.51M
  const int yshift = pcv->maxCUSizeLog2 - csy;
1176
2.51M
  const int ydiff  = ( pos.y >> yshift ) - ( curPos.y >> yshift );
1177
2.51M
  const int xdiff  = ( pos.x >> xshift ) - ( curPos.x >> xshift );
1178
1179
2.51M
  if( !xdiff && !ydiff )
1180
785k
  {
1181
785k
    return getCU( pos, _chType, _treeType );
1182
785k
  }
1183
1184
1.72M
  if( ydiff > 0 || ( ydiff == 0 && xdiff > 0 ) || ( ydiff == -1 && xdiff > ( sps->entropyCodingSyncEnabled ? 0 : 1 ) ) )
1185
33.5k
    return nullptr;
1186
1187
1.69M
  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
679k
  const CodingUnit* cu = getCU( pos, _chType, _treeType );
1190
1191
679k
  return ( cu && cu->slice->independentSliceIdx == curSliceIdx && cu->tileIdx == curTileIdx ) ? cu : nullptr;
1192
1.69M
}
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