X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2FMXF.h;h=d6e201a420a76f4bd52e300022747bd0ded226be;hb=fbdfd30bb77d37b354b19cf6cf3be72eec3bf725;hp=06d06a0521756de7621d73cb35dcb2c101c15d05;hpb=a48b3a939a031ec369c58b054c126d7dec963a18;p=asdcplib.git diff --git a/src/MXF.h b/src/MXF.h index 06d06a0..d6e201a 100755 --- a/src/MXF.h +++ b/src/MXF.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2005-2009, John Hurst +Copyright (c) 2005-2018, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -33,6 +33,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define _MXF_H_ #include "MXFTypes.h" +#include namespace ASDCP { @@ -40,14 +41,16 @@ namespace ASDCP { class InterchangeObject; + const ui32_t kl_length = ASDCP::SMPTE_UL_LENGTH + ASDCP::MXF_BER_LENGTH; + // - typedef ASDCP::MXF::InterchangeObject* (*MXFObjectFactory_t)(); + typedef ASDCP::MXF::InterchangeObject* (*MXFObjectFactory_t)(const Dictionary*&); // - void SetObjectFactory(UL label, MXFObjectFactory_t factory); + void SetObjectFactory(const UL& label, MXFObjectFactory_t factory); // - InterchangeObject* CreateObject(const byte_t* label); + InterchangeObject* CreateObject(const Dictionary*& Dict, const UL& label); // seek an open file handle to the start of the RIP KLV packet @@ -57,18 +60,19 @@ namespace ASDCP class RIP : public ASDCP::KLVFilePacket { ASDCP_NO_COPY_CONSTRUCT(RIP); + RIP(); public: // - class Pair : public Kumu::IArchive + class PartitionPair : public Kumu::IArchive { public: ui32_t BodySID; ui64_t ByteOffset; - Pair() : BodySID(0), ByteOffset(0) {} - Pair(ui32_t sid, ui64_t offset) : BodySID(sid), ByteOffset(offset) {} - virtual ~Pair() {} + PartitionPair() : BodySID(0), ByteOffset(0) {} + PartitionPair(ui32_t sid, ui64_t offset) : BodySID(sid), ByteOffset(offset) {} + virtual ~PartitionPair() {} ui32_t Size() { return sizeof(ui32_t) + sizeof(ui64_t); } @@ -94,13 +98,18 @@ namespace ASDCP } }; - Array PairArray; + const Dictionary*& m_Dict; + + typedef SimpleArray::iterator pair_iterator; + typedef SimpleArray::const_iterator const_pair_iterator; - RIP() {} + SimpleArray PairArray; + + RIP(const Dictionary*& d) : m_Dict(d) {} virtual ~RIP() {} virtual Result_t InitFromFile(const Kumu::FileReader& Reader); virtual Result_t WriteToFile(Kumu::FileWriter& Writer); - virtual Result_t GetPairBySID(ui32_t, Pair&) const; + virtual bool GetPairBySID(ui32_t, PartitionPair&) const; virtual void Dump(FILE* = 0); }; @@ -109,12 +118,27 @@ namespace ASDCP class Partition : public ASDCP::KLVFilePacket { ASDCP_NO_COPY_CONSTRUCT(Partition); + Partition(); protected: - class h__PacketList; - mem_ptr m_PacketList; + class PacketList + { + public: + std::list m_List; + std::map m_Map; + + ~PacketList(); + void AddPacket(InterchangeObject* ThePacket); // takes ownership + Result_t GetMDObjectByID(const UUID& ObjectID, InterchangeObject** Object); + Result_t GetMDObjectByType(const byte_t* ObjectID, InterchangeObject** Object); + Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list& ObjectList); + }; + + mem_ptr m_PacketList; public: + const Dictionary*& m_Dict; + ui16_t MajorVersion; ui16_t MinorVersion; ui32_t KAGSize; @@ -129,9 +153,9 @@ namespace ASDCP UL OperationalPattern; Batch
    EssenceContainers; - Partition(); + Partition(const Dictionary*&); virtual ~Partition(); - virtual void AddChildObject(InterchangeObject*); + virtual void AddChildObject(InterchangeObject*); // takes ownership 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); @@ -147,6 +171,7 @@ namespace ASDCP mem_ptr m_Lookup; ui8_t m_LocalTag; ASDCP_NO_COPY_CONSTRUCT(Primer); + Primer(); public: // @@ -156,9 +181,26 @@ namespace ASDCP TagValue Tag; ASDCP::UL UL; + LocalTagEntry() { Tag.a = Tag.b = 0; } + LocalTagEntry(const TagValue& tag, ASDCP::UL& ul) : Tag(tag), UL(ul) {} + + bool operator<(const LocalTagEntry& rhs) const { + if ( Tag.a < rhs.Tag.a ) + { + return true; + } + + if ( Tag.a == rhs.Tag.a && Tag.b < rhs.Tag.b ) + { + return true; + } + + return false; + } + 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)); + UL.EncodeString(str_buf + strlen(str_buf), buf_len - (ui32_t)strlen(str_buf)); return str_buf; } @@ -179,8 +221,9 @@ namespace ASDCP }; Batch LocalTagEntryBatch; + const Dictionary*& m_Dict; - Primer(); + Primer(const Dictionary*&); virtual ~Primer(); virtual void ClearTagList(); @@ -193,20 +236,72 @@ namespace ASDCP virtual void Dump(FILE* = 0); }; + // wrapper object manages optional properties + template + class optional_property + { + PropertyType m_property; + bool m_has_value; + public: + optional_property() : m_has_value(false) {} + optional_property(const PropertyType& value) : m_property(value), m_has_value(true) {} + const optional_property& operator=(const PropertyType& rhs) { + this->m_property = rhs; + this->m_has_value = true; + return *this; + } + bool operator==(const PropertyType& rhs) const { return this->m_property == rhs; } + bool operator==(const optional_property& rhs) const { return this->m_property == rhs.m_property; } + operator PropertyType&() { return this->m_property; } + void set(const PropertyType& rhs) { this->m_property = rhs; this->m_has_value = true; } + void set_has_value(bool has_value = true) { this->m_has_value = has_value; } + void reset(const PropertyType& rhs) { this->m_has_value = false; } + bool empty() const { return ! m_has_value; } + PropertyType& get() { return m_property; } + const PropertyType& const_get() const { return m_property; } + }; + + // wrapper object manages optional properties + template + class optional_container_property + { + PropertyType m_property; + + public: + optional_container_property() {} + optional_container_property(const PropertyType& value) : m_property(value) {} + const optional_container_property& operator=(const PropertyType& rhs) { + this->Copy(rhs.m_property); + return *this; + } + + bool operator==(const PropertyType& rhs) const { return this->m_property == rhs; } + bool operator==(const optional_property& rhs) const { return this->m_property == rhs.m_property; } + operator PropertyType&() { return this->m_property; } + void set(const PropertyType& rhs) { this->m_property = rhs; } + void reset(const PropertyType& rhs) { this->clear(); } + bool empty() const { return ! this->m_property.HasValue(); } + PropertyType& get() { return m_property; } + const PropertyType& const_get() const { return m_property; } + }; + + // base class of all metadata objects // class InterchangeObject : public ASDCP::KLVPacket { - protected: - const MDDEntry* m_Typeinfo; + InterchangeObject(); public: + const Dictionary*& m_Dict; IPrimerLookup* m_Lookup; UUID InstanceUID; - UUID GenerationUID; + optional_property GenerationUID; - InterchangeObject() : m_Typeinfo(0), m_Lookup(0) {} + InterchangeObject(const Dictionary*& d) : m_Dict(d), m_Lookup(0) {} virtual ~InterchangeObject() {} + + virtual void Copy(const InterchangeObject& rhs); virtual Result_t InitFromTLVSet(TLVReader& TLVSet); virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l); virtual Result_t WriteToTLVSet(TLVWriter& TLVSet); @@ -216,25 +311,33 @@ namespace ASDCP virtual void Dump(FILE* stream = 0); }; + // + typedef std::list InterchangeObject_list_t; + // class Preface : public InterchangeObject { ASDCP_NO_COPY_CONSTRUCT(Preface); + Preface(); public: - UUID GenerationUID; - Timestamp LastModifiedDate; + const Dictionary*& m_Dict; + Kumu::Timestamp LastModifiedDate; ui16_t Version; - ui32_t ObjectModelVersion; - UUID PrimaryPackage; - Batch Identifications; + optional_property ObjectModelVersion; + optional_property PrimaryPackage; + Array Identifications; UUID ContentStorage; UL OperationalPattern; Batch
      EssenceContainers; Batch
        DMSchemes; + optional_property > ApplicationSchemes; + optional_property > ConformsToSpecifications; - Preface() : Version(258), ObjectModelVersion(0) {} + Preface(const Dictionary*& d); virtual ~Preface() {} + + virtual void Copy(const Preface& rhs); virtual Result_t InitFromTLVSet(TLVReader& TLVSet); virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l); virtual Result_t WriteToTLVSet(TLVWriter& TLVSet); @@ -247,6 +350,7 @@ namespace ASDCP // class IndexTableSegment : public InterchangeObject { + IndexTableSegment(); ASDCP_NO_COPY_CONSTRUCT(IndexTableSegment); public: @@ -258,7 +362,8 @@ namespace ASDCP ui8_t Slice; ui32_t ElementData; - DeltaEntry() : PosTableIndex(-1), Slice(0), ElementData(0) {} + DeltaEntry() : PosTableIndex(0), Slice(0), ElementData(0) {} + DeltaEntry(i8_t pos, ui8_t slice, ui32_t data) : PosTableIndex(pos), Slice(slice), ElementData(data) {} inline bool HasValue() const { return true; } ui32_t ArchiveLength() const { return sizeof(ui32_t) + 2; } bool Unarchive(Kumu::MemIOReader* Reader); @@ -280,7 +385,9 @@ namespace ASDCP // std::list SliceOffset; // Array PosTable; - IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0), StreamOffset() {} + IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0x80), StreamOffset(0) {} + IndexEntry(i8_t t_ofst, i8_t k_ofst, ui8_t flags, ui64_t s_ofst) : + TemporalOffset(t_ofst), KeyFrameOffset(k_ofst), Flags(flags), StreamOffset(s_ofst) {} inline bool HasValue() const { return true; } ui32_t ArchiveLength() const { return sizeof(ui64_t) + 3; }; bool Unarchive(Kumu::MemIOReader* Reader); @@ -288,6 +395,10 @@ namespace ASDCP const char* EncodeString(char* str_buf, ui32_t buf_len) const; }; + const Dictionary*& m_Dict; + ui64_t RtFileOffset; // not part of the MXF structure: used to manage runtime index access + ui64_t RtEntryOffset; + Rational IndexEditRate; ui64_t IndexStartPosition; ui64_t IndexDuration; @@ -296,11 +407,13 @@ namespace ASDCP ui32_t BodySID; ui8_t SliceCount; ui8_t PosTableCount; - Batch DeltaEntryArray; - Batch IndexEntryArray; + Array DeltaEntryArray; + Array IndexEntryArray; - IndexTableSegment(); + IndexTableSegment(const Dictionary*&); virtual ~IndexTableSegment(); + + virtual void Copy(const IndexTableSegment& rhs); virtual Result_t InitFromTLVSet(TLVReader& TLVSet); virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l); virtual Result_t WriteToTLVSet(TLVWriter& TLVSet); @@ -314,19 +427,19 @@ namespace ASDCP class SourcePackage; // - class OPAtomHeader : public Partition + class OP1aHeader : public Partition { - ASDCP_NO_COPY_CONSTRUCT(OPAtomHeader); + Kumu::ByteString m_HeaderData; + ASDCP_NO_COPY_CONSTRUCT(OP1aHeader); + OP1aHeader(); public: - ASDCP::MXF::RIP m_RIP; + const Dictionary*& m_Dict; ASDCP::MXF::Primer m_Primer; Preface* m_Preface; - ASDCP::FrameBuffer m_Buffer; - bool m_HasRIP; - OPAtomHeader(); - virtual ~OPAtomHeader(); + OP1aHeader(const Dictionary*&); + virtual ~OP1aHeader(); 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); @@ -339,21 +452,29 @@ namespace ASDCP SourcePackage* GetSourcePackage(); }; + // Searches the header object and returns the edit rate based on the contents of the + // File Package items. Logs an error message and returns false if anthing goes wrong. + bool GetEditRateFromFP(ASDCP::MXF::OP1aHeader& header, ASDCP::Rational& edit_rate); + // class OPAtomIndexFooter : public Partition { + Kumu::ByteString m_FooterData; IndexTableSegment* m_CurrentSegment; - ASDCP::FrameBuffer m_Buffer; ui32_t m_BytesPerEditUnit; Rational m_EditRate; ui32_t m_BodySID; + IndexTableSegment::DeltaEntry m_DefaultDeltaEntry; + ASDCP_NO_COPY_CONSTRUCT(OPAtomIndexFooter); + OPAtomIndexFooter(); public: + const Dictionary*& m_Dict; Kumu::fpos_t m_ECOffset; IPrimerLookup* m_Lookup; - OPAtomIndexFooter(); + OPAtomIndexFooter(const Dictionary*&); virtual ~OPAtomIndexFooter(); virtual Result_t InitFromFile(const Kumu::FileReader& Reader); virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l); @@ -361,12 +482,79 @@ namespace ASDCP virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui64_t duration); virtual void Dump(FILE* = 0); + virtual Result_t GetMDObjectByID(const UUID&, InterchangeObject** = 0); + virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0); + virtual Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list& ObjectList); + virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&) const; virtual void PushIndexEntry(const IndexTableSegment::IndexEntry&); + virtual void SetDeltaParams(const IndexTableSegment::DeltaEntry&); virtual void SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate); virtual void SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset); }; + //--------------------------------------------------------------------------------- + // + + // + inline std::string to_lower(std::string str) { + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + return str; + } + + // ignore case when searching for audio labels + struct ci_comp + { + inline bool operator()(const std::string& a, const std::string& b) const { + return to_lower(a) < to_lower(b); + } + }; + + struct label_traits + { + const std::string tag_name; + const bool requires_prefix; + const UL ul; + + label_traits(const std::string& tag_name, const bool requires_prefix, const UL ul) : + tag_name(tag_name), requires_prefix(requires_prefix), ul(ul) { } + }; + + typedef std::map mca_label_map_t; + + bool decode_mca_string(const std::string& s, const mca_label_map_t& labels, + const Dictionary*& dict, const std::string& language, InterchangeObject_list_t&, ui32_t&); + + // + class ASDCP_MCAConfigParser : public InterchangeObject_list_t + { + KM_NO_COPY_CONSTRUCT(ASDCP_MCAConfigParser); + ASDCP_MCAConfigParser(); + + protected: + mca_label_map_t m_LabelMap; + ui32_t m_ChannelCount; + const Dictionary*& m_Dict; + + + public: + ASDCP_MCAConfigParser(const Dictionary*&); + bool DecodeString(const std::string& s, const std::string& language = "en-US"); + + // Valid only after a successful call to DecodeString + ui32_t ChannelCount() const; + }; + + // + class AS02_MCAConfigParser : public ASDCP_MCAConfigParser + { + KM_NO_COPY_CONSTRUCT(AS02_MCAConfigParser); + AS02_MCAConfigParser(); + + public: + AS02_MCAConfigParser(const Dictionary*&); + }; + } // namespace MXF } // namespace ASDCP