summaryrefslogtreecommitdiff
path: root/source/XMPFiles/FormatSupport/MOOV_Support.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/XMPFiles/FormatSupport/MOOV_Support.hpp')
-rw-r--r--source/XMPFiles/FormatSupport/MOOV_Support.hpp215
1 files changed, 215 insertions, 0 deletions
diff --git a/source/XMPFiles/FormatSupport/MOOV_Support.hpp b/source/XMPFiles/FormatSupport/MOOV_Support.hpp
new file mode 100644
index 0000000..3e19a9d
--- /dev/null
+++ b/source/XMPFiles/FormatSupport/MOOV_Support.hpp
@@ -0,0 +1,215 @@
+#ifndef __MOOV_Support_hpp__
+#define __MOOV_Support_hpp__ 1
+
+// =================================================================================================
+// ADOBE SYSTEMS INCORPORATED
+// Copyright 2009 Adobe Systems Incorporated
+// All Rights Reserved
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
+// of the Adobe license agreement accompanying it.
+// =================================================================================================
+
+#include "XMP_Environment.h" // ! This must be the first include.
+
+#include <vector>
+
+#include "XMP_Const.h"
+#include "XMPFiles_Impl.hpp"
+#include "EndianUtils.hpp"
+
+typedef vector<XMP_Uns8> RawDataBlock;
+
+#define moovBoxSizeLimit 100*1024*1024
+
+// =================================================================================================
+// MOOV_Manager
+// ============
+
+class MOOV_Manager {
+public:
+
+ // ---------------------------------------------------------------------------------------------
+ // Types and constants
+
+ enum { // Values for fileMode.
+ kFileIsNormalISO = 0, // A "normal" MPEG-4 file, no 'qt ' compatible brand.
+ kFileIsModernQT = 1, // Has an 'ftyp' box and 'qt ' compatible brand.
+ kFileIsTraditionalQT = 2 // Old QuickTime, no 'ftyp' box.
+ };
+
+ typedef const void * BoxRef; // Valid until a sibling or higher box is added or deleted.
+
+ struct BoxInfo {
+ XMP_Uns32 boxType; // In memory as native endian, compares work with ISOMedia::k_* constants.
+ XMP_Uns32 childCount; // ! A 'meta' box has both content (version/flags) and children!
+ XMP_Uns32 contentSize; // Does not include the size of nested boxes.
+ const XMP_Uns8 * content; // Null if contentSize is zero.
+ BoxInfo() : boxType(0), childCount(0), contentSize(0), content(0) {};
+ };
+
+ // ---------------------------------------------------------------------------------------------
+ // GetBox - Pick a box given a '/' separated list of box types. Picks the 1st of each type.
+ // GetNthChild - Pick the overall n-th child of the parent, zero based.
+ // GetTypeChild - Pick the first child of the given type.
+ // GetParsedOffset - Get the box's offset in the parsed tree, 0 if changed since parsing.
+ // GetHeaderSize - Get the box's header size in the parsed tree, 0 if changed since parsing.
+
+ BoxRef GetBox ( const char * boxPath, BoxInfo * info ) const;
+
+ BoxRef GetNthChild ( BoxRef parentRef, size_t childIndex, BoxInfo * info ) const;
+ BoxRef GetTypeChild ( BoxRef parentRef, XMP_Uns32 childType, BoxInfo * info ) const;
+
+ XMP_Uns32 GetParsedOffset ( BoxRef ref ) const;
+ XMP_Uns32 GetHeaderSize ( BoxRef ref ) const;
+
+ // ---------------------------------------------------------------------------------------------
+ // NoteChange - Note overall change, value was directly replaced.
+ // SetBox(ref) - Replace the content with a copy of the given data.
+ // SetBox(path) - Like above, but creating path to the box if necessary.
+ // AddChildBox - Add a child of the given type, using a copy of the given data (may be null)
+
+ void NoteChange();
+
+ void SetBox ( BoxRef theBox, const void* dataPtr, XMP_Uns32 size );
+ void SetBox ( const char * boxPath, const void* dataPtr, XMP_Uns32 size );
+
+ BoxRef AddChildBox ( BoxRef parentRef, XMP_Uns32 childType, const void * dataPtr, XMP_Uns32 size );
+
+ // ---------------------------------------------------------------------------------------------
+ // DeleteNthChild - Delete the overall n-th child, return true if there was one.
+ // DeleteTypeChild - Delete the first child of the given type, return true if there was one.
+
+ bool DeleteNthChild ( BoxRef parentRef, size_t childIndex );
+ bool DeleteTypeChild ( BoxRef parentRef, XMP_Uns32 childType );
+
+ // ---------------------------------------------------------------------------------------------
+
+ bool IsChanged() const { return this->moovNode.changed; };
+
+ // ---------------------------------------------------------------------------------------------
+ // The client is expected to fill in fullSubtree before calling ParseMemoryTree, and directly
+ // use fullSubtree after calling UpdateMemoryTree.
+ //
+ // IMPORTANT: We only support cases where the 'moov' subtree is significantly less than 4 GB, in
+ // particular with a threshold of probably 100 MB. This has 2 big impacts: we can safely use
+ // 32-bit offsets and sizes, and comfortably assume everything will fit in available heap space.
+
+ RawDataBlock fullSubtree; // The entire 'moov' box, straight from the file or from UpdateMemoryTree.
+
+ void ParseMemoryTree ( XMP_Uns8 fileMode );
+ void UpdateMemoryTree();
+
+ // ---------------------------------------------------------------------------------------------
+
+ #pragma pack (1) // ! These must match the file layout!
+
+ struct Content_mvhd_0 {
+ XMP_Uns32 vFlags; // 0
+ XMP_Uns32 creationTime; // 4
+ XMP_Uns32 modificationTime; // 8
+ XMP_Uns32 timescale; // 12
+ XMP_Uns32 duration; // 16
+ XMP_Int32 rate; // 20
+ XMP_Int16 volume; // 24
+ XMP_Uns16 pad_1; // 26
+ XMP_Uns32 pad_2, pad_3; // 28
+ XMP_Int32 matrix [9]; // 36
+ XMP_Uns32 preDef [6]; // 72
+ XMP_Uns32 nextTrackID; // 96
+ }; // 100
+
+ struct Content_mvhd_1 {
+ XMP_Uns32 vFlags; // 0
+ XMP_Uns64 creationTime; // 4
+ XMP_Uns64 modificationTime; // 12
+ XMP_Uns32 timescale; // 20
+ XMP_Uns64 duration; // 24
+ XMP_Int32 rate; // 32
+ XMP_Int16 volume; // 36
+ XMP_Uns16 pad_1; // 38
+ XMP_Uns32 pad_2, pad_3; // 40
+ XMP_Int32 matrix [9]; // 48
+ XMP_Uns32 preDef [6]; // 84
+ XMP_Uns32 nextTrackID; // 108
+ }; // 112
+
+ struct Content_hdlr { // An 'hdlr' box as defined by ISO 14496-12. Maps OK to the QuickTime box.
+ XMP_Uns32 versionFlags; // 0
+ XMP_Uns32 preDef; // 4
+ XMP_Uns32 handlerType; // 8
+ XMP_Uns32 reserved [3]; // 12
+ // Plus optional component name string, null terminated UTF-8.
+ }; // 24
+
+ struct Content_stsd_entry {
+ XMP_Uns32 entrySize; // 0
+ XMP_Uns32 format; // 4
+ XMP_Uns8 reserved_1 [6]; // 8
+ XMP_Uns16 dataRefIndex; // 14
+ XMP_Uns32 reserved_2; // 16
+ XMP_Uns32 flags; // 20
+ XMP_Uns32 timeScale; // 24
+ XMP_Uns32 frameDuration; // 28
+ XMP_Uns8 frameCount; // 32
+ XMP_Uns8 reserved_3; // 33
+ // Plus optional trailing ISO boxes.
+ }; // 34
+
+ struct Content_stsc_entry {
+ XMP_Uns32 firstChunkNumber; // 0
+ XMP_Uns32 samplesPerChunk; // 4
+ XMP_Uns32 sampleDescrID; // 8
+ }; // 12
+
+ // ---------------------------------------------------------------------------------------------
+
+ MOOV_Manager() : fileMode(0)
+ {
+ XMP_Assert ( sizeof ( Content_mvhd_0 ) == 100 ); // Make sure the structs really are packed.
+ XMP_Assert ( sizeof ( Content_mvhd_1 ) == 112 );
+ XMP_Assert ( sizeof ( Content_hdlr ) == 24 );
+ XMP_Assert ( sizeof ( Content_stsd_entry ) == 34 );
+ XMP_Assert ( sizeof ( Content_stsc_entry ) == 12 );
+ };
+
+ virtual ~MOOV_Manager() {};
+
+private:
+
+ struct BoxNode;
+ typedef std::vector<BoxNode> BoxList;
+ typedef BoxList::iterator BoxListPos;
+
+ struct BoxNode {
+ // ! Don't have a parent link, it will get destroyed by vector growth!
+
+ XMP_Uns32 offset; // The offset in the fullSubtree, 0 if not in the parse.
+ XMP_Uns32 boxType;
+ XMP_Uns32 headerSize; // The actual header size in the fullSubtree, 0 if not in the parse.
+ XMP_Uns32 contentSize; // The current content size, does not include nested boxes.
+ BoxList children;
+ RawDataBlock changedContent; // Might be empty even if changed is true.
+ bool changed; // If true, the content is in changedContent, else in fullSubtree.
+
+ BoxNode() : offset(0), boxType(0), headerSize(0), contentSize(0), changed(false) {};
+ BoxNode ( XMP_Uns32 _offset, XMP_Uns32 _boxType, XMP_Uns32 _headerSize, XMP_Uns32 _contentSize )
+ : offset(_offset), boxType(_boxType), headerSize(_headerSize), contentSize(_contentSize), changed(false) {};
+
+ };
+
+ XMP_Uns8 fileMode;
+ BoxNode moovNode;
+
+ void ParseNestedBoxes ( BoxNode * parentNode, const std::string & parentPath, bool ignoreMetaBoxes );
+
+ XMP_Uns8 * PickContentPtr ( const BoxNode & node ) const;
+ void FillBoxInfo ( const BoxNode & node, BoxInfo * info ) const;
+
+ XMP_Uns32 NewSubtreeSize ( const BoxNode & node, const std::string & parentPath );
+ XMP_Uns8 * AppendNewSubtree ( const BoxNode & node, const std::string & parentPath,
+ XMP_Uns8 * newPtr, XMP_Uns8 * newEnd );
+
+}; // MOOV_Manager
+
+#endif // __MOOV_Support_hpp__