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	\version \$Id: KaxBlock.cpp 1265 2007-01-14 17:20:35Z mosu $
31	\author Steve Lhomme     <robux4 @ users.sf.net>
32	\author Julien Coloos    <suiryc @ users.sf.net>
33*/
34#include <cassert>
35
36//#include <streams.h>
37
38#include "matroska/KaxBlock.h"
39#include "matroska/KaxContexts.h"
40#include "matroska/KaxBlockData.h"
41#include "matroska/KaxCluster.h"
42
43START_LIBMATROSKA_NAMESPACE
44
45#if MATROSKA_VERSION == 1
46const EbmlSemantic KaxBlockGroup_ContextList[6] =
47#else // MATROSKA_VERSION
48const EbmlSemantic KaxBlockGroup_ContextList[9] =
49#endif // MATROSKA_VERSION
50{
51	EbmlSemantic(true,  true,  KaxBlock::ClassInfos),
52#if MATROSKA_VERSION >= 2
53	EbmlSemantic(false, true,  KaxBlockVirtual::ClassInfos),
54#endif // MATROSKA_VERSION
55	EbmlSemantic(false, true,  KaxBlockDuration::ClassInfos),
56	EbmlSemantic(false, true,  KaxSlices::ClassInfos),
57	EbmlSemantic(true,  true,  KaxReferencePriority::ClassInfos),
58	EbmlSemantic(false, false, KaxReferenceBlock::ClassInfos),
59#if MATROSKA_VERSION >= 2
60	EbmlSemantic(false, true,  KaxReferenceVirtual::ClassInfos),
61	EbmlSemantic(false, true,  KaxCodecState::ClassInfos),
62#endif // MATROSKA_VERSION
63	EbmlSemantic(false, true,  KaxBlockAdditions::ClassInfos),
64};
65
66const EbmlSemantic KaxBlockAdditions_ContextList[1] =
67{
68	EbmlSemantic(true,  false,  KaxBlockMore::ClassInfos)
69};
70
71const EbmlSemantic KaxBlockMore_ContextList[2] =
72{
73	EbmlSemantic(true,  true,  KaxBlockAddID::ClassInfos),
74	EbmlSemantic(true,  true,  KaxBlockAdditional::ClassInfos)
75};
76
77EbmlId KaxBlockGroup_TheId     (0xA0, 1);
78EbmlId KaxBlock_TheId          (0xA1, 1);
79EbmlId KaxSimpleBlock_TheId    (0xA3, 1);
80EbmlId KaxBlockDuration_TheId  (0x9B, 1);
81#if MATROSKA_VERSION >= 2
82EbmlId KaxBlockVirtual_TheId   (0xA2, 1);
83EbmlId KaxCodecState_TheId     (0xA4, 1);
84#endif // MATROSKA_VERSION
85EbmlId KaxBlockAdditions_TheId (0x75A1, 2);
86EbmlId KaxBlockMore_TheId      (0xA6, 1);
87EbmlId KaxBlockAddID_TheId     (0xEE, 1);
88EbmlId KaxBlockAdditional_TheId(0xA5, 1);
89
90const EbmlSemanticContext KaxBlockGroup_Context = EbmlSemanticContext(countof(KaxBlockGroup_ContextList), KaxBlockGroup_ContextList, &KaxCluster_Context, *GetKaxGlobal_Context, &KaxBlockGroup::ClassInfos);
91const EbmlSemanticContext KaxBlock_Context = EbmlSemanticContext(0, NULL, &KaxBlockGroup_Context, *GetKaxGlobal_Context, &KaxBlock::ClassInfos);
92const EbmlSemanticContext KaxBlockDuration_Context = EbmlSemanticContext(0, NULL, &KaxBlockGroup_Context, *GetKaxGlobal_Context, &KaxBlockDuration::ClassInfos);
93#if MATROSKA_VERSION >= 2
94const EbmlSemanticContext KaxSimpleBlock_Context = EbmlSemanticContext(0, NULL, &KaxCluster_Context, *GetKaxGlobal_Context, &KaxSimpleBlock::ClassInfos);
95const EbmlSemanticContext KaxBlockVirtual_Context = EbmlSemanticContext(0, NULL, &KaxBlockGroup_Context, *GetKaxGlobal_Context, &KaxBlockVirtual::ClassInfos);
96const EbmlSemanticContext KaxCodecState_Context = EbmlSemanticContext(0, NULL, &KaxBlockGroup_Context, *GetKaxGlobal_Context, &KaxCodecState::ClassInfos);
97#endif // MATROSKA_VERSION
98const EbmlSemanticContext KaxBlockAdditions_Context = EbmlSemanticContext(countof(KaxBlockAdditions_ContextList), KaxBlockAdditions_ContextList, &KaxBlockGroup_Context, *GetKaxGlobal_Context, &KaxBlockAdditions::ClassInfos);
99const EbmlSemanticContext KaxBlockMore_Context = EbmlSemanticContext(countof(KaxBlockMore_ContextList), KaxBlockMore_ContextList, &KaxBlockAdditions_Context, *GetKaxGlobal_Context, &KaxBlockMore::ClassInfos);
100const EbmlSemanticContext KaxBlockAddID_Context = EbmlSemanticContext(0, NULL, &KaxBlockMore_Context, *GetKaxGlobal_Context, &KaxBlockAddID::ClassInfos);
101const EbmlSemanticContext KaxBlockAdditional_Context = EbmlSemanticContext(0, NULL, &KaxBlockMore_Context, *GetKaxGlobal_Context, &KaxBlockAdditional::ClassInfos);
102
103const EbmlCallbacks KaxBlockGroup::ClassInfos(KaxBlockGroup::Create, KaxBlockGroup_TheId, "BlockGroup", KaxBlockGroup_Context);
104const EbmlCallbacks KaxBlock::ClassInfos(KaxBlock::Create, KaxBlock_TheId, "Block", KaxBlock_Context);
105const EbmlCallbacks KaxBlockDuration::ClassInfos(KaxBlockDuration::Create, KaxBlockDuration_TheId, "BlockDuration", KaxBlockDuration_Context);
106#if MATROSKA_VERSION >= 2
107const EbmlCallbacks KaxSimpleBlock::ClassInfos(KaxSimpleBlock::Create, KaxSimpleBlock_TheId, "SimpleBlock", KaxSimpleBlock_Context);
108const EbmlCallbacks KaxBlockVirtual::ClassInfos(KaxBlockVirtual::Create, KaxBlockVirtual_TheId, "BlockVirtual", KaxBlockVirtual_Context);
109const EbmlCallbacks KaxCodecState::ClassInfos(KaxCodecState::Create, KaxCodecState_TheId, "CodecState", KaxCodecState_Context);
110#endif // MATROSKA_VERSION
111const EbmlCallbacks KaxBlockAdditions::ClassInfos(KaxBlockAdditions::Create, KaxBlockAdditions_TheId, "BlockAdditions", KaxBlockAdditions_Context);
112const EbmlCallbacks KaxBlockMore::ClassInfos(KaxBlockMore::Create, KaxBlockMore_TheId, "BlockMore", KaxBlockMore_Context);
113const EbmlCallbacks KaxBlockAddID::ClassInfos(KaxBlockAddID::Create, KaxBlockAddID_TheId, "BlockAddID", KaxBlockAddID_Context);
114const EbmlCallbacks KaxBlockAdditional::ClassInfos(KaxBlockAdditional::Create, KaxBlockAdditional_TheId, "BlockAdditional", KaxBlockAdditional_Context);
115
116DataBuffer * DataBuffer::Clone()
117{
118	binary *ClonedData = (binary *)malloc(mySize * sizeof(binary));
119	assert(ClonedData != NULL);
120	memcpy(ClonedData, myBuffer ,mySize );
121
122	SimpleDataBuffer * result = new SimpleDataBuffer(ClonedData, mySize, 0);
123	result->bValidValue = bValidValue;
124	return result;
125}
126
127SimpleDataBuffer::SimpleDataBuffer(const SimpleDataBuffer & ToClone)
128 :DataBuffer((binary *)malloc(ToClone.mySize * sizeof(binary)), ToClone.mySize, myFreeBuffer)
129{
130	assert(myBuffer != NULL);
131	memcpy(myBuffer, ToClone.myBuffer ,mySize );
132	bValidValue = ToClone.bValidValue;
133}
134
135bool KaxInternalBlock::ValidateSize() const
136{
137	return (Size >= 4); /// for the moment
138}
139
140KaxInternalBlock::~KaxInternalBlock()
141{
142	ReleaseFrames();
143}
144
145KaxInternalBlock::KaxInternalBlock(const KaxInternalBlock & ElementToClone)
146 :EbmlBinary(ElementToClone)
147 ,myBuffers(ElementToClone.myBuffers.size())
148 ,Timecode(ElementToClone.Timecode)
149 ,LocalTimecode(ElementToClone.LocalTimecode)
150 ,bLocalTimecodeUsed(ElementToClone.bLocalTimecodeUsed)
151 ,TrackNumber(ElementToClone.TrackNumber)
152 ,ParentCluster(ElementToClone.ParentCluster) ///< \todo not exactly
153{
154	// add a clone of the list
155	std::vector<DataBuffer *>::const_iterator Itr = ElementToClone.myBuffers.begin();
156	std::vector<DataBuffer *>::iterator myItr = myBuffers.begin();
157	while (Itr != ElementToClone.myBuffers.end())
158	{
159		*myItr = (*Itr)->Clone();
160		Itr++; myItr++;
161	}
162}
163
164
165KaxBlockGroup::~KaxBlockGroup()
166{
167//NOTE("KaxBlockGroup::~KaxBlockGroup");
168}
169
170KaxBlockGroup::KaxBlockGroup()
171 :EbmlMaster(KaxBlockGroup_Context)
172 ,ParentCluster(NULL)
173 ,ParentTrack(NULL)
174{}
175
176KaxBlockAdditions::KaxBlockAdditions()
177 :EbmlMaster(KaxBlockAdditions_Context)
178{}
179
180KaxBlockMore::KaxBlockMore()
181 :EbmlMaster(KaxBlockMore_Context)
182{}
183
184/*!
185	\todo handle flags
186	\todo hardcoded limit of the number of frames in a lace should be a parameter
187	\return true if more frames can be added to this Block
188*/
189bool KaxInternalBlock::AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing, bool invisible)
190{
191	bValueIsSet = true;
192	if (myBuffers.size() == 0) {
193		// first frame
194		Timecode = timecode;
195		TrackNumber = track.TrackNumber();
196		mInvisible = invisible;
197		mLacing = lacing;
198	}
199	myBuffers.push_back(&buffer);
200
201	// we don't allow more than 8 frames in a Block because the overhead improvement is minimal
202	if (myBuffers.size() >= 8 || lacing == LACING_NONE)
203		return false;
204
205	if (lacing == LACING_XIPH)
206		// decide whether a new frame can be added or not
207		// a frame in a lace is not efficient when the place necessary to code it in a lace is bigger
208		// than the size of a simple Block. That means more than 6 bytes (4 in struct + 2 for EBML) to code the size
209		return (buffer.Size() < 6*0xFF);
210	else
211		return true;
212}
213
214/*!
215       \return Returns the lacing type that produces the smallest footprint.
216*/
217LacingType KaxInternalBlock::GetBestLacingType() const {
218	int XiphLacingSize, EbmlLacingSize, i;
219	bool SameSize = true;
220
221	if (myBuffers.size() <= 1)
222		return LACING_NONE;
223
224	XiphLacingSize = 1; // Number of laces is stored in 1 byte.
225	EbmlLacingSize = 1;
226	for (i = 0; i < (int)myBuffers.size() - 1; i++) {
227		if (myBuffers[i]->Size() != myBuffers[i + 1]->Size())
228			SameSize = false;
229		XiphLacingSize += myBuffers[i]->Size() / 255 + 1;
230	}
231	EbmlLacingSize += CodedSizeLength(myBuffers[0]->Size(), 0, bSizeIsFinite);
232	for (i = 1; i < (int)myBuffers.size() - 1; i++)
233		EbmlLacingSize += CodedSizeLengthSigned(int64(myBuffers[i]->Size()) - int64(myBuffers[i - 1]->Size()), 0);
234	if (SameSize)
235		return LACING_FIXED;
236	else if (XiphLacingSize < EbmlLacingSize)
237		return LACING_XIPH;
238	else
239		return LACING_EBML;
240}
241
242uint64 KaxInternalBlock::UpdateSize(bool bSaveDefault, bool bForceRender)
243{
244	LacingType LacingHere;
245	assert(Data == NULL); // Data is not used for KaxInternalBlock
246	assert(TrackNumber < 0x4000); // no more allowed for the moment
247	unsigned int i;
248
249	// compute the final size of the data
250	switch (myBuffers.size()) {
251		case 0:
252			Size = 0;
253			break;
254		case 1:
255			Size = 4 + myBuffers[0]->Size();
256			break;
257		default:
258			Size = 4 + 1; // 1 for the lacing head
259			if (mLacing == LACING_AUTO)
260				LacingHere = GetBestLacingType();
261			else
262				LacingHere = mLacing;
263			switch (LacingHere)
264			{
265			case LACING_XIPH:
266				for (i=0; i<myBuffers.size()-1; i++) {
267					Size += myBuffers[i]->Size() + (myBuffers[i]->Size() / 0xFF + 1);
268				}
269				break;
270			case LACING_EBML:
271				Size += myBuffers[0]->Size() + CodedSizeLength(myBuffers[0]->Size(), 0, bSizeIsFinite);
272				for (i=1; i<myBuffers.size()-1; i++) {
273					Size += myBuffers[i]->Size()
274						+ CodedSizeLengthSigned(int64(myBuffers[i]->Size()) - int64(myBuffers[i-1]->Size()), 0);;
275				}
276				break;
277			case LACING_FIXED:
278				for (i=0; i<myBuffers.size()-1; i++) {
279					Size += myBuffers[i]->Size();
280				}
281				break;
282			default:
283				assert(0);
284			}
285			// Size of the last frame (not in lace)
286			Size += myBuffers[i]->Size();
287			break;
288	}
289
290	if (TrackNumber >= 0x80)
291		Size++; // the size will be coded with one more octet
292
293	return Size;
294}
295
296#if MATROSKA_VERSION >= 2
297KaxBlockVirtual::KaxBlockVirtual(const KaxBlockVirtual & ElementToClone)
298 :EbmlBinary(ElementToClone)
299 ,Timecode(ElementToClone.Timecode)
300 ,TrackNumber(ElementToClone.TrackNumber)
301 ,ParentCluster(ElementToClone.ParentCluster) ///< \todo not exactly
302{
303	Data = DataBlock;
304}
305
306uint64 KaxBlockVirtual::UpdateSize(bool bSaveDefault, bool bForceRender)
307{
308	assert(TrackNumber < 0x4000);
309	binary *cursor = Data;
310	// fill data
311	if (TrackNumber < 0x80) {
312		*cursor++ = TrackNumber | 0x80; // set the first bit to 1
313	} else {
314		*cursor++ = (TrackNumber >> 8) | 0x40; // set the second bit to 1
315		*cursor++ = TrackNumber & 0xFF;
316	}
317
318	assert(ParentCluster != NULL);
319	int16 ActualTimecode = ParentCluster->GetBlockLocalTimecode(Timecode);
320	big_int16 b16(ActualTimecode);
321	b16.Fill(cursor);
322	cursor += 2;
323
324	*cursor++ = 0; // flags
325
326	return Size;
327}
328#endif // MATROSKA_VERSION
329
330/*!
331	\todo more optimisation is possible (render the Block head and don't copy the buffer in memory, care should be taken with the allocation of Data)
332	\todo the actual timecode to write should be retrieved from the Cluster from here
333*/
334uint32 KaxInternalBlock::RenderData(IOCallback & output, bool bForceRender, bool bSaveDefault)
335{
336	if (myBuffers.size() == 0) {
337		return 0;
338	} else {
339		assert(TrackNumber < 0x4000);
340		binary BlockHead[5], *cursor = BlockHead;
341		unsigned int i;
342
343		if (myBuffers.size() == 1) {
344			Size = 4;
345			mLacing = LACING_NONE;
346		} else {
347			if (mLacing == LACING_NONE)
348				mLacing = LACING_EBML; // supposedly the best of all
349			Size = 4 + 1; // 1 for the lacing head (number of laced elements)
350		}
351		if (TrackNumber > 0x80)
352			Size++;
353
354		// write Block Head
355		if (TrackNumber < 0x80) {
356			*cursor++ = TrackNumber | 0x80; // set the first bit to 1
357		} else {
358			*cursor++ = (TrackNumber >> 8) | 0x40; // set the second bit to 1
359			*cursor++ = TrackNumber & 0xFF;
360		}
361
362		assert(ParentCluster != NULL);
363		int16 ActualTimecode = ParentCluster->GetBlockLocalTimecode(Timecode);
364		big_int16 b16(ActualTimecode);
365		b16.Fill(cursor);
366		cursor += 2;
367
368		*cursor = 0; // flags
369
370		if (mLacing == LACING_AUTO) {
371			mLacing = GetBestLacingType();
372		}
373
374		// invisible flag
375		if (mInvisible)
376			*cursor = 0x08;
377
378		if (bIsSimple) {
379			if (bIsKeyframe)
380				*cursor |= 0x80;
381			if (bIsDiscardable)
382				*cursor |= 0x01;
383		}
384
385		// lacing flag
386		switch (mLacing)
387		{
388		case LACING_XIPH:
389			*cursor++ |= 0x02;
390			break;
391		case LACING_EBML:
392			*cursor++ |= 0x06;
393			break;
394		case LACING_FIXED:
395			*cursor++ |= 0x04;
396			break;
397		case LACING_NONE:
398			break;
399	    default:
400			assert(0);
401		}
402
403		output.writeFully(BlockHead, 4 + ((TrackNumber > 0x80) ? 1 : 0));
404
405		binary tmpValue;
406		switch (mLacing)
407		{
408		case LACING_XIPH:
409			// number of laces
410			tmpValue = myBuffers.size()-1;
411			output.writeFully(&tmpValue, 1);
412
413			// set the size of each member in the lace
414			for (i=0; i<myBuffers.size()-1; i++) {
415				tmpValue = 0xFF;
416				uint16 tmpSize = myBuffers[i]->Size();
417				while (tmpSize >= 0xFF) {
418					output.writeFully(&tmpValue, 1);
419					Size++;
420					tmpSize -= 0xFF;
421				}
422				tmpValue = binary(tmpSize);
423				output.writeFully(&tmpValue, 1);
424				Size++;
425			}
426			break;
427		case LACING_EBML:
428			// number of laces
429			tmpValue = myBuffers.size()-1;
430			output.writeFully(&tmpValue, 1);
431
432			{
433				int64 _Size;
434				int _CodedSize;
435				binary _FinalHead[8]; // 64 bits max coded size
436
437				_Size = myBuffers[0]->Size();
438
439				_CodedSize = CodedSizeLength(_Size, 0, bSizeIsFinite);
440
441				// first size in the lace is not a signed
442				CodedValueLength(_Size, _CodedSize, _FinalHead);
443				output.writeFully(_FinalHead, _CodedSize);
444				Size += _CodedSize;
445
446				// set the size of each member in the lace
447				for (i=1; i<myBuffers.size()-1; i++) {
448					_Size = int64(myBuffers[i]->Size()) - int64(myBuffers[i-1]->Size());
449					_CodedSize = CodedSizeLengthSigned(_Size, 0);
450					CodedValueLengthSigned(_Size, _CodedSize, _FinalHead);
451					output.writeFully(_FinalHead, _CodedSize);
452					Size += _CodedSize;
453				}
454			}
455			break;
456		case LACING_FIXED:
457			// number of laces
458			tmpValue = myBuffers.size()-1;
459			output.writeFully(&tmpValue, 1);
460			break;
461		case LACING_NONE:
462			break;
463	    default:
464			assert(0);
465		}
466
467		// put the data of each frame
468		for (i=0; i<myBuffers.size(); i++) {
469			output.writeFully(myBuffers[i]->Buffer(), myBuffers[i]->Size());
470			Size += myBuffers[i]->Size();
471		}
472	}
473
474	return Size;
475}
476
477uint64 KaxInternalBlock::ReadInternalHead(IOCallback & input)
478{
479	binary Buffer[5], *cursor = Buffer;
480	uint64 Result = input.read(cursor, 4);
481	if (Result != 4)
482		return Result;
483
484	// update internal values
485	TrackNumber = *cursor++;
486	if ((TrackNumber & 0x80) == 0) {
487		// there is extra data
488		if ((TrackNumber & 0x40) == 0) {
489			// We don't support track numbers that large !
490			return Result;
491		}
492		Result += input.read(&Buffer[4], 1);
493		TrackNumber = (TrackNumber & 0x3F) << 8;
494		TrackNumber += *cursor++;
495	} else {
496		TrackNumber &= 0x7F;
497	}
498
499
500	big_int16 b16;
501	b16.Eval(cursor);
502	assert(ParentCluster != NULL);
503	Timecode = ParentCluster->GetBlockGlobalTimecode(int16(b16));
504	bLocalTimecodeUsed = false;
505	cursor += 2;
506
507	return Result;
508}
509
510/*!
511	\todo better zero copy handling
512*/
513uint64 KaxInternalBlock::ReadData(IOCallback & input, ScopeMode ReadFully)
514{
515	uint64 Result;
516
517	FirstFrameLocation = input.getFilePointer(); // will be updated accordingly below
518
519	if (ReadFully == SCOPE_ALL_DATA)
520	{
521		Result = EbmlBinary::ReadData(input, ReadFully);
522		binary *cursor = Data;
523		uint8 BlockHeadSize = 4;
524
525		// update internal values
526		TrackNumber = *cursor++;
527		if ((TrackNumber & 0x80) == 0) {
528			// there is extra data
529			if ((TrackNumber & 0x40) == 0) {
530				// We don't support track numbers that large !
531				return Result;
532			}
533			TrackNumber = (TrackNumber & 0x3F) << 8;
534			TrackNumber += *cursor++;
535			BlockHeadSize++;
536		} else {
537			TrackNumber &= 0x7F;
538		}
539
540		big_int16 b16;
541		b16.Eval(cursor);
542		LocalTimecode = int16(b16);
543		bLocalTimecodeUsed = true;
544		cursor += 2;
545
546		if (EbmlId(*this) == KaxSimpleBlock::ClassInfos.GlobalId) {
547			bIsKeyframe = (*cursor & 0x80) != 0;
548			bIsDiscardable = (*cursor & 0x01) != 0;
549		}
550		mInvisible = (*cursor & 0x08) >> 3;
551		mLacing = LacingType((*cursor++ & 0x06) >> 1);
552
553		// put all Frames in the list
554		if (mLacing == LACING_NONE) {
555			FirstFrameLocation += cursor - Data;
556			DataBuffer * soloFrame = new DataBuffer(cursor, Size - BlockHeadSize);
557			myBuffers.push_back(soloFrame);
558			SizeList.resize(1);
559			SizeList[0] = Size - BlockHeadSize;
560		} else {
561			// read the number of frames in the lace
562			uint32 LastBufferSize = Size - BlockHeadSize - 1; // 1 for number of frame
563			uint8 FrameNum = *cursor++; // number of frames in the lace - 1
564			// read the list of frame sizes
565			uint8 Index;
566			int32 FrameSize;
567			uint32 SizeRead;
568			uint64 SizeUnknown;
569
570			SizeList.resize(FrameNum + 1);
571
572			switch (mLacing)
573			{
574			case LACING_XIPH:
575				for (Index=0; Index<FrameNum; Index++) {
576					// get the size of the frame
577					FrameSize = 0;
578					do {
579						FrameSize += uint8(*cursor);
580						LastBufferSize--;
581					} while (*cursor++ == 0xFF);
582					SizeList[Index] = FrameSize;
583					LastBufferSize -= FrameSize;
584				}
585				SizeList[Index] = LastBufferSize;
586				break;
587			case LACING_EBML:
588				SizeRead = LastBufferSize;
589				FrameSize = ReadCodedSizeValue(cursor, SizeRead, SizeUnknown);
590				SizeList[0] = FrameSize;
591				cursor += SizeRead;
592				LastBufferSize -= FrameSize + SizeRead;
593
594				for (Index=1; Index<FrameNum; Index++) {
595					// get the size of the frame
596					SizeRead = LastBufferSize;
597					FrameSize += ReadCodedSizeSignedValue(cursor, SizeRead, SizeUnknown);
598					SizeList[Index] = FrameSize;
599					cursor += SizeRead;
600					LastBufferSize -= FrameSize + SizeRead;
601				}
602				SizeList[Index] = LastBufferSize;
603				break;
604			case LACING_FIXED:
605				for (Index=0; Index<=FrameNum; Index++) {
606					// get the size of the frame
607					SizeList[Index] = LastBufferSize / (FrameNum + 1);
608				}
609				break;
610			default: // other lacing not supported
611				assert(0);
612			}
613
614			FirstFrameLocation += cursor - Data;
615
616			for (Index=0; Index<=FrameNum; Index++) {
617				DataBuffer * lacedFrame = new DataBuffer(cursor, SizeList[Index]);
618				myBuffers.push_back(lacedFrame);
619				cursor += SizeList[Index];
620			}
621		}
622		bValueIsSet = true;
623	}
624	else if (ReadFully == SCOPE_PARTIAL_DATA)
625	{
626		binary _TempHead[5];
627		Result = input.read(_TempHead, 5);
628		binary *cursor = _TempHead;
629		binary *_tmpBuf;
630		uint8 BlockHeadSize = 4;
631
632		// update internal values
633		TrackNumber = *cursor++;
634		if ((TrackNumber & 0x80) == 0) {
635			// there is extra data
636			if ((TrackNumber & 0x40) == 0) {
637				// We don't support track numbers that large !
638				return Result;
639			}
640			TrackNumber = (TrackNumber & 0x3F) << 8;
641			TrackNumber += *cursor++;
642			BlockHeadSize++;
643		} else {
644			TrackNumber &= 0x7F;
645		}
646
647		big_int16 b16;
648		b16.Eval(cursor);
649		LocalTimecode = int16(b16);
650		bLocalTimecodeUsed = true;
651		cursor += 2;
652
653		if (EbmlId(*this) == KaxSimpleBlock::ClassInfos.GlobalId) {
654			bIsKeyframe = (*cursor & 0x80) != 0;
655			bIsDiscardable = (*cursor & 0x01) != 0;
656		}
657		mInvisible = (*cursor & 0x08) >> 3;
658		mLacing = LacingType((*cursor++ & 0x06) >> 1);
659		if (cursor == &_TempHead[4])
660		{
661			_TempHead[0] = _TempHead[4];
662		} else {
663			Result += input.read(_TempHead, 1);
664		}
665
666		FirstFrameLocation += cursor - _TempHead;
667
668		// put all Frames in the list
669		if (mLacing != LACING_NONE) {
670			// read the number of frames in the lace
671			uint32 LastBufferSize = Size - BlockHeadSize - 1; // 1 for number of frame
672			uint8 FrameNum = _TempHead[0]; // number of frames in the lace - 1
673			// read the list of frame sizes
674			uint8 Index;
675			int32 FrameSize;
676			uint32 SizeRead;
677			uint64 SizeUnknown;
678
679			SizeList.resize(FrameNum + 1);
680
681			switch (mLacing)
682			{
683			case LACING_XIPH:
684				for (Index=0; Index<FrameNum; Index++) {
685					// get the size of the frame
686					FrameSize = 0;
687					do {
688						Result += input.read(_TempHead, 1);
689						FrameSize += uint8(_TempHead[0]);
690						LastBufferSize--;
691
692						FirstFrameLocation++;
693					} while (_TempHead[0] == 0xFF);
694
695					FirstFrameLocation++;
696					SizeList[Index] = FrameSize;
697					LastBufferSize -= FrameSize;
698				}
699				SizeList[Index] = LastBufferSize;
700				break;
701			case LACING_EBML:
702				SizeRead = LastBufferSize;
703				cursor = _tmpBuf = new binary[FrameNum*4]; /// \warning assume the mean size will be coded in less than 4 bytes
704				Result += input.read(cursor, FrameNum*4);
705				FrameSize = ReadCodedSizeValue(cursor, SizeRead, SizeUnknown);
706				SizeList[0] = FrameSize;
707				cursor += SizeRead;
708				LastBufferSize -= FrameSize + SizeRead;
709
710				for (Index=1; Index<FrameNum; Index++) {
711					// get the size of the frame
712					SizeRead = LastBufferSize;
713					FrameSize += ReadCodedSizeSignedValue(cursor, SizeRead, SizeUnknown);
714					SizeList[Index] = FrameSize;
715					cursor += SizeRead;
716					LastBufferSize -= FrameSize + SizeRead;
717				}
718
719				FirstFrameLocation += cursor - _tmpBuf;
720
721				SizeList[Index] = LastBufferSize;
722				delete [] _tmpBuf;
723				break;
724			case LACING_FIXED:
725				for (Index=0; Index<=FrameNum; Index++) {
726					// get the size of the frame
727					SizeList[Index] = LastBufferSize / (FrameNum + 1);
728				}
729				break;
730			default: // other lacing not supported
731				assert(0);
732			}
733		} else {
734			SizeList.resize(1);
735			SizeList[0] = Size - BlockHeadSize;
736		}
737		bValueIsSet = false;
738		Result = Size;
739	} else {
740		bValueIsSet = false;
741		Result = Size;
742	}
743
744	return Result;
745}
746
747bool KaxBlockGroup::AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing)
748{
749	KaxBlock & theBlock = GetChild<KaxBlock>(*this);
750	assert(ParentCluster != NULL);
751	theBlock.SetParent(*ParentCluster);
752	ParentTrack = &track;
753	return theBlock.AddFrame(track, timecode, buffer, lacing);
754}
755
756bool KaxBlockGroup::AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, LacingType lacing)
757{
758//	assert(past_timecode < 0);
759
760	KaxBlock & theBlock = GetChild<KaxBlock>(*this);
761	assert(ParentCluster != NULL);
762	theBlock.SetParent(*ParentCluster);
763	ParentTrack = &track;
764	bool bRes = theBlock.AddFrame(track, timecode, buffer, lacing);
765
766	KaxReferenceBlock & thePastRef = GetChild<KaxReferenceBlock>(*this);
767	thePastRef.SetReferencedBlock(PastBlock);
768	thePastRef.SetParentBlock(*this);
769
770	return bRes;
771}
772
773bool KaxBlockGroup::AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, const KaxBlockGroup & ForwBlock, LacingType lacing)
774{
775//	assert(past_timecode < 0);
776
777//	assert(forw_timecode > 0);
778
779	KaxBlock & theBlock = GetChild<KaxBlock>(*this);
780	assert(ParentCluster != NULL);
781	theBlock.SetParent(*ParentCluster);
782	ParentTrack = &track;
783	bool bRes = theBlock.AddFrame(track, timecode, buffer, lacing);
784
785	KaxReferenceBlock & thePastRef = GetChild<KaxReferenceBlock>(*this);
786	thePastRef.SetReferencedBlock(PastBlock);
787	thePastRef.SetParentBlock(*this);
788
789	KaxReferenceBlock & theFutureRef = AddNewChild<KaxReferenceBlock>(*this);
790	theFutureRef.SetReferencedBlock(ForwBlock);
791	theFutureRef.SetParentBlock(*this);
792
793	return bRes;
794}
795
796bool KaxBlockGroup::AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockBlob * PastBlock, const KaxBlockBlob * ForwBlock, LacingType lacing)
797{
798	KaxBlock & theBlock = GetChild<KaxBlock>(*this);
799	assert(ParentCluster != NULL);
800	theBlock.SetParent(*ParentCluster);
801	ParentTrack = &track;
802	bool bRes = theBlock.AddFrame(track, timecode, buffer, lacing);
803
804	if (PastBlock != NULL)
805	{
806		KaxReferenceBlock & thePastRef = GetChild<KaxReferenceBlock>(*this);
807		thePastRef.SetReferencedBlock(PastBlock);
808		thePastRef.SetParentBlock(*this);
809	}
810
811	if (ForwBlock != NULL)
812	{
813		KaxReferenceBlock & theFutureRef = AddNewChild<KaxReferenceBlock>(*this);
814		theFutureRef.SetReferencedBlock(ForwBlock);
815		theFutureRef.SetParentBlock(*this);
816	}
817
818	return bRes;
819}
820
821/*!
822	\todo we may cache the reference to the timecode block
823*/
824uint64 KaxBlockGroup::GlobalTimecode() const
825{
826	assert(ParentCluster != NULL); // impossible otherwise
827	KaxInternalBlock & MyBlock = *static_cast<KaxBlock *>(this->FindElt(KaxBlock::ClassInfos));
828	return MyBlock.GlobalTimecode();
829
830}
831
832uint16 KaxBlockGroup::TrackNumber() const
833{
834	KaxInternalBlock & MyBlock = *static_cast<KaxBlock *>(this->FindElt(KaxBlock::ClassInfos));
835	return MyBlock.TrackNum();
836}
837
838uint64 KaxBlockGroup::ClusterPosition() const
839{
840	assert(ParentCluster != NULL); // impossible otherwise
841	return ParentCluster->GetPosition();
842}
843
844uint64 KaxInternalBlock::ClusterPosition() const
845{
846	assert(ParentCluster != NULL); // impossible otherwise
847	return ParentCluster->GetPosition();
848}
849
850unsigned int KaxBlockGroup::ReferenceCount() const
851{
852	unsigned int Result = 0;
853	KaxReferenceBlock * MyBlockAdds = static_cast<KaxReferenceBlock *>(FindFirstElt(KaxReferenceBlock::ClassInfos));
854	if (MyBlockAdds != NULL) {
855		Result++;
856		while ((MyBlockAdds = static_cast<KaxReferenceBlock *>(FindNextElt(*MyBlockAdds))) != NULL)
857		{
858			Result++;
859		}
860	}
861	return Result;
862}
863
864const KaxReferenceBlock & KaxBlockGroup::Reference(unsigned int Index) const
865{
866	KaxReferenceBlock * MyBlockAdds = static_cast<KaxReferenceBlock *>(FindFirstElt(KaxReferenceBlock::ClassInfos));
867	assert(MyBlockAdds != NULL); // call of a non existing reference
868
869	while (Index != 0) {
870		MyBlockAdds = static_cast<KaxReferenceBlock *>(FindNextElt(*MyBlockAdds));
871		assert(MyBlockAdds != NULL);
872		Index--;
873	}
874	return *MyBlockAdds;
875}
876
877void KaxBlockGroup::ReleaseFrames()
878{
879	KaxInternalBlock & MyBlock = *static_cast<KaxBlock *>(this->FindElt(KaxBlock::ClassInfos));
880	MyBlock.ReleaseFrames();
881}
882
883void KaxInternalBlock::ReleaseFrames()
884{
885	// free the allocated Frames
886	int i;
887	for (i=myBuffers.size()-1; i>=0; i--) {
888		if (myBuffers[i] != NULL) {
889			myBuffers[i]->FreeBuffer(*myBuffers[i]);
890			delete myBuffers[i];
891			myBuffers[i] = NULL;
892		}
893	}
894}
895
896void KaxBlockGroup::SetBlockDuration(uint64 TimeLength)
897{
898	assert(ParentTrack != NULL);
899	int64 scale = ParentTrack->GlobalTimecodeScale();
900	KaxBlockDuration & myDuration = *static_cast<KaxBlockDuration *>(FindFirstElt(KaxBlockDuration::ClassInfos, true));
901	*(static_cast<EbmlUInteger *>(&myDuration)) = TimeLength / uint64(scale);
902}
903
904bool KaxBlockGroup::GetBlockDuration(uint64 &TheTimecode) const
905{
906	KaxBlockDuration * myDuration = static_cast<KaxBlockDuration *>(FindElt(KaxBlockDuration::ClassInfos));
907	if (myDuration == NULL) {
908		return false;
909	}
910
911	assert(ParentTrack != NULL);
912	TheTimecode = uint64(*myDuration) * ParentTrack->GlobalTimecodeScale();
913	return true;
914}
915
916KaxBlockGroup::operator KaxInternalBlock &() {
917	KaxBlock & theBlock = GetChild<KaxBlock>(*this);
918	return theBlock;
919}
920
921void KaxBlockGroup::SetParent(KaxCluster & aParentCluster) {
922	ParentCluster = &aParentCluster;
923	KaxBlock & theBlock = GetChild<KaxBlock>(*this);
924	theBlock.SetParent( aParentCluster );
925}
926
927void KaxInternalBlock::SetParent(KaxCluster & aParentCluster)
928{
929	ParentCluster = &aParentCluster;
930	if (bLocalTimecodeUsed) {
931		Timecode = aParentCluster.GetBlockGlobalTimecode(LocalTimecode);
932		bLocalTimecodeUsed = false;
933	}
934}
935
936int64 KaxInternalBlock::GetDataPosition(size_t FrameNumber)
937{
938	int64 _Result = -1;
939
940	if (bValueIsSet && FrameNumber < SizeList.size())
941	{
942		_Result = FirstFrameLocation;
943
944		size_t _Idx = 0;
945		while(FrameNumber--)
946		{
947			_Result += SizeList[_Idx++];
948		}
949	}
950
951	return _Result;
952}
953
954int64 KaxInternalBlock::GetFrameSize(size_t FrameNumber)
955{
956	int64 _Result = -1;
957
958	if (/*bValueIsSet &&*/ FrameNumber < SizeList.size())
959	{
960		_Result = SizeList[FrameNumber];
961	}
962
963	return _Result;
964}
965
966KaxBlockBlob::operator KaxBlockGroup &()
967{
968	assert(!bUseSimpleBlock);
969	assert(Block.group);
970	return *Block.group;
971}
972
973KaxBlockBlob::operator const KaxBlockGroup &() const
974{
975	assert(!bUseSimpleBlock);
976	assert(Block.group);
977	return *Block.group;
978}
979
980KaxBlockBlob::operator KaxInternalBlock &()
981{
982	assert(Block.group);
983#if MATROSKA_VERSION >= 2
984	if (bUseSimpleBlock)
985		return *Block.simpleblock;
986	else
987#endif
988		return *Block.group;
989}
990
991KaxBlockBlob::operator const KaxInternalBlock &() const
992{
993	assert(Block.group);
994#if MATROSKA_VERSION >= 2
995	if (bUseSimpleBlock)
996		return *Block.simpleblock;
997	else
998#endif
999		return *Block.group;
1000}
1001
1002#if MATROSKA_VERSION >= 2
1003KaxBlockBlob::operator KaxSimpleBlock &()
1004{
1005	assert(bUseSimpleBlock);
1006	assert(Block.simpleblock);
1007	return *Block.simpleblock;
1008}
1009#endif
1010
1011bool KaxBlockBlob::AddFrameAuto(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing, const KaxBlockBlob * PastBlock, const KaxBlockBlob * ForwBlock)
1012{
1013	bool bResult = false;
1014#if MATROSKA_VERSION >= 2
1015	if ((SimpleBlockMode == BLOCK_BLOB_ALWAYS_SIMPLE) || (SimpleBlockMode == BLOCK_BLOB_SIMPLE_AUTO && PastBlock == NULL && ForwBlock == NULL)) {
1016		assert(bUseSimpleBlock == true);
1017		if (Block.simpleblock == NULL) {
1018			Block.simpleblock = new KaxSimpleBlock();
1019			Block.simpleblock->SetParent(*ParentCluster);
1020		}
1021
1022		bResult = Block.simpleblock->AddFrame(track, timecode, buffer, lacing);
1023		if (PastBlock == NULL && ForwBlock == NULL) {
1024			Block.simpleblock->SetKeyframe(true);
1025			Block.simpleblock->SetDiscardable(false);
1026		} else {
1027			Block.simpleblock->SetKeyframe(false);
1028			if ((ForwBlock == NULL || ((const KaxInternalBlock &)*ForwBlock).GlobalTimecode() <= timecode) &&
1029				(PastBlock == NULL || ((const KaxInternalBlock &)*PastBlock).GlobalTimecode() <= timecode))
1030				Block.simpleblock->SetDiscardable(false);
1031			else
1032				Block.simpleblock->SetDiscardable(true);
1033		}
1034	}
1035	else
1036#endif
1037	{
1038		if (ReplaceSimpleByGroup()) {
1039			bResult = Block.group->AddFrame(track, timecode, buffer, PastBlock, ForwBlock, lacing);
1040		}
1041	}
1042
1043	return bResult;
1044}
1045
1046void KaxBlockBlob::SetParent(KaxCluster & parent_clust)
1047{
1048	ParentCluster = &parent_clust;
1049}
1050
1051void KaxBlockBlob::SetBlockDuration(uint64 TimeLength)
1052{
1053	if (ReplaceSimpleByGroup())
1054		Block.group->SetBlockDuration(TimeLength);
1055}
1056
1057bool KaxBlockBlob::ReplaceSimpleByGroup()
1058{
1059	if (SimpleBlockMode== BLOCK_BLOB_ALWAYS_SIMPLE)
1060		return false;
1061
1062	if (!bUseSimpleBlock) {
1063		if (Block.group == NULL) {
1064			Block.group = new KaxBlockGroup();
1065		}
1066	}
1067#if MATROSKA_VERSION >= 2
1068	else
1069	{
1070
1071		if (Block.simpleblock != NULL) {
1072			KaxSimpleBlock *old_simpleblock = Block.simpleblock;
1073			Block.group = new KaxBlockGroup();
1074			// _TODO_ : move all the data to the blockgroup
1075			assert(false);
1076			// -> while(frame) AddFrame(myBuffer)
1077			delete old_simpleblock;
1078		} else {
1079			Block.group = new KaxBlockGroup();
1080		}
1081	}
1082#endif
1083	if (ParentCluster != NULL)
1084		Block.group->SetParent(*ParentCluster);
1085
1086	bUseSimpleBlock = false;
1087	return true;
1088}
1089
1090void KaxBlockBlob::SetBlockGroup( KaxBlockGroup &BlockRef )
1091{
1092	assert(!bUseSimpleBlock);
1093	Block.group = &BlockRef;
1094}
1095
1096END_LIBMATROSKA_NAMESPACE
1097