Coverage Report

Created: 2026-08-31 06:22

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