X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2FMXF.h;h=b8d11939a4e0674a03b70474fa61b35f3801efed;hb=dd3acfff947ca52e1a3260243cb38f7035626282;hp=3ae2c856e27c698e21324327822ad4b87df70eb4;hpb=fd73a272189d3d121989b8437b7fbe5402160aaa;p=asdcplib.git diff --git a/src/MXF.h b/src/MXF.h index 3ae2c85..b8d1193 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,11 +41,13 @@ namespace ASDCP { class InterchangeObject; + const ui32_t kl_length = ASDCP::SMPTE_UL_LENGTH + ASDCP::MXF_BER_LENGTH; + // 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 Dictionary*& Dict, const UL& label); @@ -61,15 +64,15 @@ namespace ASDCP 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); } @@ -96,13 +99,17 @@ namespace ASDCP }; const Dictionary*& m_Dict; - Array PairArray; + + typedef SimpleArray::iterator pair_iterator; + typedef SimpleArray::const_iterator const_pair_iterator; + + 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); }; @@ -114,8 +121,20 @@ namespace ASDCP 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; @@ -136,7 +155,7 @@ namespace ASDCP 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); @@ -162,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; } @@ -200,23 +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 { InterchangeObject(); - protected: - const MDDEntry* m_Typeinfo; - public: const Dictionary*& m_Dict; IPrimerLookup* m_Lookup; UUID InstanceUID; - UUID GenerationUID; + optional_property GenerationUID; - InterchangeObject(const Dictionary*& d) : m_Typeinfo(0), m_Dict(d), 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); @@ -226,6 +311,9 @@ namespace ASDCP virtual void Dump(FILE* stream = 0); }; + // + typedef std::list InterchangeObject_list_t; + // class Preface : public InterchangeObject { @@ -234,19 +322,22 @@ namespace ASDCP public: const Dictionary*& m_Dict; - UUID GenerationUID; - Timestamp LastModifiedDate; + 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(const Dictionary*& d) : InterchangeObject(d), m_Dict(d), 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); @@ -259,6 +350,7 @@ namespace ASDCP // class IndexTableSegment : public InterchangeObject { + IndexTableSegment(); ASDCP_NO_COPY_CONSTRUCT(IndexTableSegment); public: @@ -270,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); @@ -292,7 +385,9 @@ namespace ASDCP // std::list SliceOffset; // Array PosTable; - IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0), StreamOffset() {} + IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0), 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); @@ -301,6 +396,8 @@ namespace ASDCP }; 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; @@ -310,11 +407,13 @@ namespace ASDCP ui32_t BodySID; ui8_t SliceCount; ui8_t PosTableCount; - Batch DeltaEntryArray; - Batch IndexEntryArray; + Array DeltaEntryArray; + Array IndexEntryArray; 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); @@ -328,21 +427,19 @@ namespace ASDCP class SourcePackage; // - class OPAtomHeader : public Partition + class OP1aHeader : public Partition { - ASDCP_NO_COPY_CONSTRUCT(OPAtomHeader); - OPAtomHeader(); + Kumu::ByteString m_HeaderData; + ASDCP_NO_COPY_CONSTRUCT(OP1aHeader); + OP1aHeader(); public: - const Dictionary*& m_Dict; - 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(const Dictionary*&); - 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); @@ -355,15 +452,22 @@ 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; @@ -378,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