]> granicus.if.org Git - libmatroska/commitdiff
Do not try to free() pointers pointing to member variables
authorMoritz Bunkus <moritz@bunkus.org>
Tue, 23 Mar 2010 15:01:34 +0000 (15:01 +0000)
committerMoritz Bunkus <moritz@bunkus.org>
Tue, 23 Mar 2010 15:01:34 +0000 (15:01 +0000)
git-svn-id: https://matroska.svn.sourceforge.net/svnroot/matroska/trunk/libmatroska@52 a6f86f6d-0131-4f8e-9e7b-e335508773d5

matroska/KaxBlock.h

index fb1064f105ebd3509d327681ca4e5c92cfd1b864..9fc092dcec6de10d3db78a1776b3246453d8557b 100644 (file)
-/****************************************************************************\r
-** libmatroska : parse Matroska files, see http://www.matroska.org/\r
-**\r
-** <file/class description>\r
-**\r
-** Copyright (C) 2002-2010 Steve Lhomme.  All rights reserved.\r
-**\r
-** This library is free software; you can redistribute it and/or\r
-** modify it under the terms of the GNU Lesser General Public\r
-** License as published by the Free Software Foundation; either\r
-** version 2.1 of the License, or (at your option) any later version.\r
-** \r
-** This library is distributed in the hope that it will be useful,\r
-** but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
-** Lesser General Public License for more details.\r
-** \r
-** You should have received a copy of the GNU Lesser General Public\r
-** License along with this library; if not, write to the Free Software\r
-** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
-**\r
-** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.**\r
-** Contact license@matroska.org if any conditions of this licensing are\r
-** not clear to you.\r
-**\r
-**********************************************************************/\r
-\r
-/*!\r
-       \file\r
-       \todo add a PureBlock class to group functionalities between Block and BlockVirtual\r
-       \version \$Id: KaxBlock.h,v 1.24 2004/04/14 23:26:17 robux4 Exp $\r
-       \author Steve Lhomme     <robux4 @ users.sf.net>\r
-       \author Julien Coloos    <suiryc @ users.sf.net>\r
-*/\r
-#ifndef LIBMATROSKA_BLOCK_H\r
-#define LIBMATROSKA_BLOCK_H\r
-\r
-#include <vector>\r
-\r
-#include "matroska/KaxTypes.h"\r
-#include "ebml/EbmlBinary.h"\r
-#include "ebml/EbmlMaster.h"\r
-#include "matroska/KaxTracks.h"\r
-\r
-using namespace LIBEBML_NAMESPACE;\r
-\r
-START_LIBMATROSKA_NAMESPACE\r
-\r
-class KaxCluster;\r
-class KaxReferenceBlock;\r
-class KaxInternalBlock;\r
-class KaxBlockBlob;\r
-\r
-class MATROSKA_DLL_API DataBuffer {\r
-       protected:\r
-               binary * myBuffer;\r
-               uint32   mySize;\r
-               bool     bValidValue;\r
-               bool     (*myFreeBuffer)(const DataBuffer & aBuffer); // method to free the internal buffer\r
-\r
-       public:\r
-               DataBuffer(binary * aBuffer, uint32 aSize, bool (*aFreeBuffer)(const DataBuffer & aBuffer) = NULL)\r
-                       :myBuffer(aBuffer)\r
-                       ,mySize(aSize)\r
-                       ,bValidValue(true)      \r
-      ,myFreeBuffer(aFreeBuffer)\r
-               {}\r
-               virtual ~DataBuffer() {}\r
-               virtual binary * Buffer() {return myBuffer;}\r
-               virtual uint32   & Size() {return mySize;};\r
-               virtual const binary * Buffer() const {return myBuffer;}\r
-               virtual const uint32   Size()   const {return mySize;};\r
-               bool    FreeBuffer(const DataBuffer & aBuffer) {\r
-                       bool bResult = true;\r
-                       if (myBuffer != NULL && myFreeBuffer != NULL && bValidValue) {\r
-                               bResult = myFreeBuffer(aBuffer);\r
-                               myBuffer = NULL;\r
-                               bValidValue = false;\r
-                       }\r
-                       return bResult;\r
-               }\r
-\r
-               virtual DataBuffer * Clone();\r
-};\r
-\r
-class MATROSKA_DLL_API SimpleDataBuffer : public DataBuffer {\r
-       public:\r
-               SimpleDataBuffer(binary * aBuffer, uint32 aSize, uint32 aOffset, bool (*aFreeBuffer)(const DataBuffer & aBuffer) = myFreeBuffer)\r
-                       :DataBuffer(aBuffer + aOffset, aSize, aFreeBuffer)\r
-                       ,Offset(aOffset)\r
-                       ,BaseBuffer(aBuffer)\r
-               {}\r
-               virtual ~SimpleDataBuffer() {}\r
-\r
-               DataBuffer * Clone() {return new SimpleDataBuffer(*this);}\r
-\r
-       protected:\r
-               uint32 Offset;\r
-               binary * BaseBuffer;\r
-\r
-               static bool myFreeBuffer(const DataBuffer & aBuffer)\r
-               {\r
-                       binary *_Buffer = static_cast<const SimpleDataBuffer*>(&aBuffer)->BaseBuffer;\r
-                       if (_Buffer != NULL)\r
-                               free(_Buffer);\r
-                       return true;\r
-               }\r
-\r
-               SimpleDataBuffer(const SimpleDataBuffer & ToClone);\r
-};\r
-\r
-/*!\r
-       \note the data is copied locally, it can be freed right away\r
-* /\r
-class MATROSKA_DLL_API NotSoSimpleDataBuffer : public SimpleDataBuffer {\r
-       public:\r
-               NotSoSimpleDataBuffer(binary * aBuffer, uint32 aSize, uint32 aOffset)\r
-                       :SimpleDataBuffer(new binary[aSize - aOffset], aSize, 0)\r
-               {\r
-                       memcpy(BaseBuffer, aBuffer + aOffset, aSize - aOffset);\r
-               }\r
-};\r
-*/\r
-\r
-class MATROSKA_DLL_API KaxBlockGroup : public EbmlMaster {\r
-       public:\r
-               KaxBlockGroup();\r
-               KaxBlockGroup(const KaxBlockGroup & ElementToClone) :EbmlMaster(ElementToClone) {}\r
-\r
-               ~KaxBlockGroup();\r
-\r
-               /*!\r
-                       \brief Addition of a frame without references\r
-               */\r
-               bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO);\r
-               /*!\r
-                       \brief Addition of a frame with a backward reference (P frame)\r
-               */\r
-               bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, LacingType lacing = LACING_AUTO);\r
-\r
-               /*!\r
-                       \brief Addition of a frame with a backward+forward reference (B frame)\r
-               */\r
-               bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, const KaxBlockGroup & ForwBlock, LacingType lacing = LACING_AUTO);\r
-               bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockBlob * PastBlock, const KaxBlockBlob * ForwBlock, LacingType lacing = LACING_AUTO);\r
-\r
-               void SetParent(KaxCluster & aParentCluster);\r
-\r
-               void SetParentTrack(const KaxTrackEntry & aParentTrack) {\r
-                       ParentTrack = &aParentTrack;\r
-               }\r
-\r
-               /*!\r
-                       \brief Set the duration of the contained frame(s) (for the total number of frames)\r
-               */\r
-               void SetBlockDuration(uint64 TimeLength);\r
-               bool GetBlockDuration(uint64 &TheTimecode) const;\r
-\r
-               /*!\r
-                       \return the global timecode of this Block (not just the delta to the Cluster)\r
-               */\r
-               uint64 GlobalTimecode() const;\r
-               uint64 GlobalTimecodeScale() const {\r
-                       assert(ParentTrack != NULL);\r
-                       return ParentTrack->GlobalTimecodeScale();\r
-               }\r
-\r
-               uint16 TrackNumber() const;\r
-\r
-               uint64 ClusterPosition() const;\r
-               \r
-               /*!\r
-                       \return the number of references to other frames\r
-               */\r
-               unsigned int ReferenceCount() const;\r
-               const KaxReferenceBlock & Reference(unsigned int Index) const;\r
-\r
-               /*!\r
-                       \brief release all the frames of all Blocks\r
-               */\r
-               void ReleaseFrames();\r
-\r
-               operator KaxInternalBlock &();\r
-\r
-               const KaxCluster *GetParentCluster() const { return ParentCluster; }\r
-\r
-       protected:\r
-               KaxCluster * ParentCluster;\r
-               const KaxTrackEntry * ParentTrack;\r
-        \r
-        EBML_CONCRETE_CLASS(KaxBlockGroup)\r
-};\r
-\r
-class KaxInternalBlock : public EbmlBinary {\r
-       public:\r
-               KaxInternalBlock( bool bSimple ) :bLocalTimecodeUsed(false), mLacing(LACING_AUTO), mInvisible(false)\r
-                       ,ParentCluster(NULL), bIsSimple(bSimple), bIsKeyframe(true), bIsDiscardable(false)\r
-               {}\r
-               KaxInternalBlock(const KaxInternalBlock & ElementToClone);\r
-               ~KaxInternalBlock();\r
-               bool ValidateSize() const;\r
-\r
-               uint16 TrackNum() const {return TrackNumber;}\r
-               /*!\r
-                       \todo !!!! This method needs to be changes !\r
-               */\r
-               uint64 GlobalTimecode() const {return Timecode;}\r
-\r
-               /*!\r
-                       \note override this function to generate the Data/Size on the fly, unlike the usual binary elements\r
-               */\r
-               filepos_t UpdateSize(bool bSaveDefault = false, bool bForceRender = false);\r
-               filepos_t ReadData(IOCallback & input, ScopeMode ReadFully = SCOPE_ALL_DATA);\r
-               \r
-               /*!\r
-                       \brief Only read the head of the Block (not internal data)\r
-                       \note convenient when you are parsing the file quickly\r
-               */\r
-               uint64 ReadInternalHead(IOCallback & input);\r
-               \r
-               unsigned int NumberFrames() const { return SizeList.size();}\r
-               DataBuffer & GetBuffer(unsigned int iIndex) {return *myBuffers[iIndex];}\r
-\r
-               bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO, bool invisible = false);\r
-\r
-               /*!\r
-                       \brief release all the frames of all Blocks\r
-               */\r
-               void ReleaseFrames();\r
-\r
-               void SetParent(KaxCluster & aParentCluster);\r
-\r
-               /*!\r
-                       \return Returns the lacing type that produces the smallest footprint.\r
-               */\r
-               LacingType GetBestLacingType() const;\r
-\r
-               /*!\r
-                       \param FrameNumber 0 for the first frame\r
-                       \return the position in the stream for a given frame\r
-                       \note return -1 if the position doesn't exist\r
-               */\r
-               int64 GetDataPosition(size_t FrameNumber = 0);\r
-\r
-               /*!\r
-                       \param FrameNumber 0 for the first frame\r
-                       \return the size of a given frame\r
-                       \note return -1 if the position doesn't exist\r
-               */\r
-               int64 GetFrameSize(size_t FrameNumber = 0);\r
-               \r
-               bool IsInvisible() const { return mInvisible; }\r
-\r
-               uint64 ClusterPosition() const;\r
-\r
-       protected:\r
-               std::vector<DataBuffer *> myBuffers;\r
-               std::vector<int32>        SizeList;\r
-               uint64     Timecode; // temporary timecode of the first frame, non scaled\r
-               int16      LocalTimecode;\r
-               bool       bLocalTimecodeUsed;\r
-               uint16     TrackNumber;\r
-               LacingType mLacing;\r
-               bool       mInvisible;\r
-               uint64     FirstFrameLocation;\r
-\r
-               filepos_t RenderData(IOCallback & output, bool bForceRender, bool bSaveDefault = false);\r
-\r
-               KaxCluster * ParentCluster;\r
-               bool       bIsSimple;\r
-               bool       bIsKeyframe;\r
-               bool       bIsDiscardable;\r
-};\r
-\r
-class MATROSKA_DLL_API KaxBlock : public KaxInternalBlock {\r
-       public:\r
-               KaxBlock() :KaxInternalBlock(false) {}\r
-        \r
-        EBML_CONCRETE_CLASS(KaxBlock)\r
-};\r
-\r
-#if MATROSKA_VERSION >= 2\r
-class MATROSKA_DLL_API KaxSimpleBlock : public KaxInternalBlock {\r
-       public:\r
-               KaxSimpleBlock() :KaxInternalBlock(true) {}\r
-\r
-               void SetKeyframe(bool b_keyframe) { bIsKeyframe = b_keyframe; }\r
-               void SetDiscardable(bool b_discard) { bIsDiscardable = b_discard; }\r
-\r
-               bool IsKeyframe() const    { return bIsKeyframe; }\r
-               bool IsDiscardable() const { return bIsDiscardable; }\r
-\r
-               operator KaxInternalBlock &() { return *this; }\r
-        \r
-        EBML_CONCRETE_CLASS(KaxSimpleBlock)\r
-};\r
-#endif // MATROSKA_VERSION\r
-\r
-class MATROSKA_DLL_API KaxBlockBlob {\r
-public:\r
-       KaxBlockBlob(BlockBlobType sblock_mode) :ParentCluster(NULL), SimpleBlockMode(sblock_mode) {\r
-               bUseSimpleBlock = (sblock_mode != BLOCK_BLOB_NO_SIMPLE);\r
-               Block.group = NULL;\r
-       }\r
-\r
-       ~KaxBlockBlob() {\r
-#if MATROSKA_VERSION >= 2\r
-               if (bUseSimpleBlock)\r
-                       delete Block.simpleblock;\r
-               else\r
-#endif // MATROSKA_VERSION\r
-                       delete Block.group;\r
-       }\r
-\r
-       operator KaxBlockGroup &();\r
-       operator const KaxBlockGroup &() const;\r
-#if MATROSKA_VERSION >= 2\r
-       operator KaxSimpleBlock &();\r
-#endif\r
-       operator KaxInternalBlock &();\r
-       operator const KaxInternalBlock &() const;\r
-\r
-       void SetBlockGroup( KaxBlockGroup &BlockRef );\r
-\r
-       void SetBlockDuration(uint64 TimeLength);\r
-\r
-       void SetParent(KaxCluster & aParentCluster);\r
-       bool AddFrameAuto(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO, const KaxBlockBlob * PastBlock = NULL, const KaxBlockBlob * ForwBlock = NULL);\r
-\r
-       bool IsSimpleBlock() const {return bUseSimpleBlock;}\r
-\r
-       bool ReplaceSimpleByGroup();\r
-protected:\r
-       KaxCluster * ParentCluster;\r
-       union {\r
-               KaxBlockGroup *group;\r
-#if MATROSKA_VERSION >= 2\r
-               KaxSimpleBlock *simpleblock;\r
-#endif // MATROSKA_VERSION\r
-       } Block;\r
-       bool bUseSimpleBlock;\r
-       BlockBlobType SimpleBlockMode;\r
-};\r
-\r
-class MATROSKA_DLL_API KaxBlockDuration : public EbmlUInteger {\r
-       public:\r
-               KaxBlockDuration() {}\r
-               KaxBlockDuration(const KaxBlockDuration & ElementToClone) :EbmlUInteger(ElementToClone) {}\r
-        \r
-        EBML_CONCRETE_CLASS(KaxBlockDuration)\r
-};\r
-\r
-#if MATROSKA_VERSION >= 2\r
-class MATROSKA_DLL_API KaxBlockVirtual : public EbmlBinary {\r
-       public:\r
-               KaxBlockVirtual() :ParentCluster(NULL) {SetBuffer(DataBlock,sizeof(DataBlock)); SetValueIsSet(false);}\r
-               KaxBlockVirtual(const KaxBlockVirtual & ElementToClone);\r
-               bool ValidateSize() const {return true;}\r
-\r
-               /*!\r
-                       \note override this function to generate the Data/Size on the fly, unlike the usual binary elements\r
-               */\r
-               filepos_t UpdateSize(bool bSaveDefault = false, bool bForceRender = false);\r
-\r
-               void SetParent(const KaxCluster & aParentCluster) {ParentCluster = &aParentCluster;}\r
-\r
-       protected:\r
-               uint64 Timecode; // temporary timecode of the first frame if there are more than one\r
-               uint16 TrackNumber;\r
-               binary DataBlock[5];\r
-\r
-               const KaxCluster * ParentCluster;\r
-        \r
-        EBML_CONCRETE_CLASS(KaxBlockVirtual)\r
-};\r
-#endif // MATROSKA_VERSION\r
-\r
-class MATROSKA_DLL_API KaxBlockAdditional : public EbmlBinary {\r
-       public:\r
-               KaxBlockAdditional() {}\r
-               KaxBlockAdditional(const KaxBlockAdditional & ElementToClone) :EbmlBinary(ElementToClone){}\r
-        bool ValidateSize() const {return true;}\r
-\r
-        EBML_CONCRETE_CLASS(KaxBlockAdditional)\r
-};\r
-\r
-class MATROSKA_DLL_API KaxBlockAdditions : public EbmlMaster {\r
-       public:\r
-               KaxBlockAdditions();\r
-               KaxBlockAdditions(const KaxBlockAdditions & ElementToClone) :EbmlMaster(ElementToClone) {}\r
-        \r
-        EBML_CONCRETE_CLASS(KaxBlockAdditions)\r
-};\r
-\r
-class MATROSKA_DLL_API KaxBlockMore : public EbmlMaster {\r
-       public:\r
-               KaxBlockMore();\r
-               KaxBlockMore(const KaxBlockMore & ElementToClone) :EbmlMaster(ElementToClone) {}\r
-        \r
-        EBML_CONCRETE_CLASS(KaxBlockMore)\r
-};\r
-\r
-class MATROSKA_DLL_API KaxBlockAddID : public EbmlUInteger {\r
-       public:\r
-               KaxBlockAddID() :EbmlUInteger(1) {}\r
-               KaxBlockAddID(const KaxBlockAddID & ElementToClone) :EbmlUInteger(ElementToClone) {}\r
-        \r
-        EBML_CONCRETE_CLASS(KaxBlockAddID)\r
-};\r
-\r
-class MATROSKA_DLL_API KaxCodecState : public EbmlBinary {\r
-       public:\r
-               KaxCodecState() {}\r
-               KaxCodecState(const KaxCodecState & ElementToClone) :EbmlBinary(ElementToClone){}\r
-\r
-        bool ValidateSize() const {return true;}\r
-\r
-        EBML_CONCRETE_CLASS(KaxCodecState)\r
-};\r
-\r
-END_LIBMATROSKA_NAMESPACE\r
-\r
-#endif // LIBMATROSKA_BLOCK_H\r
+/****************************************************************************
+** libmatroska : parse Matroska files, see http://www.matroska.org/
+**
+** <file/class description>
+**
+** Copyright (C) 2002-2010 Steve Lhomme.  All rights reserved.
+**
+** This library is free software; you can redistribute it and/or
+** modify it under the terms of the GNU Lesser General Public
+** License as published by the Free Software Foundation; either
+** version 2.1 of the License, or (at your option) any later version.
+** 
+** This library is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+** Lesser General Public License for more details.
+** 
+** You should have received a copy of the GNU Lesser General Public
+** License along with this library; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+**
+** See http://www.matroska.org/license/lgpl/ for LGPL licensing information.**
+** Contact license@matroska.org if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+/*!
+       \file
+       \todo add a PureBlock class to group functionalities between Block and BlockVirtual
+       \version \$Id: KaxBlock.h,v 1.24 2004/04/14 23:26:17 robux4 Exp $
+       \author Steve Lhomme     <robux4 @ users.sf.net>
+       \author Julien Coloos    <suiryc @ users.sf.net>
+*/
+#ifndef LIBMATROSKA_BLOCK_H
+#define LIBMATROSKA_BLOCK_H
+
+#include <vector>
+
+#include "matroska/KaxTypes.h"
+#include "ebml/EbmlBinary.h"
+#include "ebml/EbmlMaster.h"
+#include "matroska/KaxTracks.h"
+
+using namespace LIBEBML_NAMESPACE;
+
+START_LIBMATROSKA_NAMESPACE
+
+class KaxCluster;
+class KaxReferenceBlock;
+class KaxInternalBlock;
+class KaxBlockBlob;
+
+class MATROSKA_DLL_API DataBuffer {
+       protected:
+               binary * myBuffer;
+               uint32   mySize;
+               bool     bValidValue;
+               bool     (*myFreeBuffer)(const DataBuffer & aBuffer); // method to free the internal buffer
+
+       public:
+               DataBuffer(binary * aBuffer, uint32 aSize, bool (*aFreeBuffer)(const DataBuffer & aBuffer) = NULL)
+                       :myBuffer(aBuffer)
+                       ,mySize(aSize)
+                       ,bValidValue(true)      
+      ,myFreeBuffer(aFreeBuffer)
+               {}
+               virtual ~DataBuffer() {}
+               virtual binary * Buffer() {return myBuffer;}
+               virtual uint32   & Size() {return mySize;};
+               virtual const binary * Buffer() const {return myBuffer;}
+               virtual const uint32   Size()   const {return mySize;};
+               bool    FreeBuffer(const DataBuffer & aBuffer) {
+                       bool bResult = true;
+                       if (myBuffer != NULL && myFreeBuffer != NULL && bValidValue) {
+                               bResult = myFreeBuffer(aBuffer);
+                               myBuffer = NULL;
+                               bValidValue = false;
+                       }
+                       return bResult;
+               }
+
+               virtual DataBuffer * Clone();
+};
+
+class MATROSKA_DLL_API SimpleDataBuffer : public DataBuffer {
+       public:
+               SimpleDataBuffer(binary * aBuffer, uint32 aSize, uint32 aOffset, bool (*aFreeBuffer)(const DataBuffer & aBuffer) = myFreeBuffer)
+                       :DataBuffer(aBuffer + aOffset, aSize, aFreeBuffer)
+                       ,Offset(aOffset)
+                       ,BaseBuffer(aBuffer)
+               {}
+               virtual ~SimpleDataBuffer() {}
+
+               DataBuffer * Clone() {return new SimpleDataBuffer(*this);}
+
+       protected:
+               uint32 Offset;
+               binary * BaseBuffer;
+
+               static bool myFreeBuffer(const DataBuffer & aBuffer)
+               {
+                       binary *_Buffer = static_cast<const SimpleDataBuffer*>(&aBuffer)->BaseBuffer;
+                       if (_Buffer != NULL)
+                               free(_Buffer);
+                       return true;
+               }
+
+               SimpleDataBuffer(const SimpleDataBuffer & ToClone);
+};
+
+/*!
+       \note the data is copied locally, it can be freed right away
+* /
+class MATROSKA_DLL_API NotSoSimpleDataBuffer : public SimpleDataBuffer {
+       public:
+               NotSoSimpleDataBuffer(binary * aBuffer, uint32 aSize, uint32 aOffset)
+                       :SimpleDataBuffer(new binary[aSize - aOffset], aSize, 0)
+               {
+                       memcpy(BaseBuffer, aBuffer + aOffset, aSize - aOffset);
+               }
+};
+*/
+
+class MATROSKA_DLL_API KaxBlockGroup : public EbmlMaster {
+       public:
+               KaxBlockGroup();
+               KaxBlockGroup(const KaxBlockGroup & ElementToClone) :EbmlMaster(ElementToClone) {}
+
+               ~KaxBlockGroup();
+
+               /*!
+                       \brief Addition of a frame without references
+               */
+               bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO);
+               /*!
+                       \brief Addition of a frame with a backward reference (P frame)
+               */
+               bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, LacingType lacing = LACING_AUTO);
+
+               /*!
+                       \brief Addition of a frame with a backward+forward reference (B frame)
+               */
+               bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockGroup & PastBlock, const KaxBlockGroup & ForwBlock, LacingType lacing = LACING_AUTO);
+               bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, const KaxBlockBlob * PastBlock, const KaxBlockBlob * ForwBlock, LacingType lacing = LACING_AUTO);
+
+               void SetParent(KaxCluster & aParentCluster);
+
+               void SetParentTrack(const KaxTrackEntry & aParentTrack) {
+                       ParentTrack = &aParentTrack;
+               }
+
+               /*!
+                       \brief Set the duration of the contained frame(s) (for the total number of frames)
+               */
+               void SetBlockDuration(uint64 TimeLength);
+               bool GetBlockDuration(uint64 &TheTimecode) const;
+
+               /*!
+                       \return the global timecode of this Block (not just the delta to the Cluster)
+               */
+               uint64 GlobalTimecode() const;
+               uint64 GlobalTimecodeScale() const {
+                       assert(ParentTrack != NULL);
+                       return ParentTrack->GlobalTimecodeScale();
+               }
+
+               uint16 TrackNumber() const;
+
+               uint64 ClusterPosition() const;
+               
+               /*!
+                       \return the number of references to other frames
+               */
+               unsigned int ReferenceCount() const;
+               const KaxReferenceBlock & Reference(unsigned int Index) const;
+
+               /*!
+                       \brief release all the frames of all Blocks
+               */
+               void ReleaseFrames();
+
+               operator KaxInternalBlock &();
+
+               const KaxCluster *GetParentCluster() const { return ParentCluster; }
+
+       protected:
+               KaxCluster * ParentCluster;
+               const KaxTrackEntry * ParentTrack;
+        
+        EBML_CONCRETE_CLASS(KaxBlockGroup)
+};
+
+class KaxInternalBlock : public EbmlBinary {
+       public:
+               KaxInternalBlock( bool bSimple ) :bLocalTimecodeUsed(false), mLacing(LACING_AUTO), mInvisible(false)
+                       ,ParentCluster(NULL), bIsSimple(bSimple), bIsKeyframe(true), bIsDiscardable(false)
+               {}
+               KaxInternalBlock(const KaxInternalBlock & ElementToClone);
+               ~KaxInternalBlock();
+               bool ValidateSize() const;
+
+               uint16 TrackNum() const {return TrackNumber;}
+               /*!
+                       \todo !!!! This method needs to be changes !
+               */
+               uint64 GlobalTimecode() const {return Timecode;}
+
+               /*!
+                       \note override this function to generate the Data/Size on the fly, unlike the usual binary elements
+               */
+               filepos_t UpdateSize(bool bSaveDefault = false, bool bForceRender = false);
+               filepos_t ReadData(IOCallback & input, ScopeMode ReadFully = SCOPE_ALL_DATA);
+               
+               /*!
+                       \brief Only read the head of the Block (not internal data)
+                       \note convenient when you are parsing the file quickly
+               */
+               uint64 ReadInternalHead(IOCallback & input);
+               
+               unsigned int NumberFrames() const { return SizeList.size();}
+               DataBuffer & GetBuffer(unsigned int iIndex) {return *myBuffers[iIndex];}
+
+               bool AddFrame(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO, bool invisible = false);
+
+               /*!
+                       \brief release all the frames of all Blocks
+               */
+               void ReleaseFrames();
+
+               void SetParent(KaxCluster & aParentCluster);
+
+               /*!
+                       \return Returns the lacing type that produces the smallest footprint.
+               */
+               LacingType GetBestLacingType() const;
+
+               /*!
+                       \param FrameNumber 0 for the first frame
+                       \return the position in the stream for a given frame
+                       \note return -1 if the position doesn't exist
+               */
+               int64 GetDataPosition(size_t FrameNumber = 0);
+
+               /*!
+                       \param FrameNumber 0 for the first frame
+                       \return the size of a given frame
+                       \note return -1 if the position doesn't exist
+               */
+               int64 GetFrameSize(size_t FrameNumber = 0);
+               
+               bool IsInvisible() const { return mInvisible; }
+
+               uint64 ClusterPosition() const;
+
+       protected:
+               std::vector<DataBuffer *> myBuffers;
+               std::vector<int32>        SizeList;
+               uint64     Timecode; // temporary timecode of the first frame, non scaled
+               int16      LocalTimecode;
+               bool       bLocalTimecodeUsed;
+               uint16     TrackNumber;
+               LacingType mLacing;
+               bool       mInvisible;
+               uint64     FirstFrameLocation;
+
+               filepos_t RenderData(IOCallback & output, bool bForceRender, bool bSaveDefault = false);
+
+               KaxCluster * ParentCluster;
+               bool       bIsSimple;
+               bool       bIsKeyframe;
+               bool       bIsDiscardable;
+};
+
+class MATROSKA_DLL_API KaxBlock : public KaxInternalBlock {
+       public:
+               KaxBlock() :KaxInternalBlock(false) {}
+        
+        EBML_CONCRETE_CLASS(KaxBlock)
+};
+
+#if MATROSKA_VERSION >= 2
+class MATROSKA_DLL_API KaxSimpleBlock : public KaxInternalBlock {
+       public:
+               KaxSimpleBlock() :KaxInternalBlock(true) {}
+
+               void SetKeyframe(bool b_keyframe) { bIsKeyframe = b_keyframe; }
+               void SetDiscardable(bool b_discard) { bIsDiscardable = b_discard; }
+
+               bool IsKeyframe() const    { return bIsKeyframe; }
+               bool IsDiscardable() const { return bIsDiscardable; }
+
+               operator KaxInternalBlock &() { return *this; }
+        
+        EBML_CONCRETE_CLASS(KaxSimpleBlock)
+};
+#endif // MATROSKA_VERSION
+
+class MATROSKA_DLL_API KaxBlockBlob {
+public:
+       KaxBlockBlob(BlockBlobType sblock_mode) :ParentCluster(NULL), SimpleBlockMode(sblock_mode) {
+               bUseSimpleBlock = (sblock_mode != BLOCK_BLOB_NO_SIMPLE);
+               Block.group = NULL;
+       }
+
+       ~KaxBlockBlob() {
+#if MATROSKA_VERSION >= 2
+               if (bUseSimpleBlock)
+                       delete Block.simpleblock;
+               else
+#endif // MATROSKA_VERSION
+                       delete Block.group;
+       }
+
+       operator KaxBlockGroup &();
+       operator const KaxBlockGroup &() const;
+#if MATROSKA_VERSION >= 2
+       operator KaxSimpleBlock &();
+#endif
+       operator KaxInternalBlock &();
+       operator const KaxInternalBlock &() const;
+
+       void SetBlockGroup( KaxBlockGroup &BlockRef );
+
+       void SetBlockDuration(uint64 TimeLength);
+
+       void SetParent(KaxCluster & aParentCluster);
+       bool AddFrameAuto(const KaxTrackEntry & track, uint64 timecode, DataBuffer & buffer, LacingType lacing = LACING_AUTO, const KaxBlockBlob * PastBlock = NULL, const KaxBlockBlob * ForwBlock = NULL);
+
+       bool IsSimpleBlock() const {return bUseSimpleBlock;}
+
+       bool ReplaceSimpleByGroup();
+protected:
+       KaxCluster * ParentCluster;
+       union {
+               KaxBlockGroup *group;
+#if MATROSKA_VERSION >= 2
+               KaxSimpleBlock *simpleblock;
+#endif // MATROSKA_VERSION
+       } Block;
+       bool bUseSimpleBlock;
+       BlockBlobType SimpleBlockMode;
+};
+
+class MATROSKA_DLL_API KaxBlockDuration : public EbmlUInteger {
+       public:
+               KaxBlockDuration() {}
+               KaxBlockDuration(const KaxBlockDuration & ElementToClone) :EbmlUInteger(ElementToClone) {}
+        
+        EBML_CONCRETE_CLASS(KaxBlockDuration)
+};
+
+#if MATROSKA_VERSION >= 2
+class MATROSKA_DLL_API KaxBlockVirtual : public EbmlBinary {
+       public:
+               KaxBlockVirtual() :ParentCluster(NULL) {SetBuffer(DataBlock,sizeof(DataBlock)); SetValueIsSet(false);}
+               KaxBlockVirtual(const KaxBlockVirtual & ElementToClone);
+               ~KaxBlockVirtual() { if( Data == DataBlock ) SetBuffer( NULL, 0 ); };
+               bool ValidateSize() const {return true;}
+
+               /*!
+                       \note override this function to generate the Data/Size on the fly, unlike the usual binary elements
+               */
+               filepos_t UpdateSize(bool bSaveDefault = false, bool bForceRender = false);
+
+               void SetParent(const KaxCluster & aParentCluster) {ParentCluster = &aParentCluster;}
+
+       protected:
+               uint64 Timecode; // temporary timecode of the first frame if there are more than one
+               uint16 TrackNumber;
+               binary DataBlock[5];
+
+               const KaxCluster * ParentCluster;
+        
+        EBML_CONCRETE_CLASS(KaxBlockVirtual)
+};
+#endif // MATROSKA_VERSION
+
+class MATROSKA_DLL_API KaxBlockAdditional : public EbmlBinary {
+       public:
+               KaxBlockAdditional() {}
+               KaxBlockAdditional(const KaxBlockAdditional & ElementToClone) :EbmlBinary(ElementToClone){}
+        bool ValidateSize() const {return true;}
+
+        EBML_CONCRETE_CLASS(KaxBlockAdditional)
+};
+
+class MATROSKA_DLL_API KaxBlockAdditions : public EbmlMaster {
+       public:
+               KaxBlockAdditions();
+               KaxBlockAdditions(const KaxBlockAdditions & ElementToClone) :EbmlMaster(ElementToClone) {}
+        
+        EBML_CONCRETE_CLASS(KaxBlockAdditions)
+};
+
+class MATROSKA_DLL_API KaxBlockMore : public EbmlMaster {
+       public:
+               KaxBlockMore();
+               KaxBlockMore(const KaxBlockMore & ElementToClone) :EbmlMaster(ElementToClone) {}
+        
+        EBML_CONCRETE_CLASS(KaxBlockMore)
+};
+
+class MATROSKA_DLL_API KaxBlockAddID : public EbmlUInteger {
+       public:
+               KaxBlockAddID() :EbmlUInteger(1) {}
+               KaxBlockAddID(const KaxBlockAddID & ElementToClone) :EbmlUInteger(ElementToClone) {}
+        
+        EBML_CONCRETE_CLASS(KaxBlockAddID)
+};
+
+class MATROSKA_DLL_API KaxCodecState : public EbmlBinary {
+       public:
+               KaxCodecState() {}
+               KaxCodecState(const KaxCodecState & ElementToClone) :EbmlBinary(ElementToClone){}
+
+        bool ValidateSize() const {return true;}
+
+        EBML_CONCRETE_CLASS(KaxCodecState)
+};
+
+END_LIBMATROSKA_NAMESPACE
+
+#endif // LIBMATROSKA_BLOCK_H