Coverage Report

Created: 2026-05-30 06:10

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