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