Coverage Report

Created: 2026-08-31 06:22

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