Coverage Report

Created: 2026-07-16 06:32

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 true, 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
  bool lockedByApplication = false;
220
221
  int         poc          = 0;
222
  uint64_t    cts          = 0;   // composition time stamp
223
  uint64_t    dts          = 0;   // decoding time stamp
224
  uint32_t    tempLayer    = std::numeric_limits<uint32_t>::max();
225
  uint32_t    depth        = 0;
226
  int         layerId      = NOT_VALID;
227
  NalUnitType eNalUnitType = NAL_UNIT_INVALID;
228
  uint32_t    bits         = 0;   // input nal bit count
229
  bool        rap          = 0;   // random access point flag
230
  void       *userData     = nullptr;      ///< opaque user data
231
  int         decodingOrderNumber = 0;
232
233
  std::vector<int>        sliceSubpicIdx;
234
  std::vector<SubPic>     subPictures;
235
  std::vector<PelStorage> m_subPicRefBufs;   // used as reference for subpictures, that are treated as pictures
236
237
  bool subLayerNonReferencePictureDueToSTSA = 0;
238
239
  PelStorage     m_bufs[NUM_PIC_TYPES];
240
  uint32_t       margin      = 0;
241
242
  WaitCounter     m_divTasksCounter;        // for all tasks, that are not covered by the other WaitCounters => only needed for cleanup during exception handling
243
  WaitCounter     m_ctuTaskCounter;
244
  WaitCounter     m_borderExtTaskCounter;
245
  Barrier         m_copyWrapBufDone;
246
  BlockingBarrier parseDone;
247
  BlockingBarrier reconDone;
248
#if RECO_WHILE_PARSE
249
  std::vector<Barrier> ctuParsedBarrier;
250
#endif
251
#if ALLOW_MIDER_LF_DURING_PICEXT
252
  CBarrierVec     refPicExtDepBarriers;
253
#endif
254
255
  CodingStructure*    cs = nullptr;
256
  std::vector<Slice*> slices;
257
258
  seiMessages        seiMessageList;
259
260
  bool               isRefScaled( const PPS* pps ) const
261
0
  {
262
0
    const PPS*  pps0     = slices[0]->getPPS();
263
0
    const Size& recoSize = m_bufs[PIC_RECONSTRUCTION].bufs[COMPONENT_Y];
264
0
    return ( recoSize.width  != pps->getPicWidthInLumaSamples()    ||
265
0
             recoSize.height != pps->getPicHeightInLumaSamples() ) ||
266
0
           ( ( pps0->getScalingWindow().getWindowEnabledFlag()   || pps->getScalingWindow().getWindowEnabledFlag() ) && (
267
0
               pps0->getScalingWindow().getWindowLeftOffset()    != pps->getScalingWindow().getWindowLeftOffset()  ||
268
0
               pps0->getScalingWindow().getWindowRightOffset()   != pps->getScalingWindow().getWindowRightOffset() ||
269
0
               pps0->getScalingWindow().getWindowTopOffset()     != pps->getScalingWindow().getWindowTopOffset()   ||
270
0
               pps0->getScalingWindow().getWindowBottomOffset()  != pps->getScalingWindow().getWindowBottomOffset() ) );
271
0
  }
272
273
0
  bool         isWrapAroundEnabled( const PPS* pps ) const  { return  pps->getUseWrapAround() && !isRefScaled( pps ); }
274
275
  Slice*       allocateNewSlice( Slice** pilot = nullptr );
276
  void         clearSliceBuffer();
277
  bool         lastSliceOfPicPresent() const;
278
279
  void         waitForAllTasks();
280
  void         ensureUsableAsRef();
281
  void         fillGrey( const SPS* fallbackSPS = nullptr );
282
283
#if TRACE_ENABLE_ITT
284
  __itt_domain* m_itt_decLibInst;
285
#endif
286
287
public:
288
289
#if  ENABLE_SIMD_OPT_PICTURE && defined( TARGET_SIMD_X86 )
290
  void initPictureX86();
291
  template <X86_VEXT vext>
292
  void _initPictureX86();
293
#endif
294
295
#if ENABLE_SIMD_OPT_PICTURE && defined( TARGET_SIMD_ARM )
296
  void initPictureARM();
297
  template <ARM_VEXT vext>
298
  void _initPictureARM();
299
#endif
300
};
301
302
int calcAndPrintHashStatus(const CPelUnitBuf& pic, const vvdecSEIDecodedPictureHash* pictureHashSEI, const BitDepths &bitDepths, const MsgLevel msgl);
303
304
}   // namespace vvdec