Coverage Report

Created: 2026-08-31 08:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/contrib/x86_64-unknown-linux-gnu/include/matroska/KaxBlock.h
Line
Count
Source
1
/****************************************************************************
2
** libmatroska : parse Matroska files, see http://www.matroska.org/
3
**
4
** <file/class description>
5
**
6
** Copyright (C) 2002-2010 Steve Lhomme.  All rights reserved.
7
**
8
** This library is free software; you can redistribute it and/or
9
** modify it under the terms of the GNU Lesser General Public
10
** License as published by the Free Software Foundation; either
11
** version 2.1 of the License, or (at your option) any later version.
12
**
13
** This library is distributed in the hope that it will be useful,
14
** but WITHOUT ANY WARRANTY; without even the implied warranty of
15
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
** Lesser General Public License for more details.
17
**
18
** You should have received a copy of the GNU Lesser General Public
19
** License along with this library; if not, write to the Free Software
20
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21
**
22
** See http://www.gnu.org/licenses/lgpl-2.1.html for LGPL licensing information.**
23
** Contact license@matroska.org if any conditions of this licensing are
24
** not clear to you.
25
**
26
**********************************************************************/
27
28
/*!
29
  \file
30
  \todo add a PureBlock class to group functionalities between Block and BlockVirtual
31
  \version \$Id: KaxBlock.h,v 1.24 2004/04/14 23:26:17 robux4 Exp $
32
  \author Steve Lhomme     <robux4 @ users.sf.net>
33
  \author Julien Coloos    <suiryc @ users.sf.net>
34
*/
35
#ifndef LIBMATROSKA_BLOCK_H
36
#define LIBMATROSKA_BLOCK_H
37
38
#include <vector>
39
40
#include "matroska/KaxTypes.h"
41
#include <ebml/EbmlBinary.h>
42
#include <ebml/EbmlMaster.h>
43
#include "matroska/KaxTracks.h"
44
#include "matroska/KaxDefines.h"
45
46
using namespace libebml;
47
48
namespace libmatroska {
49
50
class KaxCluster;
51
class KaxReferenceBlock;
52
class KaxInternalBlock;
53
class KaxBlockBlob;
54
55
class MATROSKA_DLL_API DataBuffer {
56
  protected:
57
    binary  *myBuffer{nullptr};
58
    uint32   mySize;
59
    bool     bValidValue{true};
60
    bool     (*myFreeBuffer)(const DataBuffer & aBuffer); // method to free the internal buffer
61
    bool     bInternalBuffer;
62
63
  public:
64
    DataBuffer(binary * aBuffer, uint32 aSize, bool (*aFreeBuffer)(const DataBuffer & aBuffer) = nullptr, bool _bInternalBuffer = false)
65
      :mySize(aSize)
66
      ,myFreeBuffer(aFreeBuffer)
67
      ,bInternalBuffer(_bInternalBuffer)
68
    {
69
      if (bInternalBuffer)
70
      {
71
        try {
72
          myBuffer = new binary[mySize];
73
          memcpy(myBuffer, aBuffer, mySize);
74
        } catch (const std::bad_alloc &) {
75
          bValidValue = false;
76
        }
77
      }
78
      else
79
        myBuffer = aBuffer;
80
    }
81
82
    virtual ~DataBuffer() = default;
83
    virtual binary * Buffer() {assert(bValidValue); return myBuffer;}
84
    virtual uint32   & Size() {return mySize;};
85
    virtual const binary * Buffer() const {assert(bValidValue); return myBuffer;}
86
    virtual uint32   Size()   const {return mySize;};
87
    bool    FreeBuffer(const DataBuffer & aBuffer) {
88
      bool bResult = true;
89
      if (myBuffer != nullptr && bValidValue) {
90
        if (myFreeBuffer != nullptr)
91
          bResult = myFreeBuffer(aBuffer);
92
        if (bInternalBuffer)
93
          delete [] myBuffer;
94
        myBuffer = nullptr;
95
        mySize = 0;
96
        bValidValue = false;
97
      }
98
      return bResult;
99
    }
100
101
    virtual DataBuffer * Clone();
102
};
103
104
class MATROSKA_DLL_API SimpleDataBuffer : public DataBuffer {
105
  public:
106
    SimpleDataBuffer(binary * aBuffer, uint32 aSize, uint32 aOffset, bool (*aFreeBuffer)(const DataBuffer & aBuffer) = myFreeBuffer)
107
      :DataBuffer(aBuffer + aOffset, aSize, aFreeBuffer)
108
      ,Offset(aOffset)
109
      ,BaseBuffer(aBuffer)
110
    {}
111
    ~SimpleDataBuffer() override = default;
112
113
    DataBuffer * Clone() override {return new SimpleDataBuffer(*this);}
114
115
  protected:
116
    uint32 Offset;
117
    binary * BaseBuffer;
118
119
    static bool myFreeBuffer(const DataBuffer & aBuffer)
120
    {
121
      auto _Buffer = static_cast<const SimpleDataBuffer*>(&aBuffer)->BaseBuffer;
122
      if (_Buffer != nullptr)
123
        free(_Buffer);
124
      return true;
125
    }
126
127
    SimpleDataBuffer(const SimpleDataBuffer & ToClone);
128
};
129
130
/*!
131
  \note the data is copied locally, it can be freed right away
132
* /
133
class MATROSKA_DLL_API NotSoSimpleDataBuffer : public SimpleDataBuffer {
134
  public:
135
    NotSoSimpleDataBuffer(binary * aBuffer, uint32 aSize, uint32 aOffset)
136
      :SimpleDataBuffer(new binary[aSize - aOffset], aSize, 0)
137
    {
138
      memcpy(BaseBuffer, aBuffer + aOffset, aSize - aOffset);
139
    }
140
};
141
*/
142
143
DECLARE_MKX_MASTER(KaxBlockGroup)
144
  public:
145
    ~KaxBlockGroup() override = default;
146
147
    /*!
148
      \brief Addition of a frame without references
149
    */
150
    bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO);
