X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2FMXF.cpp;h=bf99e3e522271ebc4bc9dd4538fcfe92a98fe586;hb=a26997a57c206312a334cc59d0d0347da2d1a580;hp=a04cfe24335498d5a3558a0b733979efbfb8a4d8;hpb=c6900386fb66832781456838804ed7e28c535d63;p=asdcplib.git diff --git a/src/MXF.cpp b/src/MXF.cpp index a04cfe2..bf99e3e 100755 --- a/src/MXF.cpp +++ b/src/MXF.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2005-2006, John Hurst +Copyright (c) 2005-2008, John Hurst All rights reserved. Redistribution and use in source and binary forms, with or without @@ -29,75 +29,30 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \brief MXF objects */ -#define ASDCP_DECLARE_MDD -#include "MDD.h" -#include "Mutex.h" #include "MXF.h" #include "Metadata.h" -#include +#include -//------------------------------------------------------------------------------------------ -// - -const ui32_t kl_length = ASDCP::SMPTE_UL_LENGTH + ASDCP::MXF_BER_LENGTH; - -const byte_t mdd_key[] = { 0x06, 0x0e, 0x2b, 0x34 }; - -// -const ASDCP::MDDEntry* -ASDCP::GetMDDEntry(const byte_t* ul_buf) -{ - ui32_t t_idx = 0; - ui32_t k_idx = 8; - - // must be a pointer to a SMPTE UL - if ( ul_buf == 0 || memcmp(mdd_key, ul_buf, 4) != 0 ) - return 0; - - // advance to first matching element - // TODO: optimize using binary search - while ( s_MDD_Table[t_idx].ul != 0 - && s_MDD_Table[t_idx].ul[k_idx] != ul_buf[k_idx] ) - t_idx++; - - if ( s_MDD_Table[t_idx].ul == 0 ) - return 0; +using Kumu::DefaultLogSink; +using Kumu::GenRandomValue; - // match successive elements - while ( s_MDD_Table[t_idx].ul != 0 - && k_idx < SMPTE_UL_LENGTH - 1 - && s_MDD_Table[t_idx].ul[k_idx] == ul_buf[k_idx] ) - { - if ( s_MDD_Table[t_idx].ul[k_idx+1] == ul_buf[k_idx+1] ) - { - k_idx++; - } - else - { - while ( s_MDD_Table[t_idx].ul != 0 - && s_MDD_Table[t_idx].ul[k_idx] == ul_buf[k_idx] - && s_MDD_Table[t_idx].ul[k_idx+1] != ul_buf[k_idx+1] ) - t_idx++; - - while ( s_MDD_Table[t_idx].ul[k_idx] != ul_buf[k_idx] ) - k_idx--; - } - } - - return (s_MDD_Table[t_idx].ul == 0 ? 0 : &s_MDD_Table[t_idx]); -} +// index segments must be < 64K +// NOTE: this value may too high if advanced index entry elements are used. +const ui32_t CBRIndexEntriesPerSegment = 5000; //------------------------------------------------------------------------------------------ // +const ui32_t kl_length = ASDCP::SMPTE_UL_LENGTH + ASDCP::MXF_BER_LENGTH; + // ASDCP::Result_t -ASDCP::MXF::SeekToRIP(const ASDCP::FileReader& Reader) +ASDCP::MXF::SeekToRIP(const Kumu::FileReader& Reader) { - ASDCP::fpos_t end_pos; + Kumu::fpos_t end_pos; // go to the end - 4 bytes - Result_t result = Reader.Seek(0, ASDCP::SP_END); + Result_t result = Reader.Seek(0, Kumu::SP_END); if ( ASDCP_SUCCESS(result) ) result = Reader.Tell(&end_pos); @@ -124,7 +79,7 @@ ASDCP::MXF::SeekToRIP(const ASDCP::FileReader& Reader) if ( ASDCP_SUCCESS(result) ) { - rip_size = ASDCP_i32_BE(cp2i(intbuf)); + rip_size = KM_i32_BE(Kumu::cp2i(intbuf)); if ( rip_size > end_pos ) // RIP can't be bigger than the file return RESULT_FAIL; @@ -139,14 +94,31 @@ ASDCP::MXF::SeekToRIP(const ASDCP::FileReader& Reader) // ASDCP::Result_t -ASDCP::MXF::RIP::InitFromFile(const ASDCP::FileReader& Reader) +ASDCP::MXF::RIP::GetPairBySID(ui32_t SID, Pair& outPair) const +{ + Array::const_iterator pi = PairArray.begin(); + for ( ; pi != PairArray.end(); pi++ ) + { + if ( (*pi).BodySID == SID ) + { + outPair = *pi; + return RESULT_OK; + } + } + + return RESULT_FAIL; +} + +// +ASDCP::Result_t +ASDCP::MXF::RIP::InitFromFile(const Kumu::FileReader& Reader) { - Result_t result = KLVFilePacket::InitFromFile(Reader, s_MDD_Table[MDDindex_RandomIndexMetadata].ul); + Result_t result = KLVFilePacket::InitFromFile(Reader, Dict::ul(MDD_RandomIndexMetadata)); if ( ASDCP_SUCCESS(result) ) { - MemIOReader MemRDR(m_ValueStart, m_ValueLength - 4); - result = PairArray.ReadFrom(MemRDR); + Kumu::MemIOReader MemRDR(m_ValueStart, m_ValueLength - 4); + result = PairArray.Unarchive(&MemRDR) ? RESULT_OK : RESULT_KLV_CODING; } if ( ASDCP_FAILURE(result) ) @@ -157,9 +129,31 @@ ASDCP::MXF::RIP::InitFromFile(const ASDCP::FileReader& Reader) // ASDCP::Result_t -ASDCP::MXF::RIP::WriteToFile(ASDCP::FileWriter& Writer) +ASDCP::MXF::RIP::WriteToFile(Kumu::FileWriter& Writer) { - Result_t result = WriteKLToFile(Writer, s_MDD_Table[MDDindex_RandomIndexMetadata].ul, 0); + ASDCP::FrameBuffer Buffer; + ui32_t RIPSize = ( PairArray.size() * (sizeof(ui32_t) + sizeof(ui64_t)) ) + 4; + Result_t result = Buffer.Capacity(RIPSize); + + if ( ASDCP_SUCCESS(result) ) + result = WriteKLToFile(Writer, Dict::ul(MDD_RandomIndexMetadata), RIPSize); + + if ( ASDCP_SUCCESS(result) ) + { + result = RESULT_KLV_CODING; + + Kumu::MemIOWriter MemWRT(Buffer.Data(), Buffer.Capacity()); + if ( PairArray.Archive(&MemWRT) ) + if ( MemWRT.WriteUi32BE(RIPSize + 20) ) + { + Buffer.Size(MemWRT.Length()); + result = RESULT_OK; + } + } + + if ( ASDCP_SUCCESS(result) ) + result = Writer.Write(Buffer.RoData(), Buffer.Size()); + return result; } @@ -172,16 +166,119 @@ ASDCP::MXF::RIP::Dump(FILE* stream) KLVFilePacket::Dump(stream, false); PairArray.Dump(stream, false); - - fputs("==========================================================================\n", stream); } //------------------------------------------------------------------------------------------ // +// +class ASDCP::MXF::Partition::h__PacketList +{ +public: + std::list m_List; + std::map m_Map; + + ~h__PacketList() { + while ( ! m_List.empty() ) + { + delete m_List.back(); + m_List.pop_back(); + } + } + + // + void AddPacket(InterchangeObject* ThePacket) + { + assert(ThePacket); + m_Map.insert(std::map::value_type(ThePacket->InstanceUID, ThePacket)); + m_List.push_back(ThePacket); + } + + // + Result_t GetMDObjectByID(const UUID& ObjectID, InterchangeObject** Object) + { + ASDCP_TEST_NULL(Object); + + std::map::iterator mi = m_Map.find(ObjectID); + + if ( mi == m_Map.end() ) + { + *Object = 0; + return RESULT_FAIL; + } + + *Object = (*mi).second; + return RESULT_OK; + } + + // + Result_t GetMDObjectByType(const byte_t* ObjectID, InterchangeObject** Object) + { + ASDCP_TEST_NULL(ObjectID); + ASDCP_TEST_NULL(Object); + std::list::iterator li; + *Object = 0; + + for ( li = m_List.begin(); li != m_List.end(); li++ ) + { + if ( (*li)->HasUL(ObjectID) ) + { + *Object = *li; + return RESULT_OK; + } + } + + return RESULT_FAIL; + } + + // + Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list& ObjectList) + { + ASDCP_TEST_NULL(ObjectID); + std::list::iterator li; + + for ( li = m_List.begin(); li != m_List.end(); li++ ) + { + if ( (*li)->HasUL(ObjectID) ) + ObjectList.push_back(*li); + } + + return ObjectList.empty() ? RESULT_FAIL : RESULT_OK; + } +}; + +//------------------------------------------------------------------------------------------ +// + + +ASDCP::MXF::Partition::Partition() : + MajorVersion(1), MinorVersion(2), + KAGSize(1), ThisPartition(0), PreviousPartition(0), + FooterPartition(0), HeaderByteCount(0), IndexByteCount(0), IndexSID(0), + BodyOffset(0), BodySID(0) +{ + m_PacketList = new h__PacketList; +} + +ASDCP::MXF::Partition::~Partition() +{ +} + +// +void +ASDCP::MXF::Partition::AddChildObject(InterchangeObject* Object) +{ + assert(Object); + + if ( ! Object->InstanceUID.HasValue() ) + GenRandomValue(Object->InstanceUID); + + m_PacketList->AddPacket(Object); +} + // ASDCP::Result_t -ASDCP::MXF::Partition::InitFromFile(const ASDCP::FileReader& Reader) +ASDCP::MXF::Partition::InitFromFile(const Kumu::FileReader& Reader) { Result_t result = KLVFilePacket::InitFromFile(Reader); // test the UL @@ -189,20 +286,23 @@ ASDCP::MXF::Partition::InitFromFile(const ASDCP::FileReader& Reader) if ( ASDCP_SUCCESS(result) ) { - MemIOReader MemRDR(m_ValueStart, m_ValueLength); - result = MemRDR.ReadUi16BE(&MajorVersion); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi16BE(&MinorVersion); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi32BE(&KAGSize); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&ThisPartition); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&PreviousPartition); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&FooterPartition); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&HeaderByteCount); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&IndexByteCount); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi32BE(&IndexSID); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&BodyOffset); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi32BE(&BodySID); - if ( ASDCP_SUCCESS(result) ) result = OperationalPattern.ReadFrom(MemRDR); - if ( ASDCP_SUCCESS(result) ) result = EssenceContainers.ReadFrom(MemRDR); + Kumu::MemIOReader MemRDR(m_ValueStart, m_ValueLength); + result = RESULT_KLV_CODING; + + if ( MemRDR.ReadUi16BE(&MajorVersion) ) + if ( MemRDR.ReadUi16BE(&MinorVersion) ) + if ( MemRDR.ReadUi32BE(&KAGSize) ) + if ( MemRDR.ReadUi64BE(&ThisPartition) ) + if ( MemRDR.ReadUi64BE(&PreviousPartition) ) + if ( MemRDR.ReadUi64BE(&FooterPartition) ) + if ( MemRDR.ReadUi64BE(&HeaderByteCount) ) + if ( MemRDR.ReadUi64BE(&IndexByteCount) ) + if ( MemRDR.ReadUi32BE(&IndexSID) ) + if ( MemRDR.ReadUi64BE(&BodyOffset) ) + if ( MemRDR.ReadUi32BE(&BodySID) ) + if ( OperationalPattern.Unarchive(&MemRDR) ) + if ( EssenceContainers.Unarchive(&MemRDR) ) + result = RESULT_OK; } if ( ASDCP_FAILURE(result) ) @@ -213,47 +313,66 @@ ASDCP::MXF::Partition::InitFromFile(const ASDCP::FileReader& Reader) // ASDCP::Result_t -ASDCP::MXF::Partition::WriteToFile(ASDCP::FileWriter& Writer) +ASDCP::MXF::Partition::WriteToFile(Kumu::FileWriter& Writer, UL& PartitionLabel) { - Result_t result = m_Buffer.Capacity(1024); + ASDCP::FrameBuffer Buffer; + Result_t result = Buffer.Capacity(1024); if ( ASDCP_SUCCESS(result) ) { - MemIOWriter MemWRT(m_Buffer.Data(), m_Buffer.Capacity()); - result = MemWRT.WriteUi16BE(MajorVersion); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi16BE(MinorVersion); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi32BE(KAGSize); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(ThisPartition); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(PreviousPartition); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(FooterPartition); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(HeaderByteCount); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(IndexByteCount); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi32BE(IndexSID); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(BodyOffset); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi32BE(BodySID); - if ( ASDCP_SUCCESS(result) ) result = OperationalPattern.WriteTo(MemWRT); - if ( ASDCP_SUCCESS(result) ) result = EssenceContainers.WriteTo(MemWRT); - if ( ASDCP_SUCCESS(result) ) m_Buffer.Size(MemWRT.Size()); + Kumu::MemIOWriter MemWRT(Buffer.Data(), Buffer.Capacity()); + result = RESULT_KLV_CODING; + if ( MemWRT.WriteUi16BE(MajorVersion) ) + if ( MemWRT.WriteUi16BE(MinorVersion) ) + if ( MemWRT.WriteUi32BE(KAGSize) ) + if ( MemWRT.WriteUi64BE(ThisPartition) ) + if ( MemWRT.WriteUi64BE(PreviousPartition) ) + if ( MemWRT.WriteUi64BE(FooterPartition) ) + if ( MemWRT.WriteUi64BE(HeaderByteCount) ) + if ( MemWRT.WriteUi64BE(IndexByteCount) ) + if ( MemWRT.WriteUi32BE(IndexSID) ) + if ( MemWRT.WriteUi64BE(BodyOffset) ) + if ( MemWRT.WriteUi32BE(BodySID) ) + if ( OperationalPattern.Archive(&MemWRT) ) + if ( EssenceContainers.Archive(&MemWRT) ) + { + Buffer.Size(MemWRT.Length()); + result = RESULT_OK; + } } if ( ASDCP_SUCCESS(result) ) { - ui32_t write_count; // this is subclassed, so the UL is only right some of the time - result = WriteKLToFile(Writer, s_MDD_Table[MDDindex_ClosedCompleteHeader].ul, m_Buffer.Size()); + ui32_t write_count; + result = WriteKLToFile(Writer, PartitionLabel.Value(), Buffer.Size()); if ( ASDCP_SUCCESS(result) ) - result = Writer.Write(m_Buffer.RoData(), m_Buffer.Size(), &write_count); + result = Writer.Write(Buffer.RoData(), Buffer.Size(), &write_count); } return result; } +// +ui32_t +ASDCP::MXF::Partition::ArchiveSize() +{ + return ( kl_length + + sizeof(ui16_t) + sizeof(ui16_t) + + sizeof(ui32_t) + + sizeof(ui64_t) + sizeof(ui64_t) + sizeof(ui64_t) + sizeof(ui64_t) + sizeof(ui64_t) + + sizeof(ui32_t) + + sizeof(ui64_t) + + sizeof(ui32_t) + + SMPTE_UL_LENGTH + + sizeof(ui32_t) + sizeof(ui32_t) + ( UUIDlen * EssenceContainers.size() ) ); +} + // void ASDCP::MXF::Partition::Dump(FILE* stream) { char identbuf[IdentBufferLen]; - char intbuf[IntBufferLen]; if ( stream == 0 ) stream = stderr; @@ -261,19 +380,17 @@ ASDCP::MXF::Partition::Dump(FILE* stream) KLVFilePacket::Dump(stream, false); fprintf(stream, " MajorVersion = %hu\n", MajorVersion); fprintf(stream, " MinorVersion = %hu\n", MinorVersion); - fprintf(stream, " KAGSize = %lu\n", KAGSize); - fprintf(stream, " ThisPartition = %s\n", ui64sz(ThisPartition, intbuf)); - fprintf(stream, " PreviousPartition = %s\n", ui64sz(PreviousPartition, intbuf)); - fprintf(stream, " FooterPartition = %s\n", ui64sz(FooterPartition, intbuf)); - fprintf(stream, " HeaderByteCount = %s\n", ui64sz(HeaderByteCount, intbuf)); - fprintf(stream, " IndexByteCount = %s\n", ui64sz(IndexByteCount, intbuf)); - fprintf(stream, " IndexSID = %lu\n", IndexSID); - fprintf(stream, " BodyOffset = %s\n", ui64sz(BodyOffset, intbuf)); - fprintf(stream, " BodySID = %lu\n", BodySID); - fprintf(stream, " OperationalPattern = %s\n", OperationalPattern.ToString(identbuf)); + fprintf(stream, " KAGSize = %u\n", KAGSize); + fprintf(stream, " ThisPartition = %s\n", ui64sz(ThisPartition, identbuf)); + fprintf(stream, " PreviousPartition = %s\n", ui64sz(PreviousPartition, identbuf)); + fprintf(stream, " FooterPartition = %s\n", ui64sz(FooterPartition, identbuf)); + fprintf(stream, " HeaderByteCount = %s\n", ui64sz(HeaderByteCount, identbuf)); + fprintf(stream, " IndexByteCount = %s\n", ui64sz(IndexByteCount, identbuf)); + fprintf(stream, " IndexSID = %u\n", IndexSID); + fprintf(stream, " BodyOffset = %s\n", ui64sz(BodyOffset, identbuf)); + fprintf(stream, " BodySID = %u\n", BodySID); + fprintf(stream, " OperationalPattern = %s\n", OperationalPattern.EncodeString(identbuf, IdentBufferLen)); fputs("Essence Containers:\n", stream); EssenceContainers.Dump(stream, false); - - fputs("==========================================================================\n", stream); } @@ -294,7 +411,7 @@ public: // -ASDCP::MXF::Primer::Primer() {} +ASDCP::MXF::Primer::Primer() : m_LocalTag(0xff) {} // ASDCP::MXF::Primer::~Primer() {} @@ -311,12 +428,12 @@ ASDCP::MXF::Primer::ClearTagList() ASDCP::Result_t ASDCP::MXF::Primer::InitFromBuffer(const byte_t* p, ui32_t l) { - Result_t result = KLVPacket::InitFromBuffer(p, l, s_MDD_Table[MDDindex_Primer].ul); + Result_t result = KLVPacket::InitFromBuffer(p, l, Dict::ul(MDD_Primer)); if ( ASDCP_SUCCESS(result) ) { - MemIOReader MemRDR(m_ValueStart, m_ValueLength); - result = LocalTagEntryBatch.ReadFrom(MemRDR); + Kumu::MemIOReader MemRDR(m_ValueStart, m_ValueLength); + result = LocalTagEntryBatch.Unarchive(&MemRDR) ? RESULT_OK : RESULT_KLV_CODING; } if ( ASDCP_SUCCESS(result) ) @@ -331,47 +448,74 @@ ASDCP::MXF::Primer::InitFromBuffer(const byte_t* p, ui32_t l) return result; } +// +ASDCP::Result_t +ASDCP::MXF::Primer::WriteToFile(Kumu::FileWriter& Writer) +{ + ASDCP::FrameBuffer Buffer; + Result_t result = Buffer.Capacity(128*1024); + + if ( ASDCP_SUCCESS(result) ) + result = WriteToBuffer(Buffer); + + if ( ASDCP_SUCCESS(result) ) + result = Writer.Write(Buffer.RoData(), Buffer.Size()); + + return result; +} + // ASDCP::Result_t ASDCP::MXF::Primer::WriteToBuffer(ASDCP::FrameBuffer& Buffer) { - MemIOWriter MemWRT(Buffer.Data(), Buffer.Capacity()); - Result_t result = LocalTagEntryBatch.WriteTo(MemWRT); - Buffer.Size(MemWRT.Size()); -#if 0 + ASDCP::FrameBuffer LocalTagBuffer; + Kumu::MemIOWriter MemWRT(Buffer.Data() + kl_length, Buffer.Capacity() - kl_length); + Result_t result = LocalTagEntryBatch.Archive(&MemWRT) ? RESULT_OK : RESULT_KLV_CODING; + if ( ASDCP_SUCCESS(result) ) { - ui32_t write_count; - result = WriteKLToFile(Writer, s_MDD_Table[MDDindex_Primer].ul, Buffer.Size()); + ui32_t packet_length = MemWRT.Length(); + result = WriteKLToBuffer(Buffer, Dict::ul(MDD_Primer), packet_length); if ( ASDCP_SUCCESS(result) ) - result = Writer.Write(Buffer.RoData(), Buffer.Size(), &write_count); + Buffer.Size(Buffer.Size() + packet_length); } -#endif return result; } // ASDCP::Result_t -ASDCP::MXF::Primer::InsertTag(const ASDCP::UL& Key, ASDCP::TagValue& Tag) +ASDCP::MXF::Primer::InsertTag(const MDDEntry& Entry, ASDCP::TagValue& Tag) { assert(m_Lookup); - - std::map::iterator i = m_Lookup->find(Key); + UL TestUL(Entry.ul); + std::map::iterator i = m_Lookup->find(TestUL); if ( i == m_Lookup->end() ) { - const MDDEntry* mdde = GetMDDEntry(Key.Data()); - assert(mdde); + if ( Entry.tag.a == 0 && Entry.tag.b == 0 ) + { + Tag.a = 0xff; + Tag.b = m_LocalTag--; + } + else + { + Tag.a = Entry.tag.a; + Tag.b = Entry.tag.b; + } LocalTagEntry TmpEntry; - TmpEntry.UL = Key; - TmpEntry.Tag = mdde->tag; + TmpEntry.UL = TestUL; + TmpEntry.Tag = Tag; LocalTagEntryBatch.push_back(TmpEntry); m_Lookup->insert(std::map::value_type(TmpEntry.UL, TmpEntry.Tag)); } + else + { + Tag = (*i).second; + } return RESULT_OK; } @@ -406,18 +550,16 @@ ASDCP::MXF::Primer::Dump(FILE* stream) stream = stderr; KLVPacket::Dump(stream, false); - fprintf(stream, "Primer: %lu %s\n", - LocalTagEntryBatch.ItemCount, - ( LocalTagEntryBatch.ItemCount == 1 ? "entry" : "entries" )); + fprintf(stream, "Primer: %u %s\n", + (ui32_t)LocalTagEntryBatch.size(), + ( LocalTagEntryBatch.size() == 1 ? "entry" : "entries" )); Batch::iterator i = LocalTagEntryBatch.begin(); for ( ; i != LocalTagEntryBatch.end(); i++ ) { - const MDDEntry* Entry = GetMDDEntry((*i).UL.Data()); - fprintf(stream, " %s %s\n", (*i).ToString(identbuf), (Entry ? Entry->name : "Unknown")); + const MDDEntry* Entry = Dict::FindUL((*i).UL.Value()); + fprintf(stream, " %s %s\n", (*i).EncodeString(identbuf, IdentBufferLen), (Entry ? Entry->name : "Unknown")); } - - fputs("==========================================================================\n", stream); } @@ -426,62 +568,52 @@ ASDCP::MXF::Primer::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::Preface::InitFromBuffer(const byte_t* p, ui32_t l) +ASDCP::MXF::Preface::InitFromTLVSet(TLVReader& TLVSet) { - ASDCP_TEST_NULL(p); - - Result_t result = KLVPacket::InitFromBuffer(p, l, s_MDD_Table[MDDindex_Preface].ul); - - if ( ASDCP_SUCCESS(result) ) - { - TLVReader MemRDR(m_ValueStart, m_ValueLength, m_Lookup); - - result = MemRDR.ReadObject(OBJ_READ_ARGS(InterchangeObject, InstanceUID)); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(GenerationInterchangeObject, GenerationUID)); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, LastModifiedDate)); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi16(OBJ_READ_ARGS(Preface, Version)); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi32(OBJ_READ_ARGS(Preface, ObjectModelVersion)); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, PrimaryPackage)); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, Identifications)); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, ContentStorage)); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, OperationalPattern)); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, EssenceContainers)); - if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, DMSchemes)); - } - - if ( ASDCP_FAILURE(result) ) - DefaultLogSink().Error("Failed to initialize Preface\n"); - + Result_t result = InterchangeObject::InitFromTLVSet(TLVSet); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(Preface, LastModifiedDate)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi16(OBJ_READ_ARGS(Preface, Version)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadUi32(OBJ_READ_ARGS(Preface, ObjectModelVersion)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(Preface, PrimaryPackage)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(Preface, Identifications)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(Preface, ContentStorage)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(Preface, OperationalPattern)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(Preface, EssenceContainers)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.ReadObject(OBJ_READ_ARGS(Preface, DMSchemes)); return result; } // ASDCP::Result_t -ASDCP::MXF::Preface::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +ASDCP::MXF::Preface::WriteToTLVSet(TLVWriter& TLVSet) { - TLVWriter MemWRT(Buffer.Data() + kl_length, Buffer.Capacity() - kl_length, m_Lookup); - Result_t result = MemWRT.WriteObject(OBJ_WRITE_ARGS(InterchangeObject, InstanceUID)); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(GenerationInterchangeObject, GenerationUID)); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, LastModifiedDate)); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi16(OBJ_WRITE_ARGS(Preface, Version)); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi32(OBJ_WRITE_ARGS(Preface, ObjectModelVersion)); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, PrimaryPackage)); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, Identifications)); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, ContentStorage)); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, OperationalPattern)); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, EssenceContainers)); - if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, DMSchemes)); - - if ( ASDCP_SUCCESS(result) ) - { - ui32_t packet_length = MemWRT.Size(); - result = WriteKLToBuffer(Buffer, s_MDD_Table[MDDindex_Preface].ul, packet_length); + Result_t result = InterchangeObject::WriteToTLVSet(TLVSet); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(Preface, LastModifiedDate)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi16(OBJ_WRITE_ARGS(Preface, Version)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteUi32(OBJ_WRITE_ARGS(Preface, ObjectModelVersion)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(Preface, PrimaryPackage)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(Preface, Identifications)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(Preface, ContentStorage)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(Preface, OperationalPattern)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(Preface, EssenceContainers)); + if ( ASDCP_SUCCESS(result) ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS(Preface, DMSchemes)); + return result; +} - if ( ASDCP_SUCCESS(result) ) - Buffer.Size(Buffer.Size() + packet_length); - } +// +ASDCP::Result_t +ASDCP::MXF::Preface::InitFromBuffer(const byte_t* p, ui32_t l) +{ + m_Typeinfo = &Dict::Type(MDD_Preface); + return InterchangeObject::InitFromBuffer(p, l); +} - return result; +// +ASDCP::Result_t +ASDCP::MXF::Preface::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +{ + m_Typeinfo = &Dict::Type(MDD_Preface); + return InterchangeObject::WriteToBuffer(Buffer); } // @@ -493,85 +625,27 @@ ASDCP::MXF::Preface::Dump(FILE* stream) if ( stream == 0 ) stream = stderr; - KLVPacket::Dump(stream, false); - fprintf(stream, " InstanceUID = %s\n", InstanceUID.ToString(identbuf)); - fprintf(stream, " GenerationUID = %s\n", GenerationUID.ToString(identbuf)); - fprintf(stream, " LastModifiedDate = %s\n", LastModifiedDate.ToString(identbuf)); - fprintf(stream, " Version = %hu\n", Version); - fprintf(stream, " ObjectModelVersion = %lu\n", ObjectModelVersion); - fprintf(stream, " PrimaryPackage = %s\n", PrimaryPackage.ToString(identbuf)); - fprintf(stream, " Identifications:\n"); Identifications.Dump(stream); - fprintf(stream, " ContentStorage = %s\n", ContentStorage.ToString(identbuf)); - fprintf(stream, " OperationalPattern = %s\n", OperationalPattern.ToString(identbuf)); - fprintf(stream, " EssenceContainers:\n"); EssenceContainers.Dump(stream); - fprintf(stream, " DMSchemes:\n"); DMSchemes.Dump(stream); - - fputs("==========================================================================\n", stream); + InterchangeObject::Dump(stream); + fprintf(stream, " %22s = %s\n", "LastModifiedDate", LastModifiedDate.EncodeString(identbuf, IdentBufferLen)); + fprintf(stream, " %22s = %hu\n", "Version", Version); + fprintf(stream, " %22s = %u\n", "ObjectModelVersion", ObjectModelVersion); + fprintf(stream, " %22s = %s\n", "PrimaryPackage", PrimaryPackage.EncodeHex(identbuf, IdentBufferLen)); + fprintf(stream, " %22s:\n", "Identifications"); Identifications.Dump(stream); + fprintf(stream, " %22s = %s\n", "ContentStorage", ContentStorage.EncodeHex(identbuf, IdentBufferLen)); + fprintf(stream, " %22s = %s\n", "OperationalPattern", OperationalPattern.EncodeString(identbuf, IdentBufferLen)); + fprintf(stream, " %22s:\n", "EssenceContainers"); EssenceContainers.Dump(stream); + fprintf(stream, " %22s:\n", "DMSchemes"); DMSchemes.Dump(stream); } //------------------------------------------------------------------------------------------ // -// -class ASDCP::MXF::h__PacketList -{ -public: - std::list m_List; - std::map m_Map; - - ~h__PacketList() { - while ( ! m_List.empty() ) - { - delete m_List.back(); - m_List.pop_back(); - } - } - - // - void AddPacket(InterchangeObject* ThePacket) - { - assert(ThePacket); - m_Map.insert(std::map::value_type(ThePacket->InstanceUID, ThePacket)); - m_List.push_back(ThePacket); - } - - // - Result_t GetMDObjectByType(const byte_t* ObjectID, InterchangeObject** Object) - { - ASDCP_TEST_NULL(ObjectID); - ASDCP_TEST_NULL(Object); - std::list::iterator li; - *Object = 0; - - for ( li = m_List.begin(); li != m_List.end(); li++ ) - { - if ( (*li)->HasUL(ObjectID) ) - { - *Object = *li; - return RESULT_OK; - } - } - - return RESULT_FAIL; - } -}; +ASDCP::MXF::OPAtomHeader::OPAtomHeader() : m_Preface(0), m_HasRIP(false) {} +ASDCP::MXF::OPAtomHeader::~OPAtomHeader() {} -//------------------------------------------------------------------------------------------ // - -ASDCP::MXF::OPAtomHeader::OPAtomHeader() : m_Preface(0), m_HasRIP(false) -{ - m_PacketList = new h__PacketList; -} - - -ASDCP::MXF::OPAtomHeader::~OPAtomHeader() -{ -} - - ASDCP::Result_t -ASDCP::MXF::OPAtomHeader::InitFromFile(const ASDCP::FileReader& Reader) +ASDCP::MXF::OPAtomHeader::InitFromFile(const Kumu::FileReader& Reader) { m_HasRIP = false; Result_t result = SeekToRIP(Reader); @@ -579,15 +653,34 @@ ASDCP::MXF::OPAtomHeader::InitFromFile(const ASDCP::FileReader& Reader) if ( ASDCP_SUCCESS(result) ) { result = m_RIP.InitFromFile(Reader); + ui32_t test_s = m_RIP.PairArray.size(); if ( ASDCP_FAILURE(result) ) { DefaultLogSink().Error("File contains no RIP\n"); result = RESULT_OK; } + else if ( test_s == 0 ) + { + DefaultLogSink().Error("RIP contains no Pairs.\n"); + result = RESULT_FORMAT; + } else { + if ( test_s < 2 || test_s > 3 ) + { + // OP-Atom states that there will be either two or three partitions: + // one closed header and one closed footer with an optional body + DefaultLogSink().Warn("RIP count is not 2 or 3: %u\n", test_s); + } + m_HasRIP = true; + + if ( m_RIP.PairArray.front().ByteOffset != 0 ) + { + DefaultLogSink().Error("First Partition in RIP is not at offset 0.\n"); + result = RESULT_FORMAT; + } } } @@ -597,23 +690,44 @@ ASDCP::MXF::OPAtomHeader::InitFromFile(const ASDCP::FileReader& Reader) if ( ASDCP_SUCCESS(result) ) result = Partition::InitFromFile(Reader); // test UL and OP - // slurp up the remainder of the header - ui32_t read_count; + if ( ASDCP_FAILURE(result) ) + return result; - if ( ASDCP_SUCCESS(result) ) + // is it really OP-Atom? + UL OPAtomUL(Dict::ul(MDD_OPAtom)); + UL InteropOPAtomUL(Dict::ul(MDD_MXFInterop_OPAtom)); + + if ( ! ( OperationalPattern == OPAtomUL || OperationalPattern == InteropOPAtomUL ) ) { - ui32_t buf_len = HeaderByteCount; - result = m_Buffer.Capacity(buf_len); + char strbuf[IdentBufferLen]; + const MDDEntry* Entry = Dict::FindUL(OperationalPattern.Value()); + if ( Entry == 0 ) + DefaultLogSink().Warn("Operational pattern is not OP-Atom: %s\n", OperationalPattern.EncodeString(strbuf, IdentBufferLen)); + else + DefaultLogSink().Warn("Operational pattern is not OP-Atom: %s\n", Entry->name); } - if ( ASDCP_SUCCESS(result) ) - result = Reader.Read(m_Buffer.Data(), m_Buffer.Capacity(), &read_count); + // slurp up the remainder of the header + if ( HeaderByteCount < 1024 ) + DefaultLogSink().Warn("Improbably small HeaderByteCount value: %u\n", HeaderByteCount); - if ( ASDCP_SUCCESS(result) && read_count != m_Buffer.Capacity() ) + assert (HeaderByteCount <= 0xFFFFFFFFL); + result = m_Buffer.Capacity((ui32_t) HeaderByteCount); + + if ( ASDCP_SUCCESS(result) ) { - DefaultLogSink().Error("Short read of OP-Atom header metadata; wanted %lu, got %lu\n", - m_Buffer.Capacity(), read_count); - return RESULT_FAIL; + ui32_t read_count; + result = Reader.Read(m_Buffer.Data(), m_Buffer.Capacity(), &read_count); + + if ( ASDCP_FAILURE(result) ) + return result; + + if ( read_count != m_Buffer.Capacity() ) + { + DefaultLogSink().Error("Short read of OP-Atom header metadata; wanted %u, got %u\n", + m_Buffer.Capacity(), read_count); + return RESULT_KLV_CODING; + } } const byte_t* p = m_Buffer.RoData(); @@ -633,22 +747,24 @@ ASDCP::MXF::OPAtomHeader::InitFromFile(const ASDCP::FileReader& Reader) if ( ASDCP_SUCCESS(result) ) { - if ( object->IsA(s_MDD_Table[MDDindex_KLVFill].ul) ) + if ( object->IsA(Dict::ul(MDD_KLVFill)) ) { delete object; } - else if ( object->IsA(s_MDD_Table[MDDindex_Primer].ul) ) + else if ( object->IsA(Dict::ul(MDD_Primer)) ) { delete object; result = m_Primer.InitFromBuffer(redo_p, end_p - redo_p); } - else if ( object->IsA(s_MDD_Table[MDDindex_Preface].ul) ) - { - m_Preface = object; - } - else + else { m_PacketList->AddPacket(object); + + if ( object->IsA(Dict::ul(MDD_Preface)) ) + { + assert(m_Preface == 0); + m_Preface = (Preface*)object; + } } } else @@ -661,6 +777,12 @@ ASDCP::MXF::OPAtomHeader::InitFromFile(const ASDCP::FileReader& Reader) return result; } +ASDCP::Result_t +ASDCP::MXF::OPAtomHeader::GetMDObjectByID(const UUID& ObjectID, InterchangeObject** Object) +{ + return m_PacketList->GetMDObjectByID(ObjectID, Object); +} + // ASDCP::Result_t ASDCP::MXF::OPAtomHeader::GetMDObjectByType(const byte_t* ObjectID, InterchangeObject** Object) @@ -673,6 +795,13 @@ ASDCP::MXF::OPAtomHeader::GetMDObjectByType(const byte_t* ObjectID, InterchangeO return m_PacketList->GetMDObjectByType(ObjectID, Object); } +// +ASDCP::Result_t +ASDCP::MXF::OPAtomHeader::GetMDObjectsByType(const byte_t* ObjectID, std::list& ObjectList) +{ + return m_PacketList->GetMDObjectsByType(ObjectID, ObjectList); +} + // ASDCP::MXF::Identification* ASDCP::MXF::OPAtomHeader::GetIdentification() @@ -697,41 +826,47 @@ ASDCP::MXF::OPAtomHeader::GetSourcePackage() return 0; } + // ASDCP::Result_t -ASDCP::MXF::OPAtomHeader::WriteToFile(ASDCP::FileWriter& Writer, ui32_t HeaderSize) +ASDCP::MXF::OPAtomHeader::WriteToFile(Kumu::FileWriter& Writer, ui32_t HeaderSize) { + if ( m_Preface == 0 ) + return RESULT_STATE; + if ( HeaderSize < 4096 ) { - DefaultLogSink().Error("HeaderSize %lu is too small. Must be >= 4096\n"); + DefaultLogSink().Error("HeaderSize %u is too small. Must be >= 4096\n", HeaderSize); return RESULT_FAIL; } ASDCP::FrameBuffer HeaderBuffer; + HeaderByteCount = HeaderSize - ArchiveSize(); + assert (HeaderByteCount <= 0xFFFFFFFFL); + Result_t result = HeaderBuffer.Capacity((ui32_t) HeaderByteCount); + m_Preface->m_Lookup = &m_Primer; - Result_t result = HeaderBuffer.Capacity(HeaderSize); - HeaderByteCount = HeaderSize; - - if ( ASDCP_SUCCESS(result) ) - { - assert(m_Preface); - m_Preface->m_Lookup = &m_Primer; - result = m_Preface->WriteToBuffer(HeaderBuffer); - } -#if 0 std::list::iterator pl_i = m_PacketList->m_List.begin(); for ( ; pl_i != m_PacketList->m_List.end() && ASDCP_SUCCESS(result); pl_i++ ) { InterchangeObject* object = *pl_i; object->m_Lookup = &m_Primer; - result = object->WriteToBuffer(HeaderBuffer); + + ASDCP::FrameBuffer WriteWrapper; + WriteWrapper.SetData(HeaderBuffer.Data() + HeaderBuffer.Size(), + HeaderBuffer.Capacity() - HeaderBuffer.Size()); + result = object->WriteToBuffer(WriteWrapper); + HeaderBuffer.Size(HeaderBuffer.Size() + WriteWrapper.Size()); } -#endif + if ( ASDCP_SUCCESS(result) ) - result = Partition::WriteToFile(Writer); + { + UL TmpUL(Dict::ul(MDD_ClosedCompleteHeader)); + result = Partition::WriteToFile(Writer, TmpUL); + } - // if ( ASDCP_SUCCESS(result) ) - // result = m_Primer.WriteToFile(Writer); + if ( ASDCP_SUCCESS(result) ) + result = m_Primer.WriteToFile(Writer); if ( ASDCP_SUCCESS(result) ) { @@ -743,12 +878,12 @@ ASDCP::MXF::OPAtomHeader::WriteToFile(ASDCP::FileWriter& Writer, ui32_t HeaderSi // KLV Fill if ( ASDCP_SUCCESS(result) ) { - ASDCP::fpos_t pos = Writer.Tell(); + Kumu::fpos_t pos = Writer.Tell(); - if ( pos > HeaderSize ) + if ( pos > (Kumu::fpos_t)HeaderByteCount ) { char intbuf[IntBufferLen]; - DefaultLogSink().Error("Header size %s exceeds specified value %lu\n", + DefaultLogSink().Error("Header size %s exceeds specified value %u\n", ui64sz(pos, intbuf), HeaderSize); return RESULT_FAIL; @@ -764,7 +899,7 @@ ASDCP::MXF::OPAtomHeader::WriteToFile(ASDCP::FileWriter& Writer, ui32_t HeaderSi } klv_fill_length -= kl_length; - result = WriteKLToFile(Writer, s_MDD_Table[MDDindex_KLVFill].ul, klv_fill_length); + result = WriteKLToFile(Writer, Dict::ul(MDD_KLVFill), klv_fill_length); if ( ASDCP_SUCCESS(result) ) result = NilBuf.Capacity(klv_fill_length); @@ -788,13 +923,11 @@ ASDCP::MXF::OPAtomHeader::Dump(FILE* stream) if ( stream == 0 ) stream = stderr; - if ( m_HasRIP ) - m_RIP.Dump(stream); - Partition::Dump(stream); m_Primer.Dump(stream); - assert(m_Preface); - m_Preface->Dump(stream); + + if ( m_Preface == 0 ) + fputs("No Preface loaded\n", stream); std::list::iterator i = m_PacketList->m_List.begin(); for ( ; i != m_PacketList->m_List.end(); i++ ) @@ -804,19 +937,19 @@ ASDCP::MXF::OPAtomHeader::Dump(FILE* stream) //------------------------------------------------------------------------------------------ // -ASDCP::MXF::OPAtomIndexFooter::OPAtomIndexFooter() : m_Lookup(0) +ASDCP::MXF::OPAtomIndexFooter::OPAtomIndexFooter() : + m_CurrentSegment(0), m_BytesPerEditUnit(0), m_BodySID(0), + m_ECOffset(0), m_Lookup(0) { - m_PacketList = new h__PacketList; + BodySID = 0; + IndexSID = 129; } - -ASDCP::MXF::OPAtomIndexFooter::~OPAtomIndexFooter() -{ -} +ASDCP::MXF::OPAtomIndexFooter::~OPAtomIndexFooter() {} ASDCP::Result_t -ASDCP::MXF::OPAtomIndexFooter::InitFromFile(const ASDCP::FileReader& Reader) +ASDCP::MXF::OPAtomIndexFooter::InitFromFile(const Kumu::FileReader& Reader) { Result_t result = Partition::InitFromFile(Reader); // test UL and OP @@ -824,14 +957,17 @@ ASDCP::MXF::OPAtomIndexFooter::InitFromFile(const ASDCP::FileReader& Reader) ui32_t read_count; if ( ASDCP_SUCCESS(result) ) - result = m_Buffer.Capacity(IndexByteCount); + { + assert (IndexByteCount <= 0xFFFFFFFFL); + result = m_Buffer.Capacity((ui32_t) IndexByteCount); + } if ( ASDCP_SUCCESS(result) ) result = Reader.Read(m_Buffer.Data(), m_Buffer.Capacity(), &read_count); if ( ASDCP_SUCCESS(result) && read_count != m_Buffer.Capacity() ) { - DefaultLogSink().Error("Short read of footer partition: got %lu, expecting %lu\n", + DefaultLogSink().Error("Short read of footer partition: got %u, expecting %u\n", read_count, m_Buffer.Capacity()); return RESULT_FAIL; } @@ -868,9 +1004,60 @@ ASDCP::MXF::OPAtomIndexFooter::InitFromFile(const ASDCP::FileReader& Reader) // ASDCP::Result_t -ASDCP::MXF::OPAtomIndexFooter::WriteToFile(ASDCP::FileWriter& Writer) +ASDCP::MXF::OPAtomIndexFooter::WriteToFile(Kumu::FileWriter& Writer, ui64_t duration) { - Result_t result = WriteKLToFile(Writer, s_MDD_Table[MDDindex_CompleteFooter].ul, 0); + ASDCP::FrameBuffer FooterBuffer; + ui32_t footer_size = m_PacketList->m_List.size() * MaxIndexSegmentSize; // segment-count * max-segment-size + Result_t result = FooterBuffer.Capacity(footer_size); + ui32_t iseg_count = 0; + + if ( m_CurrentSegment != 0 ) + { + m_CurrentSegment->IndexDuration = m_CurrentSegment->IndexEntryArray.size(); + m_CurrentSegment = 0; + } + + std::list::iterator pl_i = m_PacketList->m_List.begin(); + for ( ; pl_i != m_PacketList->m_List.end() && ASDCP_SUCCESS(result); pl_i++ ) + { + if ( (*pl_i)->IsA(OBJ_TYPE_ARGS(IndexTableSegment)) ) + { + iseg_count++; + IndexTableSegment* Segment = (IndexTableSegment*)(*pl_i); + + if ( m_BytesPerEditUnit != 0 ) + { + if ( iseg_count != 1 ) + return RESULT_STATE; + + Segment->IndexDuration = duration; + } + } + + InterchangeObject* object = *pl_i; + object->m_Lookup = m_Lookup; + + ASDCP::FrameBuffer WriteWrapper; + WriteWrapper.SetData(FooterBuffer.Data() + FooterBuffer.Size(), + FooterBuffer.Capacity() - FooterBuffer.Size()); + result = object->WriteToBuffer(WriteWrapper); + FooterBuffer.Size(FooterBuffer.Size() + WriteWrapper.Size()); + } + + if ( ASDCP_SUCCESS(result) ) + { + IndexByteCount = FooterBuffer.Size(); + UL FooterUL(Dict::ul(MDD_CompleteFooter)); + result = Partition::WriteToFile(Writer, FooterUL); + } + + if ( ASDCP_SUCCESS(result) ) + { + ui32_t write_count = 0; + result = Writer.Write(FooterBuffer.RoData(), FooterBuffer.Size(), &write_count); + assert(write_count == FooterBuffer.Size()); + } + return result; } @@ -890,7 +1077,7 @@ ASDCP::MXF::OPAtomIndexFooter::Dump(FILE* stream) // ASDCP::Result_t -ASDCP::MXF::OPAtomIndexFooter::Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry& Entry) +ASDCP::MXF::OPAtomIndexFooter::Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry& Entry) const { std::list::iterator li; for ( li = m_PacketList->m_List.begin(); li != m_PacketList->m_List.end(); li++ ) @@ -914,7 +1101,9 @@ ASDCP::MXF::OPAtomIndexFooter::Lookup(ui32_t frame_num, IndexTableSegment::Index else if ( (ui64_t)frame_num >= start_pos && (ui64_t)frame_num < (start_pos + Segment->IndexDuration) ) { - Entry = Segment->IndexEntryArray[frame_num]; + ui64_t tmp = frame_num - start_pos; + assert(tmp <= 0xFFFFFFFFL); + Entry = Segment->IndexEntryArray[(ui32_t) tmp]; return RESULT_OK; } } @@ -923,32 +1112,150 @@ ASDCP::MXF::OPAtomIndexFooter::Lookup(ui32_t frame_num, IndexTableSegment::Index return RESULT_FAIL; } +// +void +ASDCP::MXF::OPAtomIndexFooter::SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate) +{ + assert(lookup); + m_Lookup = lookup; + m_BytesPerEditUnit = size; + m_EditRate = Rate; + + IndexTableSegment* Index = new IndexTableSegment; + AddChildObject(Index); + Index->EditUnitByteCount = m_BytesPerEditUnit; + Index->IndexEditRate = Rate; +} + +// +void +ASDCP::MXF::OPAtomIndexFooter::SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset) +{ + assert(lookup); + m_Lookup = lookup; + m_BytesPerEditUnit = 0; + m_EditRate = Rate; + m_ECOffset = offset; +} + +// +void +ASDCP::MXF::OPAtomIndexFooter::PushIndexEntry(const IndexTableSegment::IndexEntry& Entry) +{ + if ( m_BytesPerEditUnit != 0 ) // are we CBR? that's bad + { + DefaultLogSink().Error("Call to PushIndexEntry() failed: index is CBR\n"); + return; + } + + // do we have an available segment? + if ( m_CurrentSegment == 0 ) + { // no, set up a new segment + m_CurrentSegment = new IndexTableSegment; + assert(m_CurrentSegment); + AddChildObject(m_CurrentSegment); + m_CurrentSegment->DeltaEntryArray.push_back(IndexTableSegment::DeltaEntry()); + m_CurrentSegment->IndexEditRate = m_EditRate; + m_CurrentSegment->IndexStartPosition = 0; + } + else if ( m_CurrentSegment->IndexEntryArray.size() >= CBRIndexEntriesPerSegment ) + { // no, this one is full, start another + m_CurrentSegment->IndexDuration = m_CurrentSegment->IndexEntryArray.size(); + ui64_t StartPosition = m_CurrentSegment->IndexStartPosition + m_CurrentSegment->IndexDuration; + + m_CurrentSegment = new IndexTableSegment; + assert(m_CurrentSegment); + AddChildObject(m_CurrentSegment); + m_CurrentSegment->DeltaEntryArray.push_back(IndexTableSegment::DeltaEntry()); + m_CurrentSegment->IndexEditRate = m_EditRate; + m_CurrentSegment->IndexStartPosition = StartPosition; + } + + m_CurrentSegment->IndexEntryArray.push_back(Entry); +} //------------------------------------------------------------------------------------------ // // ASDCP::Result_t -ASDCP::MXF::InterchangeObject::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +ASDCP::MXF::InterchangeObject::InitFromTLVSet(TLVReader& TLVSet) +{ + Result_t result = TLVSet.ReadObject(OBJ_READ_ARGS(InterchangeObject, InstanceUID)); + if ( ASDCP_SUCCESS(result) ) + result = TLVSet.ReadObject(OBJ_READ_ARGS(GenerationInterchangeObject, GenerationUID)); + return result; +} + +// +ASDCP::Result_t +ASDCP::MXF::InterchangeObject::WriteToTLVSet(TLVWriter& TLVSet) +{ + Result_t result = TLVSet.WriteObject(OBJ_WRITE_ARGS(InterchangeObject, InstanceUID)); + if ( ASDCP_SUCCESS(result) ) + result = TLVSet.WriteObject(OBJ_WRITE_ARGS(GenerationInterchangeObject, GenerationUID)); + return result; +} + +// +ASDCP::Result_t +ASDCP::MXF::InterchangeObject::InitFromBuffer(const byte_t* p, ui32_t l) { - if ( Buffer.Capacity() < (Buffer.Size() + m_KLLength + m_ValueLength) ) + ASDCP_TEST_NULL(p); + Result_t result = RESULT_FALSE; + + if ( m_Typeinfo == 0 ) { - DefaultLogSink().Error("InterchangeObject::WriteToBuffer: Buffer too small\n"); - Dump(); - return RESULT_READFAIL; + result = KLVPacket::InitFromBuffer(p, l); } + else + { + result = KLVPacket::InitFromBuffer(p, l, m_Typeinfo->ul); + + if ( ASDCP_SUCCESS(result) ) + { + TLVReader MemRDR(m_ValueStart, m_ValueLength, m_Lookup); + result = InitFromTLVSet(MemRDR); + } + } + + return result; +} - Result_t result = WriteKLToBuffer(Buffer, m_KeyStart, m_ValueLength); +// +ASDCP::Result_t +ASDCP::MXF::InterchangeObject::WriteToBuffer(ASDCP::FrameBuffer& Buffer) +{ + if ( m_Typeinfo == 0 ) + return RESULT_STATE; + + TLVWriter MemWRT(Buffer.Data() + kl_length, Buffer.Capacity() - kl_length, m_Lookup); + Result_t result = WriteToTLVSet(MemWRT); if ( ASDCP_SUCCESS(result) ) { - memcpy(Buffer.Data() + Buffer.Size(), m_ValueStart, m_ValueLength); - Buffer.Size(Buffer.Size() + m_ValueLength); + ui32_t packet_length = MemWRT.Length(); + result = WriteKLToBuffer(Buffer, m_Typeinfo->ul, packet_length); + + if ( ASDCP_SUCCESS(result) ) + Buffer.Size(Buffer.Size() + packet_length); } return result; } +// +void +ASDCP::MXF::InterchangeObject::Dump(FILE* stream) +{ + char identbuf[IdentBufferLen]; + + fputc('\n', stream); + KLVPacket::Dump(stream, false); + fprintf(stream, " InstanceUID = %s\n", InstanceUID.EncodeHex(identbuf, IdentBufferLen)); + fprintf(stream, " GenerationUID = %s\n", GenerationUID.EncodeHex(identbuf, IdentBufferLen)); +} + // bool ASDCP::MXF::InterchangeObject::IsA(const byte_t* label) @@ -961,65 +1268,54 @@ ASDCP::MXF::InterchangeObject::IsA(const byte_t* label) //------------------------------------------------------------------------------------------ -// -// -enum FLT_t - { - FLT_Preface, - FLT_Identification, - FLT_ContentStorage, - FLT_MaterialPackage, - FLT_SourcePackage, - FLT_Track, - FLT_Sequence, - FLT_SourceClip, - FLT_TimecodeComponent, - FLT_FileDescriptor, - FLT_WaveAudioDescriptor, - FLT_GenericPictureEssenceDescriptor, - FLT_MPEG2VideoDescriptor, - FLT_RGBAEssenceDescriptor, - FLT_JPEG2000PictureSubDescriptor, - FLT_IndexTableSegment, - FLT_CryptographicFramework, - FLT_CryptographicContext - }; -// -typedef std::map::iterator FLi_t; +typedef std::mapFactoryMap_t; +typedef FactoryMap_t::iterator FLi_t; -class FactoryList : public std::map +// +class FactoryList : public FactoryMap_t { - ASDCP::Mutex m_Lock; + Kumu::Mutex m_Lock; public: FactoryList() {} ~FactoryList() {} bool Empty() { - ASDCP::AutoMutex BlockLock(m_Lock); + Kumu::AutoMutex BlockLock(m_Lock); return empty(); } FLi_t Find(const byte_t* label) { - ASDCP::AutoMutex BlockLock(m_Lock); + Kumu::AutoMutex BlockLock(m_Lock); return find(label); } FLi_t End() { - ASDCP::AutoMutex BlockLock(m_Lock); + Kumu::AutoMutex BlockLock(m_Lock); return end(); } + void Insert(ASDCP::UL label, ASDCP::MXF::MXFObjectFactory_t factory) { + Kumu::AutoMutex BlockLock(m_Lock); + insert(FactoryList::value_type(label, factory)); + } }; // static FactoryList s_FactoryList; +static Kumu::Mutex s_InitLock; +static bool s_TypesInit = false; + + +// +void +ASDCP::MXF::SetObjectFactory(ASDCP::UL label, ASDCP::MXF::MXFObjectFactory_t factory) +{ + s_FactoryList.Insert(label, factory); +} -#define SETUP_IDX(t) const ui32_t FLT_##t = v; -#define SETUP_FACTORY(t) s_FactoryList.insert(FactoryList::value_type(s_MDD_Table[MDDindex_##t].ul, FLT_##t)); -#define CASE_FACTORY(t) case FLT_##t: return new t // ASDCP::MXF::InterchangeObject* @@ -1028,26 +1324,15 @@ ASDCP::MXF::CreateObject(const byte_t* label) if ( label == 0 ) return 0; - if ( s_FactoryList.empty() ) + if ( ! s_TypesInit ) { - SETUP_FACTORY(Preface); - SETUP_FACTORY(Identification); - SETUP_FACTORY(ContentStorage); - SETUP_FACTORY(MaterialPackage); - SETUP_FACTORY(SourcePackage); - SETUP_FACTORY(Track); - SETUP_FACTORY(Sequence); - SETUP_FACTORY(SourceClip); - SETUP_FACTORY(TimecodeComponent); - SETUP_FACTORY(FileDescriptor); - SETUP_FACTORY(WaveAudioDescriptor); - SETUP_FACTORY(GenericPictureEssenceDescriptor); - SETUP_FACTORY(MPEG2VideoDescriptor); - SETUP_FACTORY(RGBAEssenceDescriptor); - SETUP_FACTORY(JPEG2000PictureSubDescriptor); - SETUP_FACTORY(IndexTableSegment); - SETUP_FACTORY(CryptographicFramework); - SETUP_FACTORY(CryptographicContext); + Kumu::AutoMutex BlockLock(s_InitLock); + + if ( ! s_TypesInit ) + { + MXF::Metadata_InitTypes(); + s_TypesInit = true; + } } FLi_t i = s_FactoryList.find(label); @@ -1055,31 +1340,11 @@ ASDCP::MXF::CreateObject(const byte_t* label) if ( i == s_FactoryList.end() ) return new InterchangeObject; - switch ( i->second ) - { - CASE_FACTORY(Preface); - CASE_FACTORY(Identification); - CASE_FACTORY(ContentStorage); - CASE_FACTORY(MaterialPackage); - CASE_FACTORY(SourcePackage); - CASE_FACTORY(Track); - CASE_FACTORY(Sequence); - CASE_FACTORY(SourceClip); - CASE_FACTORY(TimecodeComponent); - CASE_FACTORY(FileDescriptor); - CASE_FACTORY(WaveAudioDescriptor); - CASE_FACTORY(GenericPictureEssenceDescriptor); - CASE_FACTORY(MPEG2VideoDescriptor); - CASE_FACTORY(RGBAEssenceDescriptor); - CASE_FACTORY(JPEG2000PictureSubDescriptor); - CASE_FACTORY(IndexTableSegment); - CASE_FACTORY(CryptographicFramework); - CASE_FACTORY(CryptographicContext); - } - - return new InterchangeObject; + return i->second(); } + + // // end MXF.cpp //