Coverage Report

Created: 2026-08-13 07:23

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
577k
  : area            ()
66
577k
  , picture         ( nullptr )
67
577k
  , parent          ( nullptr )
68
577k
  , lumaCS          ( nullptr )
69
577k
  , picHeader       ( nullptr )
70
577k
  , m_isTuEnc       ( false )
71
577k
  , m_cuCache       ( unitCache.cuCache )
72
577k
  , m_tuCache       ( unitCache.tuCache )
73
577k
  , m_unitCacheMutex( mutex )
74
577k
  , bestParent      ( nullptr )
75
577k
  , resetIBCBuffer  ( false )
76
577k
{
77
2.30M
  for( uint32_t i = 0; i < MAX_NUM_COMP; i++ )
78
1.73M
  {
79
1.73M
    m_coeffs[ i ] = nullptr;
80
1.73M
    m_offsets[ i ] = 0;
81
1.73M
  }
82
83
1.73M
  for( uint32_t i = 0; i < MAX_NUM_CH; i++ )
84
1.15M
  {
85
1.15M
    m_cuPtr   [ i ] = nullptr;
86
1.15M
  }
87
88
1.73M
  for( int i = 0; i < NUM_EDGE_DIR; i++ )
89
1.15M
  {
90
1.15M
    m_lfParam [ i ] = nullptr;
91
1.15M
  }
92
93
577k
  m_motionBuf = nullptr;
94
95
577k
  m_numTUs = m_numCUs = 0;
96
577k
}
97
98
void CodingStructure::destroy()
99
558k
{
100
558k
  picture   = nullptr;
101
558k
  parent    = nullptr;
102
558k
  lumaCS     = nullptr;
103
104
558k
  m_pred.destroy();
105
558k
  m_resi.destroy();
106
558k
  m_reco.destroy();
107
558k
  m_rspreco.destroy();
108
558k
  m_org = nullptr;
109
558k
  m_filtorg = nullptr;
110
111
558k
  destroyCoeffs();
112
558k
  delete[] m_motionBuf;
113
558k
  m_motionBuf = nullptr;
114
115
558k
  destroyTempBuffers();
116
117
558k
  if ( m_unitCacheMutex ) m_unitCacheMutex->lock();
118
119
558k
  m_tuCache.cache( tus );
120
558k
  m_cuCache.cache( cus );
121
122
558k
  if ( m_unitCacheMutex ) m_unitCacheMutex->unlock();
123
558k
}
124
125
void CodingStructure::releaseIntermediateData()
126
457k
{
127
457k
  clearTUs();
128
457k
  clearCUs();
129
457k
}
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.06M
{
142
5.06M
  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.06M
  CodingStructure* cs = _treeType == TREE_C && effChType == CH_L ? parent : this;
145
6.03M
  while (cs && !cs->area.blocks[effChType].contains(pos)) cs = cs->parent;
146
147
5.06M
  if (!cs)
148
203
  {
149
203
    return nullptr;
150
203
  }
151
5.06M
  else
152
5.06M
  {
153
5.06M
    const Area& _blk = cs->area.blocks[effChType];
154
5.06M
    return cs->m_cuPtr[effChType][rsAddr(pos, _blk.pos(), _blk.width, unitScale[effChType])];
155
5.06M
  }
156
5.06M
}
157
158
const CodingUnit* CodingStructure::getCU( const Position& pos, const ChannelType effChType, const TreeType _treeType ) const
159
2.97M
{
160
2.97M
  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.97M
  const CodingStructure* cs = _treeType == TREE_C && effChType == CH_L ? parent : this;
163
7.02M
  while (cs && !cs->area.blocks[effChType].contains(pos)) cs = cs->parent;
164
165
2.97M
  if (!cs)
166
14.8k
  {
167
14.8k
    return nullptr;
168
14.8k
  }
169
2.96M
  else
170
2.96M
  {
171
2.96M
    const Area& _blk = cs->area.blocks[effChType];
172
2.96M
    return cs->m_cuPtr[effChType][rsAddr( pos, _blk.pos(), _blk.width, unitScale[effChType] )];
173
2.96M
  }
174
2.97M
}
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.63M
    while( ptu && !ptu->blocks[effChType].contains( pos ) )
