Coverage Report

Created: 2026-06-15 06:25

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