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.
28 \version $Id: MXF.h,v 1.42 2012/03/05 13:11:47 jhurst Exp $
41 class InterchangeObject;
44 typedef ASDCP::MXF::InterchangeObject* (*MXFObjectFactory_t)(const Dictionary*&);
47 void SetObjectFactory(UL label, MXFObjectFactory_t factory);
50 InterchangeObject* CreateObject(const Dictionary*& Dict, const UL& label);
53 // seek an open file handle to the start of the RIP KLV packet
54 Result_t SeekToRIP(const Kumu::FileReader&);
57 class RIP : public ASDCP::KLVFilePacket
59 ASDCP_NO_COPY_CONSTRUCT(RIP);
64 class Pair : public Kumu::IArchive
70 Pair() : BodySID(0), ByteOffset(0) {}
71 Pair(ui32_t sid, ui64_t offset) : BodySID(sid), ByteOffset(offset) {}
74 ui32_t Size() { return sizeof(ui32_t) + sizeof(ui64_t); }
76 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
77 Kumu::ui64Printer offset_str(ByteOffset);
78 snprintf(str_buf, buf_len, "%-6u: %s", BodySID, offset_str.c_str());
82 inline bool HasValue() const { return true; }
83 inline ui32_t ArchiveLength() const { return sizeof(ui32_t) + sizeof(ui64_t); }
85 inline bool Unarchive(Kumu::MemIOReader* Reader) {
86 if ( ! Reader->ReadUi32BE(&BodySID) ) return false;
87 if ( ! Reader->ReadUi64BE(&ByteOffset) ) return false;
91 inline bool Archive(Kumu::MemIOWriter* Writer) const {
92 if ( ! Writer->WriteUi32BE(BodySID) ) return false;
93 if ( ! Writer->WriteUi64BE(ByteOffset) ) return false;
98 const Dictionary*& m_Dict;
99 Array<Pair> PairArray;
101 RIP(const Dictionary*& d) : m_Dict(d) {}
103 virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
104 virtual Result_t WriteToFile(Kumu::FileWriter& Writer);
105 virtual Result_t GetPairBySID(ui32_t, Pair&) const;
106 virtual void Dump(FILE* = 0);
111 class Partition : public ASDCP::KLVFilePacket
113 ASDCP_NO_COPY_CONSTRUCT(Partition);
118 mem_ptr<h__PacketList> m_PacketList;
121 const Dictionary*& m_Dict;
126 ui64_t ThisPartition;
127 ui64_t PreviousPartition;
128 ui64_t FooterPartition;
129 ui64_t HeaderByteCount;
130 ui64_t IndexByteCount;
134 UL OperationalPattern;
135 Batch<UL> EssenceContainers;
137 Partition(const Dictionary*&);
138 virtual ~Partition();
139 virtual void AddChildObject(InterchangeObject*); // takes ownership
140 virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
141 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
142 virtual Result_t WriteToFile(Kumu::FileWriter& Writer, UL& PartitionLabel);
143 virtual ui32_t ArchiveSize(); // returns the size of the archived structure
144 virtual void Dump(FILE* = 0);
149 class Primer : public ASDCP::KLVFilePacket, public ASDCP::IPrimerLookup
151 class h__PrimerLookup;
152 mem_ptr<h__PrimerLookup> m_Lookup;
154 ASDCP_NO_COPY_CONSTRUCT(Primer);
159 class LocalTagEntry : Kumu::IArchive
165 LocalTagEntry() { Tag.a = Tag.b = 0; }
166 LocalTagEntry(const TagValue& tag, ASDCP::UL& ul) : Tag(tag), UL(ul) {}
168 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
169 snprintf(str_buf, buf_len, "%02x %02x: ", Tag.a, Tag.b);
170 UL.EncodeString(str_buf + strlen(str_buf), buf_len - strlen(str_buf));
174 inline bool HasValue() const { return UL.HasValue(); }
175 inline ui32_t ArchiveLength() const { return 2 + UL.ArchiveLength(); }
177 inline bool Unarchive(Kumu::MemIOReader* Reader) {
178 if ( ! Reader->ReadUi8(&Tag.a) ) return false;
179 if ( ! Reader->ReadUi8(&Tag.b) ) return false;
180 return UL.Unarchive(Reader);
183 inline bool Archive(Kumu::MemIOWriter* Writer) const {
184 if ( ! Writer->WriteUi8(Tag.a) ) return false;
185 if ( ! Writer->WriteUi8(Tag.b) ) return false;
186 return UL.Archive(Writer);
190 Batch<LocalTagEntry> LocalTagEntryBatch;
191 const Dictionary*& m_Dict;
193 Primer(const Dictionary*&);
196 virtual void ClearTagList();
197 virtual Result_t InsertTag(const MDDEntry& Entry, ASDCP::TagValue& Tag);
198 virtual Result_t TagForKey(const ASDCP::UL& Key, ASDCP::TagValue& Tag);
200 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
201 virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
202 virtual Result_t WriteToFile(Kumu::FileWriter& Writer);
203 virtual void Dump(FILE* = 0);
208 class InterchangeObject : public ASDCP::KLVPacket
213 const Dictionary*& m_Dict;
214 IPrimerLookup* m_Lookup;
218 InterchangeObject(const Dictionary*& d) : m_Dict(d), m_Lookup(0) {}
219 virtual ~InterchangeObject() {}
221 virtual void Copy(const InterchangeObject& rhs);
222 virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
223 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
224 virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
225 virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
226 virtual bool IsA(const byte_t* label);
227 virtual const char* ObjectName() { return "InterchangeObject"; }
228 virtual void Dump(FILE* stream = 0);
232 class Preface : public InterchangeObject
234 ASDCP_NO_COPY_CONSTRUCT(Preface);
238 const Dictionary*& m_Dict;
239 Kumu::Timestamp LastModifiedDate;
241 ui32_t ObjectModelVersion;
243 Batch<UUID> Identifications;
245 UL OperationalPattern;
246 Batch<UL> EssenceContainers;
249 Preface(const Dictionary*& d);
250 virtual ~Preface() {}
252 virtual void Copy(const Preface& rhs);
253 virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
254 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
255 virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
256 virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
257 virtual void Dump(FILE* = 0);
260 const ui32_t MaxIndexSegmentSize = 65536;
263 class IndexTableSegment : public InterchangeObject
265 ASDCP_NO_COPY_CONSTRUCT(IndexTableSegment);
269 class DeltaEntry : public Kumu::IArchive
276 DeltaEntry() : PosTableIndex(-1), Slice(0), ElementData(0) {}
277 DeltaEntry(i8_t pos, ui8_t slice, ui32_t data) : PosTableIndex(pos), Slice(slice), ElementData(data) {}
278 inline bool HasValue() const { return true; }
279 ui32_t ArchiveLength() const { return sizeof(ui32_t) + 2; }
280 bool Unarchive(Kumu::MemIOReader* Reader);
281 bool Archive(Kumu::MemIOWriter* Writer) const;
282 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
286 class IndexEntry : public Kumu::IArchive
294 // if you use these, you will need to change CBRIndexEntriesPerSegment in MXF.cpp
295 // to a more suitable value
296 // std::list<ui32_t> SliceOffset;
297 // Array<Rational> PosTable;
299 IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0), StreamOffset(0) {}
300 IndexEntry(i8_t t_ofst, i8_t k_ofst, ui8_t flags, ui64_t s_ofst) :
301 TemporalOffset(t_ofst), KeyFrameOffset(k_ofst), Flags(flags), StreamOffset(s_ofst) {}
302 inline bool HasValue() const { return true; }
303 ui32_t ArchiveLength() const { return sizeof(ui64_t) + 3; };
304 bool Unarchive(Kumu::MemIOReader* Reader);
305 bool Archive(Kumu::MemIOWriter* Writer) const;
306 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
309 const Dictionary*& m_Dict;
311 Rational IndexEditRate;
312 ui64_t IndexStartPosition;
313 ui64_t IndexDuration;
314 ui32_t EditUnitByteCount;
319 Batch<DeltaEntry> DeltaEntryArray;
320 Batch<IndexEntry> IndexEntryArray;
322 IndexTableSegment(const Dictionary*&);
323 virtual ~IndexTableSegment();
325 virtual void Copy(const IndexTableSegment& rhs);
326 virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
327 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
328 virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
329 virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
330 virtual void Dump(FILE* = 0);
333 //---------------------------------------------------------------------------------
335 class Identification;
339 class OPAtomHeader : public Partition
341 ASDCP_NO_COPY_CONSTRUCT(OPAtomHeader);
345 const Dictionary*& m_Dict;
346 ASDCP::MXF::RIP m_RIP;
347 ASDCP::MXF::Primer m_Primer;
349 ASDCP::FrameBuffer m_Buffer;
352 OPAtomHeader(const Dictionary*&);
353 virtual ~OPAtomHeader();
354 virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
355 virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
356 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
357 virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui32_t HeaderLength = 16384);
358 virtual void Dump(FILE* = 0);
359 virtual Result_t GetMDObjectByID(const UUID&, InterchangeObject** = 0);
360 virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0);
361 virtual Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList);
362 virtual ASDCP::MXF::RIP& GetRIP();
363 Identification* GetIdentification();
364 SourcePackage* GetSourcePackage();
368 class OPAtomIndexFooter : public Partition
370 IndexTableSegment* m_CurrentSegment;
371 ASDCP::FrameBuffer m_Buffer;
372 ui32_t m_BytesPerEditUnit;
376 ASDCP_NO_COPY_CONSTRUCT(OPAtomIndexFooter);
380 const Dictionary*& m_Dict;
381 Kumu::fpos_t m_ECOffset;
382 IPrimerLookup* m_Lookup;
384 OPAtomIndexFooter(const Dictionary*&);
385 virtual ~OPAtomIndexFooter();
386 virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
387 virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
388 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
389 virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui64_t duration);
390 virtual void Dump(FILE* = 0);
392 virtual Result_t GetMDObjectByID(const UUID&, InterchangeObject** = 0);
393 virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0);
394 virtual Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList);
396 virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&) const;
397 virtual void PushIndexEntry(const IndexTableSegment::IndexEntry&);
398 virtual void SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate);
399 virtual void SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset);