1/****************************************************************************
2** libmatroska : parse Matroska files, see http://www.matroska.org/
3**
4** <file/class description>
5**
6** Copyright (C) 2002-2004 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	\version \$Id: KaxCluster.h,v 1.10 2004/04/14 23:26:17 robux4 Exp $
31	\author Steve Lhomme     <robux4 @ users.sf.net>
32	\author Julien Coloos    <suiryc @ users.sf.net>
33
34*/
35#ifndef LIBMATROSKA_CLUSTER_H
36#define LIBMATROSKA_CLUSTER_H
37
38#include "matroska/KaxTypes.h"
39#include "ebml/EbmlMaster.h"
40#include "matroska/KaxTracks.h"
41#include "matroska/KaxBlock.h"
42#include "matroska/KaxCues.h"
43#include "matroska/KaxClusterData.h"
44
45using namespace LIBEBML_NAMESPACE;
46
47START_LIBMATROSKA_NAMESPACE
48
49class KaxSegment;
50
51class MATROSKA_DLL_API KaxCluster : public EbmlMaster {
52	public:
53		KaxCluster();
54		KaxCluster(const KaxCluster & ElementToClone);
55		static EbmlElement & Create() {return *(new KaxCluster);}
56		const EbmlCallbacks & Generic() const {return ClassInfos;}
57		static const EbmlCallbacks ClassInfos;
58		operator const EbmlId &() const {return ClassInfos.GlobalId;}
59		EbmlElement * Clone() const {return new KaxCluster(*this);}
60
61		/*!
62			\brief Addition of a frame without references
63
64			\param the timecode is expressed in nanoseconds, relative to the beggining of the Segment
65		*/
66		bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, KaxBlockGroup * & MyNewBlock, LacingType lacing = LACING_AUTO);
67		/*!
68			\brief Addition of a frame with a backward reference (P frame)
69			\param the timecode is expressed in nanoseconds, relative to the beggining of the Segment
70
71		*/
72		bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, KaxBlockGroup * & MyNewBlock, const KaxBlockGroup & PastBlock, LacingType lacing = LACING_AUTO);
73
74		/*!
75			\brief Addition of a frame with a backward+forward reference (B frame)
76			\param the timecode is expressed in nanoseconds, relative to the beggining of the Segment
77
78		*/
79		bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, KaxBlockGroup * & MyNewBlock, const KaxBlockGroup & PastBlock, const KaxBlockGroup & ForwBlock, LacingType lacing = LACING_AUTO);
80
81		/*!
82			\brief Render the data to the stream and retrieve the position of BlockGroups for later cue entries
83		*/
84		uint32 Render(IOCallback & output, KaxCues & CueToUpdate, bool bSaveDefault = false);
85
86		/*!
87			\return the global timecode of this Cluster
88		*/
89		uint64 GlobalTimecode() const;
90
91		KaxBlockGroup & GetNewBlock();
92
93		/*!
94			\brief release all the frames of all Blocks
95			\note this is a convenience to be able to keep Clusters+Blocks in memory (for future reference) withouht being a memory hog
96		*/
97		void ReleaseFrames();
98
99		/*!
100			\brief return the position offset compared to the beggining of the Segment
101		*/
102		uint64 GetPosition() const;
103
104		void SetParent(const KaxSegment & aParentSegment) {ParentSegment = &aParentSegment;}
105
106		void SetPreviousTimecode(uint64 aPreviousTimecode, int64 aTimecodeScale) {
107			bPreviousTimecodeIsSet = true;
108			PreviousTimecode = aPreviousTimecode;
109			SetGlobalTimecodeScale(aTimecodeScale);
110		}
111
112		/*!
113			\note dirty hack to get the mandatory data back after reading
114			\todo there should be a better way to get mandatory data
115		*/
116		void InitTimecode(uint64 aTimecode, int64 aTimecodeScale) {
117			SetGlobalTimecodeScale(aTimecodeScale);
118			MinTimecode = MaxTimecode = PreviousTimecode = aTimecode * TimecodeScale;
119			bFirstFrameInside = bPreviousTimecodeIsSet = true;
120		}
121
122		int16 GetBlockLocalTimecode(uint64 GlobalTimecode) const;
123
124		uint64 GetBlockGlobalTimecode(int16 LocalTimecode);
125
126		void SetGlobalTimecodeScale(uint64 aGlobalTimecodeScale) {
127			TimecodeScale = aGlobalTimecodeScale;
128			bTimecodeScaleIsSet = true;
129		}
130		uint64 GlobalTimecodeScale() const {
131			assert(bTimecodeScaleIsSet);
132			return TimecodeScale;
133		}
134
135		bool SetSilentTrackUsed()
136		{
137			bSilentTracksUsed = true;
138			return FindFirstElt(KaxClusterSilentTracks::ClassInfos, true) != NULL;
139		}
140
141		bool AddBlockBlob(KaxBlockBlob * NewBlob);
142
143		const KaxSegment *GetParentSegment() const { return ParentSegment; }
144
145	protected:
146		KaxBlockBlob     * currentNewBlob;
147		std::vector<KaxBlockBlob*> Blobs;
148		KaxBlockGroup    * currentNewBlock;
149		const KaxSegment * ParentSegment;
150
151		uint64 MinTimecode, MaxTimecode, PreviousTimecode;
152		int64  TimecodeScale;
153
154		bool bFirstFrameInside; // used to speed research
155		bool bPreviousTimecodeIsSet;
156		bool bTimecodeScaleIsSet;
157		bool bSilentTracksUsed;
158
159		/*!
160			\note method used internally
161		*/
162		bool AddFrameInternal(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, KaxBlockGroup * & MyNewBlock, const KaxBlockGroup * PastBlock, const KaxBlockGroup * ForwBlock, LacingType lacing);
163
164};
165
166END_LIBMATROSKA_NAMESPACE
167
168#endif // LIBMATROSKA_CLUSTER_H
169