logging re-write
[asdcplib.git] / src / MXF.h
1 /*
2 Copyright (c) 2005-2006, 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)();
45
46       //
47       void SetObjectFactory(UL label, MXFObjectFactory_t factory);
48
49       //
50       InterchangeObject* CreateObject(const byte_t* 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
61         public:
62           //
63           class Pair : public Kumu::IArchive
64             {
65             public:
66               ui32_t BodySID;
67               ui64_t ByteOffset;
68
69               Pair() : BodySID(0), ByteOffset(0) {}
70               Pair(ui32_t sid, ui64_t offset) : BodySID(sid), ByteOffset(offset) {}
71               virtual ~Pair() {}
72
73               ui32_t Size() { return sizeof(ui32_t) + sizeof(ui64_t); }
74
75               inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
76                 Kumu::ui64Printer offset_str(ByteOffset);
77                 snprintf(str_buf, buf_len, "%-6u: %s", BodySID, offset_str.c_str());
78                 return str_buf;
79               }
80
81               inline bool HasValue() const { return true; }
82               inline ui32_t ArchiveLength() const { return sizeof(ui32_t) + sizeof(ui64_t); }
83
84               inline bool Unarchive(Kumu::MemIOReader* Reader) {
85                 if ( ! Reader->ReadUi32BE(&BodySID) ) return false;
86                 if ( ! Reader->ReadUi64BE(&ByteOffset) ) return false;
87                 return true;
88               }
89               
90               inline bool Archive(Kumu::MemIOWriter* Writer) const {
91                 if ( ! Writer->WriteUi32BE(BodySID) ) return false;
92                 if ( ! Writer->WriteUi64BE(ByteOffset) ) return false;
93                 return true;
94               }
95             };
96
97           Array<Pair> PairArray;
98
99           RIP() {}
100           virtual ~RIP() {}
101           virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
102           virtual Result_t WriteToFile(Kumu::FileWriter& Writer);
103           virtual Result_t GetPairBySID(ui32_t, Pair&) const;
104           virtual void     Dump(FILE* = 0);
105         };
106
107
108       //
109       class Partition : public ASDCP::KLVFilePacket
110         {
111           ASDCP_NO_COPY_CONSTRUCT(Partition);
112
113         protected:
114           class h__PacketList;
115           mem_ptr<h__PacketList> m_PacketList;
116
117         public:
118           ui16_t    MajorVersion;
119           ui16_t    MinorVersion;
120           ui32_t    KAGSize;
121           ui64_t    ThisPartition;
122           ui64_t    PreviousPartition;
123           ui64_t    FooterPartition;
124           ui64_t    HeaderByteCount;
125           ui64_t    IndexByteCount;
126           ui32_t    IndexSID;
127           ui64_t    BodyOffset;
128           ui32_t    BodySID;
129           UL        OperationalPattern;
130           Batch<UL> EssenceContainers;
131
132           Partition();
133           virtual ~Partition();
134           virtual void     AddChildObject(InterchangeObject*);
135           virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
136           virtual Result_t WriteToFile(Kumu::FileWriter& Writer, UL& PartitionLabel);
137           virtual ui32_t   ArchiveSize(); // returns the size of the archived structure
138           virtual void     Dump(FILE* = 0);
139         };
140
141
142       //
143       class Primer : public ASDCP::KLVFilePacket, public ASDCP::IPrimerLookup
144         {
145           class h__PrimerLookup;
146           mem_ptr<h__PrimerLookup> m_Lookup;
147           ui8_t   m_LocalTag;
148           ASDCP_NO_COPY_CONSTRUCT(Primer);
149
150         public:
151           //
152         class LocalTagEntry : Kumu::IArchive
153             {
154             public:
155               TagValue    Tag;
156               ASDCP::UL   UL;
157
158               inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
159                 snprintf(str_buf, buf_len, "%02x %02x: ", Tag.a, Tag.b);
160                 UL.EncodeString(str_buf + strlen(str_buf), buf_len - strlen(str_buf));
161                 return str_buf;
162               }
163
164               inline bool HasValue() const { return UL.HasValue(); }
165               inline ui32_t ArchiveLength() const { return 2 + UL.ArchiveLength(); }
166
167               inline bool Unarchive(Kumu::MemIOReader* Reader) {
168                 if ( ! Reader->ReadUi8(&Tag.a) ) return false;
169                 if ( ! Reader->ReadUi8(&Tag.b) ) return false;
170                 return UL.Unarchive(Reader);
171               }
172
173               inline bool Archive(Kumu::MemIOWriter* Writer) const {
174                 if ( ! Writer->WriteUi8(Tag.a) ) return false;
175                 if ( ! Writer->WriteUi8(Tag.b) ) return false;
176                 return UL.Archive(Writer);
177               }
178             };
179
180           Batch<LocalTagEntry> LocalTagEntryBatch;
181
182           Primer();
183           virtual ~Primer();
184
185           virtual void     ClearTagList();
186           virtual Result_t InsertTag(const MDDEntry& Entry, ASDCP::TagValue& Tag);
187           virtual Result_t TagForKey(const ASDCP::UL& Key, ASDCP::TagValue& Tag);
188
189           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
190           virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
191           virtual Result_t WriteToFile(Kumu::FileWriter& Writer);
192           virtual void     Dump(FILE* = 0);
193         };
194
195
196       //
197       class InterchangeObject : public ASDCP::KLVPacket
198         {
199         protected:
200           const MDDEntry* m_Typeinfo;
201
202         public:
203           IPrimerLookup* m_Lookup;
204           UUID           InstanceUID;
205           UUID           GenerationUID;
206
207           InterchangeObject() : m_Typeinfo(0), m_Lookup(0) {}
208           virtual ~InterchangeObject() {}
209           virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
210           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
211           virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
212           virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
213           virtual bool     IsA(const byte_t* label);
214           virtual const char* ObjectName() { return "InterchangeObject"; }
215           virtual void     Dump(FILE* stream = 0);
216         };
217
218       //
219       class Preface : public InterchangeObject
220         {
221           ASDCP_NO_COPY_CONSTRUCT(Preface);
222
223         public:
224           UUID         GenerationUID;
225           Timestamp    LastModifiedDate;
226           ui16_t       Version;
227           ui32_t       ObjectModelVersion;
228           UUID         PrimaryPackage;
229           Batch<UUID>  Identifications;
230           UUID         ContentStorage;
231           UL           OperationalPattern;
232           Batch<UL>    EssenceContainers;
233           Batch<UL>    DMSchemes;
234
235           Preface() : Version(258), ObjectModelVersion(0) {}
236           virtual ~Preface() {}
237           virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
238           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
239           virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
240           virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
241           virtual void     Dump(FILE* = 0);
242         };
243
244       const ui32_t MaxIndexSegmentSize = 65536;
245
246       //
247       class IndexTableSegment : public InterchangeObject
248         {
249           ASDCP_NO_COPY_CONSTRUCT(IndexTableSegment);
250
251         public:
252           //
253         class DeltaEntry : public Kumu::IArchive
254             {
255             public:
256               i8_t    PosTableIndex;
257               ui8_t   Slice;
258               ui32_t  ElementData;
259
260               DeltaEntry() : PosTableIndex(-1), Slice(0), ElementData(0) {}
261               inline bool HasValue() const { return true; }
262               ui32_t      ArchiveLength() const { return sizeof(ui32_t) + 2; }
263               bool        Unarchive(Kumu::MemIOReader* Reader);
264               bool        Archive(Kumu::MemIOWriter* Writer) const;
265               const char* EncodeString(char* str_buf, ui32_t buf_len) const;
266             };
267
268           //
269           class IndexEntry : public Kumu::IArchive
270             {
271             public:
272               i8_t               TemporalOffset;
273               i8_t               KeyFrameOffset;
274               ui8_t              Flags;
275               ui64_t             StreamOffset;
276
277               // if you use these, you will need to change CBRIndexEntriesPerSegment in MXF.cpp
278               // to a more suitable value
279               //              std::list<ui32_t>  SliceOffset;
280               //              Array<Rational>    PosTable;
281
282               IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0), StreamOffset() {}
283               inline bool HasValue() const { return true; }
284               ui32_t      ArchiveLength() const { return sizeof(ui64_t) + 3; };
285               bool        Unarchive(Kumu::MemIOReader* Reader);
286               bool        Archive(Kumu::MemIOWriter* Writer) const;
287               const char* EncodeString(char* str_buf, ui32_t buf_len) const;
288             };
289
290           Rational    IndexEditRate;
291           ui64_t      IndexStartPosition;
292           ui64_t      IndexDuration;
293           ui32_t      EditUnitByteCount;
294           ui32_t      IndexSID;
295           ui32_t      BodySID;
296           ui8_t       SliceCount;
297           ui8_t       PosTableCount;
298           Batch<DeltaEntry> DeltaEntryArray;
299           Batch<IndexEntry> IndexEntryArray;
300
301           IndexTableSegment();
302           virtual ~IndexTableSegment();
303           virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
304           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
305           virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
306           virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
307           virtual void     Dump(FILE* = 0);
308         };
309
310       //---------------------------------------------------------------------------------
311       //
312       class Identification;
313       class SourcePackage;
314
315       //
316       class OPAtomHeader : public Partition
317         {
318           ASDCP_NO_COPY_CONSTRUCT(OPAtomHeader);
319
320         public:
321           ASDCP::MXF::RIP     m_RIP;
322           ASDCP::MXF::Primer  m_Primer;
323           Preface*            m_Preface;
324           ASDCP::FrameBuffer  m_Buffer;
325           bool                m_HasRIP;
326
327           OPAtomHeader();
328           virtual ~OPAtomHeader();
329           virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
330           virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui32_t HeaderLength = 16384);
331           virtual void     Dump(FILE* = 0);
332           virtual Result_t GetMDObjectByID(const UUID&, InterchangeObject** = 0);
333           virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0);
334           virtual Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList);
335           Identification*  GetIdentification();
336           SourcePackage*   GetSourcePackage();
337         };
338
339       //
340       class OPAtomIndexFooter : public Partition
341         {
342           IndexTableSegment*  m_CurrentSegment;
343           ASDCP::FrameBuffer  m_Buffer;
344           ui32_t              m_BytesPerEditUnit;
345           Rational            m_EditRate;
346           ui32_t              m_BodySID;
347           ASDCP_NO_COPY_CONSTRUCT(OPAtomIndexFooter);
348
349         public:
350           Kumu::fpos_t        m_ECOffset;
351           IPrimerLookup*      m_Lookup;
352          
353           OPAtomIndexFooter();
354           virtual ~OPAtomIndexFooter();
355           virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
356           virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui64_t duration);
357           virtual void     Dump(FILE* = 0);
358
359           virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&) const;
360           virtual void     PushIndexEntry(const IndexTableSegment::IndexEntry&);
361           virtual void     SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate);
362           virtual void     SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset);
363         };
364
365     } // namespace MXF
366 } // namespace ASDCP
367
368
369 #endif // _MXF_H_
370
371 //
372 // end MXF.h
373 //