o General review of Batch/Array distinction throughout the project
[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 <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             if ( this->ItemSize() != item_size ) return false;
139
140             bool result = true;
141             for ( ui32_t i = 0; i < item_count && result; ++i )
142               {
143                 typename ContainerType::value_type tmp_item;
144                 result = tmp_item.Unarchive(Reader);
145
146                 if ( result )
147                   {
148                     this->push_back(tmp_item);
149                   }
150               }
151
152             return result;
153           }
154
155           void Dump(FILE* stream = 0, ui32_t depth = 0) {
156             char identbuf[IdentBufferLen];
157
158             if ( stream == 0 )
159               {
160                 stream = stderr;
161               }
162             
163             typename ContainerType::const_iterator i;
164             for ( i = this->begin(); i != this->end(); ++i )
165               {
166                 fprintf(stream, "  %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
167               }
168           }
169         };
170
171
172       template <class item_type>
173         class PushSet : public std::set<item_type>
174       {
175       public:
176         PushSet() {}
177         virtual ~PushSet() {}
178         void push_back(const item_type& item) { this->insert(item); }
179       };
180
181       template <class ItemType>
182         class Batch : public FixedSizeItemCollection<PushSet<ItemType> >
183       {
184       public:
185         Batch() {}
186         virtual ~Batch() {}
187       };
188
189       template <class ItemType>
190         class Array : public FixedSizeItemCollection<std::vector<ItemType> >
191       {
192       public:
193         Array() {}
194         virtual ~Array() {}
195       };
196
197       //
198       template <class T>
199         class SimpleArray : public std::list<T>, public Kumu::IArchive
200         {
201         public:
202           SimpleArray() {}
203           virtual ~SimpleArray() {}
204
205           //
206           virtual bool Unarchive(Kumu::MemIOReader* Reader)
207             {
208               bool result = true;
209
210               while ( Reader->Remainder() > 0 && result )
211                 {
212                   T Tmp;
213                   result = Tmp.Unarchive(Reader);
214                   this->push_back(Tmp);
215                 }
216
217               return result;
218             }
219
220           inline virtual bool HasValue() const { return ! this->empty(); }
221
222           virtual ui32_t ArchiveLength() const {
223             ui32_t arch_size = 0;
224
225             typename std::list<T>::const_iterator l_i = this->begin();
226
227             for ( ; l_i != this->end(); l_i++ )
228               arch_size += l_i->ArchiveLength();
229             
230             return arch_size;
231           }
232
233           //
234           virtual bool Archive(Kumu::MemIOWriter* Writer) const {
235             bool result = true;
236             typename std::list<T>::const_iterator l_i = this->begin();
237
238             for ( ; l_i != this->end() && result; l_i++ )
239               result = (*l_i).Archive(Writer);
240
241             return result;
242           }
243
244           //
245           void Dump(FILE* stream = 0, ui32_t depth = 0)
246             {
247               char identbuf[IdentBufferLen];
248
249               if ( stream == 0 )
250                 stream = stderr;
251
252               typename std::list<T>::iterator i = this->begin();
253               for ( ; i != this->end(); i++ )
254                 fprintf(stream, "  %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
255             }
256         };
257
258       //
259     class ISO8String : public std::string, public Kumu::IArchive
260         {
261         public:
262           ISO8String() {}
263           ISO8String(const char*);
264           ISO8String(const std::string&);
265           ~ISO8String() {}
266
267           const ISO8String& operator=(const char*);
268           const ISO8String& operator=(const std::string&);
269
270           const char* EncodeString(char* str_buf, ui32_t buf_len) const;
271           inline virtual bool HasValue() const { return ! empty(); }
272           inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t) + size(); }
273           virtual bool Unarchive(Kumu::MemIOReader* Reader);
274           virtual bool Archive(Kumu::MemIOWriter* Writer) const;
275         };
276
277       //
278     class UTF16String : public std::string, public Kumu::IArchive
279         {
280         public:
281           UTF16String() {}
282           UTF16String(const char*);
283           UTF16String(const std::string&);
284           ~UTF16String() {}
285
286           const UTF16String& operator=(const char*);
287           const UTF16String& operator=(const std::string&);
288
289           const char* EncodeString(char* str_buf, ui32_t buf_len) const;
290           inline virtual bool HasValue() const { return ! empty(); }
291           inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t) + size(); }
292           virtual bool Unarchive(Kumu::MemIOReader* Reader);
293           virtual bool Archive(Kumu::MemIOWriter* Writer) const;
294         };
295
296       //
297       class Rational : public ASDCP::Rational, public Kumu::IArchive
298         {
299         public:
300           Rational() {}
301           ~Rational() {}
302
303           Rational(const Rational& rhs) : ASDCP::Rational(), IArchive() {
304             Numerator = rhs.Numerator;
305             Denominator = rhs.Denominator;
306           }
307
308           const Rational& operator=(const Rational& rhs) {
309             Numerator = rhs.Numerator;
310             Denominator = rhs.Denominator;
311             return *this;
312           }
313
314           Rational(const ASDCP::Rational& rhs) {
315             Numerator = rhs.Numerator;
316             Denominator = rhs.Denominator;
317           }
318
319           const Rational& operator=(const ASDCP::Rational& rhs) {
320             Numerator = rhs.Numerator;
321             Denominator = rhs.Denominator;
322             return *this;
323           }
324
325           //
326           inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
327             snprintf(str_buf, buf_len, "%d/%d", Numerator, Denominator);
328             return str_buf;
329           }
330
331           inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
332             if ( ! Reader->ReadUi32BE((ui32_t*)&Numerator) ) return false;
333             if ( ! Reader->ReadUi32BE((ui32_t*)&Denominator) ) return false;
334             return true;
335           }
336
337           inline virtual bool HasValue() const { return true; }
338           inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*2; }
339
340           inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
341             if ( ! Writer->WriteUi32BE((ui32_t)Numerator) ) return false;
342             if ( ! Writer->WriteUi32BE((ui32_t)Denominator) ) return false;
343             return true;
344           }
345         };
346
347       //
348       class VersionType : public Kumu::IArchive
349         {
350         public:
351           enum Release_t { RL_UNKNOWN, RL_RELEASE, RL_DEVELOPMENT, RL_PATCHED, RL_BETA, RL_PRIVATE, RL_MAX };
352           ui16_t Major;
353           ui16_t Minor;
354           ui16_t Patch;
355           ui16_t Build;
356           Release_t Release;
357
358           VersionType() : Major(0), Minor(0), Patch(0), Build(0), Release(RL_UNKNOWN) {}
359           VersionType(const VersionType& rhs) { Copy(rhs); }
360           virtual ~VersionType() {}
361
362           const VersionType& operator=(const VersionType& rhs) { Copy(rhs); return *this; }
363           void Copy(const VersionType& rhs) {
364             Major = rhs.Major;
365             Minor = rhs.Minor;
366             Patch = rhs.Patch;
367             Build = rhs.Build;
368             Release = rhs.Release;
369           }
370
371           void Dump(FILE* = 0);
372
373           const char* EncodeString(char* str_buf, ui32_t buf_len) const {
374             snprintf(str_buf, buf_len, "%hu.%hu.%hu.%hur%hu", Major, Minor, Patch, Build, ui16_t(Release));
375             return str_buf;
376           }
377
378           virtual bool Unarchive(Kumu::MemIOReader* Reader) {
379             if ( ! Reader->ReadUi16BE(&Major) ) return false;
380             if ( ! Reader->ReadUi16BE(&Minor) ) return false;
381             if ( ! Reader->ReadUi16BE(&Patch) ) return false;
382             if ( ! Reader->ReadUi16BE(&Build) ) return false;
383             ui16_t tmp_release;
384             if ( ! Reader->ReadUi16BE(&tmp_release) ) return false;
385             Release = (Release_t)tmp_release;
386             return true;
387           }
388
389           inline virtual bool HasValue() const { return true; }
390           inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*5; }
391
392           virtual bool Archive(Kumu::MemIOWriter* Writer) const {
393             if ( ! Writer->WriteUi16BE(Major) ) return false;
394             if ( ! Writer->WriteUi16BE(Minor) ) return false;
395             if ( ! Writer->WriteUi16BE(Patch) ) return false;
396             if ( ! Writer->WriteUi16BE(Build) ) return false;
397             if ( ! Writer->WriteUi16BE((ui16_t)(Release & 0x0000ffffL)) ) return false;
398             return true;
399           }
400         };
401
402       /*
403         The RGBALayout type shall be a fixed-size 8 element sequence with a total length
404         of 16 bytes, where each element shall consist of the RGBAComponent type with the
405         following fields:
406
407         Code (UInt8): Enumerated value specifying component (i.e., component identifier).
408         "0" is the layout terminator.
409
410         Depth (UInt8): Integer specifying the number of bits occupied (see also G.2.26) 
411           1->32 indicates integer depth
412           253 = HALF (floating point 16-bit value)
413           254 = IEEE floating point 32-bit value
414           255 = IEEE floating point 64-bit value
415           0 = RGBALayout terminator
416
417         A Fill component indicates unused bits. After the components have been specified,
418         the remaining Code and Size fields shall be set to zero (0).
419
420         For each component in the Pixel, one of the following Codes or the terminator
421         shall be specified (explained below):
422
423         Code    ASCII
424
425       */
426       struct RGBALayoutTableEntry
427       {
428         byte_t code;
429         char symbol;
430         const char* label;
431       };
432
433       struct RGBALayoutTableEntry const RGBALayoutTable[] = {
434         { 0x52, 'R', "Red component" },
435         { 0x47, 'G', "Green component" },
436         { 0x42, 'B', "Blue component" },
437         { 0x41, 'A', "Alpha component" },
438         { 0x72, 'r', "Red component (LSBs)" },
439         { 0x67, 'g', "Green component (LSBs)" },
440         { 0x62, 'b', "Blue component (LSBs)" },
441         { 0x61, 'a', "Alpha component (LSBs)" },
442         { 0x46, 'F', "Fill component" },
443         { 0x50, 'P', "Palette code" },
444         { 0x55, 'U', "Color Difference Sample (e.g. U, Cb, I etc.)" },
445         { 0x56, 'V', "Color Difference Sample (e.g. V, Cr, Q etc.)" },
446         { 0x57, 'W', "Composite Video" },
447         { 0x58, 'X', "Non co-sited luma component" },
448         { 0x59, 'Y', "Luma component" },
449         { 0x5a, 'Z', "Depth component (SMPTE ST 268 compatible)" },
450         { 0x75, 'u', "Color Difference Sample (e.g. U, Cb, I etc.) (LSBs)" },
451         { 0x76, 'v', "Color Difference Sample (e.g. V, Cr, Q etc.) (LSBs)" },
452         { 0x77, 'w', "Composite Video (LSBs)" },
453         { 0x78, 'x', "Non co-sited luma component (LSBs)" },
454         { 0x79, 'y', "Luma component (LSBs)" },
455         { 0x7a, 'z', "Depth component (LSBs) (SMPTE ST 268 compatible)" },
456         { 0xd8, 'X', "The DCDM X color component (see SMPTE ST 428-1 X')" },
457         { 0xd9, 'Y', "The DCDM Y color component (see SMPTE ST 428-1 Y')" },
458         { 0xda, 'Z', "The DCDM Z color component (see SMPTE ST 428-1 Z')" },
459         { 0x00, '_', "Terminator" }
460       };
461
462
463       size_t const RGBAValueLength = 16;
464
465       byte_t const RGBAValue_RGB_10[RGBAValueLength] = { 'R', 10, 'G', 10, 'B', 10, 0, 0 };
466       byte_t const RGBAValue_RGB_8[RGBAValueLength]  = { 'R', 8,  'G', 8,  'B', 8,  0, 0 };
467       byte_t const RGBAValue_YUV_10[RGBAValueLength] = { 'Y', 10, 'U', 10, 'V', 10, 0, 0 };
468       byte_t const RGBAValue_YUV_8[RGBAValueLength]  = { 'Y', 8,  'U', 8,  'V', 8,  0, 0 };
469       byte_t const RGBAValue_DCDM[RGBAValueLength] = { 0xd8, 10, 0xd9, 10, 0xda, 10, 0, 0 };
470
471
472       class RGBALayout : public Kumu::IArchive
473         {
474           byte_t m_value[RGBAValueLength];
475
476         public:
477           RGBALayout();
478           RGBALayout(const byte_t* value);
479           ~RGBALayout();
480
481           RGBALayout(const RGBALayout& rhs) { Set(rhs.m_value); }
482           const RGBALayout& operator=(const RGBALayout& rhs) { Set(rhs.m_value); return *this; }
483           
484           void Set(const byte_t* value) {
485             memcpy(m_value, value, RGBAValueLength);
486           }
487
488           const char* EncodeString(char* buf, ui32_t buf_len) const;
489
490           bool HasValue() const { return true; }
491           ui32_t ArchiveLength() const { return RGBAValueLength; }
492
493           bool Archive(Kumu::MemIOWriter* Writer) const {
494             return Writer->WriteRaw(m_value, RGBAValueLength);
495           }
496
497           bool Unarchive(Kumu::MemIOReader* Reader) {
498             if ( Reader->Remainder() < RGBAValueLength )
499               {
500                 return false;
501               }
502
503             memcpy(m_value, Reader->CurrentData(), RGBAValueLength);
504             Reader->SkipOffset(RGBAValueLength);
505             return true;
506           }
507         };
508
509
510       //
511       class Raw : public Kumu::ByteString
512         {
513         public:
514           Raw();
515           Raw(const Raw& rhs) { Copy(rhs); }
516           virtual ~Raw();
517
518           const Raw& operator=(const Raw& rhs) { Copy(rhs); return *this; }
519           void Copy(const Raw& rhs) {
520             if ( KM_SUCCESS(Capacity(rhs.Length())) )
521               {
522                 Set(rhs);
523               }
524           }
525
526           //
527           virtual bool Unarchive(Kumu::MemIOReader* Reader);
528           virtual bool Archive(Kumu::MemIOWriter* Writer) const;
529           const char* EncodeString(char* str_buf, ui32_t buf_len) const;
530         };
531
532     } // namespace MXF
533 } // namespace ASDCP
534
535
536 #endif //_MXFTYPES_H_
537
538 //
539 // end MXFTypes.h
540 //