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