From 44e91f4d61a4ce542070793885dfe635c3a71401 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Tue, 23 Mar 2010 15:01:34 +0000 Subject: [PATCH] Do not try to free() pointers pointing to member variables git-svn-id: https://matroska.svn.sourceforge.net/svnroot/matroska/trunk/libmatroska@52 a6f86f6d-0131-4f8e-9e7b-e335508773d5 --- matroska/KaxBlock.h | 847 ++++++++++++++++++++++---------------------- 1 file changed, 424 insertions(+), 423 deletions(-) diff --git a/matroska/KaxBlock.h b/matroska/KaxBlock.h index fb1064f..9fc092d 100644 --- a/matroska/KaxBlock.h +++ b/matroska/KaxBlock.h @@ -1,423 +1,424 @@ -/**************************************************************************** -** libmatroska : parse Matroska files, see http://www.matroska.org/ -** -** -** -** 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 - \author Julien Coloos -*/ -#ifndef LIBMATROSKA_BLOCK_H -#define LIBMATROSKA_BLOCK_H - -#include - -#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(&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 myBuffers; - std::vector 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); - 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 +/**************************************************************************** +** libmatroska : parse Matroska files, see http://www.matroska.org/ +** +** +** +** 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 + \author Julien Coloos +*/ +#ifndef LIBMATROSKA_BLOCK_H +#define LIBMATROSKA_BLOCK_H + +#include + +#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(&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 myBuffers; + std::vector 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 -- 2.40.0