151
    /*!
152
      \brief Addition of a frame with a backward reference (P frame)
153
    */
154
    bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, LacingType lacing = LACING_AUTO);
155
156
    /*!
157
      \brief Addition of a frame with a backward+forward reference (B frame)
158
    */
159
    bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, const KaxBlockGroup & ForwBlock, LacingType lacing = LACING_AUTO);
160
    bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockBlob * PastBlock, const KaxBlockBlob * ForwBlock, LacingType lacing = LACING_AUTO);
161
162
    void SetParent(KaxCluster & aParentCluster);
163
164
0
    void SetParentTrack(const KaxTrackEntry & aParentTrack) {
165
0
      ParentTrack = &aParentTrack;
166
0
    }
167
168
    /*!
169
      \brief Set the duration of the contained frame(s) (for the total number of frames)
170
    */
171
    void SetBlockDuration(uint64 TimeLength);
172
    bool GetBlockDuration(uint64 &TheTimecode) const;
173
174
    /*!
175
      \return the global timecode of this Block (not just the delta to the Cluster)
176
    */
177
    uint64 GlobalTimecode() const;
178
    uint64 GlobalTimecodeScale() const {
179
      assert(ParentTrack != nullptr);
180
      return ParentTrack->GlobalTimecodeScale();
181
    }
182
183
    uint16 TrackNumber() const;
184
185
    uint64 ClusterPosition() const;
186
187
    /*!
188
      \return the number of references to other frames
189
    */
190
    unsigned int ReferenceCount() const;
191
    const KaxReferenceBlock & Reference(unsigned int Index) const;
192
193
    /*!
194
      \brief release all the frames of all Blocks
195
    */
196
    void ReleaseFrames();
197
198
    operator KaxInternalBlock &();
199
200
    const KaxCluster *GetParentCluster() const { return ParentCluster; }
201
202
  protected:
