megachanges
[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               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));
168                 return str_buf;
169               }
170
171               inline bool HasValue() const { return UL.HasValue(); }
172               inline ui32_t ArchiveLength() const { return 2 + UL.ArchiveLength(); }
173
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);
178               }
179
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);
184               }
185             };
186
187           Batch<LocalTagEntry> LocalTagEntryBatch;
188           const Dictionary*& m_Dict;
189
190           Primer(const Dictionary*&);
191           virtual ~Primer();
192
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);
196
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);
201         };
202
203
204       //
205       class InterchangeObject : public ASDCP::KLVPacket
206         {
207           InterchangeObject();
208
209         public:
210           const Dictionary*& m_Dict;
211           IPrimerLookup* m_Lookup;
212           UUID           InstanceUID;
213           UUID           GenerationUID;
214
215         InterchangeObject(const Dictionary*& d) : m_Dict(d), m_Lookup(0) {}
216           virtual ~InterchangeObject() {}
217
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);
226         };
227
228       //
229       class Preface : public InterchangeObject
230         {
231           ASDCP_NO_COPY_CONSTRUCT(Preface);
232           Preface();
233
234         public:
235           const Dictionary*& m_Dict;
236           ////    UUID         GenerationUID;
237           Timestamp    LastModifiedDate;
238           ui16_t       Version;
239           ui32_t       ObjectModelVersion;
240           UUID         PrimaryPackage;
241           Batch<UUID>  Identifications;
242           UUID         ContentStorage;
243           UL           OperationalPattern;
244           Batch<UL>    EssenceContainers;
245           Batch<UL>    DMSchemes;
246
247           Preface(const Dictionary*& d);
248           virtual ~Preface() {}
249
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);
256         };
257
258       const ui32_t MaxIndexSegmentSize = 65536;
259
260       //
261       class IndexTableSegment : public InterchangeObject
262         {
263           ASDCP_NO_COPY_CONSTRUCT(IndexTableSegment);
264
265         public:
266           //
267         class DeltaEntry : public Kumu::IArchive
268             {
269             public:
270               i8_t    PosTableIndex;
271               ui8_t   Slice;
272               ui32_t  ElementData;
273
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;
280             };
281
282           //
283           class IndexEntry : public Kumu::IArchive
284             {
285             public:
286               i8_t               TemporalOffset;
287               i8_t               KeyFrameOffset;
288               ui8_t              Flags;
289               ui64_t             StreamOffset;
290
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;
295
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;
302             };
303
304           const Dictionary*& m_Dict;
305
306           Rational    IndexEditRate;
307           ui64_t      IndexStartPosition;
308           ui64_t      IndexDuration;
309           ui32_t      EditUnitByteCount;
310           ui32_t      IndexSID;
311           ui32_t      BodySID;
312           ui8_t       SliceCount;
313           ui8_t       PosTableCount;
314           Batch<DeltaEntry> DeltaEntryArray;
315           Batch<IndexEntry> IndexEntryArray;
316
317           IndexTableSegment(const Dictionary*&);
318           virtual ~IndexTableSegment();
319
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);
326         };
327
328       //---------------------------------------------------------------------------------
329       //
330       class Identification;
331       class SourcePackage;
332
333       //
334       class OPAtomHeader : public Partition
335         {
336           ASDCP_NO_COPY_CONSTRUCT(OPAtomHeader);
337           OPAtomHeader();
338
339         public:
340           const Dictionary*&   m_Dict;
341           ASDCP::MXF::RIP     m_RIP;
342           ASDCP::MXF::Primer  m_Primer;
343           Preface*            m_Preface;
344           ASDCP::FrameBuffer  m_Buffer;
345           bool                m_HasRIP;
346
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();
359         };
360
361       //
362       class OPAtomIndexFooter : public Partition
363         {
364           IndexTableSegment*  m_CurrentSegment;
365           ASDCP::FrameBuffer  m_Buffer;
366           ui32_t              m_BytesPerEditUnit;
367           Rational            m_EditRate;
368           ui32_t              m_BodySID;
369
370           ASDCP_NO_COPY_CONSTRUCT(OPAtomIndexFooter);
371           OPAtomIndexFooter();
372
373         public:
374           const Dictionary*&   m_Dict;
375           Kumu::fpos_t        m_ECOffset;
376           IPrimerLookup*      m_Lookup;
377          
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);
385
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);
390         };
391
392     } // namespace MXF
393 } // namespace ASDCP
394
395
396 #endif // _MXF_H_
397
398 //
399 // end MXF.h
400 //