Coverage Report

Created: 2025-07-18 08:04

/src/vlc/contrib/x86_64-unknown-linux-gnu/include/matroska/KaxBlock.h
Line
Count
Source (jump to first uncovered line)
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
0
    {
69
0
      if (bInternalBuffer)
70
0
      {
71
0
        myBuffer = new (std::nothrow) binary[mySize];
72
0
        if (myBuffer == nullptr)
73
0
          bValidValue = false;
74
0
        else
75
0
          memcpy(myBuffer, aBuffer, mySize);
76
0
      }
77
0
      else
78
0
        myBuffer = aBuffer;
79
0
    }
80
81
    virtual ~DataBuffer() = default;
82
0
    virtual binary * Buffer() {assert(bValidValue); return myBuffer;}
83
0
    virtual uint32   & Size() {return mySize;};
84
0
    virtual const binary * Buffer() const {assert(bValidValue); return myBuffer;}
85
0
    virtual uint32   Size()   const {return mySize;};
86
0
    bool    FreeBuffer(const DataBuffer & aBuffer) {
87
0
      bool bResult = true;
88
0
      if (myBuffer != nullptr && bValidValue) {
89
0
        if (myFreeBuffer != nullptr)
90
0
          bResult = myFreeBuffer(aBuffer);
91
0
        if (bInternalBuffer)
92
0
          delete [] myBuffer;
93
0
        myBuffer = nullptr;
94
0
        mySize = 0;
95
0
        bValidValue = false;
96
0
      }
97
0
      return bResult;
98
0
    }
99
100
    virtual DataBuffer * Clone();
101
};
102
103
class MATROSKA_DLL_API SimpleDataBuffer : public DataBuffer {
104
  public:
105
    SimpleDataBuffer(binary * aBuffer, uint32 aSize, uint32 aOffset, bool (*aFreeBuffer)(const DataBuffer & aBuffer) = myFreeBuffer)
106
      :DataBuffer(aBuffer + aOffset, aSize, aFreeBuffer)
107
      ,Offset(aOffset)
108
      ,BaseBuffer(aBuffer)
109
0
    {}
110
    ~SimpleDataBuffer() override = default;
111
112
0
    DataBuffer * Clone() override {return new SimpleDataBuffer(*this);}
113
114
  protected:
115
    uint32 Offset;
116
    binary * BaseBuffer;
117
118
    static bool myFreeBuffer(const DataBuffer & aBuffer)
119
0
    {
120
0
      auto _Buffer = static_cast<const SimpleDataBuffer*>(&aBuffer)->BaseBuffer;
121
0
      if (_Buffer != nullptr)
122
0
        free(_Buffer);
123
0
      return true;
124
0
    }
125
126
    SimpleDataBuffer(const SimpleDataBuffer & ToClone);
127
};
128
129
/*!
130
  \note the data is copied locally, it can be freed right away
131
* /
132
class MATROSKA_DLL_API NotSoSimpleDataBuffer : public SimpleDataBuffer {
133
  public:
134
    NotSoSimpleDataBuffer(binary * aBuffer, uint32 aSize, uint32 aOffset)
135
      :SimpleDataBuffer(new binary[aSize - aOffset], aSize, 0)
136
    {
137
      memcpy(BaseBuffer, aBuffer + aOffset, aSize - aOffset);
138
    }
139
};
140
*/
141
142
DECLARE_MKX_MASTER(KaxBlockGroup)
143
  public:
144
    ~KaxBlockGroup() override = default;
145
146
    /*!
147
      \brief Addition of a frame without references
148
    */
149
    bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO);
150
    /*!
151
      \brief Addition of a frame with a backward reference (P frame)
152
    */
153
    bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, LacingType lacing = LACING_AUTO);
154
155
    /*!
156
      \brief Addition of a frame with a backward+forward reference (B frame)
157
    */
158
    bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, const KaxBlockGroup & ForwBlock, LacingType lacing = LACING_AUTO);
159
    bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockBlob * PastBlock, const KaxBlockBlob * ForwBlock, LacingType lacing = LACING_AUTO);
160
161
    void SetParent(KaxCluster & aParentCluster);
162
163
0
    void SetParentTrack(const KaxTrackEntry & aParentTrack) {
164
0
      ParentTrack = &aParentTrack;
165
0
    }
166
167
    /*!
168
      \brief Set the duration of the contained frame(s) (for the total number of frames)
169
    */
170
    void SetBlockDuration(uint64 TimeLength);
