Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vvdec/source/Lib/CommonLib/Picture.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     Picture.h
44
 *  \brief    Description of a coded picture
45
 */
46
47
#pragma once
48
49
#include "CommonDef.h"
50
51
#include "Common.h"
52
#include "Unit.h"
53
#include "Buffer.h"
54
#include "Unit.h"
55
#include "Slice.h"
56
#include "CodingStructure.h"
57
#include "SEI_internal.h"
58
59
#include "vvdec/sei.h"
60
61
namespace vvdec
62
{
63
#if  ENABLE_SIMD_OPT_PICTURE && defined( TARGET_SIMD_X86 )
64
using namespace x86_simd;
65
#endif
66
67
struct Picture;
68
69
typedef std::list<Picture*> PicList;
70
71
struct PicListRange
72
{
73
  PicList::const_iterator m_begin;
74
  PicList::const_iterator m_end;
75
76
0
  const PicList::const_iterator begin() const { return m_begin; }
77
0
  const PicList::const_iterator end  () const { return m_end;   }
78
};
79
80
81
struct Picture : public UnitArea
82
{
83
0
  Picture() = default;
84
0
  ~Picture() = default;
85
  CLASS_COPY_MOVE_DELETE( Picture )
86
87
  void create(const ChromaFormat &_chromaFormat, const Size &size, const unsigned _maxCUSize, const unsigned margin, const int layerId, UserAllocator* userAlloc = nullptr );
88
  void createWrapAroundBuf( const bool isWrapAround, const unsigned _maxCUSize );
89
  void resetForUse( int _layerId );
90
  void destroy();
91
92
0
         Pel*      getRecoBufPtr   (const ComponentID compID, bool wrap=false)       { return m_bufs[wrap ? PIC_RECON_WRAP : PIC_RECONSTRUCTION].bufs[compID].buf; }
93
0
  const  Pel*      getRecoBufPtr   (const ComponentID compID, bool wrap=false) const { return m_bufs[wrap ? PIC_RECON_WRAP : PIC_RECONSTRUCTION].bufs[compID].buf; }
94
0
         ptrdiff_t getRecoBufStride(const ComponentID compID, bool wrap=false)       { return m_bufs[wrap ? PIC_RECON_WRAP : PIC_RECONSTRUCTION].bufs[compID].stride; }
95
0
  const  ptrdiff_t getRecoBufStride(const ComponentID compID, bool wrap=false) const { return m_bufs[wrap ? PIC_RECON_WRAP : PIC_RECONSTRUCTION].bufs[compID].stride; }
96
         PelBuf     getRecoBuf(const ComponentID compID, bool wrap=false);
97
  const CPelBuf     getRecoBuf(const ComponentID compID, bool wrap=false) const;
98
         PelBuf     getRecoBuf(const CompArea &blk,      bool wrap=false);
99
  const CPelBuf     getRecoBuf(const CompArea &blk,      bool wrap=false) const;
100
         PelUnitBuf getRecoBuf(const UnitArea &unit,     bool wrap=false);
101
  const CPelUnitBuf getRecoBuf(const UnitArea &unit,     bool wrap=false) const;
102
         PelUnitBuf getRecoBuf(bool wrap=false);
103
  const CPelUnitBuf getRecoBuf(bool wrap=false) const;
104
105
  // This returns a CPelBuf, with the origin at the picture origin (0,0), but the actual storage size of the sub picture.
106
  // It can be used the same way as the full picture buffer, but you should only reference the data within the actual sub picture.
107
  // Also, handle with care, because stride < width.
108
  const CPelBuf getSubPicBuf( int subPicIdx, const ComponentID compID, bool wrap = false ) const
109
0
  {
110
0
    CHECK( wrap, "wraparound for subpics not supported yet" );
111
112
0
    Position subPicPos( subPictures[subPicIdx].getSubPicLeft() >> getComponentScaleX( compID, m_subPicRefBufs[subPicIdx].chromaFormat ),
113
0
                        subPictures[subPicIdx].getSubPicTop()  >> getComponentScaleY( compID, m_subPicRefBufs[subPicIdx].chromaFormat ) );
114
115
0
    Size targetSize( m_bufs[PIC_RECONSTRUCTION].get( compID ) );
116
117
0
    const auto& subPicComp = m_subPicRefBufs[subPicIdx].bufs[compID];
118
0
    return CPelBuf( subPicComp.bufAt( -subPicPos.x, -subPicPos.y ), subPicComp.stride, targetSize );
119
0
  }
120
0
  const Pel*      getSubPicBufPtr   ( int subPicIdx, const ComponentID compID, bool wrap = false ) const { return getSubPicBuf( subPicIdx, compID, wrap ).buf;    }
121
0
  const ptrdiff_t getSubPicBufStride( int subPicIdx, const ComponentID compID, bool wrap = false ) const { return getSubPicBuf( subPicIdx, compID, wrap ).stride; }
122
123
private:
124
0
         PelBuf     getBuf(const ComponentID compID, const PictureType &type)       { return m_bufs[type].bufs[ compID ]; }
125
0
  const CPelBuf     getBuf(const ComponentID compID, const PictureType &type) const { return m_bufs[type].bufs[ compID ]; }
126
         PelBuf     getBuf(const CompArea &blk,      const PictureType &type);
127
  const CPelBuf     getBuf(const CompArea &blk,      const PictureType &type) const;
128
         PelUnitBuf getBuf(const UnitArea &unit,     const PictureType &type);
129
  const CPelUnitBuf getBuf(const UnitArea &unit,     const PictureType &type) const;
130
131
public:
132
  void extendPicBorder    (                  bool top = true, bool bottom = true, bool leftrightT = true, bool leftrightB = true, ChannelType chType = MAX_NUM_CHANNEL_TYPE );
133
  void extendPicBorderBuf ( PelStorage& buf, bool top = true, bool bottom = true, bool leftrightT = true, bool leftrightB = true, ChannelType chType = MAX_NUM_CHANNEL_TYPE );
134
  void extendPicBorderWrap(                  bool top = true, bool bottom = true, bool leftrightT = true, bool leftrightB = true, ChannelType chType = MAX_NUM_CHANNEL_TYPE );
135
136
  void (*paddPicBorderBot) (Pel *pi, ptrdiff_t stride,int width,int xmargin,int ymargin);
137
  void (*paddPicBorderTop) (Pel *pi, ptrdiff_t stride,int width,int xmargin,int ymargin);
138
  void (*paddPicBorderLeftRight) (Pel *pi, ptrdiff_t stride,int width,int xmargin,int height);
139
140
  void finalInit( CUChunkCache* cuChunkCache, TUChunkCache* tuChunkCache, const SPS * sps, const PPS * pps, const std::shared_ptr<PicHeader>& ph, const APS* const alfApss[ALF_CTB_MAX_NUM_APS], const APS * lmcsAps, const APS* scalingListAps, bool phPSupdate = true );
141
142
0
  int      getPOC()                           const { return poc; }
143
0
  uint64_t getCts()                           const { return cts; }
144
0
  uint64_t getDts()                           const { return dts; }
145
0
  uint32_t getTLayer()                        const { return tempLayer; }
146
0
  uint32_t getNaluBits()                      const { return bits; }
147
0
  bool     getRap()                           const { return rap; }
148
149
0
  bool     isCLVSS()                          const { return !slices.empty() && slices[0]->isClvssPu(); }
150
151
  Pel*   getOrigin( const PictureType &type, const ComponentID compID ) const;
152
  PelBuf getOriginBuf( const PictureType &type, const ComponentID compID );
153
154
  Size   getBufSize( const PictureType &type, const ComponentID compID ) const;
155
  void*  getBufAllocator( const ComponentID compID );
156
  bool   isExternAllocator() const;
157
  const  UserAllocator* getUserAllocator() const;
158
159
0
  int  getDecodingOrderNumber()               const { return decodingOrderNumber; }
160
0
  void setDecodingOrderNumber(const int val)        { decodingOrderNumber = val;  }
161
162
0
  bool getMixedNaluTypesInPicFlag()           const { return slices[0]->getPPS()->getMixedNaluTypesInPicFlag(); }
163
164
  std::vector<Picture*> buildAllRefPicsVec();
165
166
public:
167
  void startProcessingTimer();
168
  void stopProcessingTimer();
169
0
  void resetProcessingTime() { m_dProcessingTime = 0; }
170
0
  double getProcessingTime() const { return m_dProcessingTime; }
171
172
  std::chrono::time_point<std::chrono::steady_clock> m_processingStartTime;
173
  double                                             m_dProcessingTime = 0;
174
  std::mutex                                         m_timerMutex;
175
176
  enum PicStateEnum
177
  {
178
    init,
179
    parsing,
180
    parsed,
181
    reconstructing,
182
    reconstructed,
183
    finished
184
  };
185
  using PicState = std::atomic<PicStateEnum>;
186
  PicState progress{ init };
187
188
  enum RefMark : uint8_t
189
  {
190
    unreferenced = 0,
191
    ShortTerm,
192
    LongTerm
193
  };
194
195
  bool             subPicExtStarted        = false;
196
  bool             borderExtStarted        = false;
197
  RefMark          dpbReferenceMark        = unreferenced;   // only used during parsing, manage the DPB and to build the reference picture lists
198
  bool             neededForOutput         = false;
199
  std::atomic_bool stillReferenced         { false };        // set as long as there is a picture in progress, that references this one. ('referenced' might be unset during parsing)
200
  bool             isReferencePic          = false;          // mainly for setting vvdecPicAttributes::isRefPic for the library output frame
201
  bool             wasLost                 = false;
202
  bool             error                   = false;
203
  bool             exceptionThrownOut      = false;
204
  bool             topField                = false;
205
  bool             fieldPic                = false;
206
  bool             nonReferencePictureFlag = false;
207
  int              skippedDecCount         = 0;
208
209
  bool              picCheckedDPH = false;
210
  std::vector<bool> subpicsCheckedDPH;
211
  bool              dphMismatch   = false;
212
213
  // As long as this field is true, the picture will not be reused or deleted.
214
  // An external application needs to call DecLib::releasePicture(), when it is done using the picture buffer.
215
  bool lockedByApplication = false;
216
217
  int         poc          = 0;
218
  uint64_t    cts          = 0;   // composition time stamp
219
  uint64_t    dts          = 0;   // decoding time stamp
220
  uint32_t    tempLayer    = std::numeric_limits<uint32_t>::max();
221
  uint32_t    depth        = 0;
222
  int         layerId      = NOT_VALID;
223
  NalUnitType eNalUnitType = NAL_UNIT_INVALID;
224
  uint32_t    bits         = 0;   // input nal bit count
225
  bool        rap          = 0;   // random access point flag
226
  void       *userData     = nullptr;      ///< opaque user data
227
  int         decodingOrderNumber = 0;
228
229
  std::vector<int>        sliceSubpicIdx;
230
  std::vector<SubPic>     subPictures;
231
  std::vector<PelStorage> m_subPicRefBufs;   // used as reference for subpictures, that are treated as pictures
232
233
  bool subLayerNonReferencePictureDueToSTSA = 0;
234
235
  PelStorage     m_bufs[NUM_PIC_TYPES];
236
  uint32_t       margin      = 0;
237
238
  WaitCounter     m_divTasksCounter;        // for all tasks, that are not covered by the other WaitCounters => only needed for cleanup during exception handling
239
  WaitCounter     m_ctuTaskCounter;
240
  WaitCounter     m_borderExtTaskCounter;
241
  Barrier         m_copyWrapBufDone;
242
  BlockingBarrier parseDone;
243
  BlockingBarrier reconDone;
244
#if RECO_WHILE_PARSE
245
  std::vector<Barrier> ctuParsedBarrier;
246
#endif
247
#if ALLOW_MIDER_LF_DURING_PICEXT
248
  CBarrierVec     refPicExtDepBarriers;
249
#endif
250
251
  CodingStructure*    cs = nullptr;
252
  std::vector<Slice*> slices;
253
254
  seiMessages        seiMessageList;
255
256
  bool               isRefScaled( const PPS* pps ) const
257
0
  {
258
0
    const PPS*  pps0     = slices[0]->getPPS();
259
0
    const Size& recoSize = m_bufs[PIC_RECONSTRUCTION].bufs[COMPONENT_Y];
260
0
    return ( recoSize.width  != pps->getPicWidthInLumaSamples()    ||
261
0
             recoSize.height != pps->getPicHeightInLumaSamples() ) ||
262
0
           ( ( pps0->getScalingWindow().getWindowEnabledFlag()   || pps->getScalingWindow().getWindowEnabledFlag() ) && (
263
0
               pps0->getScalingWindow().getWindowLeftOffset()    != pps->getScalingWindow().getWindowLeftOffset()  ||
264
0
               pps0->getScalingWindow().getWindowRightOffset()   != pps->getScalingWindow().getWindowRightOffset() ||
265
0
               pps0->getScalingWindow().getWindowTopOffset()     != pps->getScalingWindow().getWindowTopOffset()   ||
266
0
               pps0->getScalingWindow().getWindowBottomOffset()  != pps->getScalingWindow().getWindowBottomOffset() ) );
267
0
  }
268
269
0
  bool         isWrapAroundEnabled( const PPS* pps ) const  { return  pps->getUseWrapAround() && !isRefScaled( pps ); }
270
271
  Slice*       allocateNewSlice( Slice** pilot = nullptr );
272
  void         clearSliceBuffer();
273
  bool         lastSliceOfPicPresent() const;
274
275
  void         waitForAllTasks();
276
  void         ensureUsableAsRef();
277
  void         fillGrey( const SPS* sps );
278
279
#if TRACE_ENABLE_ITT
280
  __itt_domain* m_itt_decLibInst;
281
#endif
282
283
public:
284
285
#if  ENABLE_SIMD_OPT_PICTURE && defined( TARGET_SIMD_X86 )
286
  void initPictureX86();
287
  template <X86_VEXT vext>
288
  void _initPictureX86();
289
#endif
290
};
291
292
int calcAndPrintHashStatus(const CPelUnitBuf& pic, const vvdecSEIDecodedPictureHash* pictureHashSEI, const BitDepths &bitDepths, const MsgLevel msgl);
293
294
}   // namespace vvdec