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