Coverage Report

Created: 2026-05-24 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vvdec/source/Lib/CommonLib/Unit.h
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) 2018-2026, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. & The VVdeC 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
/** \file     Unit.h
44
 *  \brief    defines unit as a set of blocks and basic unit types (coding, prediction, transform)
45
 */
46
47
#pragma once
48
49
#include "CommonDef.h"
50
#include "Common.h"
51
#include "Mv.h"
52
#include "MotionInfo.h"
53
#include "ChromaFormat.h"
54
55
#include <mutex>
56
57
namespace vvdec
58
{
59
60
// ---------------------------------------------------------------------------
61
// tools
62
// ---------------------------------------------------------------------------
63
inline Position recalcPosition(const ChromaFormat _cf, const ComponentID srcCId, const ComponentID dstCId, const Position &pos)
64
0
{
65
0
  if( toChannelType( srcCId ) == toChannelType( dstCId ) )
66
0
  {
67
0
    return pos;
68
0
  }
69
0
  else if (isLuma(srcCId) && isChroma(dstCId))
70
0
  {
71
0
    return Position(pos.x >> getComponentScaleX(dstCId, _cf), pos.y >> getComponentScaleY(dstCId, _cf));
72
0
  }
73
0
  else
74
0
  {
75
0
    return Position(pos.x << getComponentScaleX(srcCId, _cf), pos.y << getComponentScaleY(srcCId, _cf));
76
0
  }
77
0
}
78
79
inline Position recalcPosition( const ChromaFormat _cf, const ChannelType srcCHt, const ChannelType dstCHt, const Position &pos )
80
357k
{
81
357k
  if( srcCHt == dstCHt )
82
245k
  {
83
245k
    return pos;
84
245k
  }
85
111k
  else if( isLuma( srcCHt ) && isChroma( dstCHt ) )
86
0
  {
87
0
    return Position( pos.x >> getChannelTypeScaleX( dstCHt, _cf ), pos.y >> getChannelTypeScaleY( dstCHt, _cf ) );
88
0
  }
89
111k
  else
90
111k
  {
91
111k
    return Position( pos.x << getChannelTypeScaleX( srcCHt, _cf ), pos.y << getChannelTypeScaleY( srcCHt, _cf ) );
92
111k
  }
93
357k
}
94
95
inline Size recalcSize( const ChromaFormat _cf, const ComponentID srcCId, const ComponentID dstCId, const Size &size )
96
0
{
97
0
  if( toChannelType( srcCId ) == toChannelType( dstCId ) )
98
0
  {
99
0
    return size;
100
0
  }
101
0
  else if( isLuma( srcCId ) && isChroma( dstCId ) )
102
0
  {
103
0
    return Size( size.width >> getComponentScaleX( dstCId, _cf ), size.height >> getComponentScaleY( dstCId, _cf ) );
104
0
  }
105
0
  else
106
0
  {
107
0
    return Size( size.width << getComponentScaleX( srcCId, _cf ), size.height << getComponentScaleY( srcCId, _cf ) );
108
0
  }
109
0
}
110
111
inline Size recalcSize( const ChromaFormat _cf, const ChannelType srcCHt, const ChannelType dstCHt, const Size &size )
112
3.42k
{
113
3.42k
  if( srcCHt == dstCHt )
114
0
  {
115
0
    return size;
116
0
  }
117
3.42k
  else if( isLuma( srcCHt ) && isChroma( dstCHt ) )
118
0
  {
119
0
    return Size( size.width >> getChannelTypeScaleX( dstCHt, _cf ), size.height >> getChannelTypeScaleY( dstCHt, _cf ) );
120
0
  }
121
3.42k
  else
122
3.42k
  {
123
3.42k
    return Size( size.width << getChannelTypeScaleX( srcCHt, _cf ), size.height << getChannelTypeScaleY( srcCHt, _cf ) );
124
3.42k
  }
125
3.42k
}
126
127
// ---------------------------------------------------------------------------
128
// block definition
129
// ---------------------------------------------------------------------------
130
131
struct CompArea : public Area
132
{
133
736k
  CompArea() : Area()                                                                                                                                                          { }
134
13.0k
  CompArea(const ComponentID _compID, const Area &_area)                                                          : Area(_area.x, _area.y, _area.width, _area.height, _compID) { }
135
81.2k
  CompArea(const ComponentID _compID, const Position& _pos, const Size& _size)                                    : Area(_pos, Size( _size.width, _size.height, _compID))      { }
136
0
  CompArea(const ComponentID _compID, const uint32_t _x, const uint32_t _y, const uint32_t _w, const uint32_t _h) : Area(_x, _y, _w, _h, _compID)                              { }
137
138
  Position chromaPos(const ChromaFormat chromaFormat) const;
139
  Position lumaPos(const ChromaFormat chromaFormat)   const;
140
141
  Size     chromaSize(const ChromaFormat chromaFormat) const;
142
  Size     lumaSize(const ChromaFormat chromaFormat)   const;
143
144
  Position compPos(const ChromaFormat chromaFormat, const ComponentID compID) const;
145
  Position chanPos(const ChromaFormat chromaFormat, const ChannelType chType) const;
146
147
0
  Position topLeftComp    (const ChromaFormat chromaFormat, const ComponentID _compID) const { return recalcPosition(chromaFormat, compID(), _compID, *this);                                                     }
148
0
  Position topRightComp   (const ChromaFormat chromaFormat, const ComponentID _compID) const { return recalcPosition(chromaFormat, compID(), _compID, { (PosType) (x + width - 1), y                          }); }
149
0
  Position bottomLeftComp (const ChromaFormat chromaFormat, const ComponentID _compID) const { return recalcPosition(chromaFormat, compID(), _compID, { x                        , (PosType) (y + height - 1 )}); }
150
0
  Position bottomRightComp(const ChromaFormat chromaFormat, const ComponentID _compID) const { return recalcPosition(chromaFormat, compID(), _compID, { (PosType) (x + width - 1), (PosType) (y + height - 1 )}); }
151
152
2.03M
  bool valid() const { return compID() < MAX_NUM_TBLOCKS && width != 0 && height != 0; }
153
154
  bool operator==(const CompArea &other) const
155
0
  {
156
0
    if (compID()       != other.compID())       return false;
157
0
158
0
    return Position::operator==(other) && Size::operator==(other);
159
0
  }
160
161
0
  bool operator!=(const CompArea &other) const { return !(operator==(other)); }
162
163
0
  void     repositionTo      (const Position& newPos)       { Position::repositionTo(newPos); }
164
0
  void     positionRelativeTo(const CompArea& origCompArea) { Position::relativeTo(origCompArea); }
165
};
166
167
inline CompArea clipArea(const CompArea &compArea, const Area &boundingBox)
168
669
{
169
669
  return CompArea(compArea.compID(), clipArea((const Area&) compArea, boundingBox));
170
669
}
171
172
// ---------------------------------------------------------------------------
173
// unit definition
174
// ---------------------------------------------------------------------------
175
176
typedef static_vector<CompArea, MAX_NUM_TBLOCKS> UnitBlocksType;
177
178
struct UnitArea
179
{
180
  ChromaFormat chromaFormat;
181
  UnitBlocksType blocks;
182
183
100k
  UnitArea() : chromaFormat(NUM_CHROMA_FORMAT) { }
184
  UnitArea(const ChromaFormat _chromaFormat);
185
  UnitArea(const ChromaFormat _chromaFormat, const Area &area);
186
  UnitArea(const ChromaFormat _chromaFormat, const CompArea  &blkY);
187
  UnitArea(const ChromaFormat _chromaFormat,       CompArea &&blkY);
188
  UnitArea(const ChromaFormat _chromaFormat, const CompArea  &blkY, const CompArea  &blkCb, const CompArea  &blkCr);
189
  UnitArea(const ChromaFormat _chromaFormat,       CompArea &&blkY,       CompArea &&blkCb,       CompArea &&blkCr);
190
191
291k
        CompArea& Y()                                  { return blocks[COMPONENT_Y];  }
192
2.36M
  const CompArea& Y()                            const { return blocks[COMPONENT_Y];  }
193
115k
        CompArea& Cb()                                 { return blocks[COMPONENT_Cb]; }
194
770k
  const CompArea& Cb()                           const { return blocks[COMPONENT_Cb]; }
195
110k
        CompArea& Cr()                                 { return blocks[COMPONENT_Cr]; }
196
20.7k
  const CompArea& Cr()                           const { return blocks[COMPONENT_Cr]; }
197
198
18.8k
        CompArea& block(const ComponentID comp)       { return blocks[comp]; }
199
151k
  const CompArea& block(const ComponentID comp) const { return blocks[comp]; }
200
201
  bool contains(const UnitArea& other) const;
202
  bool contains(const UnitArea& other, const ChannelType chType) const;
203
204
0
        CompArea& operator[]( const int n )       { return blocks[n]; }
205
0
  const CompArea& operator[]( const int n ) const { return blocks[n]; }
206
207
  bool operator==(const UnitArea &other) const
208
0
  {
209
0
    if (chromaFormat != other.chromaFormat)   return false;
210
0
    if (blocks.size() != other.blocks.size()) return false;
211
0
212
0
    for (uint32_t i = 0; i < blocks.size(); i++)
213
0
    {
214
0
      if (blocks[i] != other.blocks[i]) return false;
215
0
    }
216
0
217
0
    return true;
218
0
  }
219
220
  void repositionTo(const UnitArea& unit);
221
222
0
  bool operator!=(const UnitArea &other) const { return !(*this == other); }
223
224
134k
  const Position& lumaPos () const { return Y(); }
225
241k
  const Size&     lumaSize() const { return Y(); }
226
0
  const Area&     lumaArea() const { return Y(); }
227
228
78.8k
  const Position& chromaPos () const { return Cb(); }
229
155k
  const Size&     chromaSize() const { return Cb(); }
230
0
  const Area&     chromaArea() const { return Cb(); }
231
232
  const UnitArea  singleComp(const ComponentID compID) const;
233
  const UnitArea  singleChan(const ChannelType chType) const;
234
235
664k
  SizeType  lwidth()  const { return Y().width; }  /*! luma width  */
236
445k
  SizeType  lheight() const { return Y().height; } /*! luma height */
237
238
897
  PosType   lx() const { return Y().x; }           /*! luma x-pos */
239
17.6k
  PosType   ly() const { return Y().y; }           /*! luma y-pos */
240
241
0
  bool valid() const { return chromaFormat != NUM_CHROMA_FORMAT && blocks.size() > 0; }
242
};
243
244
inline UnitArea clipArea(const UnitArea &area, const UnitArea &boundingBox)
245
223
{
246
223
  UnitArea ret(area.chromaFormat);
247
248
892
  for (uint32_t i = 0; i < area.blocks.size(); i++)
249
669
  {
250
669
    ret.blocks.push_back(clipArea(area.blocks[i], boundingBox.blocks[i]));
251
669
  }
252
253
223
  return ret;
254
223
}
255
256
struct UnitAreaRelative : public UnitArea
257
{
258
  UnitAreaRelative(const UnitArea& origUnit, const UnitArea& unit)
259
0
  {
260
0
    *((UnitArea*)this) = unit;
261
0
    for(uint32_t i = 0; i < blocks.size(); i++)
262
0
    {
263
0
      blocks[i].positionRelativeTo(origUnit.blocks[i]);
264
0
    }
265
0
  }
266
};
267
268
class SPS;
269
class VPS;
270
class PPS;
271
class Slice;
272
struct CodingUnit;
273
274
}
275
276
#include "Buffer.h"
277
278
namespace vvdec
279
{
280
281
// ---------------------------------------------------------------------------
282
// transform unit
283
// ---------------------------------------------------------------------------
284
285
struct TransformUnit : public UnitArea
286
{
287
  CodingUnit     *cu;
288
  TransformUnit  *next;
289
  unsigned        idx;
290
291
  uint8_t         maxScanPosX  [MAX_NUM_TBLOCKS];
292
  uint8_t         maxScanPosY  [MAX_NUM_TBLOCKS];
293
  int8_t          chromaQp     [2];
294
295
  uint8_t         _chType    : 2;
296
  uint8_t         jointCbCr  : 2;
297
  uint8_t         cbf        : 3;
298
  uint8_t         _mtsIdxL   : 3;
299
  uint8_t         _mtsIdxU   : 1;
300
  uint8_t         _mtsIdxV   : 1;
301
302
104k
  ChannelType     chType()                const { return ChannelType( _chType ); }
303
71.4k
  void            setChType( ChannelType ch )   { _chType = ch; }
304
588k
  uint8_t         mtsIdx   ( int c )      const { return !c ? _mtsIdxL :             c == 1 ? _mtsIdxU :         _mtsIdxV; }
305
114k
  void            setMtsIdx( int c, uint8_t v ) { if   ( !c ) _mtsIdxL = v; else if( c == 1 ) _mtsIdxU = v; else _mtsIdxV = v; }
306
};
307
308
// ---------------------------------------------------------------------------
309
// coding unit
310
// ---------------------------------------------------------------------------
311
312
class  CodingStructure;
313
314
struct CodingUnit : public UnitArea
315
{
316
  TransformUnit     firstTU;
317
  TransformUnit    *lastTU;
318
319
  struct CtuData   *ctuData;
320
  CodingStructure  *cs;
321
  const Slice      *slice;
322
  const PPS        *pps;
323
  const SPS        *sps;
324
        CodingUnit *next;
325
  const CodingUnit *above;
326
  const CodingUnit *left;
327
  ptrdiff_t         mvdL0SubPuOff; // 7 ptr (8 byte)
328
  ptrdiff_t         predBufOff;
329
  uint32_t          idx;
330
  uint32_t          tileIdx;
331
332
  Mv                mv       [NUM_REF_PIC_LIST_01][3];
333
334
  uint8_t           mvpIdx   [NUM_REF_PIC_LIST_01];
335
  int8_t            refIdx   [NUM_REF_PIC_LIST_01];
336
  int8_t            intraDir [MAX_NUM_CHANNEL_TYPE];
337
338
  SplitSeries       splitSeries;
339
340
  uint8_t           geoSplitDir;
341
  uint8_t           mmvdIdx;
342
343
  int8_t            chromaQpAdj;
344
  int8_t            qp;
345
  uint8_t           _interDir       : 2;
346
  uint8_t           _imv            : 2;
347
  uint8_t           _bcw            : 3;
348
  uint8_t           _mergeType      : 2;
349
  bool              _dmvrCond;      // avoid data races in a separate bit
350
351
  uint8_t           _sbtInfo;
352
  uint8_t           qtDepth         : 3;
353
  uint8_t           depth           : 4;
354
  uint8_t           _chType         : 1;
355
356
  bool              _rootCbf        : 1;
357
  bool              _skip           : 1;
358
  bool              _colorTransform : 1;
359
  bool              _mipTranspose   : 1;
360
  uint8_t           _treeType       : 2;
361
  uint8_t           _modeType       : 2;
362
363
  uint8_t           _predMode       : 2;
364
  uint8_t           _bdpcmL         : 2;
365
  uint8_t           _bdpcmC         : 2;
366
  uint8_t           _lfnstIdx       : 2;
367
368
  uint8_t           _ispIdx         : 2;
369
  bool              _ciipFlag       : 1;
370
  bool              _mergeFlag      : 1;
371
  bool              _mmvdFlag       : 1;
372
  bool              _affineFlag     : 1;
373
  bool              _geoFlag        : 1;
374
375
  uint8_t           _mrgIdx         : 3;
376
  uint8_t           _geoMrgIdx0     : 3;
377
378
  uint8_t           _geoMrgIdx1     : 3;
379
  uint8_t           _affineType     : 2;
380
  bool              _mipFlag        : 1;
381
382
  uint8_t           _multiRefIdx    : 2;
383
  bool              planeCbfY       : 1;
384
  bool              planeCbfU       : 1;
385
  bool              planeCbfV       : 1;
386
387
  uint8_t           _smvd           : 2;
388
389
  uint8_t            _geoDir0, _geoDir1;
390
391
426k
  uint8_t           sbtInfo()                const        { return _sbtInfo; }
392
2.04M
  ChannelType       chType()                 const        { return ChannelType( _chType ); }
393
77.6k
  bool              rootCbf()                const        { return _rootCbf; }
394
154k
  bool              skip()                   const        { return _skip; }
395
111k
  bool              colorTransform()         const        { return _colorTransform; }
396
464k
  TreeType          treeType()               const        { return TreeType( _treeType ); }
397
64.3k
  ModeType          modeType()               const        { return ModeType( _modeType ); }
398
1.98M
  PredMode          predMode()               const        { return PredMode( _predMode ); }
399
1.27M
  uint8_t           ispMode()                const        { return _ispIdx; }
400
660k
  uint8_t           bdpcmMode()              const        { return _bdpcmL; }
401
464k
  uint8_t           bdpcmModeChroma()        const        { return _bdpcmC; }
402
62.5k
  uint8_t           lfnstIdx()               const        { return _lfnstIdx; }
403
312k
  bool              planeCbf( int c )        const        { return !c ? planeCbfY : c == 1 ? planeCbfU : planeCbfV; }
404
405
131k
  void              setChType( ChannelType ch )           { _chType         = ch ; }
406
125k
  void              setRootCbf( bool b )                  { _rootCbf        =  b ; }
407
1.34k
  void              setSkip( bool b )                     { _skip           =  b ; }
408
1.34k
  void              setColorTransform( bool b )           { _colorTransform =  b ; }
409
65.7k
  void              setTreeType( TreeType n )             { _treeType       =  n ; }
410
65.7k
  void              setModeType( ModeType n )             { _modeType       =  n ; }
411
80.7k
  void              setPredMode( PredMode n )             { _predMode       =  n ; }
412
1.97k
  void              setIspMode( uint8_t n )               { _ispIdx         =  n ; }
413
10.5k
  void              setBdpcmMode( uint8_t n )             { _bdpcmL         =  n ; }
414
18.1k
  void              setBdpcmModeChroma( uint8_t n )       { _bdpcmC         =  n ; }
415
13.9k
  void              setLfnstIdx( uint8_t n )              { _lfnstIdx       =  n ; }
416
0
  void              setSbtInfo( uint8_t n )               { _sbtInfo        =  n ; }
417
211k
  void              setPlaneCbf( int c, bool b )          { if( !c ) planeCbfY = b; else if( c == 1 ) planeCbfU = b; else planeCbfV = b; }
418
419
  // Prediction Unit Part
420
421
0
  bool              dmvrCondition()          const         { return _dmvrCond; }
422
514
  bool              mipTransposedFlag()      const         { return _mipTranspose; }
423
242k
  bool              ciipFlag()               const         { return _ciipFlag; }
424
102k
  bool              mergeFlag()              const         { return _mergeFlag; }
425
10.6k
  bool              mmvdFlag()               const         { return _mmvdFlag; }
426
217k
  bool              affineFlag()             const         { return _affineFlag; }
427
14.6k
  MergeType         mergeType()              const         { return MergeType( _mergeType ); }
428
0
  AffineModel       affineType()             const         { return AffineModel( _affineType ); }
429
38.4k
  bool              geoFlag()                const         { return _geoFlag; }
430
9.78k
  uint8_t           mergeIdx()               const         { return _mrgIdx; }
431
0
  uint8_t           geoMergeIdx0()           const         { return _geoMrgIdx0; }
432
0
  uint8_t           geoMergeIdx1()           const         { return _geoMrgIdx1; }
433
35.9k
  uint8_t           interDir()               const         { return _interDir; }
434
56.1k
  uint8_t           multiRefIdx()            const         { return _multiRefIdx; }
435
157k
  bool              mipFlag()                const         { return _mipFlag; }
436
32.4k
  uint8_t           imv()                    const         { return _imv; }
437
16.3k
  uint8_t           smvdMode()               const         { return _smvd; }
438
8.84k
  uint8_t           BcwIdx()                 const         { return _bcw; }
439
440
0
  uint8_t           interDirrefIdxGeo0()     const         { return _geoDir0; }
441
0
  uint8_t           interDirrefIdxGeo1()     const         { return _geoDir1; }
442
443
0
  void              setDmvrCondition( bool b )             { _dmvrCond      = b ; }
444
3.37k
  void              setMipTransposedFlag( bool b )         { _mipTranspose  = b ; }
445
0
  void              setCiipFlag( bool b )                  { _ciipFlag      = b ; }
446
16.3k
  void              setMergeFlag( bool b )                 { _mergeFlag     = b ; }
447
0
  void              setMmvdFlag( bool b )                  { _mmvdFlag      = b ; }
448
0
  void              setAffineFlag( bool b )                { _affineFlag    = b ; }
449
4.89k
  void              setMergeType( MergeType mt )           { _mergeType     = mt; }
450
0
  void              setAffineType( AffineModel at )        { _affineType    = at; CHECKD( at >= AFFINE_MODEL_NUM, "Needs to be '0' or '1'!" ); }
451
0
  void              setGeoFlag( bool b )                   { _geoFlag       = b ; }
452
7.54k
  void              setMergeIdx( uint8_t id )              { _mrgIdx        = id; CHECKD( id >=  8, "Merge index needs to be smaller than '8'!"); }
453
0
  void              setGeoMergeIdx0( uint8_t id )          { _geoMrgIdx0    = id; CHECKD( id >=  8, "Merge index needs to be smaller than '8'!"); }
454
0
  void              setGeoMergeIdx1( uint8_t id )          { _geoMrgIdx1    = id; CHECKD( id >=  8, "Merge index needs to be smaller than '8'!"); }
455
13.7k
  void              setInterDir( uint8_t id )              { _interDir      = id; CHECKD( id >=  4, "Inter dir needs to be smaller than '4'!"); }
456
13.6k
  void              setMultiRefIdx( uint8_t id )           { _multiRefIdx   = id; CHECKD( id >=  3, "Multi-ref. index needs to be smaller than '3'!"); }
457
20.0k
  void              setMipFlag( bool b )                   { _mipFlag       = b ; }
458
20.0k
  void              setImv( uint8_t id )                   { _imv           = id; CHECKD( id >=  4, "IMV needs to be smaller than '4'!"); }
459
0
  void              setSmvdMode( uint8_t id )              { _smvd          = id; CHECKD( id >=  4, "SMVD mode needs to be smaller than '4'!"); }
460
4.89k
  void              setBcwIdx( uint8_t id )                { _bcw           = id; CHECKD( id >=  5, "BCW idx needs to be smaller than '5'!"); }
461
462
0
  void              setInterDirrefIdxGeo0( uint8_t id )    { _geoDir0       = id; }
463
0
  void              setInterDirrefIdxGeo1( uint8_t id )    { _geoDir1       = id; }
464
465
  CodingUnit& operator=(const MotionInfo& mi);
466
467
  // for accessing motion information, which can have higher resolution than PUs (should always be used, when accessing neighboring motion information)
468
  const MotionInfo& getMotionInfo() const;
469
  const MotionInfo& getMotionInfo( const Position& pos ) const;
470
  MotionBuf         getMotionBuf();
471
  CMotionBuf        getMotionBuf() const;
472
473
  void              minInit( const UnitArea& unit );
474
};
475
476
// ---------------------------------------------------------------------------
477
// Utility class for easy for-each like unit traversing
478
// ---------------------------------------------------------------------------
479
480
}
481
482
#include <iterator>
483
484
namespace vvdec {
485
486
template<typename T>
487
class UnitIterator
488
{
489
private:
490
  T* m_punit = nullptr;
491
492
public:
493
321k
  explicit UnitIterator( T* _punit ) : m_punit( _punit ) {}
vvdec::UnitIterator<vvdec::CodingUnit>::UnitIterator(vvdec::CodingUnit*)
Line
Count
Source
493
9.86k
  explicit UnitIterator( T* _punit ) : m_punit( _punit ) {}
vvdec::UnitIterator<vvdec::TransformUnit const>::UnitIterator(vvdec::TransformUnit const*)
Line
Count
Source
493
110k
  explicit UnitIterator( T* _punit ) : m_punit( _punit ) {}
vvdec::UnitIterator<vvdec::TransformUnit>::UnitIterator(vvdec::TransformUnit*)
Line
Count
Source
493
200k
  explicit UnitIterator( T* _punit ) : m_punit( _punit ) {}
494
495
  using iterator_category = std::forward_iterator_tag;
496
  using value_type        = T;
497
  using pointer           = T*;
498
  using const_pointer     = T const*;
499
  using reference         = T&;
500
  using const_reference   = T const&;
501
  using difference_type   = ptrdiff_t;
502
503
285k
  reference        operator*()                                      { return *m_punit; }
vvdec::UnitIterator<vvdec::CodingUnit>::operator*()
Line
Count
Source
503
110k
  reference        operator*()                                      { return *m_punit; }
vvdec::UnitIterator<vvdec::TransformUnit const>::operator*()
Line
Count
Source
503
66.3k
  reference        operator*()                                      { return *m_punit; }
vvdec::UnitIterator<vvdec::TransformUnit>::operator*()
Line
Count
Source
503
109k
  reference        operator*()                                      { return *m_punit; }
504
  const_reference  operator*()                                const { return *m_punit; }
505
  pointer          operator->()                                     { return  m_punit; }
506
  const_pointer    operator->()                               const { return  m_punit; }
507
508
285k
  UnitIterator<T>& operator++()                                     { m_punit = m_punit->next; return *this; }
vvdec::UnitIterator<vvdec::CodingUnit>::operator++()
Line
Count
Source
508
110k
  UnitIterator<T>& operator++()                                     { m_punit = m_punit->next; return *this; }
vvdec::UnitIterator<vvdec::TransformUnit const>::operator++()
Line
Count
Source
508
66.3k
  UnitIterator<T>& operator++()                                     { m_punit = m_punit->next; return *this; }
vvdec::UnitIterator<vvdec::TransformUnit>::operator++()
Line
Count
Source
508
109k
  UnitIterator<T>& operator++()                                     { m_punit = m_punit->next; return *this; }
509
  UnitIterator<T>  operator++( int )                                { auto x = *this; ++( *this ); return x; }
510
445k
  bool             operator!=( const UnitIterator<T>& other ) const { return m_punit != other.m_punit; }
vvdec::UnitIterator<vvdec::CodingUnit>::operator!=(vvdec::UnitIterator<vvdec::CodingUnit> const&) const
Line
Count
Source
510
115k
  bool             operator!=( const UnitIterator<T>& other ) const { return m_punit != other.m_punit; }
vvdec::UnitIterator<vvdec::TransformUnit const>::operator!=(vvdec::UnitIterator<vvdec::TransformUnit const> const&) const
Line
Count
Source
510
121k
  bool             operator!=( const UnitIterator<T>& other ) const { return m_punit != other.m_punit; }
vvdec::UnitIterator<vvdec::TransformUnit>::operator!=(vvdec::UnitIterator<vvdec::TransformUnit> const&) const
Line
Count
Source
510
209k
  bool             operator!=( const UnitIterator<T>& other ) const { return m_punit != other.m_punit; }
511
  bool             operator==( const UnitIterator<T>& other ) const { return m_punit == other.m_punit; }
512
};
513
514
template<typename T>
515
class UnitTraverser
516
{
517
private:
518
  T* m_begin;
519
  T* m_end;
520
521
public:
522
  UnitTraverser(                    ) : m_begin( nullptr ), m_end( nullptr ) { }
523
160k
  UnitTraverser( T* _begin, T* _end ) : m_begin( _begin  ), m_end( _end    ) { }
vvdec::UnitTraverser<vvdec::TransformUnit const>::UnitTraverser(vvdec::TransformUnit const*, vvdec::TransformUnit const*)
Line
Count
Source
523
55.2k
  UnitTraverser( T* _begin, T* _end ) : m_begin( _begin  ), m_end( _end    ) { }
vvdec::UnitTraverser<vvdec::CodingUnit>::UnitTraverser(vvdec::CodingUnit*, vvdec::CodingUnit*)
Line
Count
Source
523
4.93k
  UnitTraverser( T* _begin, T* _end ) : m_begin( _begin  ), m_end( _end    ) { }
vvdec::UnitTraverser<vvdec::TransformUnit>::UnitTraverser(vvdec::TransformUnit*, vvdec::TransformUnit*)
Line
Count
Source
523
100k
  UnitTraverser( T* _begin, T* _end ) : m_begin( _begin  ), m_end( _end    ) { }
524
525
  typedef T                     value_type;
526
  typedef size_t                size_type;
527
  typedef T&                    reference;
528
  typedef T const&              const_reference;
529
  typedef T*                    pointer;
530
  typedef T const*              const_pointer;
531
  typedef UnitIterator<T>       iterator;
532
  typedef UnitIterator<const T> const_iterator;
533
534
160k
  iterator        begin()        { return UnitIterator<T>( m_begin ); }
vvdec::UnitTraverser<vvdec::CodingUnit>::begin()
Line
Count
Source
534
4.93k
  iterator        begin()        { return UnitIterator<T>( m_begin ); }
vvdec::UnitTraverser<vvdec::TransformUnit const>::begin()
Line
Count
Source
534
55.2k
  iterator        begin()        { return UnitIterator<T>( m_begin ); }
vvdec::UnitTraverser<vvdec::TransformUnit>::begin()
Line
Count
Source
534
100k
  iterator        begin()        { return UnitIterator<T>( m_begin ); }
535
  const_iterator  begin()  const { return UnitIterator<T>( m_begin ); }
536
  const_iterator  cbegin() const { return UnitIterator<T>( m_begin ); }
537
160k
  iterator        end()          { return UnitIterator<T>( m_end   ); }
vvdec::UnitTraverser<vvdec::CodingUnit>::end()
Line
Count
Source
537
4.93k
  iterator        end()          { return UnitIterator<T>( m_end   ); }
vvdec::UnitTraverser<vvdec::TransformUnit const>::end()
Line
Count
Source
537
55.2k
  iterator        end()          { return UnitIterator<T>( m_end   ); }
vvdec::UnitTraverser<vvdec::TransformUnit>::end()
Line
Count
Source
537
100k
  iterator        end()          { return UnitIterator<T>( m_end   ); }
538
  const_iterator  end()    const { return UnitIterator<T>( m_end   ); }
539
  const_iterator  cend()   const { return UnitIterator<T>( m_end   ); }
540
};
541
542
typedef UnitTraverser<CodingUnit>            CUTraverser;
543
typedef UnitTraverser<const CodingUnit>     cCUTraverser;
544
545
typedef UnitTraverser<      TransformUnit>   TUTraverser;
546
typedef UnitTraverser<const TransformUnit>  cTUTraverser;
547
548
}
549
550
#include <memory>
551
#include <mutex>
552
553
namespace vvdec {
554
555
// ---------------------------------------------------------------------------
556
// dynamic cache
557
// ---------------------------------------------------------------------------
558
559
static constexpr size_t DYN_CACHE_CHUNK_SIZE = 1024;
560
561
template<typename T>
562
class thread_safe_chunk_cache
563
{
564
  std::vector<T*> m_cacheChunks;
565
  std::mutex      m_mutex;
566
567
public:
568
569
  ~thread_safe_chunk_cache()
570
1.61k
  {
571
1.61k
    clear_chunks();
572
1.61k
  }
vvdec::thread_safe_chunk_cache<vvdec::CodingUnit>::~thread_safe_chunk_cache()
Line
Count
Source
570
808
  {
571
808
    clear_chunks();
572
808
  }
vvdec::thread_safe_chunk_cache<vvdec::TransformUnit>::~thread_safe_chunk_cache()
Line
Count
Source
570
808
  {
571
808
    clear_chunks();
572
808
  }
573
574
  void clear_chunks()
575
1.61k
  {
576
1.61k
    for( auto& chunk : m_cacheChunks )
577
508
    {
578
508
      free( chunk );
579
508
    }
580
581
1.61k
    m_cacheChunks.clear();
582
1.61k
  }
vvdec::thread_safe_chunk_cache<vvdec::CodingUnit>::clear_chunks()
Line
Count
Source
575
808
  {
576
808
    for( auto& chunk : m_cacheChunks )
577
287
    {
578
287
      free( chunk );
579
287
    }
580
581
808
    m_cacheChunks.clear();
582
808
  }
vvdec::thread_safe_chunk_cache<vvdec::TransformUnit>::clear_chunks()
Line
Count
Source
575
808
  {
576
808
    for( auto& chunk : m_cacheChunks )
577
221
    {
578
221
      free( chunk );
579
221
    }
580
581
808
    m_cacheChunks.clear();
582
808
  }
583
584
  T* get()
585
508
  {
586
508
    std::unique_lock<std::mutex> l( m_mutex );
587
588
508
    if( m_cacheChunks.empty() )
589
508
    {
590
508
      l.unlock();
591
508
      return ( T* ) malloc( DYN_CACHE_CHUNK_SIZE * sizeof( T ) );
592
508
    }
593
0
    else
594
0
    {
595
0
      T* chunk = m_cacheChunks.back();
596
0
      m_cacheChunks.pop_back();
597
0
      return chunk;
598
0
    }
599
508
  }
vvdec::thread_safe_chunk_cache<vvdec::CodingUnit>::get()
Line
Count
Source
585
287
  {
586
287
    std::unique_lock<std::mutex> l( m_mutex );
587
588
287
    if( m_cacheChunks.empty() )
589
287
    {
590
287
      l.unlock();
591
287
      return ( T* ) malloc( DYN_CACHE_CHUNK_SIZE * sizeof( T ) );
592
287
    }
593
0
    else
594
0
    {
595
0
      T* chunk = m_cacheChunks.back();
596
0
      m_cacheChunks.pop_back();
597
0
      return chunk;
598
0
    }
599
287
  }
vvdec::thread_safe_chunk_cache<vvdec::TransformUnit>::get()
Line
Count
Source
585
221
  {
586
221
    std::unique_lock<std::mutex> l( m_mutex );
587
588
221
    if( m_cacheChunks.empty() )
589
221
    {
590
221
      l.unlock();
591
221
      return ( T* ) malloc( DYN_CACHE_CHUNK_SIZE * sizeof( T ) );
592
221
    }
593
0
    else
594
0
    {
595
0
      T* chunk = m_cacheChunks.back();
596
0
      m_cacheChunks.pop_back();
597
0
      return chunk;
598
0
    }
599
221
  }
600
601
  void cache( std::vector<T*>& chunks )
602
1.72k
  {
603
1.72k
    std::unique_lock<std::mutex> l( m_mutex );
604
605
1.72k
    m_cacheChunks.insert( m_cacheChunks.end(), chunks.begin(), chunks.end() );
606
1.72k
    chunks.clear();
607
1.72k
  }
vvdec::thread_safe_chunk_cache<vvdec::TransformUnit>::cache(std::__1::vector<vvdec::TransformUnit*, std::__1::allocator<vvdec::TransformUnit*> >&)
Line
Count
Source
602
864
  {
603
864
    std::unique_lock<std::mutex> l( m_mutex );
604
605
864
    m_cacheChunks.insert( m_cacheChunks.end(), chunks.begin(), chunks.end() );
606
864
    chunks.clear();
607
864
  }
vvdec::thread_safe_chunk_cache<vvdec::CodingUnit>::cache(std::__1::vector<vvdec::CodingUnit*, std::__1::allocator<vvdec::CodingUnit*> >&)
Line
Count
Source
602
864
  {
603
864
    std::unique_lock<std::mutex> l( m_mutex );
604
605
864
    m_cacheChunks.insert( m_cacheChunks.end(), chunks.begin(), chunks.end() );
606
864
    chunks.clear();
607
864
  }
608
};
609
610
template<typename T>
611
class dynamic_cache
612
{
613
  ptrdiff_t       m_lastIdx;
614
  std::vector<T*> m_cache;
615
616
  thread_safe_chunk_cache<T> *m_chunkCache;
617
618
  void clear_chunks()
619
1.72k
  {
620
1.72k
    m_chunkCache->cache( m_cache );
621
1.72k
  }
vvdec::dynamic_cache<vvdec::TransformUnit>::clear_chunks()
Line
Count
Source
619
864
  {
620
864
    m_chunkCache->cache( m_cache );
621
864
  }
vvdec::dynamic_cache<vvdec::CodingUnit>::clear_chunks()
Line
Count
Source
619
864
  {
620
864
    m_chunkCache->cache( m_cache );
621
864
  }
622
623
public:
624
625
574
  explicit dynamic_cache( thread_safe_chunk_cache<T>* chunkCache ) : m_lastIdx( DYN_CACHE_CHUNK_SIZE ), m_chunkCache( chunkCache )
626
574
  {
627
574
  }
vvdec::dynamic_cache<vvdec::CodingUnit>::dynamic_cache(vvdec::thread_safe_chunk_cache<vvdec::CodingUnit>*)
Line
Count
Source
625
287
  explicit dynamic_cache( thread_safe_chunk_cache<T>* chunkCache ) : m_lastIdx( DYN_CACHE_CHUNK_SIZE ), m_chunkCache( chunkCache )
626
287
  {
627
287
  }
vvdec::dynamic_cache<vvdec::TransformUnit>::dynamic_cache(vvdec::thread_safe_chunk_cache<vvdec::TransformUnit>*)
Line
Count
Source
625
287
  explicit dynamic_cache( thread_safe_chunk_cache<T>* chunkCache ) : m_lastIdx( DYN_CACHE_CHUNK_SIZE ), m_chunkCache( chunkCache )
626
287
  {
627
287
  }
628
629
  ~dynamic_cache()
630
574
  {
631
574
    clear_chunks();
632
574
  }
vvdec::dynamic_cache<vvdec::TransformUnit>::~dynamic_cache()
Line
Count
Source
630
287
  {
631
287
    clear_chunks();
632
287
  }
vvdec::dynamic_cache<vvdec::CodingUnit>::~dynamic_cache()
Line
Count
Source
630
287
  {
631
287
    clear_chunks();
632
287
  }
633
634
  T* get()
635
71.4k
  {
636
71.4k
    T* ret;
637
638
71.4k
    if( m_lastIdx < DYN_CACHE_CHUNK_SIZE )
639
70.9k
    {
640
70.9k
      ret = &m_cache.back()[m_lastIdx++];
641
70.9k
    }
642
508
    else
643
508
    {
644
508
      T* chunk = m_chunkCache->get();
645
646
508
      m_cache.push_back( chunk );
647
648
508
      ret = &chunk[0];
649
508
      m_lastIdx = 1;
650
508
    }
651
652
71.4k
    return ret;
653
71.4k
  }
vvdec::dynamic_cache<vvdec::CodingUnit>::get()
Line
Count
Source
635
65.7k
  {
636
65.7k
    T* ret;
637
638
65.7k
    if( m_lastIdx < DYN_CACHE_CHUNK_SIZE )
639
65.4k
    {
640
65.4k
      ret = &m_cache.back()[m_lastIdx++];
641
65.4k
    }
642
287
    else
643
287
    {
644
287
      T* chunk = m_chunkCache->get();
645
646
287
      m_cache.push_back( chunk );
647
648
287
      ret = &chunk[0];
649
287
      m_lastIdx = 1;
650
287
    }
651
652
65.7k
    return ret;
653
65.7k
  }
vvdec::dynamic_cache<vvdec::TransformUnit>::get()
Line
Count
Source
635
5.76k
  {
636
5.76k
    T* ret;
637
638
5.76k
    if( m_lastIdx < DYN_CACHE_CHUNK_SIZE )
639
5.54k
    {
640
5.54k
      ret = &m_cache.back()[m_lastIdx++];
641
5.54k
    }
642
221
    else
643
221
    {
644
221
      T* chunk = m_chunkCache->get();
645
646
221
      m_cache.push_back( chunk );
647
648
221
      ret = &chunk[0];
649
221
      m_lastIdx = 1;
650
221
    }
651
652
5.76k
    return ret;
653
5.76k
  }
654
655
  void releaseAll()
656
1.15k
  {
657
1.15k
    clear_chunks();
658
1.15k
    m_lastIdx = DYN_CACHE_CHUNK_SIZE;
659
1.15k
  }
vvdec::dynamic_cache<vvdec::CodingUnit>::releaseAll()
Line
Count
Source
656
577
  {
657
577
    clear_chunks();
658
577
    m_lastIdx = DYN_CACHE_CHUNK_SIZE;
659
577
  }
vvdec::dynamic_cache<vvdec::TransformUnit>::releaseAll()
Line
Count
Source
656
577
  {
657
577
    clear_chunks();
658
577
    m_lastIdx = DYN_CACHE_CHUNK_SIZE;
659
577
  }
660
};
661
662
typedef dynamic_cache<struct CodingUnit>    CUCache;
663
typedef dynamic_cache<struct TransformUnit> TUCache;
664
665
typedef thread_safe_chunk_cache<struct CodingUnit>    CUChunkCache;
666
typedef thread_safe_chunk_cache<struct TransformUnit> TUChunkCache;
667
668
}
669