193
24.7k
    {
194
24.7k
      ptu = ptu->next;
195
24.7k
    }
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
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
210
    {
219
210
      ptu = ptu->next;
220
210
    }
221
222
163k
    return ptu;
223
163k
  }
224
163k
}
225
226
CodingUnit& CodingStructure::addCU( const UnitArea& unit, const ChannelType chType, CodingUnit* cuInit )
227
442k
{
228
442k
  CodingUnit* cu;
229
230
442k
  if( cuInit )
231
152k
  {
232
152k
    cu = cuInit;
233
152k
  }
234
290k
  else
235
290k
  {
236
290k
    if( m_unitCacheMutex ) m_unitCacheMutex->lock();
237
238
290k
    cu = m_cuCache.get();
239
240
290k
    if( m_unitCacheMutex ) m_unitCacheMutex->unlock();
241
242
290k
    cu->UnitArea::operator=( unit );
243
290k
    cu->initData();
244
290k
    cu->slice   = nullptr;
245
290k
  }
246
  
247
442k
  cu->next      = nullptr;
248
442k
  cu->firstTU   = nullptr;
249
442k
  cu->lastTU    = nullptr;
250
442k
  cu->chType    = chType;
251
442k
  cu->cs        = this;
252
253
442k
  CodingUnit *prevCU = m_numCUs > 0 ? cus.back() : nullptr;
254
255
442k
  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
121k
    {
262
121k
      prevCU->next = cu;
263
121k
    }
264
123k
  }
265
266
442k
  cus.push_back( cu );
267
268
442k
  Mv* prevCuMvd = cuInit ? cuInit->mvdL0SubPu : nullptr;
269
  
270
442k
  cu->idx        = ++m_numCUs;
271
442k
  cu->mvdL0SubPu = nullptr;
272
273
442k
  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.3k
      memcpy( cu->mvdL0SubPu, prevCuMvd, sizeof( Mv ) * mvdArrSize );
283
276k
  }
284
285
442k
  uint32_t numCh = getNumberValidChannels( area.chromaFormat );
286
287
1.32M
  for( uint32_t i = 0; i < numCh; i++ )
288
885k
  {
289
885k
    if( !cu->blocks[i].valid() )
290
442k
    {
291
442k
      continue;
292
442k
    }
293
294
442k
    const CompArea& _selfBlk = area.blocks[i];
295
442k
    const CompArea     &_blk = cu-> blocks[i];
296
297
442k
    const UnitScale& scale = unitScale[_blk.compID];
298
442k
    const Area scaledSelf  = scale.scale( _selfBlk );
299
442k
    const Area scaledBlk   = scale.scale(     _blk );
300
442k
    CodingUnit **cuPtr     = m_cuPtr[i] + rsAddr( scaledBlk.pos(), scaledSelf.pos(), scaledSelf.width );
301
302
442k
    CHECKD( *cuPtr, "Overwriting a pre-existing value, should be '0'!" );
303
304
442k
    g_pelBufOP.fillPtrMap( ( void** ) cuPtr, scaledSelf.width, scaledBlk.width, scaledBlk.height, ( void* ) cu );
305
442k
  }
306
307
442k
  return *cu;
