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