1 /* -----------------------------------------------------------------------------
2 The copyright in this software is being made available under the 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 For any license concerning other Intellectual Property rights than the software,
8 especially patent licenses, a separate Agreement needs to be closed.
9 For more information please contact:
10 
11 Fraunhofer Heinrich Hertz Institute
12 Einsteinufer 37
13 10587 Berlin, Germany
14 www.hhi.fraunhofer.de/vvc
15 vvc@hhi.fraunhofer.de
16 
17 Copyright (c) 2018-2021, Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V.
18 All rights reserved.
19 
20 Redistribution and use in source and binary forms, with or without
21 modification, are permitted provided that the following conditions are met:
22 
23  * Redistributions of source code must retain the above copyright notice,
24    this list of conditions and the following disclaimer.
25  * Redistributions in binary form must reproduce the above copyright notice,
26    this list of conditions and the following disclaimer in the documentation
27    and/or other materials provided with the distribution.
28  * Neither the name of Fraunhofer nor the names of its contributors may
29    be used to endorse or promote products derived from this software without
30    specific prior written permission.
31 
32 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
36 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
42 THE POSSIBILITY OF SUCH DAMAGE.
43 
44 
45 ------------------------------------------------------------------------------------------- */
46 
47 /** \file     Unit.h
48  *  \brief    defines unit as a set of blocks and basic unit types (coding, prediction, transform)
49  */
50 
51 #pragma once
52 
53 #include "CommonDef.h"
54 #include "Common.h"
55 #include "Mv.h"
56 #include "MotionInfo.h"
57 #include "ChromaFormat.h"
58 
59 namespace vvdec
60 {
61 
62 // ---------------------------------------------------------------------------
63 // tools
64 // ---------------------------------------------------------------------------
recalcPosition(const ChromaFormat _cf,const ComponentID srcCId,const ComponentID dstCId,const Position & pos)65 inline Position recalcPosition(const ChromaFormat _cf, const ComponentID srcCId, const ComponentID dstCId, const Position &pos)
66 {
67   if( toChannelType( srcCId ) == toChannelType( dstCId ) )
68   {
69     return pos;
70   }
71   else if (isLuma(srcCId) && isChroma(dstCId))
72   {
73     return Position(pos.x >> getComponentScaleX(dstCId, _cf), pos.y >> getComponentScaleY(dstCId, _cf));
74   }
75   else
76   {
77     return Position(pos.x << getComponentScaleX(srcCId, _cf), pos.y << getComponentScaleY(srcCId, _cf));
78   }
79 }
80 
recalcPosition(const ChromaFormat _cf,const ChannelType srcCHt,const ChannelType dstCHt,const Position & pos)81 inline Position recalcPosition( const ChromaFormat _cf, const ChannelType srcCHt, const ChannelType dstCHt, const Position &pos )
82 {
83   if( srcCHt == dstCHt )
84   {
85     return pos;
86   }
87   else if( isLuma( srcCHt ) && isChroma( dstCHt ) )
88   {
89     return Position( pos.x >> getChannelTypeScaleX( dstCHt, _cf ), pos.y >> getChannelTypeScaleY( dstCHt, _cf ) );
90   }
91   else
92   {
93     return Position( pos.x << getChannelTypeScaleX( srcCHt, _cf ), pos.y << getChannelTypeScaleY( srcCHt, _cf ) );
94   }
95 }
96 
recalcSize(const ChromaFormat _cf,const ComponentID srcCId,const ComponentID dstCId,const Size & size)97 inline Size recalcSize( const ChromaFormat _cf, const ComponentID srcCId, const ComponentID dstCId, const Size &size )
98 {
99   if( toChannelType( srcCId ) == toChannelType( dstCId ) )
100   {
101     return size;
102   }
103   else if( isLuma( srcCId ) && isChroma( dstCId ) )
104   {
105     return Size( size.width >> getComponentScaleX( dstCId, _cf ), size.height >> getComponentScaleY( dstCId, _cf ) );
106   }
107   else
108   {
109     return Size( size.width << getComponentScaleX( srcCId, _cf ), size.height << getComponentScaleY( srcCId, _cf ) );
110   }
111 }
112 
recalcSize(const ChromaFormat _cf,const ChannelType srcCHt,const ChannelType dstCHt,const Size & size)113 inline Size recalcSize( const ChromaFormat _cf, const ChannelType srcCHt, const ChannelType dstCHt, const Size &size )
114 {
115   if( srcCHt == dstCHt )
116   {
117     return size;
118   }
119   else if( isLuma( srcCHt ) && isChroma( dstCHt ) )
120   {
121     return Size( size.width >> getChannelTypeScaleX( dstCHt, _cf ), size.height >> getChannelTypeScaleY( dstCHt, _cf ) );
122   }
123   else
124   {
125     return Size( size.width << getChannelTypeScaleX( srcCHt, _cf ), size.height << getChannelTypeScaleY( srcCHt, _cf ) );
126   }
127 }
128 
129 // ---------------------------------------------------------------------------
130 // block definition
131 // ---------------------------------------------------------------------------
132 
133 struct CompArea : public Area
134 {
CompAreaCompArea135   CompArea() : Area()                                                                                                                                                          { }
CompAreaCompArea136   CompArea(const ComponentID _compID, const Area &_area)                                                          : Area(_area.x, _area.y, _area.width, _area.height, _compID) { }
CompAreaCompArea137   CompArea(const ComponentID _compID, const Position& _pos, const Size& _size)                                    : Area(_pos, Size( _size.width, _size.height, _compID))      { }
CompAreaCompArea138   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)                              { }
139 
140   Position chromaPos(const ChromaFormat chromaFormat) const;
141   Position lumaPos(const ChromaFormat chromaFormat)   const;
142 
143   Size     chromaSize(const ChromaFormat chromaFormat) const;
144   Size     lumaSize(const ChromaFormat chromaFormat)   const;
145 
146   Position compPos(const ChromaFormat chromaFormat, const ComponentID compID) const;
147   Position chanPos(const ChromaFormat chromaFormat, const ChannelType chType) const;
148 
topLeftCompCompArea149   Position topLeftComp    (const ChromaFormat chromaFormat, const ComponentID _compID) const { return recalcPosition(chromaFormat, compID(), _compID, *this);                                                     }
topRightCompCompArea150   Position topRightComp   (const ChromaFormat chromaFormat, const ComponentID _compID) const { return recalcPosition(chromaFormat, compID(), _compID, { (PosType) (x + width - 1), y                          }); }
bottomLeftCompCompArea151   Position bottomLeftComp (const ChromaFormat chromaFormat, const ComponentID _compID) const { return recalcPosition(chromaFormat, compID(), _compID, { x                        , (PosType) (y + height - 1 )}); }
bottomRightCompCompArea152   Position bottomRightComp(const ChromaFormat chromaFormat, const ComponentID _compID) const { return recalcPosition(chromaFormat, compID(), _compID, { (PosType) (x + width - 1), (PosType) (y + height - 1 )}); }
153 
validCompArea154   bool valid() const { return compID() < MAX_NUM_TBLOCKS && width != 0 && height != 0; }
155 
156   bool operator==(const CompArea &other) const
157   {
158     if (compID()       != other.compID())       return false;
159 
160     return Position::operator==(other) && Size::operator==(other);
161   }
162 
163   bool operator!=(const CompArea &other) const { return !(operator==(other)); }
164 
repositionToCompArea165   void     repositionTo      (const Position& newPos)       { Position::repositionTo(newPos); }
positionRelativeToCompArea166   void     positionRelativeTo(const CompArea& origCompArea) { Position::relativeTo(origCompArea); }
167 };
168 
clipArea(const CompArea & compArea,const Area & boundingBox)169 inline CompArea clipArea(const CompArea &compArea, const Area &boundingBox)
170 {
171   return CompArea(compArea.compID(), clipArea((const Area&) compArea, boundingBox));
172 }
173 
174 // ---------------------------------------------------------------------------
175 // unit definition
176 // ---------------------------------------------------------------------------
177 
178 typedef static_vector<CompArea, MAX_NUM_TBLOCKS> UnitBlocksType;
179 
180 struct UnitArea
181 {
182   ChromaFormat chromaFormat;
183   UnitBlocksType blocks;
184 
UnitAreaUnitArea185   UnitArea() : chromaFormat(NUM_CHROMA_FORMAT) { }
186   UnitArea(const ChromaFormat _chromaFormat);
187   UnitArea(const ChromaFormat _chromaFormat, const Area &area);
188   UnitArea(const ChromaFormat _chromaFormat, const CompArea  &blkY);
189   UnitArea(const ChromaFormat _chromaFormat,       CompArea &&blkY);
190   UnitArea(const ChromaFormat _chromaFormat, const CompArea  &blkY, const CompArea  &blkCb, const CompArea  &blkCr);
191   UnitArea(const ChromaFormat _chromaFormat,       CompArea &&blkY,       CompArea &&blkCb,       CompArea &&blkCr);
192 
YUnitArea193         CompArea& Y()                                  { return blocks[COMPONENT_Y];  }
YUnitArea194   const CompArea& Y()                            const { return blocks[COMPONENT_Y];  }
CbUnitArea195         CompArea& Cb()                                 { return blocks[COMPONENT_Cb]; }
CbUnitArea196   const CompArea& Cb()                           const { return blocks[COMPONENT_Cb]; }
CrUnitArea197         CompArea& Cr()                                 { return blocks[COMPONENT_Cr]; }
CrUnitArea198   const CompArea& Cr()                           const { return blocks[COMPONENT_Cr]; }
199 
blockUnitArea200         CompArea& block(const ComponentID comp)       { return blocks[comp]; }
blockUnitArea201   const CompArea& block(const ComponentID comp) const { return blocks[comp]; }
202 
203   bool contains(const UnitArea& other) const;
204   bool contains(const UnitArea& other, const ChannelType chType) const;
205 
206         CompArea& operator[]( const int n )       { return blocks[n]; }
207   const CompArea& operator[]( const int n ) const { return blocks[n]; }
208 
209   bool operator==(const UnitArea &other) const
210   {
211     if (chromaFormat != other.chromaFormat)   return false;
212     if (blocks.size() != other.blocks.size()) return false;
213 
214     for (uint32_t i = 0; i < blocks.size(); i++)
215     {
216       if (blocks[i] != other.blocks[i]) return false;
217     }
218 
219     return true;
220   }
221 
222   void repositionTo(const UnitArea& unit);
223 
224   bool operator!=(const UnitArea &other) const { return !(*this == other); }
225 
lumaPosUnitArea226   const Position& lumaPos () const { return Y(); }
lumaSizeUnitArea227   const Size&     lumaSize() const { return Y(); }
lumaAreaUnitArea228   const Area&     lumaArea() const { return Y(); }
229 
chromaPosUnitArea230   const Position& chromaPos () const { return Cb(); }
chromaSizeUnitArea231   const Size&     chromaSize() const { return Cb(); }
chromaAreaUnitArea232   const Area&     chromaArea() const { return Cb(); }
233 
234   const UnitArea  singleComp(const ComponentID compID) const;
235   const UnitArea  singleChan(const ChannelType chType) const;
236 
lwidthUnitArea237   SizeType  lwidth()  const { return Y().width; }  /*! luma width  */
lheightUnitArea238   SizeType  lheight() const { return Y().height; } /*! luma height */
239 
lxUnitArea240   PosType   lx() const { return Y().x; }           /*! luma x-pos */
lyUnitArea241   PosType   ly() const { return Y().y; }           /*! luma y-pos */
242 
validUnitArea243   bool valid() const { return chromaFormat != NUM_CHROMA_FORMAT && blocks.size() > 0; }
244 };
245 
clipArea(const UnitArea & area,const UnitArea & boundingBox)246 inline UnitArea clipArea(const UnitArea &area, const UnitArea &boundingBox)
247 {
248   UnitArea ret(area.chromaFormat);
249 
250   for (uint32_t i = 0; i < area.blocks.size(); i++)
251   {
252     ret.blocks.push_back(clipArea(area.blocks[i], boundingBox.blocks[i]));
253   }
254 
255   return ret;
256 }
257 
258 struct UnitAreaRelative : public UnitArea
259 {
UnitAreaRelativeUnitAreaRelative260   UnitAreaRelative(const UnitArea& origUnit, const UnitArea& unit)
261   {
262     *((UnitArea*)this) = unit;
263     for(uint32_t i = 0; i < blocks.size(); i++)
264     {
265       blocks[i].positionRelativeTo(origUnit.blocks[i]);
266     }
267   }
268 };
269 
270 class SPS;
271 class VPS;
272 class PPS;
273 class Slice;
274 struct CodingUnit;
275 
276 }
277 
278 #include "Buffer.h"
279 
280 namespace vvdec
281 {
282 
283 // ---------------------------------------------------------------------------
284 // transform unit
285 // ---------------------------------------------------------------------------
286 
287 struct TransformUnit : public UnitArea
288 {
289   CodingUnit     *cu;
290   TransformUnit  *next;
291   unsigned        idx;
292 
293   uint8_t         maxScanPosX  [MAX_NUM_TBLOCKS];
294   uint8_t         maxScanPosY  [MAX_NUM_TBLOCKS];
295   int8_t          chromaQp     [2];
296 
297   uint8_t         _chType    : 2;
298   uint8_t         jointCbCr  : 2;
299   uint8_t         cbf        : 3;
300   uint8_t         _mtsIdxL   : 3;
301   uint8_t         _mtsIdxU   : 1;
302   uint8_t         _mtsIdxV   : 1;
303 
chTypeTransformUnit304   ChannelType     chType()                const { return ChannelType( _chType ); }
setChTypeTransformUnit305   void            setChType( ChannelType ch )   { _chType = ch; }
mtsIdxTransformUnit306   uint8_t         mtsIdx   ( int c )      const { return !c ? _mtsIdxL :             c == 1 ? _mtsIdxU :         _mtsIdxV; }
setMtsIdxTransformUnit307   void            setMtsIdx( int c, uint8_t v ) { if   ( !c ) _mtsIdxL = v; else if( c == 1 ) _mtsIdxU = v; else _mtsIdxV = v; }
308 };
309 
310 // ---------------------------------------------------------------------------
311 // coding unit
312 // ---------------------------------------------------------------------------
313 
314 class  CodingStructure;
315 
316 struct CodingUnit : public UnitArea
317 {
318   TransformUnit     firstTU;
319   TransformUnit    *lastTU;
320 
321   struct CtuData   *ctuData;
322   CodingStructure  *cs;
323   const Slice      *slice;
324   const PPS        *pps;
325   const SPS        *sps;
326         CodingUnit *next;
327   const CodingUnit *above;
328   const CodingUnit *left;
329   Mv               *mvdL0SubPu; // 7 ptr (8 byte)
330   Pel              *predBuf;
331   uint32_t          idx;
332   uint32_t          tileIdx;
333 
334   Mv                mv       [NUM_REF_PIC_LIST_01][3];
335 
336   uint8_t           mvpIdx   [NUM_REF_PIC_LIST_01];
337   int8_t            refIdx   [NUM_REF_PIC_LIST_01];
338   int8_t            intraDir [MAX_NUM_CHANNEL_TYPE];
339 
340   SplitSeries       splitSeries;
341 
342   uint8_t           geoSplitDir;
343   uint8_t           mmvdIdx;
344 
345   int8_t            chromaQpAdj;
346   int8_t            qp;
347 
348   uint8_t           _sbtInfo;
349   uint8_t           qtDepth         : 3;
350   uint8_t           depth           : 4;
351   uint8_t           _chType         : 1;
352 
353   bool              _rootCbf        : 1;
354   bool              _skip           : 1;
355   bool              _colorTransform : 1;
356   bool              _mipTranspose   : 1;
357   uint8_t           _treeType       : 2;
358   uint8_t           _modeType       : 2;
359 
360   uint8_t           _predMode       : 2;
361   uint8_t           _bdpcmL         : 2;
362   uint8_t           _bdpcmC         : 2;
363   uint8_t           _lfnstIdx       : 2;
364 
365   uint8_t           _ispIdx         : 2;
366   bool              _dmvrCond       : 1;
367   bool              _ciipFlag       : 1;
368   bool              _mergeFlag      : 1;
369   bool              _mmvdFlag       : 1;
370   bool              _affineFlag     : 1;
371   bool              _geoFlag        : 1;
372 
373   uint8_t           _mergeType      : 2;
374   uint8_t           _mrgIdx         : 3;
375   uint8_t           _geoMrgIdx0     : 3;
376 
377   uint8_t           _geoMrgIdx1     : 3;
378   uint8_t           _affineType     : 2;
379   uint8_t           _interDir       : 2;
380   bool              _mipFlag        : 1;
381 
382   uint8_t           _bcw            : 3;
383   uint8_t           _multiRefIdx    : 2;
384   bool              planeCbfY       : 1;
385   bool              planeCbfU       : 1;
386   bool              planeCbfV       : 1;
387 
388   uint8_t           _imv            : 2;
389   uint8_t           _smvd           : 2;
390 
391   uint8_t            _geoDir0, _geoDir1;
392 
sbtInfoCodingUnit393   uint8_t           sbtInfo()                const        { return _sbtInfo; }
chTypeCodingUnit394   ChannelType       chType()                 const        { return ChannelType( _chType ); }
rootCbfCodingUnit395   bool              rootCbf()                const        { return _rootCbf; }
skipCodingUnit396   bool              skip()                   const        { return _skip; }
colorTransformCodingUnit397   bool              colorTransform()         const        { return _colorTransform; }
treeTypeCodingUnit398   TreeType          treeType()               const        { return TreeType( _treeType ); }
modeTypeCodingUnit399   ModeType          modeType()               const        { return ModeType( _modeType ); }
predModeCodingUnit400   PredMode          predMode()               const        { return PredMode( _predMode ); }
ispModeCodingUnit401   uint8_t           ispMode()                const        { return _ispIdx; }
bdpcmModeCodingUnit402   uint8_t           bdpcmMode()              const        { return _bdpcmL; }
bdpcmModeChromaCodingUnit403   uint8_t           bdpcmModeChroma()        const        { return _bdpcmC; }
lfnstIdxCodingUnit404   uint8_t           lfnstIdx()               const        { return _lfnstIdx; }
planeCbfCodingUnit405   bool              planeCbf( int c )        const        { return !c ? planeCbfY : c == 1 ? planeCbfU : planeCbfV; }
406 
setChTypeCodingUnit407   void              setChType( ChannelType ch )           { _chType         = ch ; }
setRootCbfCodingUnit408   void              setRootCbf( bool b )                  { _rootCbf        =  b ; }
setSkipCodingUnit409   void              setSkip( bool b )                     { _skip           =  b ; }
setColorTransformCodingUnit410   void              setColorTransform( bool b )           { _colorTransform =  b ; }
setTreeTypeCodingUnit411   void              setTreeType( TreeType n )             { _treeType       =  n ; }
setModeTypeCodingUnit412   void              setModeType( ModeType n )             { _modeType       =  n ; }
setPredModeCodingUnit413   void              setPredMode( PredMode n )             { _predMode       =  n ; }
setIspModeCodingUnit414   void              setIspMode( uint8_t n )               { _ispIdx         =  n ; }
setBdpcmModeCodingUnit415   void              setBdpcmMode( uint8_t n )             { _bdpcmL         =  n ; }
setBdpcmModeChromaCodingUnit416   void              setBdpcmModeChroma( uint8_t n )       { _bdpcmC         =  n ; }
setLfnstIdxCodingUnit417   void              setLfnstIdx( uint8_t n )              { _lfnstIdx       =  n ; }
setSbtInfoCodingUnit418   void              setSbtInfo( uint8_t n )               { _sbtInfo        =  n ; }
setPlaneCbfCodingUnit419   void              setPlaneCbf( int c, bool b )          { if( !c ) planeCbfY = b; else if( c == 1 ) planeCbfU = b; else planeCbfV = b; }
420 
421   // Prediction Unit Part
422 
dmvrConditionCodingUnit423   bool              dmvrCondition()          const         { return _dmvrCond; }
mipTransposedFlagCodingUnit424   bool              mipTransposedFlag()      const         { return _mipTranspose; }
ciipFlagCodingUnit425   bool              ciipFlag()               const         { return _ciipFlag; }
mergeFlagCodingUnit426   bool              mergeFlag()              const         { return _mergeFlag; }
mmvdFlagCodingUnit427   bool              mmvdFlag()               const         { return _mmvdFlag; }
affineFlagCodingUnit428   bool              affineFlag()             const         { return _affineFlag; }
mergeTypeCodingUnit429   MergeType         mergeType()              const         { return MergeType( _mergeType ); }
affineTypeCodingUnit430   AffineModel       affineType()             const         { return AffineModel( _affineType ); }
geoFlagCodingUnit431   bool              geoFlag()                const         { return _geoFlag; }
mergeIdxCodingUnit432   uint8_t           mergeIdx()               const         { return _mrgIdx; }
geoMergeIdx0CodingUnit433   uint8_t           geoMergeIdx0()           const         { return _geoMrgIdx0; }
geoMergeIdx1CodingUnit434   uint8_t           geoMergeIdx1()           const         { return _geoMrgIdx1; }
interDirCodingUnit435   uint8_t           interDir()               const         { return _interDir; }
multiRefIdxCodingUnit436   uint8_t           multiRefIdx()            const         { return _multiRefIdx; }
mipFlagCodingUnit437   bool              mipFlag()                const         { return _mipFlag; }
imvCodingUnit438   uint8_t           imv()                    const         { return _imv; }
smvdModeCodingUnit439   uint8_t           smvdMode()               const         { return _smvd; }
BcwIdxCodingUnit440   uint8_t           BcwIdx()                 const         { return _bcw; }
441 
interDirrefIdxGeo0CodingUnit442   uint8_t           interDirrefIdxGeo0()     const         { return _geoDir0; }
interDirrefIdxGeo1CodingUnit443   uint8_t           interDirrefIdxGeo1()     const         { return _geoDir1; }
444 
setDmvrConditionCodingUnit445   void              setDmvrCondition( bool b )             { _dmvrCond      = b ; }
setMipTransposedFlagCodingUnit446   void              setMipTransposedFlag( bool b )         { _mipTranspose  = b ; }
setCiipFlagCodingUnit447   void              setCiipFlag( bool b )                  { _ciipFlag      = b ; }
setMergeFlagCodingUnit448   void              setMergeFlag( bool b )                 { _mergeFlag     = b ; }
setMmvdFlagCodingUnit449   void              setMmvdFlag( bool b )                  { _mmvdFlag      = b ; }
setAffineFlagCodingUnit450   void              setAffineFlag( bool b )                { _affineFlag    = b ; }
setMergeTypeCodingUnit451   void              setMergeType( MergeType mt )           { _mergeType     = mt; }
setAffineTypeCodingUnit452   void              setAffineType( AffineModel at )        { _affineType    = at; CHECKD( at >= AFFINE_MODEL_NUM, "Needs to be '0' or '1'!" ); }
setGeoFlagCodingUnit453   void              setGeoFlag( bool b )                   { _geoFlag       = b ; }
setMergeIdxCodingUnit454   void              setMergeIdx( uint8_t id )              { _mrgIdx        = id; CHECKD( id >=  8, "Merge index needs to be smaller than '8'!"); }
setGeoMergeIdx0CodingUnit455   void              setGeoMergeIdx0( uint8_t id )          { _geoMrgIdx0    = id; CHECKD( id >=  8, "Merge index needs to be smaller than '8'!"); }
setGeoMergeIdx1CodingUnit456   void              setGeoMergeIdx1( uint8_t id )          { _geoMrgIdx1    = id; CHECKD( id >=  8, "Merge index needs to be smaller than '8'!"); }
setInterDirCodingUnit457   void              setInterDir( uint8_t id )              { _interDir      = id; CHECKD( id >=  4, "Inter dir needs to be smaller than '4'!"); }
setMultiRefIdxCodingUnit458   void              setMultiRefIdx( uint8_t id )           { _multiRefIdx   = id; CHECKD( id >=  3, "Multi-ref. index needs to be smaller than '3'!"); }
setMipFlagCodingUnit459   void              setMipFlag( bool b )                   { _mipFlag       = b ; }
setImvCodingUnit460   void              setImv( uint8_t id )                   { _imv           = id; CHECKD( id >=  4, "IMV needs to be smaller than '4'!"); }
setSmvdModeCodingUnit461   void              setSmvdMode( uint8_t id )              { _smvd          = id; CHECKD( id >=  4, "SMVD mode needs to be smaller than '4'!"); }
setBcwIdxCodingUnit462   void              setBcwIdx( uint8_t id )                { _bcw           = id; CHECKD( id >=  5, "BCW idx needs to be smaller than '5'!"); }
463 
setInterDirrefIdxGeo0CodingUnit464   void              setInterDirrefIdxGeo0( uint8_t id )    { _geoDir0       = id; }
setInterDirrefIdxGeo1CodingUnit465   void              setInterDirrefIdxGeo1( uint8_t id )    { _geoDir1       = id; }
466 
467   CodingUnit& operator=(const MotionInfo& mi);
468 
469   // for accessing motion information, which can have higher resolution than PUs (should always be used, when accessing neighboring motion information)
470   const MotionInfo& getMotionInfo() const;
471   const MotionInfo& getMotionInfo( const Position& pos ) const;
472   MotionBuf         getMotionBuf();
473   CMotionBuf        getMotionBuf() const;
474 
475   void              minInit( const UnitArea& unit );
476 };
477 
478 typedef CodingUnit PredictionUnit;
479 
480 // ---------------------------------------------------------------------------
481 // Utility class for easy for-each like unit traversing
482 // ---------------------------------------------------------------------------
483 
484 }
485 
486 #include <iterator>
487 
488 namespace vvdec {
489 
490 template<typename T>
491 class UnitIterator : public std::iterator<std::forward_iterator_tag, T>
492 {
493 private:
494   T* m_punit;
495 
496 public:
UnitIterator()497   UnitIterator(           ) : m_punit( nullptr ) { }
UnitIterator(T * _punit)498   UnitIterator( T* _punit ) : m_punit( _punit  ) { }
499 
500   typedef T&       reference;
501   typedef T const& const_reference;
502   typedef T*       pointer;
503   typedef T const* const_pointer;
504 
505   reference        operator*()                                      { return *m_punit; }
506   const_reference  operator*()                                const { return *m_punit; }
507   pointer          operator->()                                     { return  m_punit; }
508   const_pointer    operator->()                               const { return  m_punit; }
509 
510   UnitIterator<T>& operator++()                                     { m_punit = m_punit->next; return *this; }
511   UnitIterator<T>  operator++( int )                                { auto x = *this; ++( *this ); return x; }
512   bool             operator!=( const UnitIterator<T>& other ) const { return m_punit != other.m_punit; }
513   bool             operator==( const UnitIterator<T>& other ) const { return m_punit == other.m_punit; }
514 };
515 
516 template<typename T>
517 class UnitTraverser
518 {
519 private:
520   T* m_begin;
521   T* m_end;
522 
523 public:
UnitTraverser()524   UnitTraverser(                    ) : m_begin( nullptr ), m_end( nullptr ) { }
UnitTraverser(T * _begin,T * _end)525   UnitTraverser( T* _begin, T* _end ) : m_begin( _begin  ), m_end( _end    ) { }
526 
527   typedef T                     value_type;
528   typedef size_t                size_type;
529   typedef T&                    reference;
530   typedef T const&              const_reference;
531   typedef T*                    pointer;
532   typedef T const*              const_pointer;
533   typedef UnitIterator<T>       iterator;
534   typedef UnitIterator<const T> const_iterator;
535 
begin()536   iterator        begin()        { return UnitIterator<T>( m_begin ); }
begin()537   const_iterator  begin()  const { return UnitIterator<T>( m_begin ); }
cbegin()538   const_iterator  cbegin() const { return UnitIterator<T>( m_begin ); }
end()539   iterator        end()          { return UnitIterator<T>( m_end   ); }
end()540   const_iterator  end()    const { return UnitIterator<T>( m_end   ); }
cend()541   const_iterator  cend()   const { return UnitIterator<T>( m_end   ); }
542 };
543 
544 typedef UnitTraverser<CodingUnit>            CUTraverser;
545 typedef UnitTraverser<const CodingUnit>     cCUTraverser;
546 
547 typedef UnitTraverser<      TransformUnit>   TUTraverser;
548 typedef UnitTraverser<const TransformUnit>  cTUTraverser;
549 
550 }
551 
552 #include <memory>
553 #include <mutex>
554 
555 namespace vvdec {
556 
557 // ---------------------------------------------------------------------------
558 // dynamic cache
559 // ---------------------------------------------------------------------------
560 
561 static constexpr size_t DYN_CACHE_CHUNK_SIZE = 1024;
562 
563 template<typename T>
564 class dynamic_cache
565 {
566   std::vector<T*> m_cache;
567   std::vector<T*> m_cacheChunks;
568 
569 public:
570 
~dynamic_cache()571   ~dynamic_cache()
572   {
573     deleteEntries();
574   }
575 
deleteEntries()576   void deleteEntries()
577   {
578     for( auto &chunk : m_cacheChunks )
579     {
580       free( chunk );
581     }
582 
583     m_cache      .clear();
584     m_cacheChunks.clear();
585   }
586 
get()587   T* get()
588   {
589     T* ret;
590 
591     if( !m_cache.empty() )
592     {
593       ret = m_cache.back();
594       m_cache.pop_back();
595     }
596     else
597     {
598       T* chunk = (T*) malloc( DYN_CACHE_CHUNK_SIZE * sizeof( T ) );
599 
600       //GCC_WARNING_DISABLE_class_memaccess
601       //memset( chunk, 0, DYN_CACHE_CHUNK_SIZE * sizeof( T ) );
602       //GCC_WARNING_RESET
603 
604       m_cacheChunks.push_back( chunk );
605       m_cache      .reserve( m_cache.size() + DYN_CACHE_CHUNK_SIZE );
606 
607       for( ptrdiff_t p = 0; p < DYN_CACHE_CHUNK_SIZE; p++ )
608       {
609         //m_cache.push_back( &chunk[DYN_CACHE_CHUNK_SIZE - p - 1] );
610         m_cache.push_back( &chunk[p] );
611       }
612 
613       ret = m_cache.back();
614       m_cache.pop_back();
615     }
616 
617     return ret;
618   }
619 
defragment()620   void defragment()
621   {
622     m_cache.clear();
623 
624     for( T* chunk : m_cacheChunks )
625     {
626       //GCC_WARNING_DISABLE_class_memaccess
627       //memset( chunk, 0, DYN_CACHE_CHUNK_SIZE * sizeof( T ) );
628       //GCC_WARNING_RESET
629 
630       for( ptrdiff_t p = 0; p < DYN_CACHE_CHUNK_SIZE; p++ )
631       {
632         //m_cache.push_back( &chunk[DYN_CACHE_CHUNK_SIZE - p - 1] );
633         m_cache.push_back( &chunk[p] );
634       }
635     }
636   }
637 
cache(std::vector<T * > & vel)638   void cache( std::vector<T*>& vel )
639   {
640     m_cache.insert( m_cache.end(), vel.begin(), vel.end() );
641     vel.clear();
642   }
643 };
644 
645 typedef dynamic_cache<struct CodingUnit> CUCache;
646 typedef dynamic_cache<struct TransformUnit> TUCache;
647 
648 struct ThreadSafeCUCache
649 {
650   std::shared_ptr<CUCache> getCuCache();
651   std::shared_ptr<TUCache> getTuCache();
652 
653 private:
654   std::mutex m_mutex;
655 
656   // we use the shared_ptr reference-count to track if a cache is in use or available
657   std::vector< std::shared_ptr<CUCache> > m_cuCaches;
658   std::vector< std::shared_ptr<TUCache> > m_tuCaches;
659 };
660 
661 }
662 
663