Coverage Report

Created: 2026-07-16 06:32

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