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