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