Fix a type-punning warning.
[asdcplib-cth.git] / src / MXFTypes.h
1 /*
2 Copyright (c) 2005-2015, 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: MXFTypes.h,v 1.38 2015/10/12 15:30:46 jhurst Exp $
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           bool FindTL(const MDDEntry&);
69
70         public:
71           TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* = 0);
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 = 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 = 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 VersionType : public Kumu::IArchive
357         {
358         public:
359           enum Release_t { RL_UNKNOWN, RL_RELEASE, RL_DEVELOPMENT, RL_PATCHED, RL_BETA, RL_PRIVATE, RL_MAX };
360           ui16_t Major;
361           ui16_t Minor;
362           ui16_t Patch;
363           ui16_t Build;
364           Release_t Release;
365
366           VersionType() : Major(0), Minor(0), Patch(0), Build(0), Release(RL_UNKNOWN) {}
367           VersionType(const VersionType& rhs) { Copy(rhs); }
368           virtual ~VersionType() {}
369
370           const VersionType& operator=(const VersionType& rhs) { Copy(rhs); return *this; }
371           void Copy(const VersionType& rhs) {
372             Major = rhs.Major;
373             Minor = rhs.Minor;
374             Patch = rhs.Patch;
375             Build = rhs.Build;
376             Release = rhs.Release;
377           }
378
379           void Dump(FILE* = 0);
380
381           const char* EncodeString(char* str_buf, ui32_t buf_len) const {
382             snprintf(str_buf, buf_len, "%hu.%hu.%hu.%hur%hu", Major, Minor, Patch, Build, ui16_t(Release));
383             return str_buf;
384           }
385
386           virtual bool Unarchive(Kumu::MemIOReader* Reader) {
387             if ( ! Reader->ReadUi16BE(&Major) ) return false;
388             if ( ! Reader->ReadUi16BE(&Minor) ) return false;
389             if ( ! Reader->ReadUi16BE(&Patch) ) return false;
390             if ( ! Reader->ReadUi16BE(&Build) ) return false;
391             ui16_t tmp_release;
392             if ( ! Reader->ReadUi16BE(&tmp_release) ) return false;
393             Release = (Release_t)tmp_release;
394             return true;
395           }
396
397           inline virtual bool HasValue() const { return true; }
398           inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*5; }
399
400           virtual bool Archive(Kumu::MemIOWriter* Writer) const {
401             if ( ! Writer->WriteUi16BE(Major) ) return false;
402             if ( ! Writer->WriteUi16BE(Minor) ) return false;
403             if ( ! Writer->WriteUi16BE(Patch) ) return false;
404             if ( ! Writer->WriteUi16BE(Build) ) return false;
405             if ( ! Writer->WriteUi16BE((ui16_t)(Release & 0x0000ffffL)) ) return false;
406             return true;
407           }
408         };
409
410       /*
411         The RGBALayout type shall be a fixed-size 8 element sequence with a total length
412         of 16 bytes, where each element shall consist of the RGBAComponent type with the
413         following fields:
414
415         Code (UInt8): Enumerated value specifying component (i.e., component identifier).
416         "0" is the layout terminator.
417
418         Depth (UInt8): Integer specifying the number of bits occupied (see also G.2.26) 
419           1->32 indicates integer depth
420           253 = HALF (floating point 16-bit value)
421           254 = IEEE floating point 32-bit value
422           255 = IEEE floating point 64-bit value
423           0 = RGBALayout terminator
424
425         A Fill component indicates unused bits. After the components have been specified,
426         the remaining Code and Size fields shall be set to zero (0).
427
428         For each component in the Pixel, one of the following Codes or the terminator
429         shall be specified (explained below):
430
431         Code    ASCII
432
433       */
434       struct RGBALayoutTableEntry
435       {
436         byte_t code;
437         char symbol;
438         const char* label;
439       };
440
441       struct RGBALayoutTableEntry const RGBALayoutTable[] = {
442         { 0x52, 'R', "Red component" },
443         { 0x47, 'G', "Green component" },
444         { 0x42, 'B', "Blue component" },
445         { 0x41, 'A', "Alpha component" },
446         { 0x72, 'r', "Red component (LSBs)" },
447         { 0x67, 'g', "Green component (LSBs)" },
448         { 0x62, 'b', "Blue component (LSBs)" },
449         { 0x61, 'a', "Alpha component (LSBs)" },
450         { 0x46, 'F', "Fill component" },
451         { 0x50, 'P', "Palette code" },
452         { 0x55, 'U', "Color Difference Sample (e.g. U, Cb, I etc.)" },
453         { 0x56, 'V', "Color Difference Sample (e.g. V, Cr, Q etc.)" },
454         { 0x57, 'W', "Composite Video" },
455         { 0x58, 'X', "Non co-sited luma component" },
456         { 0x59, 'Y', "Luma component" },
457         { 0x5a, 'Z', "Depth component (SMPTE ST 268 compatible)" },
458         { 0x75, 'u', "Color Difference Sample (e.g. U, Cb, I etc.) (LSBs)" },
459         { 0x76, 'v', "Color Difference Sample (e.g. V, Cr, Q etc.) (LSBs)" },
460         { 0x77, 'w', "Composite Video (LSBs)" },
461         { 0x78, 'x', "Non co-sited luma component (LSBs)" },
462         { 0x79, 'y', "Luma component (LSBs)" },
463         { 0x7a, 'z', "Depth component (LSBs) (SMPTE ST 268 compatible)" },
464         { 0xd8, 'X', "The DCDM X color component (see SMPTE ST 428-1 X')" },
465         { 0xd9, 'Y', "The DCDM Y color component (see SMPTE ST 428-1 Y')" },
466         { 0xda, 'Z', "The DCDM Z color component (see SMPTE ST 428-1 Z')" },
467         { 0x00, '_', "Terminator" }
468       };
469
470
471       size_t const RGBAValueLength = 16;
472
473       byte_t const RGBAValue_RGB_10[RGBAValueLength] = { 'R', 10, 'G', 10, 'B', 10, 0, 0 };
474       byte_t const RGBAValue_RGB_8[RGBAValueLength]  = { 'R', 8,  'G', 8,  'B', 8,  0, 0 };
475       byte_t const RGBAValue_YUV_10[RGBAValueLength] = { 'Y', 10, 'U', 10, 'V', 10, 0, 0 };
476       byte_t const RGBAValue_YUV_8[RGBAValueLength]  = { 'Y', 8,  'U', 8,  'V', 8,  0, 0 };
477       byte_t const RGBAValue_DCDM[RGBAValueLength] = { 0xd8, 10, 0xd9, 10, 0xda, 10, 0, 0 };
478
479
480       class RGBALayout : public Kumu::IArchive
481         {
482           byte_t m_value[RGBAValueLength];
483
484         public:
485           RGBALayout();
486           RGBALayout(const byte_t* value);
487           ~RGBALayout();
488
489           RGBALayout(const RGBALayout& rhs) { Set(rhs.m_value); }
490           const RGBALayout& operator=(const RGBALayout& rhs) { Set(rhs.m_value); return *this; }
491           
492           void Set(const byte_t* value) {
493             memcpy(m_value, value, RGBAValueLength);
494           }
495
496           const char* EncodeString(char* buf, ui32_t buf_len) const;
497
498           bool HasValue() const { return true; }
499           ui32_t ArchiveLength() const { return RGBAValueLength; }
500
501           bool Archive(Kumu::MemIOWriter* Writer) const {
502             return Writer->WriteRaw(m_value, RGBAValueLength);
503           }
504
505           bool Unarchive(Kumu::MemIOReader* Reader) {
506             if ( Reader->Remainder() < RGBAValueLength )
507               {
508                 return false;
509               }
510
511             memcpy(m_value, Reader->CurrentData(), RGBAValueLength);
512             Reader->SkipOffset(RGBAValueLength);
513             return true;
514           }
515         };
516
517
518       //
519       class Raw : public Kumu::ByteString
520         {
521         public:
522           Raw();
523           Raw(const Raw& rhs) : Kumu::ByteString() { Copy(rhs); }
524           virtual ~Raw();
525
526           const Raw& operator=(const Raw& rhs) { Copy(rhs); return *this; }
527           void Copy(const Raw& rhs) {
528             if ( KM_SUCCESS(Capacity(rhs.Length())) )
529               {
530                 Set(rhs);
531               }
532           }
533
534           //
535           virtual bool Unarchive(Kumu::MemIOReader* Reader);
536           virtual bool Archive(Kumu::MemIOWriter* Writer) const;
537           const char* EncodeString(char* str_buf, ui32_t buf_len) const;
538         };
539
540     } // namespace MXF
541 } // namespace ASDCP
542
543
544 #endif //_MXFTYPES_H_
545
546 //
547 // end MXFTypes.h
548 //