Coverage Report

Created: 2026-04-01 07:49

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