1/****************************************************************************
2** libmatroska : parse Matroska files, see http://www.matroska.org/
3**
4** <file/class description>
5**
6** Copyright (C) 2002-2005 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21**
22** See http://www.matroska.org/license/lgpl/ 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
45using namespace LIBEBML_NAMESPACE;
46
47START_LIBMATROSKA_NAMESPACE
48
49class KaxCluster;
50class KaxReferenceBlock;
51class KaxInternalBlock;
52class KaxBlockBlob;
53
54class MATROSKA_DLL_API DataBuffer {
55	protected:
56		binary * myBuffer;
57		uint32   mySize;
58		bool     bValidValue;
59		bool     (*myFreeBuffer)(const DataBuffer & aBuffer); // method to free the internal buffer
60
61	public:
62		DataBuffer(binary * aBuffer, uint32 aSize, bool (*aFreeBuffer)(const DataBuffer & aBuffer) = NULL)
63			:myBuffer(aBuffer)
64			,mySize(aSize)
65			,bValidValue(true)
66      ,myFreeBuffer(aFreeBuffer)
67		{}
68		virtual ~DataBuffer() {}
69		virtual binary * Buffer() {return myBuffer;}
70		virtual uint32   & Size() {return mySize;};
71		virtual const binary * Buffer() const {return myBuffer;}
72		virtual const uint32   Size()   const {return mySize;};
73		bool    FreeBuffer(const DataBuffer & aBuffer) {
74			bool bResult = true;
75			if (myBuffer != NULL && myFreeBuffer != NULL && bValidValue) {
76				bResult = myFreeBuffer(aBuffer);
77				myBuffer = NULL;
78				bValidValue = false;
79			}
80			return bResult;
81		}
82
83		virtual DataBuffer * Clone();
84};
85
86class MATROSKA_DLL_API SimpleDataBuffer : public DataBuffer {
87	public:
88		SimpleDataBuffer(binary * aBuffer, uint32 aSize, uint32 aOffset, bool (*aFreeBuffer)(const DataBuffer & aBuffer) = myFreeBuffer)
89			:DataBuffer(aBuffer + aOffset, aSize, aFreeBuffer)
90			,Offset(aOffset)
91			,BaseBuffer(aBuffer)
92		{}
93		virtual ~SimpleDataBuffer() {}
94
95		DataBuffer * Clone() {return new SimpleDataBuffer(*this);}
96
97	protected:
98		uint32 Offset;
99		binary * BaseBuffer;
100
101		static bool myFreeBuffer(const DataBuffer & aBuffer)
102		{
103			binary *_Buffer = static_cast<const SimpleDataBuffer*>(&aBuffer)->BaseBuffer;
104			if (_Buffer != NULL)
105				free(_Buffer);
106			return true;
107		}
108
109		SimpleDataBuffer(const SimpleDataBuffer & ToClone);
110};
111
112/*!
113	\note the data is copied locally, it can be freed right away
114* /
115class MATROSKA_DLL_API NotSoSimpleDataBuffer : public SimpleDataBuffer {
116	public:
117		NotSoSimpleDataBuffer(binary * aBuffer, uint32 aSize, uint32 aOffset)
118			:SimpleDataBuffer(new binary[aSize - aOffset], aSize, 0)
119		{
120			memcpy(BaseBuffer, aBuffer + aOffset, aSize - aOffset);
121		}
122};
123*/
124
125class MATROSKA_DLL_API KaxBlockGroup : public EbmlMaster {
126	public:
127		KaxBlockGroup();
128		KaxBlockGroup(const KaxBlockGroup & ElementToClone) :EbmlMaster(ElementToClone) {}
129		static EbmlElement & Create() {return *(new KaxBlockGroup);}
130		const EbmlCallbacks & Generic() const {return ClassInfos;}
131		static const EbmlCallbacks ClassInfos;
132		operator const EbmlId &() const {return ClassInfos.GlobalId;}
133		EbmlElement * Clone() const {return new KaxBlockGroup(*this);}
134
135		~KaxBlockGroup();
136
137		/*!
138			\brief Addition of a frame without references
139		*/
140		bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO);
141		/*!
142			\brief Addition of a frame with a backward reference (P frame)
143		*/
144		bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, LacingType lacing = LACING_AUTO);
145
146		/*!
147			\brief Addition of a frame with a backward+forward reference (B frame)
148		*/
149		bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, const KaxBlockGroup & ForwBlock, LacingType lacing = LACING_AUTO);
150		bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockBlob * PastBlock, const KaxBlockBlob * ForwBlock, LacingType lacing = LACING_AUTO);
151
152		void SetParent(KaxCluster & aParentCluster);
153
154		void SetParentTrack(const KaxTrackEntry & aParentTrack) {
155			ParentTrack = &aParentTrack;
156		}
157
158		/*!
159			\brief Set the duration of the contained frame(s) (for the total number of frames)
160		*/
161		void SetBlockDuration(uint64 TimeLength);
162		bool GetBlockDuration(uint64 &TheTimecode) const;
163
164		/*!
165			\return the global timecode of this Block (not just the delta to the Cluster)
166		*/
167		uint64 GlobalTimecode() const;
168		uint64 GlobalTimecodeScale() const {
169			assert(ParentTrack != NULL);
170			return ParentTrack->GlobalTimecodeScale();
171		}
172
173		uint16 TrackNumber() const;
174
175		uint64 ClusterPosition() const;
176
177		/*!
178			\return the number of references to other frames
179		*/
180		unsigned int ReferenceCount() const;
181		const KaxReferenceBlock & Reference(unsigned int Index) const;
182
183		/*!
184			\brief release all the frames of all Blocks
185		*/
186		void ReleaseFrames();
187
188		operator KaxInternalBlock &();
189
190		const KaxCluster *GetParentCluster() const { return ParentCluster; }
191
192	protected:
193		KaxCluster * ParentCluster;
194		const KaxTrackEntry * ParentTrack;
195};
196
197class KaxInternalBlock : public EbmlBinary {
198	public:
199		KaxInternalBlock( bool bSimple ) :bLocalTimecodeUsed(false), mLacing(LACING_AUTO), mInvisible(false)
200			,ParentCluster(NULL), bIsSimple(bSimple), bIsKeyframe(true), bIsDiscardable(false)
201		{}
202		KaxInternalBlock(const KaxInternalBlock & ElementToClone);
203		~KaxInternalBlock();
204		bool ValidateSize() const;
205
206		uint16 TrackNum() const {return TrackNumber;}
207		/*!
208			\todo !!!! This method needs to be changes !
209		*/
210		uint64 GlobalTimecode() const {return Timecode;}
211
212		/*!
213			\note override this function to generate the Data/Size on the fly, unlike the usual binary elements
214		*/
215		uint64 UpdateSize(bool bSaveDefault = false, bool bForceRender = false);
216		uint64 ReadData(IOCallback & input, ScopeMode ReadFully = SCOPE_ALL_DATA);
217
218		/*!
219			\brief Only read the head of the Block (not internal data)
220			\note convenient when you are parsing the file quickly
221		*/
222		uint64 ReadInternalHead(IOCallback & input);
223
224		unsigned int NumberFrames() const { return SizeList.size();}
225		DataBuffer & GetBuffer(unsigned int iIndex) {return *myBuffers[iIndex];}
226
227		bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO, bool invisible = false);
228
229		/*!
230			\brief release all the frames of all Blocks
231		*/
232		void ReleaseFrames();
233
234		void SetParent(KaxCluster & aParentCluster);
235
236		/*!
237			\return Returns the lacing type that produces the smallest footprint.
238		*/
239		LacingType GetBestLacingType() const;
240
241		/*!
242			\param FrameNumber 0 for the first frame
243			\return the position in the stream for a given frame
244			\note return -1 if the position doesn't exist
245		*/
246		int64 GetDataPosition(size_t FrameNumber = 0);
247
248		/*!
249			\param FrameNumber 0 for the first frame
250			\return the size of a given frame
251			\note return -1 if the position doesn't exist
252		*/
253		int64 GetFrameSize(size_t FrameNumber = 0);
254
255		bool IsInvisible() const { return mInvisible; }
256
257		uint64 ClusterPosition() const;
258
259	protected:
260		std::vector<DataBuffer *> myBuffers;
261		std::vector<int32>        SizeList;
262		uint64     Timecode; // temporary timecode of the first frame, non scaled
263		int16      LocalTimecode;
264		bool       bLocalTimecodeUsed;
265		uint16     TrackNumber;
266		LacingType mLacing;
267		bool       mInvisible;
268		uint64     FirstFrameLocation;
269
270		uint32 RenderData(IOCallback & output, bool bForceRender, bool bSaveDefault = false);
271
272		KaxCluster * ParentCluster;
273		bool       bIsSimple;
274		bool       bIsKeyframe;
275		bool       bIsDiscardable;
276};
277
278class MATROSKA_DLL_API KaxBlock : public KaxInternalBlock {
279	public:
280		KaxBlock() :KaxInternalBlock(false) {}
281		static EbmlElement & Create() {return *(new KaxBlock);}
282		static const EbmlCallbacks ClassInfos;
283		operator const EbmlId &() const {return ClassInfos.GlobalId;}
284		const EbmlCallbacks & Generic() const {return ClassInfos;}
285		EbmlElement * Clone() const {return new KaxBlock(*this);}
286};
287
288#if MATROSKA_VERSION >= 2
289class MATROSKA_DLL_API KaxSimpleBlock : public KaxInternalBlock {
290	public:
291		KaxSimpleBlock() :KaxInternalBlock(true) {}
292		static EbmlElement & Create() {return *(new KaxSimpleBlock);}
293		static const EbmlCallbacks ClassInfos;
294		operator const EbmlId &() const {return ClassInfos.GlobalId;}
295		const EbmlCallbacks & Generic() const {return ClassInfos;}
296		EbmlElement * Clone() const {return new KaxSimpleBlock(*this);}
297
298		void SetKeyframe(bool b_keyframe) { bIsKeyframe = b_keyframe; }
299		void SetDiscardable(bool b_discard) { bIsDiscardable = b_discard; }
300
301		bool IsKeyframe() const    { return bIsKeyframe; }
302		bool IsDiscardable() const { return bIsDiscardable; }
303
304		operator KaxInternalBlock &() { return *this; }
305};
306#endif // MATROSKA_VERSION
307
308class MATROSKA_DLL_API KaxBlockBlob {
309public:
310	KaxBlockBlob(BlockBlobType sblock_mode) :ParentCluster(NULL), SimpleBlockMode(sblock_mode) {
311		bUseSimpleBlock = (sblock_mode != BLOCK_BLOB_NO_SIMPLE);
312		Block.group = NULL;
313	}
314
315	~KaxBlockBlob() {
316#if MATROSKA_VERSION >= 2
317		if (bUseSimpleBlock)
318			delete Block.simpleblock;
319		else
320#endif // MATROSKA_VERSION
321			delete Block.group;
322	}
323
324	operator KaxBlockGroup &();
325	operator const KaxBlockGroup &() const;
326#if MATROSKA_VERSION >= 2
327	operator KaxSimpleBlock &();
328#endif
329	operator KaxInternalBlock &();
330	operator const KaxInternalBlock &() const;
331
332	void SetBlockGroup( KaxBlockGroup &BlockRef );
333
334	void SetBlockDuration(uint64 TimeLength);
335
336	void SetParent(KaxCluster & aParentCluster);
337	bool AddFrameAuto(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO, const KaxBlockBlob * PastBlock = NULL, const KaxBlockBlob * ForwBlock = NULL);
338
339	bool IsSimpleBlock() const {return bUseSimpleBlock;}
340
341	bool ReplaceSimpleByGroup();
342protected:
343	KaxCluster * ParentCluster;
344	union {
345		KaxBlockGroup *group;
346#if MATROSKA_VERSION >= 2
347		KaxSimpleBlock *simpleblock;
348#endif // MATROSKA_VERSION
349	} Block;
350	bool bUseSimpleBlock;
351	BlockBlobType SimpleBlockMode;
352};
353
354class MATROSKA_DLL_API KaxBlockDuration : public EbmlUInteger {
355	public:
356		KaxBlockDuration() {}
357		KaxBlockDuration(const KaxBlockDuration & ElementToClone) :EbmlUInteger(ElementToClone) {}
358		static EbmlElement & Create() {return *(new KaxBlockDuration);}
359		const EbmlCallbacks & Generic() const {return ClassInfos;}
360		static const EbmlCallbacks ClassInfos;
361		operator const EbmlId &() const {return ClassInfos.GlobalId;}
362		EbmlElement * Clone() const {return new KaxBlockDuration(*this);}
363};
364
365#if MATROSKA_VERSION >= 2
366class MATROSKA_DLL_API KaxBlockVirtual : public EbmlBinary {
367	public:
368		KaxBlockVirtual() :ParentCluster(NULL) {Data = DataBlock; Size = countof(DataBlock);}
369		KaxBlockVirtual(const KaxBlockVirtual & ElementToClone);
370		static EbmlElement & Create() {return *(new KaxBlockVirtual);}
371		const EbmlCallbacks & Generic() const {return ClassInfos;}
372		static const EbmlCallbacks ClassInfos;
373		operator const EbmlId &() const {return ClassInfos.GlobalId;}
374		bool ValidateSize() const {return true;}
375
376		/*!
377			\note override this function to generate the Data/Size on the fly, unlike the usual binary elements
378		*/
379		uint64 UpdateSize(bool bSaveDefault = false, bool bForceRender = false);
380
381		void SetParent(const KaxCluster & aParentCluster) {ParentCluster = &aParentCluster;}
382
383		EbmlElement * Clone() const {return new KaxBlockVirtual(*this);}
384
385	protected:
386		uint64 Timecode; // temporary timecode of the first frame if there are more than one
387		uint16 TrackNumber;
388		binary DataBlock[5];
389
390		const KaxCluster * ParentCluster;
391};
392#endif // MATROSKA_VERSION
393
394class MATROSKA_DLL_API KaxBlockAdditional : public EbmlBinary {
395	public:
396		KaxBlockAdditional() {}
397		KaxBlockAdditional(const KaxBlockAdditional & ElementToClone) :EbmlBinary(ElementToClone){}
398		static EbmlElement & Create() {return *(new KaxBlockAdditional);}
399		const EbmlCallbacks & Generic() const {return ClassInfos;}
400		static const EbmlCallbacks ClassInfos;
401		operator const EbmlId &() const {return ClassInfos.GlobalId;}
402		bool ValidateSize() const {return true;}
403
404		EbmlElement * Clone() const {return new KaxBlockAdditional(*this);}
405};
406
407class MATROSKA_DLL_API KaxBlockAdditions : public EbmlMaster {
408	public:
409		KaxBlockAdditions();
410		KaxBlockAdditions(const KaxBlockAdditions & ElementToClone) :EbmlMaster(ElementToClone) {}
411		static EbmlElement & Create() {return *(new KaxBlockAdditions);}
412		const EbmlCallbacks & Generic() const {return ClassInfos;}
413		static const EbmlCallbacks ClassInfos;
414		operator const EbmlId &() const {return ClassInfos.GlobalId;}
415		EbmlElement * Clone() const {return new KaxBlockAdditions(*this);}
416};
417
418class MATROSKA_DLL_API KaxBlockMore : public EbmlMaster {
419	public:
420		KaxBlockMore();
421		KaxBlockMore(const KaxBlockMore & ElementToClone) :EbmlMaster(ElementToClone) {}
422		static EbmlElement & Create() {return *(new KaxBlockMore);}
423		const EbmlCallbacks & Generic() const {return ClassInfos;}
424		static const EbmlCallbacks ClassInfos;
425		operator const EbmlId &() const {return ClassInfos.GlobalId;}
426		EbmlElement * Clone() const {return new KaxBlockMore(*this);}
427};
428
429class MATROSKA_DLL_API KaxBlockAddID : public EbmlUInteger {
430	public:
431		KaxBlockAddID() :EbmlUInteger(1) {}
432		KaxBlockAddID(const KaxBlockAddID & ElementToClone) :EbmlUInteger(ElementToClone) {}
433		static EbmlElement & Create() {return *(new KaxBlockAddID);}
434		const EbmlCallbacks & Generic() const {return ClassInfos;}
435		static const EbmlCallbacks ClassInfos;
436		operator const EbmlId &() const {return ClassInfos.GlobalId;}
437		EbmlElement * Clone() const {return new KaxBlockAddID(*this);}
438};
439
440class MATROSKA_DLL_API KaxCodecState : public EbmlBinary {
441	public:
442		KaxCodecState() {}
443		KaxCodecState(const KaxCodecState & ElementToClone) :EbmlBinary(ElementToClone){}
444		static EbmlElement & Create() {return *(new KaxCodecState);}
445		const EbmlCallbacks & Generic() const {return ClassInfos;}
446		static const EbmlCallbacks ClassInfos;
447		operator const EbmlId &() const {return ClassInfos.GlobalId;}
448		bool ValidateSize() const {return true;}
449
450		EbmlElement * Clone() const {return new KaxCodecState(*this);}
451};
452
453END_LIBMATROSKA_NAMESPACE
454
455#endif // LIBMATROSKA_BLOCK_H
456