mega datetime patch
[asdcplib.git] / src / MXF.h
1 /*
2 Copyright (c) 2005-2012, John Hurst
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
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.
15
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.
26 */
27 /*! \file    MXF.h
28     \version $Id$
29     \brief   MXF objects
30 */
31
32 #ifndef _MXF_H_
33 #define _MXF_H_
34
35 #include "MXFTypes.h"
36
37 namespace ASDCP
38 {
39   namespace MXF
40     {
41       class InterchangeObject;
42
43       //
44       typedef ASDCP::MXF::InterchangeObject* (*MXFObjectFactory_t)(const Dictionary*&);
45
46       //
47       void SetObjectFactory(UL label, MXFObjectFactory_t factory);
48
49       //
50       InterchangeObject* CreateObject(const Dictionary*& Dict, const UL& label);
51
52
53       // seek an open file handle to the start of the RIP KLV packet
54       Result_t SeekToRIP(const Kumu::FileReader&);
55       
56       //
57       class RIP : public ASDCP::KLVFilePacket
58         {
59           ASDCP_NO_COPY_CONSTRUCT(RIP);
60           RIP();
61
62         public:
63           //
64           class Pair : public Kumu::IArchive
65             {
66             public:
67               ui32_t BodySID;
68               ui64_t ByteOffset;
69
70               Pair() : BodySID(0), ByteOffset(0) {}
71               Pair(ui32_t sid, ui64_t offset) : BodySID(sid), ByteOffset(offset) {}
72               virtual ~Pair() {}
73
74               ui32_t Size() { return sizeof(ui32_t) + sizeof(ui64_t); }
75
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());
79                 return str_buf;
80               }
81
82               inline bool HasValue() const { return true; }
83               inline ui32_t ArchiveLength() const { return sizeof(ui32_t) + sizeof(ui64_t); }
84
85               inline bool Unarchive(Kumu::MemIOReader* Reader) {
86                 if ( ! Reader->ReadUi32BE(&BodySID) ) return false;
87                 if ( ! Reader->ReadUi64BE(&ByteOffset) ) return false;
88                 return true;
89               }
90               
91               inline bool Archive(Kumu::MemIOWriter* Writer) const {
92                 if ( ! Writer->WriteUi32BE(BodySID) ) return false;
93                 if ( ! Writer->WriteUi64BE(ByteOffset) ) return false;
94                 return true;
95               }
96             };
97
98           const Dictionary*& m_Dict;
99           Array<Pair> PairArray;
100
101         RIP(const Dictionary*& d) : m_Dict(d) {}
102           virtual ~RIP() {}
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);
107         };
108
109
110       //
111       class Partition : public ASDCP::KLVFilePacket
112         {
113           ASDCP_NO_COPY_CONSTRUCT(Partition);
114           Partition();
115
116         protected:
117           class h__PacketList;
118           mem_ptr<h__PacketList> m_PacketList;
119
120         public:
121           const Dictionary*& m_Dict;
122
123           ui16_t    MajorVersion;
124           ui16_t    MinorVersion;
125           ui32_t    KAGSize;
126           ui64_t    ThisPartition;
127           ui64_t    PreviousPartition;
128           ui64_t    FooterPartition;
129           ui64_t    HeaderByteCount;
130           ui64_t    IndexByteCount;
131           ui32_t    IndexSID;
132           ui64_t    BodyOffset;
133           ui32_t    BodySID;
134           UL        OperationalPattern;
135           Batch<UL> EssenceContainers;
136
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);
145         };
146
147
148       //
149       class Primer : public ASDCP::KLVFilePacket, public ASDCP::IPrimerLookup
150         {
151           class h__PrimerLookup;
152           mem_ptr<h__PrimerLookup> m_Lookup;
153           ui8_t   m_LocalTag;
154           ASDCP_NO_COPY_CONSTRUCT(Primer);
155           Primer();
156
157         public:
158           //
159         class LocalTagEntry : Kumu::IArchive
160             {
161             public:
162               TagValue    Tag;
163               ASDCP::UL   UL;
164
165               LocalTagEntry() { Tag.a = Tag.b = 0; }
166             LocalTagEntry(const TagValue& tag, ASDCP::UL& ul) : Tag(tag), UL(ul) {}
167
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));
171                 return str_buf;
172               }
173
174               inline bool HasValue() const { return UL.HasValue(); }
175               inline ui32_t ArchiveLength() const { return 2 + UL.ArchiveLength(); }
176
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);
181               }
182
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);
187               }
188             };
189
190           Batch<LocalTagEntry> LocalTagEntryBatch;
191           const Dictionary*& m_Dict;
192
193           Primer(const Dictionary*&);
194           virtual ~Primer();
195
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);
199
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);
204         };
205
206
207       //
208       class InterchangeObject : public ASDCP::KLVPacket
209         {
210           InterchangeObject();
211
212         public:
213           const Dictionary*& m_Dict;
214           IPrimerLookup* m_Lookup;
215           UUID           InstanceUID;
216           UUID           GenerationUID;
217
218         InterchangeObject(const Dictionary*& d) : m_Dict(d), m_Lookup(0) {}
219           virtual ~InterchangeObject() {}
220
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);
229         };
230
231       //
232       class Preface : public InterchangeObject
233         {
234           ASDCP_NO_COPY_CONSTRUCT(Preface);
235           Preface();
236
237         public:
238           const Dictionary*& m_Dict;
239           Kumu::Timestamp    LastModifiedDate;
240           ui16_t       Version;
241           ui32_t       ObjectModelVersion;
242           UUID         PrimaryPackage;
243           Batch<UUID>  Identifications;
244           UUID         ContentStorage;
245           UL           OperationalPattern;
246           Batch<UL>    EssenceContainers;
247           Batch<UL>    DMSchemes;
248
249           Preface(const Dictionary*& d);
250           virtual ~Preface() {}
251
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);
258         };
259
260       const ui32_t MaxIndexSegmentSize = 65536;
261
262       //
263       class IndexTableSegment : public InterchangeObject
264         {
265           ASDCP_NO_COPY_CONSTRUCT(IndexTableSegment);
266
267         public:
268           //
269         class DeltaEntry : public Kumu::IArchive
270             {
271             public:
272               i8_t    PosTableIndex;
273               ui8_t   Slice;
274               ui32_t  ElementData;
275
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;
283             };
284
285           //
286           class IndexEntry : public Kumu::IArchive
287             {
288             public:
289               i8_t               TemporalOffset;
290               i8_t               KeyFrameOffset;
291               ui8_t              Flags;
292               ui64_t             StreamOffset;
293
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;
298
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;
307             };
308
309           const Dictionary*& m_Dict;
310
311           Rational    IndexEditRate;
312           ui64_t      IndexStartPosition;
313           ui64_t      IndexDuration;
314           ui32_t      EditUnitByteCount;
315           ui32_t      IndexSID;
316           ui32_t      BodySID;
317           ui8_t       SliceCount;
318           ui8_t       PosTableCount;
319           Batch<DeltaEntry> DeltaEntryArray;
320           Batch<IndexEntry> IndexEntryArray;
321
322           IndexTableSegment(const Dictionary*&);
323           virtual ~IndexTableSegment();
324
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);
331         };
332
333       //---------------------------------------------------------------------------------
334       //
335       class Identification;
336       class SourcePackage;
337
338       //
339       class OPAtomHeader : public Partition
340         {
341           ASDCP_NO_COPY_CONSTRUCT(OPAtomHeader);
342           OPAtomHeader();
343
344         public:
345           const Dictionary*&   m_Dict;
346           ASDCP::MXF::RIP     m_RIP;
347           ASDCP::MXF::Primer  m_Primer;
348           Preface*            m_Preface;
349           ASDCP::FrameBuffer  m_Buffer;
350           bool                m_HasRIP;
351
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           Identification*  GetIdentification();
363           SourcePackage*   GetSourcePackage();
364         };
365
366       //
367       class OPAtomIndexFooter : public Partition
368         {
369           IndexTableSegment*  m_CurrentSegment;
370           ASDCP::FrameBuffer  m_Buffer;
371           ui32_t              m_BytesPerEditUnit;
372           Rational            m_EditRate;
373           ui32_t              m_BodySID;
374
375           ASDCP_NO_COPY_CONSTRUCT(OPAtomIndexFooter);
376           OPAtomIndexFooter();
377
378         public:
379           const Dictionary*&   m_Dict;
380           Kumu::fpos_t        m_ECOffset;
381           IPrimerLookup*      m_Lookup;
382          
383           OPAtomIndexFooter(const Dictionary*&);
384           virtual ~OPAtomIndexFooter();
385           virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
386           virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
387           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
388           virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui64_t duration);
389           virtual void     Dump(FILE* = 0);
390
391           virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&) const;
392           virtual void     PushIndexEntry(const IndexTableSegment::IndexEntry&);
393           virtual void     SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate);
394           virtual void     SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset);
395         };
396
397     } // namespace MXF
398 } // namespace ASDCP
399
400
401 #endif // _MXF_H_
402
403 //
404 // end MXF.h
405 //