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;
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 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
166 snprintf(str_buf, buf_len, "%02x %02x: ", Tag.a, Tag.b);
167 UL.EncodeString(str_buf + strlen(str_buf), buf_len - strlen(str_buf));
171 inline bool HasValue() const { return UL.HasValue(); }
172 inline ui32_t ArchiveLength() const { return 2 + UL.ArchiveLength(); }
174 inline bool Unarchive(Kumu::MemIOReader* Reader) {
175 if ( ! Reader->ReadUi8(&Tag.a) ) return false;
176 if ( ! Reader->ReadUi8(&Tag.b) ) return false;
177 return UL.Unarchive(Reader);
180 inline bool Archive(Kumu::MemIOWriter* Writer) const {
181 if ( ! Writer->WriteUi8(Tag.a) ) return false;
182 if ( ! Writer->WriteUi8(Tag.b) ) return false;
183 return UL.Archive(Writer);
187 Batch<LocalTagEntry> LocalTagEntryBatch;
188 const Dictionary*& m_Dict;
190 Primer(const Dictionary*&);
193 virtual void ClearTagList();
194 virtual Result_t InsertTag(const MDDEntry& Entry, ASDCP::TagValue& Tag);
195 virtual Result_t TagForKey(const ASDCP::UL& Key, ASDCP::TagValue& Tag);
197 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
198 virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
199 virtual Result_t WriteToFile(Kumu::FileWriter& Writer);
200 virtual void Dump(FILE* = 0);
205 class InterchangeObject : public ASDCP::KLVPacket
210 const Dictionary*& m_Dict;
211 IPrimerLookup* m_Lookup;
215 InterchangeObject(const Dictionary*& d) : m_Dict(d), m_Lookup(0) {}
216 virtual ~InterchangeObject() {}
218 virtual void Copy(const InterchangeObject& rhs);
219 virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
220 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
221 virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
222 virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
223 virtual bool IsA(const byte_t* label);
224 virtual const char* ObjectName() { return "InterchangeObject"; }
225 virtual void Dump(FILE* stream = 0);
229 class Preface : public InterchangeObject
231 ASDCP_NO_COPY_CONSTRUCT(Preface);
235 const Dictionary*& m_Dict;
236 //// UUID GenerationUID;
237 Timestamp LastModifiedDate;
239 ui32_t ObjectModelVersion;
241 Batch<UUID> Identifications;
243 UL OperationalPattern;
244 Batch<UL> EssenceContainers;
247 Preface(const Dictionary*& d);
248 virtual ~Preface() {}
250 virtual void Copy(const Preface& rhs);
251 virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
252 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
253 virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
254 virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
255 virtual void Dump(FILE* = 0);
258 const ui32_t MaxIndexSegmentSize = 65536;
261 class IndexTableSegment : public InterchangeObject
263 ASDCP_NO_COPY_CONSTRUCT(IndexTableSegment);
267 class DeltaEntry : public Kumu::IArchive
274 DeltaEntry() : PosTableIndex(-1), Slice(0), ElementData(0) {}
275 inline bool HasValue() const { return true; }
276 ui32_t ArchiveLength() const { return sizeof(ui32_t) + 2; }
277 bool Unarchive(Kumu::MemIOReader* Reader);
278 bool Archive(Kumu::MemIOWriter* Writer) const;
279 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
283 class IndexEntry : public Kumu::IArchive
291 // if you use these, you will need to change CBRIndexEntriesPerSegment in MXF.cpp
292 // to a more suitable value
293 // std::list<ui32_t> SliceOffset;
294 // Array<Rational> PosTable;
296 IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0), StreamOffset() {}
297 inline bool HasValue() const { return true; }
298 ui32_t ArchiveLength() const { return sizeof(ui64_t) + 3; };
299 bool Unarchive(Kumu::MemIOReader* Reader);
300 bool Archive(Kumu::MemIOWriter* Writer) const;
301 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
304 const Dictionary*& m_Dict;
306 Rational IndexEditRate;
307 ui64_t IndexStartPosition;
308 ui64_t IndexDuration;
309 ui32_t EditUnitByteCount;
314 Batch<DeltaEntry> DeltaEntryArray;
315 Batch<IndexEntry> IndexEntryArray;
317 IndexTableSegment(const Dictionary*&);
318 virtual ~IndexTableSegment();
320 virtual void Copy(const IndexTableSegment& rhs);
321 virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
322 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
323 virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
324 virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
325 virtual void Dump(FILE* = 0);
328 //---------------------------------------------------------------------------------
330 class Identification;
334 class OPAtomHeader : public Partition
336 ASDCP_NO_COPY_CONSTRUCT(OPAtomHeader);
340 const Dictionary*& m_Dict;
341 ASDCP::MXF::RIP m_RIP;
342 ASDCP::MXF::Primer m_Primer;
344 ASDCP::FrameBuffer m_Buffer;
347 OPAtomHeader(const Dictionary*&);
348 virtual ~OPAtomHeader();
349 virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
350 virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
351 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
352 virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui32_t HeaderLength = 16384);
353 virtual void Dump(FILE* = 0);
354 virtual Result_t GetMDObjectByID(const UUID&, InterchangeObject** = 0);
355 virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0);
356 virtual Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList);
357 Identification* GetIdentification();
358 SourcePackage* GetSourcePackage();
362 class OPAtomIndexFooter : public Partition
364 IndexTableSegment* m_CurrentSegment;
365 ASDCP::FrameBuffer m_Buffer;
366 ui32_t m_BytesPerEditUnit;
370 ASDCP_NO_COPY_CONSTRUCT(OPAtomIndexFooter);
374 const Dictionary*& m_Dict;
375 Kumu::fpos_t m_ECOffset;
376 IPrimerLookup* m_Lookup;
378 OPAtomIndexFooter(const Dictionary*&);
379 virtual ~OPAtomIndexFooter();
380 virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
381 virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
382 virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
383 virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui64_t duration);
384 virtual void Dump(FILE* = 0);
386 virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&) const;
387 virtual void PushIndexEntry(const IndexTableSegment::IndexEntry&);
388 virtual void SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate);
389 virtual void SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset);