Denis' bug fixes
[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, "%-6u: %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
263               // if you use these, you will need to change CBRIndexEntriesPerSegment in MXF.cpp
264               // to a more suitable value
265               //              std::list<ui32_t>  SliceOffset;
266               //              Array<Rational>    PosTable;
267
268               IndexEntry() : TemporalOffset(0), KeyFrameOffset(0), Flags(0), StreamOffset() {}
269               bool        Unarchive(Kumu::MemIOReader* Reader);
270               bool        Archive(Kumu::MemIOWriter* Writer) const;
271               const char* EncodeString(char* str_buf, ui32_t buf_len) const;
272             };
273
274           Rational    IndexEditRate;
275           ui64_t      IndexStartPosition;
276           ui64_t      IndexDuration;
277           ui32_t      EditUnitByteCount;
278           ui32_t      IndexSID;
279           ui32_t      BodySID;
280           ui8_t       SliceCount;
281           ui8_t       PosTableCount;
282           Batch<DeltaEntry> DeltaEntryArray;
283           Batch<IndexEntry> IndexEntryArray;
284
285           IndexTableSegment();
286           virtual ~IndexTableSegment();
287           virtual Result_t InitFromTLVSet(TLVReader& TLVSet);
288           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
289           virtual Result_t WriteToTLVSet(TLVWriter& TLVSet);
290           virtual Result_t WriteToBuffer(ASDCP::FrameBuffer&);
291           virtual void     Dump(FILE* = 0);
292         };
293
294       //---------------------------------------------------------------------------------
295       //
296       class h__PacketList; // See MXF.cpp
297       class Identification;
298       class SourcePackage;
299
300       //
301       class OPAtomHeader : public Partition
302         {
303           ASDCP_NO_COPY_CONSTRUCT(OPAtomHeader);
304
305         public:
306           ASDCP::MXF::RIP     m_RIP;
307           ASDCP::MXF::Primer  m_Primer;
308           Preface*            m_Preface;
309           ASDCP::FrameBuffer  m_Buffer;
310           bool                m_HasRIP;
311
312           OPAtomHeader();
313           virtual ~OPAtomHeader();
314           virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
315           virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui32_t HeaderLength = 16384);
316           virtual void     Dump(FILE* = 0);
317           virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0);
318           Identification*  GetIdentification();
319           SourcePackage*   GetSourcePackage();
320         };
321
322       //
323       class OPAtomIndexFooter : public Partition
324         {
325           IndexTableSegment*  m_CurrentSegment;
326           ASDCP::FrameBuffer  m_Buffer;
327           ui32_t              m_BytesPerEditUnit;
328           Rational            m_EditRate;
329           ui32_t              m_BodySID;
330           ASDCP_NO_COPY_CONSTRUCT(OPAtomIndexFooter);
331
332         public:
333           Kumu::fpos_t        m_ECOffset;
334           IPrimerLookup*      m_Lookup;
335          
336           OPAtomIndexFooter();
337           virtual ~OPAtomIndexFooter();
338           virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
339           virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui64_t duration);
340           virtual void     Dump(FILE* = 0);
341
342           virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&);
343           virtual void     PushIndexEntry(const IndexTableSegment::IndexEntry&);
344           virtual void     SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate);
345           virtual void     SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset);
346         };
347
348     } // namespace MXF
349 } // namespace ASDCP
350
351
352 #endif // _MXF_H_
353
354 //
355 // end MXF.h
356 //