308
442k
}
309
310
TransformUnit& CodingStructure::addTU( const UnitArea& unit, const ChannelType chType, CodingUnit* cu, TransformUnit* tuInit )
311
521k
{
312
521k
  TransformUnit* tu;
313
314
521k
  if( tuInit )
315
178k
  {
316
178k
    tu = tuInit;
317
178k
  }
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
521k
  tu->next   = nullptr;
331
521k
  tu->prev   = nullptr;
332
521k
  tu->cs     = this;
333
521k
  tu->cu     = cu;
334
521k
  tu->chType = chType;
335
336
521k
  TransformUnit *prevTU = m_numTUs > 0 ? tus.back() : nullptr;
337
338
521k
  if( prevTU && prevTU->cu == tu->cu )
339
18.4k
  {
340
18.4k
    prevTU->next = tu;
341
18.4k
    tu->prev     = prevTU;
342
18.4k
  }
343
344
521k
  tus.push_back( tu );
345
346
521k
  if( tu->cu )
347
460k
  {
348
460k
    if( tu->cu->firstTU == nullptr )
349
437k
    {
350
437k
      tu->cu->firstTU = tu;
351
437k
    }
352
460k
    tu->cu->lastTU = tu;
353
460k
  }
354
355
521k
  uint32_t idx = ++m_numTUs;
356
521k
  tu->idx = idx;
357
358
521k
  TCoeffSig *coeffs[3] = { nullptr, nullptr, nullptr };
359
360
521k
  uint32_t numCh = getNumberValidComponents( area.chromaFormat );
361
362
2.08M
  for( uint32_t i = 0; i < numCh; i++ )
363
1.56M
  {
364
1.56M
    if( !tu->blocks[i].valid() )
365
819k
    {
366
819k
      continue;
367
819k
    }
368
369
743k
    coeffs[i] = m_coeffs[i] + m_offsets[i];
370
371
743k
    unsigned areaSize = tu->blocks[i].area();
372
743k
    m_offsets[i] += areaSize;
373
374
743k
    const bool cpyRsi = tuInit &&
375
263k
                      ( tuInit->cbf[i] ||
376
215k
                 ( i && tuInit->jointCbCr && numCh > 1 && ( TU::getCbf( *tuInit, COMP_Cb ) || TU::getCbf( *tuInit, COMP_Cr ) ) )
377
263k
                      );
378
379
743k
    if( cpyRsi )
380
48.1k
      memcpy( coeffs[i], tu->m_coeffs[i], areaSize * sizeof( TCoeffSig ) );
381
743k
  }
382
383
521k
  tu->init( coeffs );
384
385
521k
  return *tu;
386
521k
}
387
388
void CodingStructure::addEmptyTUs( Partitioner &partitioner, CodingUnit* cu )
389
22.6k
{
390
22.6k
  const UnitArea& area    = partitioner.currArea();
391
22.6k
  bool            split   = partitioner.canSplit(TU_MAX_TR_SPLIT, *this);
392
22.6k
  const unsigned  trDepth = partitioner.currTrDepth;
393
394
22.6k
  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.6k
  else
405
22.6k
  {
406
22.6k
    TransformUnit& tu = addTU(CS::getArea(*this, area, partitioner.chType, TreeType(partitioner.treeType)), partitioner.chType, cu);
407
22.6k
    tu.depth = trDepth;
408
22.6k
  }
409
22.6k
}
410
411
CUTraverser CodingStructure::traverseCUs( const UnitArea& unit, const ChannelType effChType )
412
7.68k
{
413
  //  CHECK( _treeType != treeType, "not good");
414
7.68k
  CodingUnit* firstCU = getCU( isLuma( effChType ) ? unit.lumaPos() : unit.chromaPos(), effChType, TREE_D );
415
7.68k
  CodingUnit* lastCU = firstCU;
416
7.68k
  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.68k
  else
448
7.68k
  {
449
40.1k
  do { } while( lastCU && (0 != ( lastCU = lastCU->next )) && unit.contains( *lastCU ) );
450
7.68k
  }
451
452
7.68k
  return CUTraverser( firstCU, lastCU );
453
7.68k
}
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.68k
{
489
7.68k
  return LFPBuf(m_lfParam[edgeDir], m_mapSize[0]);
490
7.68k
}
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
556k
{
513
556k
  createInternals( UnitArea( _chromaFormat, _area ), false );
514
515
556k
  m_reco.create( area );
516
556k
  m_pred.create( area );
517
556k
  m_resi.create( area );
518
556k
  m_rspreco.create( CHROMA_400, area.Y() );
519
556k
}
520
521
void CodingStructure::createPicLevel( const UnitArea& _unit, const PreCalcValues* _pcv )
522
1.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
558k
{
538
558k
  area     = _unit;
539
558k
  _maxArea = _unit;
540
541
558k
  unitScale[COMP_Y ] = UnitScale( UnitScaleArray[area.chromaFormat][COMP_Y ][0], UnitScaleArray[area.chromaFormat][COMP_Y ][1] );
542
558k
  unitScale[COMP_Cb] = UnitScale( UnitScaleArray[area.chromaFormat][COMP_Cb][0], UnitScaleArray[area.chromaFormat][COMP_Cb][1] );
543
558k
  unitScale[COMP_Cr] = UnitScale( UnitScaleArray[area.chromaFormat][COMP_Cr][0], UnitScaleArray[area.chromaFormat][COMP_Cr][1] );
544
545
558k
  picture = nullptr;
546
558k
  parent  = nullptr;
547
558k
  lumaCS  = nullptr;
548
549
558k
  unsigned _lumaAreaScaled = g_miScaling.scale( area.lumaSize() ).area();
550
558k
  m_motionBuf = new MotionInfo[_lumaAreaScaled];
551
552
558k
  if( isTopLayer )
553
1.20k
  {
554
1.20k
    motionLutBuf.resize( pps->getNumTileLineIds() );
555
1.20k
  }
556
556k
  else
557
556k
  {
558
556k
    createCoeffs();
559
556k
    createTempBuffers( false );
560
556k
    initStructData( MAX_INT, false, nullptr );
561
556k
  }
562
558k
}
563
564
void CodingStructure::createTempBuffers( const bool isTopLayer )
565
558k
{
566
558k
  unsigned numCh = getNumberValidChannels( area.chromaFormat );
567
568
1.67M
  for( unsigned i = 0; i < numCh; i++ )
569
1.11M
  {
570
1.11M
    Size allocArea  = area.blocks[i].size();
571
1.11M
    m_mapSize[i]    = unitScale[i].scale(allocArea);
572
573
1.11M
    unsigned _area  = unitScale[i].scale( area.blocks[i].size() ).area();
574
575
1.11M
    m_cuPtr[i]      = _area > 0 ? new CodingUnit*    [_area] : nullptr;
576
1.11M
  }
577
578
558k
  clearCUs( true );
579
580
1.67M
  for( unsigned i = 0; i < NUM_EDGE_DIR; i++ )
581
1.11M
  {
582
1.11M
    m_lfParam[i] = ( isTopLayer && m_mapSize[0].area() > 0 ) ? ( LoopFilterParam* ) xMalloc( LoopFilterParam, m_mapSize[0].area() ) : nullptr;
583
1.11M
  }
584
585
558k
  unsigned _maxNumDmvrMvs = ( area.lwidth() >> 3 ) * ( area.lheight() >> 3 );
586
558k
  m_dmvrMvCache.resize( _maxNumDmvrMvs );
587
558k
}
588
589
void CodingStructure::destroyTempBuffers()
590
559k
{
591
1.67M
  for( uint32_t i = 0; i < MAX_NUM_CH; i++ )
592
1.11M
  {
593
1.11M
    delete[] m_cuPtr[i];
594
1.11M
    m_cuPtr[i] = nullptr;
595
1.11M
  }
596
597
1.67M
  for( int i = 0; i < NUM_EDGE_DIR; i++ )
598
1.11M
  {
599
1.11M
    xFree( m_lfParam[i] );
600
1.11M
    m_lfParam[i] = nullptr;
601
1.11M
  }
602
603
  // swap the contents of the vector so that memory released
604
559k
  std::vector<Mv>().swap( m_dmvrMvCache );
605
559k
  std::vector<CodingUnit*>().swap( cus );
606
559k
  std::vector<TransformUnit*>().swap( tus );
607
559k
}
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.40k
{
636
2.40k
  CHECK( parent, "rebindPicBufs can only be used for the top level CodingStructure" );
637
638
2.40k
  if( !picture->m_picBufs[ PIC_RECONSTRUCTION ].bufs.empty() ) m_reco.createFromBuf( picture->m_picBufs[ PIC_RECONSTRUCTION ] );
639
0
  else                                                         m_reco.destroy();
640
2.40k
  if( !picture->m_picBufs[ PIC_PREDICTION     ].bufs.empty() ) m_pred.createFromBuf( picture->m_picBufs[ PIC_PREDICTION ] );
641
2.40k
  else                                                         m_pred.destroy();
642
2.40k
  if( !picture->m_picBufs[ PIC_RESIDUAL       ].bufs.empty() ) m_resi.createFromBuf( picture->m_picBufs[ PIC_RESIDUAL ] );
643
2.40k
  else                                                         m_resi.destroy();
644
2.40k
}
645
646
void CodingStructure::createCoeffs()
647
558k
{
648
558k
  const unsigned numComp = getNumberValidComponents( area.chromaFormat );
649
2.23M
  for( unsigned i = 0; i < numComp; i++ )
650
1.67M
  {
651
1.67M
    unsigned _area = area.blocks[i].area();
652
1.67M
    m_coeffs[i] = _area > 0 ? ( TCoeffSig* ) xMalloc( TCoeffSig, _area ) : nullptr;
653
1.67M
  }
654
655
2.23M
  for( unsigned i = 0; i < numComp; i++ )
656
1.67M
  {
657
1.67M
    m_offsets[i] = 0;
658
1.67M
  }
659
558k
}
660
661
void CodingStructure::destroyCoeffs()
662
559k
{
663
2.23M
  for( uint32_t i = 0; i < MAX_NUM_COMP; i++ )
664
1.67M
  {
665
1.67M
    if( m_coeffs[i] ) { xFree( m_coeffs[i] ); m_coeffs[i] = nullptr; }
666
1.67M
  }
667
559k
}
668
669
void CodingStructure::initSubStructure( CodingStructure& subStruct, const ChannelType _chType, const UnitArea& subArea, const bool isTuEnc, PelStorage* pOrgBuffer, PelStorage* pFiltOrgBuffer )
670
378k
{
671
378k
  CHECK( this == &subStruct, "Trying to init self as sub-structure" );
672
673
378k
  subStruct.parent = this;
674
675
378k
  if( pOrgBuffer ) pOrgBuffer->compactResize( subArea );
676
378k
  UnitArea subAreaLuma = subArea;
677
378k
  subAreaLuma.blocks.resize( 1 );
678
378k
  if( pFiltOrgBuffer ) pFiltOrgBuffer->compactResize( subAreaLuma );
679
680
378k
  subStruct.m_org    = (pOrgBuffer) ? pOrgBuffer : m_org;
681
378k
  subStruct.m_filtorg = (pFiltOrgBuffer) ? pFiltOrgBuffer : m_filtorg;
682
378k
  subStruct.compactResize( subArea );
683
684
378k
  subStruct.costDbOffset = 0;
685
686
378k
  if( parent )
687
363k
  {
688
    // allow this to be false at the top level (need for edge CTU's)
689
363k
    CHECKD( !area.contains( subArea ), "Trying to init sub-structure not contained in the parent" );
690
363k
  }
691
692
378k
  subStruct.parent    = this;
693
378k
  subStruct.picture   = picture;
694
378k
  subStruct.lumaCS    = picture->cs;
695
696
378k
  subStruct.sps       = sps;
697
378k
  subStruct.vps       = vps;
698
378k
  subStruct.pps       = pps;
699
378k
  subStruct.picHeader = picHeader;
700
701
378k
  memcpy(subStruct.alfAps, alfAps, sizeof(alfAps));
702
703
378k
  subStruct.slice     = slice;
704
378k
  subStruct.baseQP    = baseQP;
705
378k
  subStruct.prevQP[_chType]
706
378k
                      = prevQP[_chType];
707
378k
  subStruct.pcv       = pcv;
708
709
378k
  subStruct.m_isTuEnc = isTuEnc;
710
711
378k
  if( nullptr == parent )
712
15.3k
  {
713
15.3k
    const int ctuPosX = subArea.lx() >> pcv->maxCUSizeLog2;
714
15.3k
    const int ctuPosY = subArea.ly() >> pcv->maxCUSizeLog2;
715
15.3k
    subStruct.motionLut = motionLutBuf[pps->getTileLineId( ctuPosX, ctuPosY )];
716
15.3k
  }
717
363k
  else
718
363k
  {
719
363k
    subStruct.motionLut = motionLut;
720
363k
  }
721
722
378k
  subStruct.initStructData( currQP[_chType] );
723
724
378k
  if( isTuEnc )
725
116k
  {
726
116k
    CHECKD( area != subStruct.area, "Trying to init sub-structure for TU-encoding of incompatible size" );
727
728
116k
    for( const auto &pcu : cus )
729
116k
    {
730
116k
      CodingUnit &cu = subStruct.addCU( *pcu, _chType );
731
732
116k
      cu = *pcu;
733
116k
    }
734
116k
  }
735
378k
}
736
737
void CodingStructure::useSubStructure( CodingStructure& subStruct, const ChannelType chType, const TreeType _treeType, const UnitArea& subArea, const bool cpyRecoToPic )
738
156k
{
739
156k
  UnitArea clippedArea = clipArea( subArea, *picture );
740
741
156k
  CPelUnitBuf subRecoBuf = subStruct.getRecoBuf( clippedArea );
742
743
156k
  if( parent )
744
148k
  {
745
    // copy data to picture
746
148k
    getRecoBuf( clippedArea ).copyFrom( subRecoBuf );
747
148k
  }
748
749
156k
  if( cpyRecoToPic )
750
124k
  {
751
124k
    picture->getRecoBuf( clippedArea ).copyFrom( subRecoBuf );
752
124k
  }
753
754
156k
  if( !subStruct.m_isTuEnc && ( ( !slice->isIntra() || slice->sps->IBC ) && chType != CH_C ) )
755
52.3k
  {
756
    // copy motion buffer
757
52.3k
    MotionBuf ownMB  = getMotionBuf          ( clippedArea );
758
52.3k
    CMotionBuf subMB = subStruct.getMotionBuf( clippedArea );
759
760
52.3k
    ownMB.copyFrom( subMB );
761
762
52.3k
    if( nullptr == parent )
763
3.84k
    {
764
3.84k
      const int ctuPosX = subStruct.area.lx() >> pcv->maxCUSizeLog2;
765
3.84k
      const int ctuPosY = subStruct.area.ly() >> pcv->maxCUSizeLog2;
766
3.84k
      motionLutBuf[pps->getTileLineId( ctuPosX, ctuPosY )] = subStruct.motionLut;
767
3.84k
    }
768
48.5k
    else
769
48.5k
    {
770
48.5k
      motionLut = subStruct.motionLut;
771
48.5k
    }
772
52.3k
  }
773
774
156k
  fracBits += subStruct.fracBits;
775
156k
  dist     += subStruct.dist;
776
156k
  cost     += subStruct.cost;
777
156k
  costDbOffset += subStruct.costDbOffset;
778
779
156k
  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
156k
  if( subStruct.m_isTuEnc )
787
25.4k
  {
788
    // don't copy if the substruct was created for encoding of the TUs
789
25.4k
  }
790
130k
  else
791
130k
  {
792
130k
    if( &m_cuCache == &subStruct.m_cuCache )
793
123k
    {
794
      // copy the CUs over with taking ownership
795
123k
      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
123k
      subStruct.cus.resize( 0 );
803
123k
    }
804
7.68k
    else
805
7.68k
    {
806
      // copy the CUs over
807
7.68k
      for( const auto& pcu : subStruct.cus )
808
40.1k
      {
809
        // add an analogue CU into own CU store
810
40.1k
        const UnitArea& cuPatch = *pcu;
811
812
40.1k
        CodingUnit& cu = addCU( cuPatch, pcu->chType );
813
814
        // copy the CU info from subPatch
815
40.1k
        cu = *pcu;
816
40.1k
      }
817
7.68k
    }
818
130k
  }
819
820
156k
  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
178k
    {
825
      // add an analogue TU into own TU store
826
178k
      const UnitArea& tuPatch = *ptu;
827
178k
      addTU( tuPatch, ptu->chType, getCU( tuPatch.blocks[ptu->chType].pos(), ptu->chType, _treeType ), ptu );
828
178k
    }
829
830
148k
    subStruct.tus.resize( 0 );
831
148k
  }
