Coverage Report

Created: 2026-10-28 06:18

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