203
    KaxCluster * ParentCluster{nullptr};
204
    const KaxTrackEntry * ParentTrack{nullptr};
205
};
206
207
class MATROSKA_DLL_API KaxInternalBlock : public EbmlBinary {
208
  public:
209
    KaxInternalBlock(EBML_DEF_CONS EBML_DEF_SEP bool bSimple EBML_DEF_SEP EBML_EXTRA_PARAM) :EBML_DEF_BINARY_INIT EBML_DEF_SEP bIsSimple(bSimple)
210
    {}
211
    KaxInternalBlock(const KaxInternalBlock & ElementToClone);
212
    ~KaxInternalBlock() override;
213
    bool ValidateSize() const override;
214
215
281k
    uint16 TrackNum() const {return TrackNumber;}
216
    /*!
217
      \todo !!!! This method needs to be changes !
218
    */
219
87.2k
    uint64 GlobalTimecode() const {return Timecode;}
220
221
    /*!
222
      \note override this function to generate the Data/Size on the fly, unlike the usual binary elements
223
    */
224
    filepos_t UpdateSize(bool bSaveDefault = false, bool bForceRender = false) override;
225
    filepos_t ReadData(IOCallback & input, ScopeMode ReadFully = SCOPE_ALL_DATA) override;
226
227
    /*!
228
      \brief Only read the head of the Block (not internal data)
229
      \note convenient when you are parsing the file quickly
230
    */
231
    uint64 ReadInternalHead(IOCallback & input);
232
233
61.2k
    unsigned int NumberFrames() const { return SizeList.size();}
234
594k
    DataBuffer & GetBuffer(unsigned int iIndex) {return *myBuffers[iIndex];}
235
236
    bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO, bool invisible = false);
237
238
    /*!
239
      \brief release all the frames of all Blocks
240
    */
241
    void ReleaseFrames();
242
243
    void SetParent(KaxCluster & aParentCluster);
244
245
    /*!
246
      \return Returns the lacing type that produces the smallest footprint.
247
    */
248
    LacingType GetBestLacingType() const;
249
250
    /*!
251
      \param FrameNumber 0 for the first frame
252
      \return the position in the stream for a given frame
253
      \note return -1 if the position doesn't exist
254
    */
255
    int64 GetDataPosition(size_t FrameNumber = 0);
256
257
    /*!
258
      \param FrameNumber 0 for the first frame
259
      \return the size of a given frame
260
      \note return -1 if the position doesn't exist
261
    */
262
    int64 GetFrameSize(size_t FrameNumber = 0);
263
264
0
    bool IsInvisible() const { return mInvisible; }
265
266
    uint64 ClusterPosition() const;
267
268
    /*!
269
     * \return Get the timestamp as written in the Block (not scaled).
270
     * \since LIBMATROSKA_VERSION >= 0x010700
271
     */
272
0
    int16 GetRelativeTimestamp() const { return LocalTimecode; }
273
274
  protected:
275
    std::vector<DataBuffer *> myBuffers;
276
    std::vector<int32>        SizeList;
277
    uint64                    Timecode; // temporary timecode of the first frame, non scaled
278
    int16                     LocalTimecode;
279
    bool                      bLocalTimecodeUsed{false};
280
    uint16                    TrackNumber;
281
    LacingType                mLacing{LACING_AUTO};
282
    bool                      mInvisible{false};
283
    uint64                    FirstFrameLocation;
284
285
    KaxCluster               *ParentCluster{nullptr};
286
    bool                      bIsSimple;
287
    bool                      bIsKeyframe{true};
288
    bool                      bIsDiscardable{false};
289
290
    filepos_t RenderData(IOCallback & output, bool bForceRender, bool bSaveDefault = false) override;