832
7.68k
  else
833
7.68k
  {
834
    // copy the TUs over
835
7.68k
    for( const auto& ptu : subStruct.tus )
836
40.1k
    {
837
      // add an analogue TU into own TU store
838
40.1k
      const UnitArea& tuPatch = *ptu;
839
840
40.1k
      TransformUnit& tu = addTU( tuPatch, ptu->chType, getCU( tuPatch.blocks[ptu->chType], ptu->chType, _treeType ) );
841
842
      // copy the TU info from subPatch
843
40.1k
      tu = *ptu;
844
40.1k
    }
845
7.68k
  }
846
156k
}
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
429k
{
921
429k
  UnitArea areaLuma = _area;
922
429k
  areaLuma.blocks.resize( 1 );
923
924
429k
  m_pred   .compactResize( _area );
925
429k
  m_reco   .compactResize( _area );
926
429k
  m_resi   .compactResize( _area );
927
429k
  m_rspreco.compactResize( areaLuma );
928
929
1.71M
  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
429k
  area = _area;
935
429k
}
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
717k
  {
946
717k
    currQP[0] = currQP[1] = QP;
947
717k
  }
948
949
1.38M
  if( !skipMotBuf && ( !parent || ( ( !slice->isIntra() || slice->sps->IBC ) && !m_isTuEnc ) ) )
