o Added optional Generic Partition to IMF Aux Data prototype, used to carry global...
[asdcplib.git] / src / MXFTypes.h
1 /*
2 Copyright (c) 2005-2016, 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    MXFTypes.h
28     \version $Id$
29     \brief   MXF objects
30 */
31
32 #ifndef _MXFTYPES_H_
33 #define _MXFTYPES_H_
34
35 #include "KLV.h"
36 #include <list>
37 #include <vector>
38 #include <set>
39 #include <map>
40 #include <wchar.h>
41
42 // used with TLVReader::Read*
43 //
44 // these are used below to manufacture arguments
45 #define OBJ_READ_ARGS(s,l) m_Dict->Type(MDD_##s##_##l), &l
46 #define OBJ_WRITE_ARGS(s,l) m_Dict->Type(MDD_##s##_##l), &l
47 #define OBJ_READ_ARGS_OPT(s,l) m_Dict->Type(MDD_##s##_##l), &l.get()
48 #define OBJ_WRITE_ARGS_OPT(s,l) m_Dict->Type(MDD_##s##_##l), &l.get()
49 #define OBJ_TYPE_ARGS(t) m_Dict->Type(MDD_##t).ul
50
51
52 namespace ASDCP
53 {
54   namespace MXF
55     {
56       typedef std::pair<ui32_t, ui32_t> ItemInfo;
57       typedef std::map<TagValue, ItemInfo> TagMap;
58
59       //      
60       class TLVReader : public Kumu::MemIOReader
61         {
62
63           TagMap         m_ElementMap;
64           IPrimerLookup* m_Lookup;
65
66           TLVReader();
67           ASDCP_NO_COPY_CONSTRUCT(TLVReader);
68
69         public:
70           TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* = 0);
71           bool FindTL(const MDDEntry&);
72           Result_t ReadObject(const MDDEntry&, Kumu::IArchive*);
73           Result_t ReadUi8(const MDDEntry&, ui8_t*);
74           Result_t ReadUi16(const MDDEntry&, ui16_t*);
75           Result_t ReadUi32(const MDDEntry&, ui32_t*);
76           Result_t ReadUi64(const MDDEntry&, ui64_t*);
77         };
78
79       //      
80       class TLVWriter : public Kumu::MemIOWriter
81         {
82
83           TagMap         m_ElementMap;
84           IPrimerLookup* m_Lookup;
85
86           TLVWriter();
87           ASDCP_NO_COPY_CONSTRUCT(TLVWriter);
88           Result_t WriteTag(const MDDEntry&);
89
90         public:
91           TLVWriter(byte_t* p, ui32_t c, IPrimerLookup* = 0);
92           Result_t WriteObject(const MDDEntry&, Kumu::IArchive*);
93           Result_t WriteUi8(const MDDEntry&, ui8_t*);
94           Result_t WriteUi16(const MDDEntry&, ui16_t*);
95           Result_t WriteUi32(const MDDEntry&, ui32_t*);
96           Result_t WriteUi64(const MDDEntry&, ui64_t*);
97         };
98
99       //
100       template <class ContainerType>
101         class FixedSizeItemCollection : public ContainerType, public Kumu::IArchive
102         {
103         public:
104           FixedSizeItemCollection() {}
105           virtual ~FixedSizeItemCollection() {}
106
107           ui32_t ItemSize() const {
108             typename ContainerType::value_type tmp_item;
109             return tmp_item.ArchiveLength();
110           }
111
112           bool HasValue() const { return ! this->empty(); }
113
114           ui32_t ArchiveLength() const {
115             return ( sizeof(ui32_t) * 2 ) +  ( this->size() * this->ItemSize() );
116           }
117
118           bool Archive(Kumu::MemIOWriter* Writer) const {
119             if ( ! Writer->WriteUi32BE(this->size()) ) return false;
120             if ( ! Writer->WriteUi32BE(this->ItemSize()) ) return false;
121             if ( this->empty() ) return true;
122             
123             typename ContainerType::const_iterator i;
124             bool result = true;
125             for ( i = this->begin(); i != this->end() && result; ++i )
126               {
127                 result = i->Archive(Writer);
128               }
129
130             return result;
131           }
132
133           //
134           bool Unarchive(Kumu::MemIOReader* Reader) {
135             ui32_t item_count, item_size;
136             if ( ! Reader->ReadUi32BE(&item_count) ) return false;
137             if ( ! Reader->ReadUi32BE(&item_size) ) return false;
138
139             if ( item_count > 0 )
140               {
141                 if ( this->ItemSize() != item_size ) return false;
142               }
143
144             bool result = true;
145             for ( ui32_t i = 0; i < item_count && result; ++i )
146               {
147                 typename ContainerType::value_type tmp_item;
148                 result = tmp_item.Unarchive(Reader);
149
150                 if ( result )
151                   {
152                     this->push_back(tmp_item);
153                   }
154               }
155
156             return result;
157           }
158
159           void Dump(FILE* stream = 0, ui32_t depth = 0) {
160             char identbuf[IdentBufferLen];
161
162             if ( stream == 0 )
163               {
164                 stream = stderr;
165               }
166             
167             typename ContainerType::const_iterator i;
168             for ( i = this->begin(); i != this->end(); ++i )
169               {
170                 fprintf(stream, "  %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
171               }
172           }
173         };
174
175
176       template <class item_type>
177         class PushSet : public std::set<item_type>
178       {
179       public:
180         PushSet() {}
181         virtual ~PushSet() {}
182         void push_back(const item_type& item) { this->insert(item); }
183       };
184
185       template <class ItemType>
186         class Batch : public FixedSizeItemCollection<PushSet<ItemType> >
187       {
188       public:
189         Batch() {}
190         virtual ~Batch() {}
191       };
192
193       template <class ItemType>
194         class Array : public FixedSizeItemCollection<std::vector<ItemType> >
195       {
196       public:
197         Array() {}
198         virtual ~Array() {}
199       };
200
201       //
202       template <class T>
203         class SimpleArray : public std::list<T>, public Kumu::IArchive
204         {
205         public:
206           SimpleArray() {}
207           virtual ~SimpleArray() {}
208
209           //
210           bool Unarchive(Kumu::MemIOReader* Reader)
211             {
212               bool result = true;
213
214               while ( Reader->Remainder() > 0 && result )
215                 {
216                   T Tmp;
217                   result = Tmp.Unarchive(Reader);
218
219                   if ( result )
220                     {
221                       this->push_back(Tmp);
222                     }
223                 }
224
225               return result;
226             }
227
228           inline bool HasValue() const { return ! this->empty(); }
229
230           ui32_t ArchiveLength() const {
231             ui32_t arch_size = 0;
232
233             typename std::list<T>::const_iterator l_i = this->begin();
234
235             for ( ; l_i != this->end(); l_i++ )
236               arch_size += l_i->ArchiveLength();
237             
238             return arch_size;
239           }
240
241           //
242           bool Archive(Kumu::MemIOWriter* Writer) const {
243             bool result = true;
244             typename std::list<T>::const_iterator l_i = this->begin();
245
246             for ( ; l_i != this->end() && result; l_i++ )
247               result = (*l_i).Archive(Writer);
248
249             return result;
250           }
251
252           //
253           void Dump(FILE* stream = 0, ui32_t depth = 0)
254             {
255               char identbuf[IdentBufferLen];
256
257               if ( stream == 0 )
258                 stream = stderr;
259
260               typename std::list<T>::iterator i = this->begin();
261               for ( ; i != this->end(); i++ )
262                 fprintf(stream, "  %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
263             }
264         };
265
266       //
267     class ISO8String : public std::string, public Kumu::IArchive
268         {
269         public:
270           ISO8String() {}
271           ISO8String(const char*);
272           ISO8String(const std::string&);
273           ~ISO8String() {}
274
275           const ISO8String& operator=(const char*);
276           const ISO8String& operator=(const std::string&);
277
278           const char* EncodeString(char* str_buf, ui32_t buf_len) const;
279           inline virtual bool HasValue() const { return ! empty(); }
280           inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t) + size(); }
281           virtual bool Unarchive(Kumu::MemIOReader* Reader);
282           virtual bool Archive(Kumu::MemIOWriter* Writer) const;
283         };
284
285       //
286     class UTF16String : public std::string, public Kumu::IArchive
287         {
288         public:
289           UTF16String() {}
290           UTF16String(const char*);
291           UTF16String(const std::string&);
292           ~UTF16String() {}
293
294           const UTF16String& operator=(const char*);
295           const UTF16String& operator=(const std::string&);
296
297           const char* EncodeString(char* str_buf, ui32_t buf_len) const;
298           inline virtual bool HasValue() const { return ! empty(); }
299           inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t) + size(); }
300           virtual bool Unarchive(Kumu::MemIOReader* Reader);
301           virtual bool Archive(Kumu::MemIOWriter* Writer) const;
302         };
303
304       //
305       class Rational : public ASDCP::Rational, public Kumu::IArchive
306         {
307         public:
308           Rational() {}
309           ~Rational() {}
310
311           Rational(const Rational& rhs) : ASDCP::Rational(), IArchive() {
312             Numerator = rhs.Numerator;
313             Denominator = rhs.Denominator;
314           }
315
316           const Rational& operator=(const Rational& rhs) {
317             Numerator = rhs.Numerator;
318             Denominator = rhs.Denominator;
319             return *this;
320           }
321
322           Rational(const ASDCP::Rational& rhs) {
323             Numerator = rhs.Numerator;
324             Denominator = rhs.Denominator;
325           }
326
327           const Rational& operator=(const ASDCP::Rational& rhs) {
328             Numerator = rhs.Numerator;
329             Denominator = rhs.Denominator;
330             return *this;
331           }
332
333           //
334           inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
335             snprintf(str_buf, buf_len, "%d/%d", Numerator, Denominator);
336             return str_buf;
337           }
338
339           inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
340             if ( ! Reader->ReadUi32BE((ui32_t*)&Numerator) ) return false;
341             if ( ! Reader->ReadUi32BE((ui32_t*)&Denominator) ) return false;
342             return true;
343           }
344
345           inline virtual bool HasValue() const { return true; }
346           inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*2; }
347
348           inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
349             if ( ! Writer->WriteUi32BE((ui32_t)Numerator) ) return false;
350             if ( ! Writer->WriteUi32BE((ui32_t)Denominator) ) return false;
351             return true;
352           }
353         };
354
355       //
356       class LineMapPair : public Kumu::IArchive
357         {
358         public:
359           ui32_t First;
360           ui32_t Second;
361
362           LineMapPair() {}
363           ~LineMapPair() {}
364
365         LineMapPair(const ui32_t& first, const ui32_t& second) : IArchive() {
366             First = first;
367             Second = second;
368           }
369
370           LineMapPair(const LineMapPair& rhs) : IArchive() {
371             First = rhs.First;
372             Second = rhs.Second;
373           }
374
375           const LineMapPair& operator=(const LineMapPair& rhs) {
376             First = rhs.First;
377             Second = rhs.Second;
378             return *this;
379           }
380
381           //
382           inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
383             snprintf(str_buf, buf_len, "%d,%d", First, Second);
384             return str_buf;
385           }
386
387           inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
388             ui32_t n;
389             if ( ! Reader->ReadUi32BE(&n) ) return false;
390             if ( n != 4 ) return false;
391             if ( ! Reader->ReadUi32BE(&n) ) return false;
392             if ( n != 2 ) return false;
393             if ( ! Reader->ReadUi32BE((ui32_t*)&First) ) return false;
394             if ( ! Reader->ReadUi32BE((ui32_t*)&Second) ) return false;
395             return true;
396           }
397
398           inline virtual bool HasValue() const { return true; }
399           inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*4; }
400
401           inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
402             if ( ! Writer->WriteUi32BE(4UL) ) return false;
403             if ( ! Writer->WriteUi32BE(2UL) ) return false;
404             if ( ! Writer->WriteUi32BE((ui32_t)First) ) return false;
405             if ( ! Writer->WriteUi32BE((ui32_t)Second) ) return false;
406             return true;
407           }
408         };
409
410       //
411       class VersionType : public Kumu::IArchive
412         {
413         public:
414           enum Release_t { RL_UNKNOWN, RL_RELEASE, RL_DEVELOPMENT, RL_PATCHED, RL_BETA, RL_PRIVATE, RL_MAX };
415           ui16_t Major;
416           ui16_t Minor;
417           ui16_t Patch;
418           ui16_t Build;
419           Release_t Release;
420
421           VersionType() : Major(0), Minor(0), Patch(0), Build(0), Release(RL_UNKNOWN) {}
422           VersionType(const VersionType& rhs) { Copy(rhs); }
423           virtual ~VersionType() {}
424
425           const VersionType& operator=(const VersionType& rhs) { Copy(rhs); return *this; }
426           void Copy(const VersionType& rhs) {
427             Major = rhs.Major;
428             Minor = rhs.Minor;
429             Patch = rhs.Patch;
430             Build = rhs.Build;
431             Release = rhs.Release;
432           }
433
434           void Dump(FILE* = 0);
435
436           const char* EncodeString(char* str_buf, ui32_t buf_len) const {
437             snprintf(str_buf, buf_len, "%hu.%hu.%hu.%hur%hu", Major, Minor, Patch, Build, ui16_t(Release));
438             return str_buf;
439           }
440
441           virtual bool Unarchive(Kumu::MemIOReader* Reader) {
442             if ( ! Reader->ReadUi16BE(&Major) ) return false;
443             if ( ! Reader->ReadUi16BE(&Minor) ) return false;
444             if ( ! Reader->ReadUi16BE(&Patch) ) return false;
445             if ( ! Reader->ReadUi16BE(&Build) ) return false;
446             ui16_t tmp_release;
447             if ( ! Reader->ReadUi16BE(&tmp_release) ) return false;
448             Release = (Release_t)tmp_release;
449             return true;
450           }
451
452           inline virtual bool HasValue() const { return true; }
453           inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*5; }
454
455           virtual bool Archive(Kumu::MemIOWriter* Writer) const {
456             if ( ! Writer->WriteUi16BE(Major) ) return false;
457             if ( ! Writer->WriteUi16BE(Minor) ) return false;
458             if ( ! Writer->WriteUi16BE(Patch) ) return false;
459             if ( ! Writer->WriteUi16BE(Build) ) return false;
460             if ( ! Writer->WriteUi16BE((ui16_t)(Release & 0x0000ffffL)) ) return false;
461             return true;
462           }
463         };
464
465       /*
466         The RGBALayout type shall be a fixed-size 8 element sequence with a total length
467         of 16 bytes, where each element shall consist of the RGBAComponent type with the
468         following fields:
469
470         Code (UInt8): Enumerated value specifying component (i.e., component identifier).
471         "0" is the layout terminator.
472
473         Depth (UInt8): Integer specifying the number of bits occupied (see also G.2.26) 
474           1->32 indicates integer depth
475           253 = HALF (floating point 16-bit value)
476           254 = IEEE floating point 32-bit value
477           255 = IEEE floating point 64-bit value
478           0 = RGBALayout terminator
479
480         A Fill component indicates unused bits. After the components have been specified,
481         the remaining Code and Size fields shall be set to zero (0).
482
483         For each component in the Pixel, one of the following Codes or the terminator
484         shall be specified (explained below):
485
486         Code    ASCII
487
488       */
489       struct RGBALayoutTableEntry
490       {
491         byte_t code;
492         char symbol;
493         const char* label;
494       };
495
496       struct RGBALayoutTableEntry const RGBALayoutTable[] = {
497         { 0x52, 'R', "Red component" },
498         { 0x47, 'G', "Green component" },
499         { 0x42, 'B', "Blue component" },
500         { 0x41, 'A', "Alpha component" },
501         { 0x72, 'r', "Red component (LSBs)" },
502         { 0x67, 'g', "Green component (LSBs)" },
503         { 0x62, 'b', "Blue component (LSBs)" },
504         { 0x61, 'a', "Alpha component (LSBs)" },
505         { 0x46, 'F', "Fill component" },
506         { 0x50, 'P', "Palette code" },
507         { 0x55, 'U', "Color Difference Sample (e.g. U, Cb, I etc.)" },
508         { 0x56, 'V', "Color Difference Sample (e.g. V, Cr, Q etc.)" },
509         { 0x57, 'W', "Composite Video" },
510         { 0x58, 'X', "Non co-sited luma component" },
511         { 0x59, 'Y', "Luma component" },
512         { 0x5a, 'Z', "Depth component (SMPTE ST 268 compatible)" },
513         { 0x75, 'u', "Color Difference Sample (e.g. U, Cb, I etc.) (LSBs)" },
514         { 0x76, 'v', "Color Difference Sample (e.g. V, Cr, Q etc.) (LSBs)" },
515         { 0x77, 'w', "Composite Video (LSBs)" },
516         { 0x78, 'x', "Non co-sited luma component (LSBs)" },
517         { 0x79, 'y', "Luma component (LSBs)" },
518         { 0x7a, 'z', "Depth component (LSBs) (SMPTE ST 268 compatible)" },
519         { 0xd8, 'X', "The DCDM X color component (see SMPTE ST 428-1 X')" },
520         { 0xd9, 'Y', "The DCDM Y color component (see SMPTE ST 428-1 Y')" },
521         { 0xda, 'Z', "The DCDM Z color component (see SMPTE ST 428-1 Z')" },
522         { 0x00, '_', "Terminator" }
523       };
524
525
526       size_t const RGBAValueLength = 16;
527
528       byte_t const RGBAValue_RGB_10[RGBAValueLength] = { 'R', 10, 'G', 10, 'B', 10, 0, 0 };
529       byte_t const RGBAValue_RGB_8[RGBAValueLength]  = { 'R', 8,  'G', 8,  'B', 8,  0, 0 };
530       byte_t const RGBAValue_YUV_10[RGBAValueLength] = { 'Y', 10, 'U', 10, 'V', 10, 0, 0 };
531       byte_t const RGBAValue_YUV_8[RGBAValueLength]  = { 'Y', 8,  'U', 8,  'V', 8,  0, 0 };
532       byte_t const RGBAValue_DCDM[RGBAValueLength] = { 0xd8, 10, 0xd9, 10, 0xda, 10, 0, 0 };
533
534
535       class RGBALayout : public Kumu::IArchive
536         {
537           byte_t m_value[RGBAValueLength];
538
539         public:
540           RGBALayout();
541           RGBALayout(const byte_t* value);
542           ~RGBALayout();
543
544           RGBALayout(const RGBALayout& rhs) { Set(rhs.m_value); }
545           const RGBALayout& operator=(const RGBALayout& rhs) { Set(rhs.m_value); return *this; }
546           
547           void Set(const byte_t* value) {
548             memcpy(m_value, value, RGBAValueLength);
549           }
550
551           const char* EncodeString(char* buf, ui32_t buf_len) const;
552
553           bool HasValue() const { return true; }
554           ui32_t ArchiveLength() const { return RGBAValueLength; }
555
556           bool Archive(Kumu::MemIOWriter* Writer) const {
557             return Writer->WriteRaw(m_value, RGBAValueLength);
558           }
559
560           bool Unarchive(Kumu::MemIOReader* Reader) {
561             if ( Reader->Remainder() < RGBAValueLength )
562               {
563                 return false;
564               }
565
566             memcpy(m_value, Reader->CurrentData(), RGBAValueLength);
567             Reader->SkipOffset(RGBAValueLength);
568             return true;
569           }
570         };
571
572
573       //
574       class Raw : public Kumu::ByteString
575         {
576         public:
577           Raw();
578           Raw(const Raw& rhs) { Copy(rhs); }
579           virtual ~Raw();
580
581           const Raw& operator=(const Raw& rhs) { Copy(rhs); return *this; }
582           void Copy(const Raw& rhs) {
583             if ( KM_SUCCESS(Capacity(rhs.Length())) )
584               {
585                 Set(rhs);
586               }
587           }
588
589           //
590           virtual bool Unarchive(Kumu::MemIOReader* Reader);
591           virtual bool Archive(Kumu::MemIOWriter* Writer) const;
592           const char* EncodeString(char* str_buf, ui32_t buf_len) const;
593         };
594
595     } // namespace MXF
596 } // namespace ASDCP
597
598
599 #endif //_MXFTYPES_H_
600
601 //
602 // end MXFTypes.h
603 //