6 #define ASDCP_DECLARE_MDD
11 #include <hex_utils.h>
13 //------------------------------------------------------------------------------------------
16 const ui32_t kl_length = ASDCP::SMPTE_UL_LENGTH + ASDCP::MXF_BER_LENGTH;
18 const byte_t mdd_key[] = { 0x06, 0x0e, 0x2b, 0x34 };
21 const ASDCP::MDDEntry*
22 ASDCP::GetMDDEntry(const byte_t* ul_buf)
27 // must be a pointer to a SMPTE UL
28 if ( ul_buf == 0 || memcmp(mdd_key, ul_buf, 4) != 0 )
31 // advance to first matching element
32 // TODO: optimize using binary search
33 while ( s_MDD_Table[t_idx].ul != 0
34 && s_MDD_Table[t_idx].ul[k_idx] != ul_buf[k_idx] )
37 if ( s_MDD_Table[t_idx].ul == 0 )
40 // match successive elements
41 while ( s_MDD_Table[t_idx].ul != 0
42 && k_idx < SMPTE_UL_LENGTH - 1
43 && s_MDD_Table[t_idx].ul[k_idx] == ul_buf[k_idx] )
45 if ( s_MDD_Table[t_idx].ul[k_idx+1] == ul_buf[k_idx+1] )
51 while ( s_MDD_Table[t_idx].ul != 0
52 && s_MDD_Table[t_idx].ul[k_idx] == ul_buf[k_idx]
53 && s_MDD_Table[t_idx].ul[k_idx+1] != ul_buf[k_idx+1] )
56 while ( s_MDD_Table[t_idx].ul[k_idx] != ul_buf[k_idx] )
61 return (s_MDD_Table[t_idx].ul == 0 ? 0 : &s_MDD_Table[t_idx]);
64 //------------------------------------------------------------------------------------------
69 ASDCP::MXF::SeekToRIP(const ASDCP::FileReader& Reader)
71 ASDCP::fpos_t end_pos;
73 // go to the end - 4 bytes
74 Result_t result = Reader.Seek(0, ASDCP::SP_END);
76 if ( ASDCP_SUCCESS(result) )
77 result = Reader.Tell(&end_pos);
79 if ( ASDCP_SUCCESS(result)
80 && end_pos < (SMPTE_UL_LENGTH+MXF_BER_LENGTH) )
81 result = RESULT_FAIL; // File is smaller than an empty packet!
83 if ( ASDCP_SUCCESS(result) )
84 result = Reader.Seek(end_pos - 4);
86 // get the ui32_t RIP length
88 byte_t intbuf[MXF_BER_LENGTH];
91 if ( ASDCP_SUCCESS(result) )
93 result = Reader.Read(intbuf, MXF_BER_LENGTH, &read_count);
95 if ( ASDCP_SUCCESS(result) && read_count != 4 )
99 if ( ASDCP_SUCCESS(result) )
101 rip_size = ASDCP_i32_BE(cp2i<ui32_t>(intbuf));
103 if ( rip_size > end_pos ) // RIP can't be bigger than the file
107 // reposition to start of RIP
108 if ( ASDCP_SUCCESS(result) )
109 result = Reader.Seek(end_pos - rip_size);
116 ASDCP::MXF::RIP::InitFromFile(const ASDCP::FileReader& Reader)
118 Result_t result = KLVFilePacket::InitFromFile(Reader, s_MDD_Table[MDDindex_RandomIndexMetadata].ul);
120 if ( ASDCP_SUCCESS(result) )
122 MemIOReader MemRDR(m_ValueStart, m_ValueLength - 4);
123 result = PairArray.ReadFrom(MemRDR);
126 if ( ASDCP_FAILURE(result) )
127 DefaultLogSink().Error("Failed to initialize RIP\n");
134 ASDCP::MXF::RIP::WriteToFile(ASDCP::FileWriter& Writer)
136 Result_t result = WriteKLToFile(Writer, s_MDD_Table[MDDindex_RandomIndexMetadata].ul, 0);
142 ASDCP::MXF::RIP::Dump(FILE* stream)
147 KLVFilePacket::Dump(stream, false);
148 PairArray.Dump(stream, false);
150 fputs("==========================================================================\n", stream);
153 //------------------------------------------------------------------------------------------
158 ASDCP::MXF::Partition::InitFromFile(const ASDCP::FileReader& Reader)
160 Result_t result = KLVFilePacket::InitFromFile(Reader);
162 // could be one of several values
164 if ( ASDCP_SUCCESS(result) )
166 MemIOReader MemRDR(m_ValueStart, m_ValueLength);
167 result = MemRDR.ReadUi16BE(&MajorVersion);
168 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi16BE(&MinorVersion);
169 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi32BE(&KAGSize);
170 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&ThisPartition);
171 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&PreviousPartition);
172 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&FooterPartition);
173 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&HeaderByteCount);
174 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&IndexByteCount);
175 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi32BE(&IndexSID);
176 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi64BE(&BodyOffset);
177 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi32BE(&BodySID);
178 if ( ASDCP_SUCCESS(result) ) result = OperationalPattern.ReadFrom(MemRDR);
179 if ( ASDCP_SUCCESS(result) ) result = EssenceContainers.ReadFrom(MemRDR);
182 if ( ASDCP_FAILURE(result) )
183 DefaultLogSink().Error("Failed to initialize Partition\n");
190 ASDCP::MXF::Partition::WriteToFile(ASDCP::FileWriter& Writer)
192 Result_t result = m_Buffer.Capacity(1024);
194 if ( ASDCP_SUCCESS(result) )
196 MemIOWriter MemWRT(m_Buffer.Data(), m_Buffer.Capacity());
197 result = MemWRT.WriteUi16BE(MajorVersion);
198 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi16BE(MinorVersion);
199 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi32BE(KAGSize);
200 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(ThisPartition);
201 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(PreviousPartition);
202 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(FooterPartition);
203 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(HeaderByteCount);
204 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(IndexByteCount);
205 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi32BE(IndexSID);
206 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi64BE(BodyOffset);
207 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi32BE(BodySID);
208 if ( ASDCP_SUCCESS(result) ) result = OperationalPattern.WriteTo(MemWRT);
209 if ( ASDCP_SUCCESS(result) ) result = EssenceContainers.WriteTo(MemWRT);
210 if ( ASDCP_SUCCESS(result) ) m_Buffer.Size(MemWRT.Size());
213 if ( ASDCP_SUCCESS(result) )
215 ui32_t write_count; // this is subclassed, so the UL is only right some of the time
216 result = WriteKLToFile(Writer, s_MDD_Table[MDDindex_ClosedCompleteHeader].ul, m_Buffer.Size());
218 if ( ASDCP_SUCCESS(result) )
219 result = Writer.Write(m_Buffer.RoData(), m_Buffer.Size(), &write_count);
227 ASDCP::MXF::Partition::Dump(FILE* stream)
229 char identbuf[IdentBufferLen];
230 char intbuf[IntBufferLen];
235 KLVFilePacket::Dump(stream, false);
236 fprintf(stream, " MajorVersion = %hu\n", MajorVersion);
237 fprintf(stream, " MinorVersion = %hu\n", MinorVersion);
238 fprintf(stream, " KAGSize = %lu\n", KAGSize);
239 fprintf(stream, " ThisPartition = %s\n", ui64sz(ThisPartition, intbuf));
240 fprintf(stream, " PreviousPartition = %s\n", ui64sz(PreviousPartition, intbuf));
241 fprintf(stream, " FooterPartition = %s\n", ui64sz(FooterPartition, intbuf));
242 fprintf(stream, " HeaderByteCount = %s\n", ui64sz(HeaderByteCount, intbuf));
243 fprintf(stream, " IndexByteCount = %s\n", ui64sz(IndexByteCount, intbuf));
244 fprintf(stream, " IndexSID = %lu\n", IndexSID);
245 fprintf(stream, " BodyOffset = %s\n", ui64sz(BodyOffset, intbuf));
246 fprintf(stream, " BodySID = %lu\n", BodySID);
247 fprintf(stream, " OperationalPattern = %s\n", OperationalPattern.ToString(identbuf));
248 fputs("Essence Containers:\n", stream); EssenceContainers.Dump(stream, false);
250 fputs("==========================================================================\n", stream);
254 //------------------------------------------------------------------------------------------
257 class ASDCP::MXF::Primer::h__PrimerLookup : public std::map<UL, TagValue>
260 void InitWithBatch(ASDCP::MXF::Batch<ASDCP::MXF::Primer::LocalTagEntry>& Batch)
262 ASDCP::MXF::Batch<ASDCP::MXF::Primer::LocalTagEntry>::iterator i = Batch.begin();
264 for ( ; i != Batch.end(); i++ )
265 insert(std::map<UL, TagValue>::value_type((*i).UL, (*i).Tag));
271 ASDCP::MXF::Primer::Primer() {}
274 ASDCP::MXF::Primer::~Primer() {}
278 ASDCP::MXF::Primer::ClearTagList()
280 LocalTagEntryBatch.clear();
281 m_Lookup = new h__PrimerLookup;
286 ASDCP::MXF::Primer::InitFromBuffer(const byte_t* p, ui32_t l)
288 Result_t result = KLVPacket::InitFromBuffer(p, l, s_MDD_Table[MDDindex_Primer].ul);
290 if ( ASDCP_SUCCESS(result) )
292 MemIOReader MemRDR(m_ValueStart, m_ValueLength);
293 result = LocalTagEntryBatch.ReadFrom(MemRDR);
296 if ( ASDCP_SUCCESS(result) )
298 m_Lookup = new h__PrimerLookup;
299 m_Lookup->InitWithBatch(LocalTagEntryBatch);
302 if ( ASDCP_FAILURE(result) )
303 DefaultLogSink().Error("Failed to initialize Primer\n");
310 ASDCP::MXF::Primer::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
312 MemIOWriter MemWRT(Buffer.Data(), Buffer.Capacity());
313 Result_t result = LocalTagEntryBatch.WriteTo(MemWRT);
314 Buffer.Size(MemWRT.Size());
316 if ( ASDCP_SUCCESS(result) )
319 result = WriteKLToFile(Writer, s_MDD_Table[MDDindex_Primer].ul, Buffer.Size());
321 if ( ASDCP_SUCCESS(result) )
322 result = Writer.Write(Buffer.RoData(), Buffer.Size(), &write_count);
331 ASDCP::MXF::Primer::InsertTag(const ASDCP::UL& Key, ASDCP::TagValue& Tag)
335 std::map<UL, TagValue>::iterator i = m_Lookup->find(Key);
337 if ( i == m_Lookup->end() )
339 const MDDEntry* mdde = GetMDDEntry(Key.Data());
342 LocalTagEntry TmpEntry;
344 TmpEntry.Tag = mdde->tag;
346 LocalTagEntryBatch.push_back(TmpEntry);
347 m_Lookup->insert(std::map<UL, TagValue>::value_type(TmpEntry.UL, TmpEntry.Tag));
355 ASDCP::MXF::Primer::TagForKey(const ASDCP::UL& Key, ASDCP::TagValue& Tag)
358 if ( m_Lookup.empty() )
360 DefaultLogSink().Error("Primer lookup is empty\n");
364 std::map<UL, TagValue>::iterator i = m_Lookup->find(Key);
366 if ( i == m_Lookup->end() )
375 ASDCP::MXF::Primer::Dump(FILE* stream)
377 char identbuf[IdentBufferLen];
382 KLVPacket::Dump(stream, false);
383 fprintf(stream, "Primer: %lu %s\n",
384 LocalTagEntryBatch.ItemCount,
385 ( LocalTagEntryBatch.ItemCount == 1 ? "entry" : "entries" ));
387 Batch<LocalTagEntry>::iterator i = LocalTagEntryBatch.begin();
388 for ( ; i != LocalTagEntryBatch.end(); i++ )
390 const MDDEntry* Entry = GetMDDEntry((*i).UL.Data());
391 fprintf(stream, " %s %s\n", (*i).ToString(identbuf), (Entry ? Entry->name : "Unknown"));
394 fputs("==========================================================================\n", stream);
398 //------------------------------------------------------------------------------------------
403 ASDCP::MXF::Preface::InitFromBuffer(const byte_t* p, ui32_t l)
407 Result_t result = KLVPacket::InitFromBuffer(p, l, s_MDD_Table[MDDindex_Preface].ul);
409 if ( ASDCP_SUCCESS(result) )
411 TLVReader MemRDR(m_ValueStart, m_ValueLength, m_Lookup);
413 result = MemRDR.ReadObject(OBJ_READ_ARGS(InterchangeObject, InstanceUID));
414 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(GenerationInterchangeObject, GenerationUID));
415 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, LastModifiedDate));
416 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi16(OBJ_READ_ARGS(Preface, Version));
417 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadUi32(OBJ_READ_ARGS(Preface, ObjectModelVersion));
418 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, PrimaryPackage));
419 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, Identifications));
420 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, ContentStorage));
421 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, OperationalPattern));
422 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, EssenceContainers));
423 if ( ASDCP_SUCCESS(result) ) result = MemRDR.ReadObject(OBJ_READ_ARGS(Preface, DMSchemes));
426 if ( ASDCP_FAILURE(result) )
427 DefaultLogSink().Error("Failed to initialize Preface\n");
434 ASDCP::MXF::Preface::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
436 TLVWriter MemWRT(Buffer.Data() + kl_length, Buffer.Capacity() - kl_length, m_Lookup);
437 Result_t result = MemWRT.WriteObject(OBJ_WRITE_ARGS(InterchangeObject, InstanceUID));
438 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(GenerationInterchangeObject, GenerationUID));
439 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, LastModifiedDate));
440 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi16(OBJ_WRITE_ARGS(Preface, Version));
441 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteUi32(OBJ_WRITE_ARGS(Preface, ObjectModelVersion));
442 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, PrimaryPackage));
443 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, Identifications));
444 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, ContentStorage));
445 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, OperationalPattern));
446 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, EssenceContainers));
447 if ( ASDCP_SUCCESS(result) ) result = MemWRT.WriteObject(OBJ_WRITE_ARGS(Preface, DMSchemes));
449 if ( ASDCP_SUCCESS(result) )
451 ui32_t packet_length = MemWRT.Size();
452 result = WriteKLToBuffer(Buffer, s_MDD_Table[MDDindex_Preface].ul, packet_length);
454 if ( ASDCP_SUCCESS(result) )
455 Buffer.Size(Buffer.Size() + packet_length);
463 ASDCP::MXF::Preface::Dump(FILE* stream)
465 char identbuf[IdentBufferLen];
470 KLVPacket::Dump(stream, false);
471 fprintf(stream, " InstanceUID = %s\n", InstanceUID.ToString(identbuf));
472 fprintf(stream, " GenerationUID = %s\n", GenerationUID.ToString(identbuf));
473 fprintf(stream, " LastModifiedDate = %s\n", LastModifiedDate.ToString(identbuf));
474 fprintf(stream, " Version = %hu\n", Version);
475 fprintf(stream, " ObjectModelVersion = %lu\n", ObjectModelVersion);
476 fprintf(stream, " PrimaryPackage = %s\n", PrimaryPackage.ToString(identbuf));
477 fprintf(stream, " Identifications:\n"); Identifications.Dump(stream);
478 fprintf(stream, " ContentStorage = %s\n", ContentStorage.ToString(identbuf));
479 fprintf(stream, " OperationalPattern = %s\n", OperationalPattern.ToString(identbuf));
480 fprintf(stream, " EssenceContainers:\n"); EssenceContainers.Dump(stream);
481 fprintf(stream, " DMSchemes:\n"); DMSchemes.Dump(stream);
483 fputs("==========================================================================\n", stream);
486 //------------------------------------------------------------------------------------------
490 class ASDCP::MXF::h__PacketList
493 std::list<InterchangeObject*> m_List;
494 std::map<UL, InterchangeObject*> m_Map;
497 while ( ! m_List.empty() )
499 delete m_List.back();
505 void AddPacket(InterchangeObject* ThePacket)
508 m_Map.insert(std::map<UID, InterchangeObject*>::value_type(ThePacket->InstanceUID, ThePacket));
509 m_List.push_back(ThePacket);
513 Result_t GetMDObjectByType(const byte_t* ObjectID, InterchangeObject** Object)
515 ASDCP_TEST_NULL(ObjectID);
516 ASDCP_TEST_NULL(Object);
517 std::list<InterchangeObject*>::iterator li;
520 for ( li = m_List.begin(); li != m_List.end(); li++ )
522 if ( (*li)->HasUL(ObjectID) )
533 //------------------------------------------------------------------------------------------
536 ASDCP::MXF::OPAtomHeader::OPAtomHeader() : m_Preface(0), m_HasRIP(false)
538 m_PacketList = new h__PacketList;
542 ASDCP::MXF::OPAtomHeader::~OPAtomHeader()
548 ASDCP::MXF::OPAtomHeader::InitFromFile(const ASDCP::FileReader& Reader)
551 Result_t result = SeekToRIP(Reader);
553 if ( ASDCP_SUCCESS(result) )
555 result = m_RIP.InitFromFile(Reader);
557 if ( ASDCP_FAILURE(result) )
559 DefaultLogSink().Error("File contains no RIP\n");
568 if ( ASDCP_SUCCESS(result) )
569 result = Reader.Seek(0);
571 if ( ASDCP_SUCCESS(result) )
572 result = Partition::InitFromFile(Reader); // test UL and OP
574 // slurp up the remainder of the header
577 if ( ASDCP_SUCCESS(result) )
579 ui64_t here = Reader.Tell();
580 ui32_t buf_len = HeaderByteCount;
581 result = m_Buffer.Capacity(buf_len);
584 if ( ASDCP_SUCCESS(result) )
585 result = Reader.Read(m_Buffer.Data(), m_Buffer.Capacity(), &read_count);
587 if ( ASDCP_SUCCESS(result) && read_count != m_Buffer.Capacity() )
589 DefaultLogSink().Error("Short read of OP-Atom header metadata; wanted %lu, got %lu\n",
590 m_Buffer.Capacity(), read_count);
594 const byte_t* p = m_Buffer.RoData();
595 const byte_t* end_p = p + m_Buffer.Capacity();
597 while ( ASDCP_SUCCESS(result) && p < end_p )
599 // parse the packets and index them by uid, discard KLVFill items
600 InterchangeObject* object = CreateObject(p);
603 object->m_Lookup = &m_Primer;
604 result = object->InitFromBuffer(p, end_p - p);
605 const byte_t* redo_p = p;
606 p += object->PacketLength();
607 // hexdump(p, object->PacketLength());
609 if ( ASDCP_SUCCESS(result) )
611 if ( object->IsA(s_MDD_Table[MDDindex_KLVFill].ul) )
615 else if ( object->IsA(s_MDD_Table[MDDindex_Primer].ul) )
618 result = m_Primer.InitFromBuffer(redo_p, end_p - redo_p);
620 else if ( object->IsA(s_MDD_Table[MDDindex_Preface].ul) )
626 m_PacketList->AddPacket(object);
631 DefaultLogSink().Error("Error initializing packet\n");
641 ASDCP::MXF::OPAtomHeader::GetMDObjectByType(const byte_t* ObjectID, InterchangeObject** Object)
643 InterchangeObject* TmpObject;
648 return m_PacketList->GetMDObjectByType(ObjectID, Object);
651 ASDCP::MXF::Identification*
652 ASDCP::MXF::OPAtomHeader::GetIdentification()
654 InterchangeObject* Object;
656 if ( ASDCP_SUCCESS(GetMDObjectByType(OBJ_TYPE_ARGS(Identification), &Object)) )
657 return (Identification*)Object;
664 ASDCP::MXF::OPAtomHeader::WriteToFile(ASDCP::FileWriter& Writer, ui32_t HeaderSize)
666 if ( HeaderSize < 4096 )
668 DefaultLogSink().Error("HeaderSize %lu is too small. Must be >= 4096\n");
672 ASDCP::FrameBuffer HeaderBuffer;
674 Result_t result = HeaderBuffer.Capacity(HeaderSize);
675 HeaderByteCount = HeaderSize;
677 if ( ASDCP_SUCCESS(result) )
680 m_Preface->m_Lookup = &m_Primer;
681 result = m_Preface->WriteToBuffer(HeaderBuffer);
684 std::list<InterchangeObject*>::iterator pl_i = m_PacketList->m_List.begin();
685 for ( ; pl_i != m_PacketList->m_List.end() && ASDCP_SUCCESS(result); pl_i++ )
687 InterchangeObject* object = *pl_i;
688 object->m_Lookup = &m_Primer;
689 result = object->WriteToBuffer(HeaderBuffer);
692 if ( ASDCP_SUCCESS(result) )
693 result = Partition::WriteToFile(Writer);
695 // if ( ASDCP_SUCCESS(result) )
696 // result = m_Primer.WriteToFile(Writer);
698 if ( ASDCP_SUCCESS(result) )
701 Writer.Write(HeaderBuffer.RoData(), HeaderBuffer.Size(), &write_count);
702 assert(write_count == HeaderBuffer.Size());
706 if ( ASDCP_SUCCESS(result) )
708 ASDCP::fpos_t pos = Writer.Tell();
710 if ( pos > HeaderSize )
712 char intbuf[IntBufferLen];
713 DefaultLogSink().Error("Header size %s exceeds specified value %lu\n",
719 ASDCP::FrameBuffer NilBuf;
720 ui32_t klv_fill_length = HeaderSize - (ui32_t)pos;
722 if ( klv_fill_length < kl_length )
724 DefaultLogSink().Error("Remaining region too small for KLV Fill header\n");
728 klv_fill_length -= kl_length;
729 result = WriteKLToFile(Writer, s_MDD_Table[MDDindex_KLVFill].ul, klv_fill_length);
731 if ( ASDCP_SUCCESS(result) )
732 result = NilBuf.Capacity(klv_fill_length);
734 if ( ASDCP_SUCCESS(result) )
736 memset(NilBuf.Data(), 0, klv_fill_length);
738 Writer.Write(NilBuf.RoData(), klv_fill_length, &write_count);
739 assert(write_count == klv_fill_length);
748 ASDCP::MXF::OPAtomHeader::Dump(FILE* stream)
756 Partition::Dump(stream);
757 m_Primer.Dump(stream);
759 m_Preface->Dump(stream);
761 std::list<InterchangeObject*>::iterator i = m_PacketList->m_List.begin();
762 for ( ; i != m_PacketList->m_List.end(); i++ )
766 //------------------------------------------------------------------------------------------
769 ASDCP::MXF::OPAtomIndexFooter::OPAtomIndexFooter() : m_Lookup(0)
771 m_PacketList = new h__PacketList;
775 ASDCP::MXF::OPAtomIndexFooter::~OPAtomIndexFooter()
781 ASDCP::MXF::OPAtomIndexFooter::InitFromFile(const ASDCP::FileReader& Reader)
783 Result_t result = Partition::InitFromFile(Reader); // test UL and OP
785 // slurp up the remainder of the footer
788 if ( ASDCP_SUCCESS(result) )
789 result = m_Buffer.Capacity(IndexByteCount);
791 if ( ASDCP_SUCCESS(result) )
792 result = Reader.Read(m_Buffer.Data(), m_Buffer.Capacity(), &read_count);
794 if ( ASDCP_SUCCESS(result) && read_count != m_Buffer.Capacity() )
796 DefaultLogSink().Error("Short read of footer partition: got %lu, expecting %lu\n",
797 read_count, m_Buffer.Capacity());
801 const byte_t* p = m_Buffer.RoData();
802 const byte_t* end_p = p + m_Buffer.Capacity();
804 while ( ASDCP_SUCCESS(result) && p < end_p )
806 // parse the packets and index them by uid, discard KLVFill items
807 InterchangeObject* object = CreateObject(p);
810 object->m_Lookup = m_Lookup;
811 result = object->InitFromBuffer(p, end_p - p);
812 p += object->PacketLength();
814 if ( ASDCP_SUCCESS(result) )
816 m_PacketList->AddPacket(object);
820 DefaultLogSink().Error("Error initializing packet\n");
825 if ( ASDCP_FAILURE(result) )
826 DefaultLogSink().Error("Failed to initialize OPAtomIndexFooter\n");
833 ASDCP::MXF::OPAtomIndexFooter::WriteToFile(ASDCP::FileWriter& Writer)
835 Result_t result = WriteKLToFile(Writer, s_MDD_Table[MDDindex_CompleteFooter].ul, 0);
841 ASDCP::MXF::OPAtomIndexFooter::Dump(FILE* stream)
846 Partition::Dump(stream);
848 std::list<InterchangeObject*>::iterator i = m_PacketList->m_List.begin();
849 for ( ; i != m_PacketList->m_List.end(); i++ )
855 ASDCP::MXF::OPAtomIndexFooter::Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry& Entry)
857 std::list<InterchangeObject*>::iterator li;
858 for ( li = m_PacketList->m_List.begin(); li != m_PacketList->m_List.end(); li++ )
860 if ( (*li)->IsA(OBJ_TYPE_ARGS(IndexTableSegment)) )
862 IndexTableSegment* Segment = (IndexTableSegment*)(*li);
863 ui64_t start_pos = Segment->IndexStartPosition;
865 if ( Segment->EditUnitByteCount > 0 )
867 if ( m_PacketList->m_List.size() > 1 )
868 DefaultLogSink().Error("Unexpected multiple IndexTableSegment in CBR file\n");
870 if ( ! Segment->IndexEntryArray.empty() )
871 DefaultLogSink().Error("Unexpected IndexEntryArray contents in CBR file\n");
873 Entry.StreamOffset = (ui64_t)frame_num * Segment->EditUnitByteCount;
876 else if ( (ui64_t)frame_num >= start_pos
877 && (ui64_t)frame_num < (start_pos + Segment->IndexDuration) )
879 Entry = Segment->IndexEntryArray[frame_num];
889 //------------------------------------------------------------------------------------------
894 ASDCP::MXF::InterchangeObject::WriteToBuffer(ASDCP::FrameBuffer& Buffer)
896 if ( Buffer.Capacity() < (Buffer.Size() + m_KLLength + m_ValueLength) )
898 DefaultLogSink().Error("InterchangeObject::WriteToBuffer: Buffer too small\n");
900 return RESULT_READFAIL;
903 Result_t result = WriteKLToBuffer(Buffer, m_KeyStart, m_ValueLength);
905 if ( ASDCP_SUCCESS(result) )
907 memcpy(Buffer.Data() + Buffer.Size(), m_ValueStart, m_ValueLength);
908 Buffer.Size(Buffer.Size() + m_ValueLength);
916 ASDCP::MXF::InterchangeObject::IsA(const byte_t* label)
918 if ( m_KLLength == 0 )
921 return ( memcmp(label, m_KeyStart, SMPTE_UL_LENGTH) == 0 );
925 //------------------------------------------------------------------------------------------
939 FLT_TimecodeComponent,
941 FLT_WaveAudioDescriptor,
942 FLT_GenericPictureEssenceDescriptor,
943 FLT_MPEG2VideoDescriptor,
944 FLT_RGBAEssenceDescriptor,
945 FLT_JPEG2000PictureSubDescriptor,
946 FLT_IndexTableSegment,
947 FLT_CryptographicFramework,
948 FLT_CryptographicContext
952 typedef std::map<ASDCP::UL, FLT_t> FactoryList;
953 #define SETUP_IDX(t) const ui32_t FLT_##t = v;
955 static FactoryList s_FactoryList;
956 #define SETUP_FACTORY(t) s_FactoryList.insert(FactoryList::value_type(s_MDD_Table[MDDindex_##t].ul, FLT_##t));
957 #define CASE_FACTORY(t) case FLT_##t: return new t
960 ASDCP::MXF::InterchangeObject*
961 ASDCP::MXF::CreateObject(const byte_t* label)
966 if ( s_FactoryList.empty() )
968 SETUP_FACTORY(Preface);
969 SETUP_FACTORY(Identification);
970 SETUP_FACTORY(ContentStorage);
971 SETUP_FACTORY(MaterialPackage);
972 SETUP_FACTORY(SourcePackage);
973 SETUP_FACTORY(Track);
974 SETUP_FACTORY(Sequence);
975 SETUP_FACTORY(SourceClip);
976 SETUP_FACTORY(TimecodeComponent);
977 SETUP_FACTORY(FileDescriptor);
978 SETUP_FACTORY(WaveAudioDescriptor);
979 SETUP_FACTORY(GenericPictureEssenceDescriptor);
980 SETUP_FACTORY(MPEG2VideoDescriptor);
981 SETUP_FACTORY(RGBAEssenceDescriptor);
982 SETUP_FACTORY(JPEG2000PictureSubDescriptor);
983 SETUP_FACTORY(IndexTableSegment);
984 SETUP_FACTORY(CryptographicFramework);
985 SETUP_FACTORY(CryptographicContext);
988 FactoryList::iterator i = s_FactoryList.find(label);
990 if ( i == s_FactoryList.end() )
991 return new InterchangeObject;
995 CASE_FACTORY(Preface);
996 CASE_FACTORY(Identification);
997 CASE_FACTORY(ContentStorage);
998 CASE_FACTORY(MaterialPackage);
999 CASE_FACTORY(SourcePackage);
1000 CASE_FACTORY(Track);
1001 CASE_FACTORY(Sequence);
1002 CASE_FACTORY(SourceClip);
1003 CASE_FACTORY(TimecodeComponent);
1004 CASE_FACTORY(FileDescriptor);
1005 CASE_FACTORY(WaveAudioDescriptor);
1006 CASE_FACTORY(GenericPictureEssenceDescriptor);
1007 CASE_FACTORY(MPEG2VideoDescriptor);
1008 CASE_FACTORY(RGBAEssenceDescriptor);
1009 CASE_FACTORY(JPEG2000PictureSubDescriptor);
1010 CASE_FACTORY(IndexTableSegment);
1011 CASE_FACTORY(CryptographicFramework);
1012 CASE_FACTORY(CryptographicContext);
1015 return new InterchangeObject;