950
640k
  {
951
640k
    getMotionBuf().memset( -1 );
952
640k
  }
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
305k
  {
975
305k
    pcu->firstTU = pcu->lastTU = nullptr;
976
305k
  }
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
875k
  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
875k
  if ( m_unitCacheMutex ) m_unitCacheMutex->lock();
996
875k
  m_cuCache.cache( cus );
997
875k
  if ( m_unitCacheMutex ) m_unitCacheMutex->unlock();
998
999
875k
  m_numCUs = 0;
1000
875k
}
1001
1002
MotionBuf CodingStructure::getMotionBuf( const Area& _area )
1003
771k
{
1004
771k
  const CompArea& _luma = area.Y();
1005
1006
771k
  CHECKD( !_luma.contains( _area ), "Trying to access motion information outside of this coding structure" );
1007
1008
771k
  const Area miArea   = g_miScaling.scale( _area );
1009
771k
  const Area selfArea = g_miScaling.scale( _luma );
1010
1011
771k
  return MotionBuf( m_motionBuf + rsAddr( miArea.pos(), selfArea.pos(), selfArea.width ), selfArea.width, miArea.size() );
1012
771k
}
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
507k
  {
1052
507k
    return PelBuf();
1053
507k
  }
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.36M
  {
1060
2.36M
    buf = m_org;
1061
2.36M
  }
