as-02ooooooooooo!
[asdcplib.git] / src / MXF.h
1 /*
2 Copyright (c) 2005-2012, 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 OPAtomHeader : public Partition
354         {
355           ASDCP_NO_COPY_CONSTRUCT(OPAtomHeader);
356           OPAtomHeader();
357
358         public:
359           const Dictionary*&   m_Dict;
360           ASDCP::MXF::RIP     m_RIP;
361           ASDCP::MXF::Primer  m_Primer;
362           Preface*            m_Preface;
363           ASDCP::FrameBuffer  m_Buffer;
364           bool                m_HasRIP;
365
366           OPAtomHeader(const Dictionary*&);
367           virtual ~OPAtomHeader();
368           virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
369           virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
370           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
371           virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui32_t HeaderLength = 16384);
372           virtual void     Dump(FILE* = 0);
373           virtual Result_t GetMDObjectByID(const UUID&, InterchangeObject** = 0);
374           virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0);
375           virtual Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList);
376           virtual ASDCP::MXF::RIP& GetRIP();
377           Identification*  GetIdentification();
378           SourcePackage*   GetSourcePackage();
379         };
380
381       //
382       class OPAtomIndexFooter : public Partition
383         {
384           IndexTableSegment*  m_CurrentSegment;
385           ASDCP::FrameBuffer  m_Buffer;
386           ui32_t              m_BytesPerEditUnit;
387           Rational            m_EditRate;
388           ui32_t              m_BodySID;
389
390           ASDCP_NO_COPY_CONSTRUCT(OPAtomIndexFooter);
391           OPAtomIndexFooter();
392
393         public:
394           const Dictionary*&   m_Dict;
395           Kumu::fpos_t        m_ECOffset;
396           IPrimerLookup*      m_Lookup;
397          
398           OPAtomIndexFooter(const Dictionary*&);
399           virtual ~OPAtomIndexFooter();
400           virtual Result_t InitFromFile(const Kumu::FileReader& Reader);
401           virtual Result_t InitFromPartitionBuffer(const byte_t* p, ui32_t l);
402           virtual Result_t InitFromBuffer(const byte_t* p, ui32_t l);
403           virtual Result_t WriteToFile(Kumu::FileWriter& Writer, ui64_t duration);
404           virtual void     Dump(FILE* = 0);
405
406           virtual Result_t GetMDObjectByID(const UUID&, InterchangeObject** = 0);
407           virtual Result_t GetMDObjectByType(const byte_t*, InterchangeObject** = 0);
408           virtual Result_t GetMDObjectsByType(const byte_t* ObjectID, std::list<InterchangeObject*>& ObjectList);
409
410           virtual Result_t Lookup(ui32_t frame_num, IndexTableSegment::IndexEntry&) const;
411           virtual void     PushIndexEntry(const IndexTableSegment::IndexEntry&);
412           virtual void     SetIndexParamsCBR(IPrimerLookup* lookup, ui32_t size, const Rational& Rate);
413           virtual void     SetIndexParamsVBR(IPrimerLookup* lookup, const Rational& Rate, Kumu::fpos_t offset);
414         };
415
416     } // namespace MXF
417 } // namespace ASDCP
418
419
420 #endif // _MXF_H_
421
422 //
423 // end MXF.h
424 //