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