171
    bool GetBlockDuration(uint64 &TheTimecode) const;
172
173
    /*!
174
      \return the global timecode of this Block (not just the delta to the Cluster)
175
    */
176
    uint64 GlobalTimecode() const;
177
0
    uint64 GlobalTimecodeScale() const {
178
0
      assert(ParentTrack != nullptr);
179
0
      return ParentTrack->GlobalTimecodeScale();
180
0
    }
181
182
    uint16 TrackNumber() const;
183
184
    uint64 ClusterPosition() const;
185
186
    /*!
187
      \return the number of references to other frames
188
    */
189
    unsigned int ReferenceCount() const;
190
    const KaxReferenceBlock & Reference(unsigned int Index) const;
191
192
    /*!
193
      \brief release all the frames of all Blocks
194
    */
195
    void ReleaseFrames();
196
197
    operator KaxInternalBlock &();
198
199
0
    const KaxCluster *GetParentCluster() const { return ParentCluster; }
200
201
  protected:
202
    KaxCluster * ParentCluster{nullptr};
203
    const KaxTrackEntry * ParentTrack{nullptr};
204
};
205
206
class MATROSKA_DLL_API KaxInternalBlock : public EbmlBinary {
207
  public:
208
    KaxInternalBlock(EBML_DEF_CONS EBML_DEF_SEP bool bSimple EBML_DEF_SEP EBML_EXTRA_PARAM) :EBML_DEF_BINARY_INIT EBML_DEF_SEP bIsSimple(bSimple)
209
0
    {}
210
    KaxInternalBlock(const KaxInternalBlock & ElementToClone);
211
    ~KaxInternalBlock() override;
212
    bool ValidateSize() const override;
213
214
4.94k
    uint16 TrackNum() const {return TrackNumber;}
215
    /*!
216
      \todo !!!! This method needs to be changes !
217
    */
218
1.33k
    uint64 GlobalTimecode() const {return Timecode;}
219
220
    /*!
221
      \note override this function to generate the Data/Size on the fly, unlike the usual binary elements
222
    */
223
    filepos_t UpdateSize(bool bSaveDefault = false, bool bForceRender = false) override;
224
    filepos_t ReadData(IOCallback & input, ScopeMode ReadFully = SCOPE_ALL_DATA) override;
225
226
    /*!
227
      \brief Only read the head of the Block (not internal data)
228
      \note convenient when you are parsing the file quickly
229
    */
230
    uint64 ReadInternalHead(IOCallback & input);
231
232
1.22k
    unsigned int NumberFrames() const { return SizeList.size();}
233
1.84k
    DataBuffer & GetBuffer(unsigned int iIndex) {return *myBuffers[iIndex];}
234
235
    bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO, bool invisible = false);
236
237
    /*!
238
      \brief release all the frames of all Blocks
239
    */
240
    void ReleaseFrames();
241
242
    void SetParent(KaxCluster & aParentCluster);
243
244
    /*!
245
      \return Returns the lacing type that produces the smallest footprint.
246
    */
247
    LacingType GetBestLacingType() const;
248
249
    /*!
250
      \param FrameNumber 0 for the first frame
251
      \return the position in the stream for a given frame
252
      \note return -1 if the position doesn't exist
253
    */
254
    int64 GetDataPosition(size_t FrameNumber = 0);
255
256
    /*!
257
      \param FrameNumber 0 for the first frame
258
      \return the size of a given frame
259
      \note return -1 if the position doesn't exist
260
    */
261
    int64 GetFrameSize(size_t FrameNumber = 0);
262
263
0
    bool IsInvisible() const { return mInvisible; }
264
265
    uint64 ClusterPosition() const;
266
267
    /*!
268
     * \return Get the timestamp as written in the Block (not scaled).
269
     * \since LIBMATROSKA_VERSION >= 0x010700
270
     */
271
0
    int16 GetRelativeTimestamp() const { return LocalTimecode; }
272
273
  protected:
274
    std::vector<DataBuffer *> myBuffers;
275
    std::vector<int32>        SizeList;
276
    uint64                    Timecode; // temporary timecode of the first frame, non scaled
277
    int16                     LocalTimecode;
278
    bool                      bLocalTimecodeUsed{false};
279
    uint16                    TrackNumber;
280
    LacingType                mLacing{LACING_AUTO};
281
    bool                      mInvisible{false};
282
    uint64                    FirstFrameLocation;
283
284
    KaxCluster               *ParentCluster{nullptr};
285
    bool                      bIsSimple;