291
};
292
293
DECLARE_MKX_CONTEXT(KaxBlock)
294
class MATROSKA_DLL_API KaxBlock : public KaxInternalBlock {
295
  public:
296
    KaxBlock(EBML_EXTRA_PARAM) :KaxInternalBlock(EBML_DEF_BINARY_CTX(KaxBlock)EBML_DEF_SEP false EBML_DEF_SEP EBML_EXTRA_CALL) {}
297
        EBML_CONCRETE_CLASS(KaxBlock)
298
};
299
300
DECLARE_MKX_CONTEXT(KaxSimpleBlock)
301
class MATROSKA_DLL_API KaxSimpleBlock : public KaxInternalBlock {
302
  public:
303
    KaxSimpleBlock(EBML_EXTRA_PARAM) :KaxInternalBlock(EBML_DEF_BINARY_CTX(KaxSimpleBlock)EBML_DEF_SEP true EBML_DEF_SEP EBML_EXTRA_CALL) {}
304
305
    void SetKeyframe(bool b_keyframe) { bIsKeyframe = b_keyframe; }
306
    void SetDiscardable(bool b_discard) { bIsDiscardable = b_discard; }
307
308
66.4k
    bool IsKeyframe() const    { return bIsKeyframe; }
309
32.0k
    bool IsDiscardable() const { return bIsDiscardable; }
310
311
    void SetParent(KaxCluster & aParentCluster);
312
313
        EBML_CONCRETE_CLASS(KaxSimpleBlock)
314
};
315
316
/// Placeholder class for either a BlockGroup or a SimpleBlock
317
class MATROSKA_DLL_API KaxBlockBlob {
318
public:
319
  KaxBlockBlob(BlockBlobType sblock_mode) : SimpleBlockMode(sblock_mode) {
320
    bUseSimpleBlock = (sblock_mode != BLOCK_BLOB_NO_SIMPLE);
321
    Block.group = nullptr;
322
  }
323
324
  ~KaxBlockBlob() {
325
    if (bUseSimpleBlock)
326
      delete Block.simpleblock;
327
    else
328
      delete Block.group;
329
  }
330
331
  operator KaxBlockGroup &();
332
  operator const KaxBlockGroup &() const;
333
  operator KaxSimpleBlock &();
334
  operator KaxInternalBlock &();
335
  operator const KaxInternalBlock &() const;
336
337
  void SetBlockGroup( KaxBlockGroup &BlockRef );
338
339
  void SetBlockDuration(uint64 TimeLength);
340
341
  void SetParent(KaxCluster & aParentCluster);
342
  bool AddFrameAuto(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO, const KaxBlockBlob * PastBlock = nullptr, const KaxBlockBlob * ForwBlock = nullptr);
343
344
  bool IsSimpleBlock() const {return bUseSimpleBlock;}
345
346
  bool ReplaceSimpleByGroup();
347
protected:
348
  KaxCluster *ParentCluster{nullptr};
349
  union {
350
    KaxBlockGroup *group;
351
    KaxSimpleBlock *simpleblock;
352
  } Block;
353
  bool bUseSimpleBlock;
354
  BlockBlobType SimpleBlockMode;
355
};
356
357
DECLARE_MKX_BINARY_CONS(KaxBlockVirtual)
358
  public:
359
    ~KaxBlockVirtual() override;
360
361
    /*!
362
      \note override this function to generate the Data/Size on the fly, unlike the usual binary elements
363
    */
364
    filepos_t UpdateSize(bool bSaveDefault = false, bool bForceRender = false) override;
365
366
    void SetParent(const KaxCluster & aParentCluster) {ParentCluster = &aParentCluster;}
367
368
    filepos_t RenderData(IOCallback & output, bool bForceRender, bool bSaveDefault) override;
369
370
    filepos_t ReadData(IOCallback & input, ScopeMode ReadFully = SCOPE_ALL_DATA) override;
371
372
  protected:
373
    uint64 Timecode; // temporary timecode of the first frame if there are more than one
374
    uint16 TrackNumber;
375
    binary DataBlock[5];
376
377
    const KaxCluster * ParentCluster{nullptr};
378
};
379
380
} // namespace libmatroska
381
382
#endif // LIBMATROSKA_BLOCK_H