1062
15.9M
  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.3k
  {
1076
37.3k
    cFinal.x &= ( pcv->maxCUSizeMask >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
1077
37.3k
    cFinal.y &= ( pcv->maxCUSizeMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
1078
37.3k
  }
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
28.3k
{
1085
28.3k
  if (!blk.valid())
1086
0
  {
1087
0
    return PelBuf();
1088
0
  }
1089
1090
28.3k
  const ComponentID compID = blk.compID;
1091
1092
28.3k
  const PelStorage* buf = type == PIC_PREDICTION ? &m_pred : ( type == PIC_RESIDUAL ? &m_resi : ( type == PIC_RECONSTRUCTION ? &m_reco : nullptr ) );
1093
28.3k
  if (type == PIC_ORIGINAL)
1094
28.3k
  {
1095
28.3k
    buf = m_org;
1096
28.3k
  }
1097
0
  else if( type == PIC_FILT_ORIGINAL)
1098
0
  {
1099
0
    buf = m_filtorg;
1100
0
  }
1101
1102
28.3k
  CHECK( !buf, "Unknown buffer requested" );
1103
1104
28.3k
  CHECKD( !area.blocks[compID].contains( blk ), "Buffer not contained in self requested" );
1105
1106
28.3k
  CompArea cFinal = blk;
1107
28.3k
  cFinal.relativeTo( area.blocks[compID] );
1108
1109
28.3k
  if( !parent && ( type == PIC_RESIDUAL || type == PIC_PREDICTION ) )
1110
0
  {
1111
0
    cFinal.x &= ( pcv->maxCUSizeMask >> getComponentScaleX( blk.compID, blk.chromaFormat ) );
1112
0
    cFinal.y &= ( pcv->maxCUSizeMask >> getComponentScaleY( blk.compID, blk.chromaFormat ) );
1113
0
  }
1114
1115
28.3k
  return buf->getBuf( cFinal );
1116
28.3k
}
1117
1118
PelUnitBuf CodingStructure::getBuf( const UnitArea& unit, const PictureType type )
1119
480k
{
1120
  // no parent fetching for buffers
1121
480k
  if( area.chromaFormat == CHROMA_400 )
1122
0
  {
1123
0
    return PelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ) );
1124
0
  }
1125
480k
  else
1126
480k
  {
1127
480k
    return PelUnitBuf( area.chromaFormat, getBuf( unit.Y(), type ), getBuf( unit.Cb(), type ), getBuf( unit.Cr(), type ) );
1128
480k
  }
1129
480k
}
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.03M
{
1146
2.03M
  const int csx    = getChannelTypeScaleX( _chType, area.chromaFormat );
1147
2.03M
  const int csy    = getChannelTypeScaleY( _chType, area.chromaFormat );
1148
2.03M
  const int xshift = pcv->maxCUSizeLog2 - csx;
1149
2.03M
  const int yshift = pcv->maxCUSizeLog2 - csy;
1150
2.03M
  const int ydiff  = ( pos.y >> yshift ) - ( curCu.blocks[_chType].y >> yshift );
1151
2.03M
  const int xdiff  = ( pos.x >> xshift ) - ( curCu.blocks[_chType].x >> xshift );
1152
1153
2.03M
  if( !xdiff && !ydiff )
1154
876k
  {
1155
876k
    const CodingUnit* cu = getCU( pos, _chType, curCu.treeType );
1156
1157
876k
    return ( cu && ( cu->cs != curCu.cs || cu->idx <= curCu.idx ) ) ? cu : nullptr;
1158
876k
  }
1159
1160
1.15M
  if( ydiff > 0 || ( ydiff == 0 && xdiff > 0 ) || ( ydiff == -1 && xdiff > ( sps->entropyCodingSyncEnabled ? 0 : 1 ) ) )
1161
31.3k
    return nullptr;
1162
1163
1.12M
  if( pos.x < 0 || pos.y < 0 || ( pos.x * ( 1 << csx ) ) >= pcv->lumaWidth || pps->getTileIdx( pos.x >> xshift, pos.y >> yshift ) != curCu.tileIdx ) return nullptr;
1164
1165
270k
  const CodingUnit* cu = getCU( pos, _chType, curCu.treeType );
1166
1167
270k
  return ( cu && CU::isSameSlice( *cu, curCu ) ) ? cu : nullptr;
1168
1.12M
}
1169
1170
const CodingUnit *CodingStructure::getCURestricted( const Position &pos, const Position curPos, const unsigned curSliceIdx, const unsigned curTileIdx, const ChannelType _chType, const TreeType _treeType ) const
1171
2.53M
{
1172
2.53M
  const int csx    = getChannelTypeScaleX( _chType, area.chromaFormat );
1173
2.53M
  const int csy    = getChannelTypeScaleY( _chType, area.chromaFormat );
1174
2.53M
  const int xshift = pcv->maxCUSizeLog2 - csx;
1175
2.53M
  const int yshift = pcv->maxCUSizeLog2 - csy;
1176
2.53M
  const int ydiff  = ( pos.y >> yshift ) - ( curPos.y >> yshift );
1177
2.53M
  const int xdiff  = ( pos.x >> xshift ) - ( curPos.x >> xshift );
1178
1179
2.53M
  if( !xdiff && !ydiff )
1180
796k
  {
1181
796k
    return getCU( pos, _chType, _treeType );
1182
796k
  }
1183
1184
1.73M
  if( ydiff > 0 || ( ydiff == 0 && xdiff > 0 ) || ( ydiff == -1 && xdiff > ( sps->entropyCodingSyncEnabled ? 0 : 1 ) ) )
1185
33.7k
    return nullptr;
1186
1187
1.70M
  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
683k
  const CodingUnit* cu = getCU( pos, _chType, _treeType );
1190
1191
683k
  return ( cu && cu->slice->independentSliceIdx == curSliceIdx && cu->tileIdx == curTileIdx ) ? cu : nullptr;
1192
1.70M
}
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