286
    bool                      bIsKeyframe{true};
287
    bool                      bIsDiscardable{false};
288
289
    filepos_t RenderData(IOCallback & output, bool bForceRender, bool bSaveDefault = false) override;
290
};
291
292
DECLARE_MKX_CONTEXT(KaxBlock)
293
class MATROSKA_DLL_API KaxBlock : public KaxInternalBlock {
294
  public:
295
0
    KaxBlock(EBML_EXTRA_PARAM) :KaxInternalBlock(EBML_DEF_BINARY_CTX(KaxBlock)EBML_DEF_SEP false EBML_DEF_SEP EBML_EXTRA_CALL) {}
296
        EBML_CONCRETE_CLASS(KaxBlock)
297
};
298
299
DECLARE_MKX_CONTEXT(KaxSimpleBlock)
300
class MATROSKA_DLL_API KaxSimpleBlock : public KaxInternalBlock {
301
  public:
302
0
    KaxSimpleBlock(EBML_EXTRA_PARAM) :KaxInternalBlock(EBML_DEF_BINARY_CTX(KaxSimpleBlock)EBML_DEF_SEP true EBML_DEF_SEP EBML_EXTRA_CALL) {}
303
304
0
    void SetKeyframe(bool b_keyframe) { bIsKeyframe = b_keyframe; }
305
0
    void SetDiscardable(bool b_discard) { bIsDiscardable = b_discard; }
306
307
349
    bool IsKeyframe() const    { return bIsKeyframe; }
308
166
    bool IsDiscardable() const { return bIsDiscardable; }
309
310
    void SetParent(KaxCluster & aParentCluster);
311
312
        EBML_CONCRETE_CLASS(KaxSimpleBlock)
313
};
314
315
/// Placeholder class for either a BlockGroup or a SimpleBlock
316
class MATROSKA_DLL_API KaxBlockBlob {
317
public:
318
0
  KaxBlockBlob(BlockBlobType sblock_mode) : SimpleBlockMode(sblock_mode) {
319
0
    bUseSimpleBlock = (sblock_mode != BLOCK_BLOB_NO_SIMPLE);
320
0
    Block.group = nullptr;
321
0
  }
322
323
0
  ~KaxBlockBlob() {
324
0
    if (bUseSimpleBlock)
325
0
      delete Block.simpleblock;
326
0
    else
327
0
      delete Block.group;
328
0
  }
329
330
  operator KaxBlockGroup &();
331
  operator const KaxBlockGroup &() const;
332
  operator KaxSimpleBlock &();
333
  operator KaxInternalBlock &();
334
  operator const KaxInternalBlock &() const;
335
336
  void SetBlockGroup( KaxBlockGroup &BlockRef );
337
338
  void SetBlockDuration(uint64 TimeLength);
339
340
  void SetParent(KaxCluster & aParentCluster);
341
  bool AddFrameAuto(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO, const KaxBlockBlob * PastBlock = nullptr, const KaxBlockBlob * ForwBlock = nullptr);
342
343
0
  bool IsSimpleBlock() const {return bUseSimpleBlock;}
344
345
  bool ReplaceSimpleByGroup();
346
protected:
347
  KaxCluster *ParentCluster{nullptr};
348
  union {
349
    KaxBlockGroup *group;
350
    KaxSimpleBlock *simpleblock;
351
  } Block;
352
  bool bUseSimpleBlock;
353
  BlockBlobType SimpleBlockMode;
354
};
355
356
DECLARE_MKX_BINARY_CONS(KaxBlockVirtual)
357
  public:
358
    ~KaxBlockVirtual() override;
359
360
    /*!
361
      \note override this function to generate the Data/Size on the fly, unlike the usual binary elements
362
    */
363
    filepos_t UpdateSize(bool bSaveDefault = false, bool bForceRender = false) override;
364
365
0
    void SetParent(const KaxCluster & aParentCluster) {ParentCluster = &aParentCluster;}
366
367
    filepos_t RenderData(IOCallback & output, bool bForceRender, bool bSaveDefault) override;
368
369
    filepos_t ReadData(IOCallback & input, ScopeMode ReadFully = SCOPE_ALL_DATA) override;
370
371
  protected:
372
    uint64 Timecode; // temporary timecode of the first frame if there are more than one
373
    uint16 TrackNumber;
374
    binary DataBlock[5];
375
376
    const KaxCluster * ParentCluster{nullptr};
377
};
378
379
} // namespace libmatroska
380
381
#endif // LIBMATROSKA_BLOCK_H