eliminated spurious estra leading '/'
[asdcplib.git] / src / MXF.h
index fc0d9962430efc517a9454be2252e7fee33efc5d..3ae2c856e27c698e21324327822ad4b87df70eb4 100755 (executable)
--- a/src/MXF.h
+++ b/src/MXF.h
@@ -1,6 +1,33 @@
-//
-//
-//
+/*
+Copyright (c) 2005-2009, John Hurst
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*! \file    MXF.h
+    \version $Id$
+    \brief   MXF objects
+*/
 
 #ifndef _MXF_H_
 #define _MXF_H_
@@ -11,64 +38,88 @@ namespace ASDCP
 {
   namespace MXF
     {
+      class InterchangeObject;
+
+      //
+      typedef ASDCP::MXF::InterchangeObject* (*MXFObjectFactory_t)(const Dictionary*&);
+
+      //
+      void SetObjectFactory(UL label, MXFObjectFactory_t factory);
+
+      //
+      InterchangeObject* CreateObject(const Dictionary*& Dict, const UL& label);
+
+
       // seek an open file handle to the start of the RIP KLV packet
-      Result_t SeekToRIP(const FileReader&);
+      Result_t SeekToRIP(const Kumu::FileReader&);
       
       //
       class RIP : public ASDCP::KLVFilePacket
        {
          ASDCP_NO_COPY_CONSTRUCT(RIP);
+         RIP();
 
        public:
          //
-         class Pair {
-         public:
-           ui32_t BodySID;
-           ui64_t ByteOffset;
-
-           ui32_t Size() { return sizeof(ui32_t) + sizeof(ui64_t); }
-
-           inline const char* ToString(char* str_buf) const {
-             char intbuf[IntBufferLen];
-             sprintf(str_buf, "%-6lu: %s", BodySID, ui64sz(ByteOffset, intbuf));
-             return str_buf;
-           }
-
-           inline Result_t ReadFrom(ASDCP::MemIOReader& Reader) {
-             Result_t result = Reader.ReadUi32BE(&BodySID);
+         class Pair : public Kumu::IArchive
+           {
+           public:
+             ui32_t BodySID;
+             ui64_t ByteOffset;
 
-             if ( ASDCP_SUCCESS(result) )
-               result = Reader.ReadUi64BE(&ByteOffset);
+             Pair() : BodySID(0), ByteOffset(0) {}
+             Pair(ui32_t sid, ui64_t offset) : BodySID(sid), ByteOffset(offset) {}
+             virtual ~Pair() {}
 
-             return result;
-           }
+             ui32_t Size() { return sizeof(ui32_t) + sizeof(ui64_t); }
 
-           inline Result_t WriteTo(ASDCP::MemIOWriter& Writer) {
-             Result_t result = Writer.WriteUi32BE(BodySID);
+             inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+               Kumu::ui64Printer offset_str(ByteOffset);
+               snprintf(str_buf, buf_len, "%-6u: %s", BodySID, offset_str.c_str());
+               return str_buf;
+             }
 
-             if ( ASDCP_SUCCESS(result) )
-               result = Writer.WriteUi64BE(ByteOffset);
+             inline bool HasValue() const { return true; }
+             inline ui32_t ArchiveLength() const { return sizeof(ui32_t) + sizeof(ui64_t); }
 
-             return result;
-           }
-         };
+             inline bool Unarchive(Kumu::MemIOReader* Reader) {
+               if ( ! Reader->ReadUi32BE(&BodySID) ) return false;
+               if ( ! Reader->ReadUi64BE(&ByteOffset) ) return false;
+               return true;
+             }
+             
+             inline bool Archive(Kumu::MemIOWriter* Writer) const {
+               if ( ! Writer->WriteUi32BE(BodySID) ) return false;
+               if ( ! Writer->WriteUi64BE(ByteOffset) ) return false;
+               return true;
+             }
+           };
 
+         const Dictionary*& m_Dict;
          Array<Pair> PairArray;
 
-         RIP() {}
+       RIP(const Dictionary*& d) : m_Dict(d) {}
          virtual ~RIP() {}
-         virtual Result_t InitFromFile(const ASDCP::FileReader& Reader);
-         virtual Result_t WriteToFile(ASDCP::FileWriter& Writer);
+         virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
+         virtual Result_t WriteToFile(Kumu::FileWriter& Writer);
+         virtual Result_t GetPairBySID(ui32_t, Pair&) const;
          virtual void     Dump(FILE* = 0);
        };
 
 
       //
       class Partition : public ASDCP::KLVFilePacket
-       {       
+       {
          ASDCP_NO_COPY_CONSTRUCT(Partition);
+         Partition();
+
+       protected:
+         class h__PacketList;
+         mem_ptr<h__PacketList> m_PacketList;
 
        public:
+         const Dictionary*& m_Dict;
+
          ui16_t    MajorVersion;
          ui16_t    MinorVersion;
          ui32_t    KAGSize;
@@ -83,71 +134,69 @@ namespace ASDCP
          UL        OperationalPattern;
          Batch<UL> EssenceContainers;
 
-         Partition() {}
-         virtual ~Partition() {}
-         virtual Result_t InitFromFile(const ASDCP::FileReader& Reader);
-         virtual Result_t WriteToFile(ASDCP::FileWriter& Writer);
+         Partition(const Dictionary*&);
+         virtual ~Partition();
+         virtual void     AddChildObject(InterchangeObject*);
+         virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
+         virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
+         virtual Result_t WriteToFile(Kumu::FileWriter& Writer, UL& PartitionLabel);
+         virtual ui32_t   ArchiveSize(); // returns the size of the archived structure
          virtual void     Dump(FILE* = 0);
        };
 
 
       //
-      class Primer : public ASDCP::KLVPacket, public ASDCP::IPrimerLookup
+      class Primer : public ASDCP::KLVFilePacket, public ASDCP::IPrimerLookup
        {
          class h__PrimerLookup;
          mem_ptr<h__PrimerLookup> m_Lookup;
+         ui8_t   m_LocalTag;
          ASDCP_NO_COPY_CONSTRUCT(Primer);
+         Primer();
 
        public:
          //
-         class LocalTagEntry
+       class LocalTagEntry : Kumu::IArchive
            {
            public:
              TagValue    Tag;
              ASDCP::UL   UL;
 
-             inline const char* ToString(char* str_buf) const {
-               sprintf(str_buf, "%02x %02x: ", Tag.a, Tag.b);
-               UL.ToString(str_buf + strlen(str_buf));
+             inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+               snprintf(str_buf, buf_len, "%02x %02x: ", Tag.a, Tag.b);
+               UL.EncodeString(str_buf + strlen(str_buf), buf_len - strlen(str_buf));
                return str_buf;
              }
 
-             inline Result_t ReadFrom(ASDCP::MemIOReader& Reader) {
-               Result_t result = Reader.ReadUi8(&Tag.a);
-               
-               if ( ASDCP_SUCCESS(result) )
-                 result = Reader.ReadUi8(&Tag.b);
-
-               if ( ASDCP_SUCCESS(result) )
-                 result = UL.ReadFrom(Reader);
+             inline bool HasValue() const { return UL.HasValue(); }
+             inline ui32_t ArchiveLength() const { return 2 + UL.ArchiveLength(); }
 
-               return result;
+             inline bool Unarchive(Kumu::MemIOReader* Reader) {
+               if ( ! Reader->ReadUi8(&Tag.a) ) return false;
+               if ( ! Reader->ReadUi8(&Tag.b) ) return false;
+               return UL.Unarchive(Reader);
              }
 
-             inline Result_t WriteTo(ASDCP::MemIOWriter& Writer) {
-               Result_t result = Writer.WriteUi8(Tag.a);
-               
-               if ( ASDCP_SUCCESS(result) )
-                 result = Writer.WriteUi8(Tag.b);
-
-               if ( ASDCP_SUCCESS(result) )
-                 result = UL.WriteTo(Writer);
-
-               return result;
+             inline bool Archive(Kumu::MemIOWriter* Writer) const {
+               if ( ! Writer->WriteUi8(Tag.a) ) return false;
+               if ( ! Writer->WriteUi8(Tag.b) ) return false;
+               return UL.Archive(Writer);
              }
            };
 
          Batch<LocalTagEntry> LocalTagEntryBatch;
+         const Dictionary*& m_Dict;
 
-         Primer();
+         Primer(const Dictionary*&);
          virtual ~Primer();
 
          virtual void     ClearTagList();
-         virtual Result_t InsertTag(const ASDCP::UL& Key, ASDCP::TagValue& Tag);
+         virtual Result_t InsertTag(const MDDEntry& Entry, ASDCP::TagValue& Tag);
          virtual Result_t TagForKey(const ASDCP::UL& Key, ASDCP::TagValue& Tag);
 
           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
           virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
+         virtual Result_t WriteToFile(Kumu::FileWriter& Writer);
          virtual void     Dump(FILE* = 0);
        };
 
@@ -155,48 +204,58 @@ namespace ASDCP
       //
       class InterchangeObject : public ASDCP::KLVPacket
        {
+         InterchangeObject();
+
+       protected:
+         const MDDEntry* m_Typeinfo;
+
        public:
+         const Dictionary*& m_Dict;
          IPrimerLookup* m_Lookup;
-         UID            InstanceUID;
+         UUID           InstanceUID;
+         UUID           GenerationUID;
 
-         InterchangeObject() : m_Lookup(0) {}
+       InterchangeObject(const Dictionary*& d) : m_Typeinfo(0), m_Dict(d), m_Lookup(0) {}
          virtual ~InterchangeObject() {}
+          virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
+         virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
+         virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
          virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
          virtual bool     IsA(const byte_t* label);
-
-         virtual void Dump(FILE* stream = 0) {
-           KLVPacket::Dump(stream, true);
-         }
+         virtual const char* ObjectName() { return "InterchangeObject"; }
+         virtual void     Dump(FILE* stream = 0);
        };
 
-      //
-      InterchangeObject* CreateObject(const byte_t* label);
-
-
       //
       class Preface : public InterchangeObject
        {
          ASDCP_NO_COPY_CONSTRUCT(Preface);
+         Preface();
 
        public:
+         const Dictionary*& m_Dict;
          UUID         GenerationUID;
          Timestamp    LastModifiedDate;
          ui16_t       Version;
          ui32_t       ObjectModelVersion;
-         UID          PrimaryPackage;
-         Batch<UID>   Identifications;
-         UID          ContentStorage;
+         UUID         PrimaryPackage;
+         Batch<UUID>  Identifications;
+         UUID         ContentStorage;
          UL           OperationalPattern;
          Batch<UL>    EssenceContainers;
          Batch<UL>    DMSchemes;
 
-         Preface() {}
+       Preface(const Dictionary*& d) : InterchangeObject(d), m_Dict(d), Version(258), ObjectModelVersion(0) {}
          virtual ~Preface() {}
-          virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
-         virtual Result_t WriteToBuffer(ASDCP::FrameBuffer& Buffer);
+          virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
+         virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
+         virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
+         virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
          virtual void     Dump(FILE* = 0);
        };
 
+      const ui32_t MaxIndexSegmentSize = 65536;
+
       //
       class IndexTableSegment : public InterchangeObject
        {
@@ -204,34 +263,45 @@ namespace ASDCP
 
        public:
          //
-         class DeltaEntry
+       class DeltaEntry : public Kumu::IArchive
            {
            public:
              i8_t    PosTableIndex;
              ui8_t   Slice;
              ui32_t  ElementData;
 
-             Result_t ReadFrom(ASDCP::MemIOReader& Reader);
-             Result_t WriteTo(ASDCP::MemIOWriter& Writer);
-             inline const char* ToString(char* str_buf) const;
+             DeltaEntry() : PosTableIndex(-1), Slice(0), ElementData(0) {}
+             inline bool HasValue() const { return true; }
+             ui32_t      ArchiveLength() const { return sizeof(ui32_t) + 2; }
+             bool        Unarchive(Kumu::MemIOReader* Reader);
+             bool        Archive(Kumu::MemIOWriter* Writer) const;
+             const char* EncodeString(char* str_buf, ui32_t buf_len) const;
            };
 
          //
-         class IndexEntry
+         class IndexEntry : public Kumu::IArchive
            {
            public:
              i8_t               TemporalOffset;
              i8_t               KeyFrameOffset;
              ui8_t              Flags;
              ui64_t             StreamOffset;
-             std::list<ui32_t>  SliceOffset;
-             Array<Rational>    PosTable;
 
-             Result_t ReadFrom(ASDCP::MemIOReader& Reader);
-             Result_t WriteTo(ASDCP::MemIOWriter& Writer);
-             inline const char* ToString(char* str_buf) const;
+             // if you use these, you will need to change CBRIndexEntriesPerSegment in MXF.cpp
+             // to a more suitable value
+             //              std::list<ui32_t>  SliceOffset;
+             //              Array<Rational>    PosTable;
+
+             IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0), StreamOffset() {}
+             inline bool HasValue() const { return true; }
+             ui32_t      ArchiveLength() const { return sizeof(ui64_t) + 3; };
+             bool        Unarchive(Kumu::MemIOReader* Reader);
+             bool        Archive(Kumu::MemIOWriter* Writer) const;
+             const char* EncodeString(char* str_buf, ui32_t buf_len) const;
            };
 
+         const Dictionary*& m_Dict;
+
          Rational    IndexEditRate;
          ui64_t      IndexStartPosition;
          ui64_t      IndexDuration;
@@ -243,57 +313,75 @@ namespace ASDCP
          Batch<DeltaEntry> DeltaEntryArray;
          Batch<IndexEntry> IndexEntryArray;
 
-         IndexTableSegment();
+         IndexTableSegment(const Dictionary*&);
          virtual ~IndexTableSegment();
+         virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
          virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
-         virtual Result_t WriteToBuffer(ASDCP::FrameBuffer& Buffer);
+         virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
+         virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
          virtual void     Dump(FILE* = 0);
        };
 
       //---------------------------------------------------------------------------------
       //
-      class h__PacketList; // See MXF.cpp
       class Identification;
+      class SourcePackage;
 
       //
       class OPAtomHeader : public Partition
        {
-         mem_ptr<h__PacketList>   m_PacketList;
          ASDCP_NO_COPY_CONSTRUCT(OPAtomHeader);
+         OPAtomHeader();
 
        public:
-         ASDCP::MXF::RIP          m_RIP;
-         ASDCP::MXF::Primer       m_Primer;
-         InterchangeObject*       m_Preface;
-         ASDCP::FrameBuffer       m_Buffer;
-         bool                     m_HasRIP;
-
-         OPAtomHeader();
+         const Dictionary*&   m_Dict;
+         ASDCP::MXF::RIP     m_RIP;
+         ASDCP::MXF::Primer  m_Primer;
+         Preface*            m_Preface;
+         ASDCP::FrameBuffer  m_Buffer;
+         bool                m_HasRIP;
+
+         OPAtomHeader(const Dictionary*&);
          virtual ~OPAtomHeader();
-         virtual Result_t InitFromFile(const ASDCP::FileReader& Reader);
-         virtual Result_t WriteToFile(ASDCP::FileWriter& Writer, ui32_t HeaderLength = 16384);
+         virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
+         virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
+         virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
+         virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui32_t HeaderLength = 16384);
          virtual void     Dump(FILE* = 0);
+         virtual Result_t GetMDObjectByID(const UUID&, InterchangeObject** = 0);
          virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0);
-         Identification* GetIdentification();
+         virtual Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList);
+         Identification*  GetIdentification();
+         SourcePackage*   GetSourcePackage();
        };
 
       //
       class OPAtomIndexFooter : public Partition
        {
-         mem_ptr<h__PacketList>   m_PacketList;
-         ASDCP::FrameBuffer       m_Buffer;
+         IndexTableSegment*  m_CurrentSegment;
+         ASDCP::FrameBuffer  m_Buffer;
+         ui32_t              m_BytesPerEditUnit;
+         Rational            m_EditRate;
+         ui32_t              m_BodySID;
          ASDCP_NO_COPY_CONSTRUCT(OPAtomIndexFooter);
 
        public:
-         IPrimerLookup* m_Lookup;
+         const Dictionary*&   m_Dict;
+         Kumu::fpos_t        m_ECOffset;
+         IPrimerLookup*      m_Lookup;
         
-         OPAtomIndexFooter();
+         OPAtomIndexFooter(const Dictionary*&);
          virtual ~OPAtomIndexFooter();
-         virtual Result_t InitFromFile(const ASDCP::FileReader& Reader);
-         virtual Result_t WriteToFile(ASDCP::FileWriter& Writer);
+         virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
+         virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
+         virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
+         virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui64_t duration);
          virtual void     Dump(FILE* = 0);
 
-         virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&);
+         virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&) const;
+         virtual void     PushIndexEntry(const IndexTableSegment::IndexEntry&);
+         virtual void     SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate);
+         virtual void     SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset);
        };
 
     } // namespace MXF