2 Copyright (c) 2005-2012, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 class InterchangeObject;
43 const ui32_t kl_length = ASDCP::SMPTE_UL_LENGTH + ASDCP::MXF_BER_LENGTH;
46 typedef ASDCP::MXF::InterchangeObject* (*MXFObjectFactory_t)(const Dictionary*&);
49 void SetObjectFactory(UL label, MXFObjectFactory_t factory);
52 InterchangeObject* CreateObject(const Dictionary*& Dict, const UL& label);
55 // seek an open file handle to the start of the RIP KLV packet
56 Result_t SeekToRIP(const Kumu::FileReader&);
59 class RIP : public ASDCP::KLVFilePacket
61 ASDCP_NO_COPY_CONSTRUCT(RIP);
66 class Pair : public Kumu::IArchive
72 Pair() : BodySID(0), ByteOffset(0) {}
73 Pair(ui32_t sid, ui64_t offset) : BodySID(sid), ByteOffset(offset) {}
76 ui32_t Size() { return sizeof(ui32_t) + sizeof(ui64_t); }
78 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
79 Kumu::ui64Printer offset_str(ByteOffset);
80 snprintf(str_buf, buf_len, "%-6u: %s", BodySID, offset_str.c_str());
84 inline bool HasValue() const { return true; }
85 inline ui32_t ArchiveLength() const { return sizeof(ui32_t) + sizeof(ui64_t); }
87 inline bool Unarchive(Kumu::MemIOReader* Reader) {
88 if ( ! Reader->ReadUi32BE(&BodySID) ) return false;
89 if ( ! Reader->ReadUi64BE(&ByteOffset) ) return false;
93 inline bool Archive(Kumu::MemIOWriter* Writer) const {
94 if ( ! Writer->WriteUi32BE(BodySID) ) return false;
95 if ( ! Writer->WriteUi64BE(ByteOffset) ) return false;
100 const Dictionary*& m_Dict;
101 Array<Pair> PairArray;
103 RIP(const Dictionary*& d) : m_Dict(d) {}
105 virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
106 virtual Result_t WriteToFile(Kumu::FileWriter& Writer);
107 virtual Result_t GetPairBySID(ui32_t, Pair&) const;
108 virtual void Dump(FILE* = 0);
113 class Partition : public ASDCP::KLVFilePacket
115 ASDCP_NO_COPY_CONSTRUCT(Partition);
122 std::list<InterchangeObject*> m_List;
123 std::map<UUID, InterchangeObject*> m_Map;
126 void AddPacket(InterchangeObject* ThePacket); // takes ownership
127 Result_t GetMDObjectByID(const UUID& ObjectID, InterchangeObject** Object);
128 Result_t GetMDObjectByType(const byte_t* ObjectID, InterchangeObject** Object);
129 Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList);
132 mem_ptr<PacketList> m_PacketList;
135 const Dictionary*& m_Dict;
140 ui64_t ThisPartition;
141 ui64_t PreviousPartition;
142 ui64_t FooterPartition;
143 ui64_t HeaderByteCount;
144 ui64_t IndexByteCount;
148 UL OperationalPattern;
149 Batch<UL> EssenceContainers;
151 Partition(const Dictionary*&);
152 virtual ~Partition();
153 virtual void AddChildObject(InterchangeObject*); // takes ownership
154 virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
155 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
156 virtual Result_t WriteToFile(Kumu::FileWriter& Writer, UL& PartitionLabel);
157 virtual ui32_t ArchiveSize(); // returns the size of the archived structure
158 virtual void Dump(FILE* = 0);
163 class Primer : public ASDCP::KLVFilePacket, public ASDCP::IPrimerLookup
165 class h__PrimerLookup;
166 mem_ptr<h__PrimerLookup> m_Lookup;
168 ASDCP_NO_COPY_CONSTRUCT(Primer);
173 class LocalTagEntry : Kumu::IArchive
179 LocalTagEntry() { Tag.a = Tag.b = 0; }
180 LocalTagEntry(const TagValue& tag, ASDCP::UL& ul) : Tag(tag), UL(ul) {}
182 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
183 snprintf(str_buf, buf_len, "%02x %02x: ", Tag.a, Tag.b);
184 UL.EncodeString(str_buf + strlen(str_buf), buf_len - strlen(str_buf));
188 inline bool HasValue() const { return UL.HasValue(); }
189 inline ui32_t ArchiveLength() const { return 2 + UL.ArchiveLength(); }
191 inline bool Unarchive(Kumu::MemIOReader* Reader) {
192 if ( ! Reader->ReadUi8(&Tag.a) ) return false;
193 if ( ! Reader->ReadUi8(&Tag.b) ) return false;
194 return UL.Unarchive(Reader);
197 inline bool Archive(Kumu::MemIOWriter* Writer) const {
198 if ( ! Writer->WriteUi8(Tag.a) ) return false;
199 if ( ! Writer->WriteUi8(Tag.b) ) return false;
200 return UL.Archive(Writer);
204 Batch<LocalTagEntry> LocalTagEntryBatch;
205 const Dictionary*& m_Dict;
207 Primer(const Dictionary*&);
210 virtual void ClearTagList();
211 virtual Result_t InsertTag(const MDDEntry& Entry, ASDCP::TagValue& Tag);
212 virtual Result_t TagForKey(const ASDCP::UL& Key, ASDCP::TagValue& Tag);
214 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
215 virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
216 virtual Result_t WriteToFile(Kumu::FileWriter& Writer);
217 virtual void Dump(FILE* = 0);
222 class InterchangeObject : public ASDCP::KLVPacket
227 const Dictionary*& m_Dict;
228 IPrimerLookup* m_Lookup;
232 InterchangeObject(const Dictionary*& d) : m_Dict(d), m_Lookup(0) {}
233 virtual ~InterchangeObject() {}
235 virtual void Copy(const InterchangeObject& rhs);
236 virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
237 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
238 virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
239 virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
240 virtual bool IsA(const byte_t* label);
241 virtual const char* ObjectName() { return "InterchangeObject"; }
242 virtual void Dump(FILE* stream = 0);
246 class Preface : public InterchangeObject
248 ASDCP_NO_COPY_CONSTRUCT(Preface);
252 const Dictionary*& m_Dict;
253 Kumu::Timestamp LastModifiedDate;
255 ui32_t ObjectModelVersion;
257 Batch<UUID> Identifications;
259 UL OperationalPattern;
260 Batch<UL> EssenceContainers;
263 Preface(const Dictionary*& d);
264 virtual ~Preface() {}
266 virtual void Copy(const Preface& rhs);
267 virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
268 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
269 virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
270 virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
271 virtual void Dump(FILE* = 0);
274 const ui32_t MaxIndexSegmentSize = 65536;
277 class IndexTableSegment : public InterchangeObject
279 ASDCP_NO_COPY_CONSTRUCT(IndexTableSegment);
283 class DeltaEntry : public Kumu::IArchive
290 DeltaEntry() : PosTableIndex(-1), Slice(0), ElementData(0) {}
291 DeltaEntry(i8_t pos, ui8_t slice, ui32_t data) : PosTableIndex(pos), Slice(slice), ElementData(data) {}
292 inline bool HasValue() const { return true; }
293 ui32_t ArchiveLength() const { return sizeof(ui32_t) + 2; }
294 bool Unarchive(Kumu::MemIOReader* Reader);
295 bool Archive(Kumu::MemIOWriter* Writer) const;
296 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
300 class IndexEntry : public Kumu::IArchive
308 // if you use these, you will need to change CBRIndexEntriesPerSegment in MXF.cpp
309 // to a more suitable value
310 // std::list<ui32_t> SliceOffset;
311 // Array<Rational> PosTable;
313 IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0), StreamOffset(0) {}
314 IndexEntry(i8_t t_ofst, i8_t k_ofst, ui8_t flags, ui64_t s_ofst) :
315 TemporalOffset(t_ofst), KeyFrameOffset(k_ofst), Flags(flags), StreamOffset(s_ofst) {}
316 inline bool HasValue() const { return true; }
317 ui32_t ArchiveLength() const { return sizeof(ui64_t) + 3; };
318 bool Unarchive(Kumu::MemIOReader* Reader);
319 bool Archive(Kumu::MemIOWriter* Writer) const;
320 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
323 const Dictionary*& m_Dict;
325 Rational IndexEditRate;
326 ui64_t IndexStartPosition;
327 ui64_t IndexDuration;
328 ui32_t EditUnitByteCount;
333 Batch<DeltaEntry> DeltaEntryArray;
334 Batch<IndexEntry> IndexEntryArray;
336 IndexTableSegment(const Dictionary*&);
337 virtual ~IndexTableSegment();
339 virtual void Copy(const IndexTableSegment& rhs);
340 virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
341 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
342 virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
343 virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
344 virtual void Dump(FILE* = 0);
347 //---------------------------------------------------------------------------------
349 class Identification;
353 class OPAtomHeader : public Partition
355 ASDCP_NO_COPY_CONSTRUCT(OPAtomHeader);
359 const Dictionary*& m_Dict;
360 ASDCP::MXF::RIP m_RIP;
361 ASDCP::MXF::Primer m_Primer;
363 ASDCP::FrameBuffer m_Buffer;
366 OPAtomHeader(const Dictionary*&);
367 virtual ~OPAtomHeader();
368 virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
369 virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
370 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
371 virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui32_t HeaderLength = 16384);
372 virtual void Dump(FILE* = 0);
373 virtual Result_t GetMDObjectByID(const UUID&, InterchangeObject** = 0);
374 virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0);
375 virtual Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList);
376 virtual ASDCP::MXF::RIP& GetRIP();
377 Identification* GetIdentification();
378 SourcePackage* GetSourcePackage();
382 class OPAtomIndexFooter : public Partition
384 IndexTableSegment* m_CurrentSegment;
385 ASDCP::FrameBuffer m_Buffer;
386 ui32_t m_BytesPerEditUnit;
390 ASDCP_NO_COPY_CONSTRUCT(OPAtomIndexFooter);
394 const Dictionary*& m_Dict;
395 Kumu::fpos_t m_ECOffset;
396 IPrimerLookup* m_Lookup;
398 OPAtomIndexFooter(const Dictionary*&);
399 virtual ~OPAtomIndexFooter();
400 virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
401 virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
402 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
403 virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui64_t duration);
404 virtual void Dump(FILE* = 0);
406 virtual Result_t GetMDObjectByID(const UUID&, InterchangeObject** = 0);
407 virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0);
408 virtual Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList);
410 virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&) const;
411 virtual void PushIndexEntry(const IndexTableSegment::IndexEntry&);
412 virtual void SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate);
413 virtual void SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset);