make way for MCA
[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         protected:
210           const MDDEntry* m_Typeinfo;
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_Typeinfo(0), m_Dict(d), m_Lookup(0) {}
219           virtual ~InterchangeObject() {}
220           virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
221           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
222           virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
223           virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
224           virtual bool     IsA(const byte_t* label);
225           virtual const char* ObjectName() { return "InterchangeObject"; }
226           virtual void     Dump(FILE* stream = 0);
227         };
228
229       //
230       class Preface : public InterchangeObject
231         {
232           ASDCP_NO_COPY_CONSTRUCT(Preface);
233           Preface();
234
235         public:
236           const Dictionary*& m_Dict;
237           UUID         GenerationUID;
238           Timestamp    LastModifiedDate;
239           ui16_t       Version;
240           ui32_t       ObjectModelVersion;
241           UUID         PrimaryPackage;
242           Batch<UUID>  Identifications;
243           UUID         ContentStorage;
244           UL           OperationalPattern;
245           Batch<UL>    EssenceContainers;
246           Batch<UL>    DMSchemes;
247
248         Preface(const Dictionary*& d) : InterchangeObject(d), m_Dict(d), Version(258), ObjectModelVersion(0) {}
249           virtual ~Preface() {}
250           virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
251           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
252           virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
253           virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
254           virtual void     Dump(FILE* = 0);
255         };
256
257       const ui32_t MaxIndexSegmentSize = 65536;
258
259       //
260       class IndexTableSegment : public InterchangeObject
261         {
262           ASDCP_NO_COPY_CONSTRUCT(IndexTableSegment);
263
264         public:
265           //
266         class DeltaEntry : public Kumu::IArchive
267             {
268             public:
269               i8_t    PosTableIndex;
270               ui8_t   Slice;
271               ui32_t  ElementData;
272
273               DeltaEntry() : PosTableIndex(-1), Slice(0), ElementData(0) {}
274               inline bool HasValue() const { return true; }
275               ui32_t      ArchiveLength() const { return sizeof(ui32_t) + 2; }
276               bool        Unarchive(Kumu::MemIOReader* Reader);
277               bool        Archive(Kumu::MemIOWriter* Writer) const;
278               const char* EncodeString(char* str_buf, ui32_t buf_len) const;
279             };
280
281           //
282           class IndexEntry : public Kumu::IArchive
283             {
284             public:
285               i8_t               TemporalOffset;
286               i8_t               KeyFrameOffset;
287               ui8_t              Flags;
288               ui64_t             StreamOffset;
289
290               // if you use these, you will need to change CBRIndexEntriesPerSegment in MXF.cpp
291               // to a more suitable value
292               //              std::list<ui32_t>  SliceOffset;
293               //              Array<Rational>    PosTable;
294
295               IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0), StreamOffset() {}
296               inline bool HasValue() const { return true; }
297               ui32_t      ArchiveLength() const { return sizeof(ui64_t) + 3; };
298               bool        Unarchive(Kumu::MemIOReader* Reader);
299               bool        Archive(Kumu::MemIOWriter* Writer) const;
300               const char* EncodeString(char* str_buf, ui32_t buf_len) const;
301             };
302
303           const Dictionary*& m_Dict;
304
305           Rational    IndexEditRate;
306           ui64_t      IndexStartPosition;
307           ui64_t      IndexDuration;
308           ui32_t      EditUnitByteCount;
309           ui32_t      IndexSID;
310           ui32_t      BodySID;
311           ui8_t       SliceCount;
312           ui8_t       PosTableCount;
313           Batch<DeltaEntry> DeltaEntryArray;
314           Batch<IndexEntry> IndexEntryArray;
315
316           IndexTableSegment(const Dictionary*&);
317           virtual ~IndexTableSegment();
318           virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
319           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
320           virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
321           virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
322           virtual void     Dump(FILE* = 0);
323         };
324
325       //---------------------------------------------------------------------------------
326       //
327       class Identification;
328       class SourcePackage;
329
330       //
331       class OPAtomHeader : public Partition
332         {
333           ASDCP_NO_COPY_CONSTRUCT(OPAtomHeader);
334           OPAtomHeader();
335
336         public:
337           const Dictionary*&   m_Dict;
338           ASDCP::MXF::RIP     m_RIP;
339           ASDCP::MXF::Primer  m_Primer;
340           Preface*            m_Preface;
341           ASDCP::FrameBuffer  m_Buffer;
342           bool                m_HasRIP;
343
344           OPAtomHeader(const Dictionary*&);
345           virtual ~OPAtomHeader();
346           virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
347           virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
348           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
349           virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui32_t HeaderLength = 16384);
350           virtual void     Dump(FILE* = 0);
351           virtual Result_t GetMDObjectByID(const UUID&, InterchangeObject** = 0);
352           virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0);
353           virtual Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList);
354           Identification*  GetIdentification();
355           SourcePackage*   GetSourcePackage();
356         };
357
358       //
359       class OPAtomIndexFooter : public Partition
360         {
361           IndexTableSegment*  m_CurrentSegment;
362           ASDCP::FrameBuffer  m_Buffer;
363           ui32_t              m_BytesPerEditUnit;
364           Rational            m_EditRate;
365           ui32_t              m_BodySID;
366
367           ASDCP_NO_COPY_CONSTRUCT(OPAtomIndexFooter);
368           OPAtomIndexFooter();
369
370         public:
371           const Dictionary*&   m_Dict;
372           Kumu::fpos_t        m_ECOffset;
373           IPrimerLookup*      m_Lookup;
374          
375           OPAtomIndexFooter(const Dictionary*&);
376           virtual ~OPAtomIndexFooter();
377           virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
378           virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
379           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
380           virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui64_t duration);
381           virtual void     Dump(FILE* = 0);
382
383           virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&) const;
384           virtual void     PushIndexEntry(const IndexTableSegment::IndexEntry&);
385           virtual void     SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate);
386           virtual void     SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset);
387         };
388
389     } // namespace MXF
390 } // namespace ASDCP
391
392
393 #endif // _MXF_H_
394
395 //
396 // end MXF.h
397 //