2 Copyright (c) 2005-2019, John Hurst
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
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.
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.
43 // used with TLVReader::Read*
45 // these are used below to manufacture arguments
46 #define OBJ_READ_ARGS(s,l) m_Dict->Type(MDD_##s##_##l), &l
47 #define OBJ_WRITE_ARGS(s,l) m_Dict->Type(MDD_##s##_##l), &l
48 #define OBJ_READ_ARGS_OPT(s,l) m_Dict->Type(MDD_##s##_##l), &l.get()
49 #define OBJ_WRITE_ARGS_OPT(s,l) m_Dict->Type(MDD_##s##_##l), &l.get()
50 #define OBJ_TYPE_ARGS(t) m_Dict->Type(MDD_##t).ul
57 typedef std::pair<ui32_t, ui32_t> ItemInfo;
58 typedef std::map<TagValue, ItemInfo> TagMap;
61 class TLVReader : public Kumu::MemIOReader
65 IPrimerLookup* m_Lookup;
68 ASDCP_NO_COPY_CONSTRUCT(TLVReader);
71 TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* = 0);
72 bool FindTL(const MDDEntry&);
73 Result_t ReadObject(const MDDEntry&, Kumu::IArchive*);
74 Result_t ReadUi8(const MDDEntry&, ui8_t*);
75 Result_t ReadUi16(const MDDEntry&, ui16_t*);
76 Result_t ReadUi32(const MDDEntry&, ui32_t*);
77 Result_t ReadUi64(const MDDEntry&, ui64_t*);
81 class TLVWriter : public Kumu::MemIOWriter
85 IPrimerLookup* m_Lookup;
88 ASDCP_NO_COPY_CONSTRUCT(TLVWriter);
89 Result_t WriteTag(const MDDEntry&);
92 TLVWriter(byte_t* p, ui32_t c, IPrimerLookup* = 0);
93 Result_t WriteObject(const MDDEntry&, Kumu::IArchive*);
94 Result_t WriteUi8(const MDDEntry&, ui8_t*);
95 Result_t WriteUi16(const MDDEntry&, ui16_t*);
96 Result_t WriteUi32(const MDDEntry&, ui32_t*);
97 Result_t WriteUi64(const MDDEntry&, ui64_t*);
101 template <class ContainerType>
102 class FixedSizeItemCollection : public ContainerType, public Kumu::IArchive
105 FixedSizeItemCollection() {}
106 virtual ~FixedSizeItemCollection() {}
108 ui32_t ItemSize() const {
109 typename ContainerType::value_type tmp_item;
110 return tmp_item.ArchiveLength();
113 bool HasValue() const { return ! this->empty(); }
115 ui32_t ArchiveLength() const {
116 return ( sizeof(ui32_t) * 2 ) + ( (ui32_t)this->size() * this->ItemSize() );
119 bool Archive(Kumu::MemIOWriter* Writer) const {
120 if ( ! Writer->WriteUi32BE((ui32_t)this->size()) ) return false;
121 if ( ! Writer->WriteUi32BE((ui32_t)this->ItemSize()) ) return false;
122 if ( this->empty() ) return true;
124 typename ContainerType::const_iterator i;
126 for ( i = this->begin(); i != this->end() && result; ++i )
128 result = i->Archive(Writer);
135 bool Unarchive(Kumu::MemIOReader* Reader) {
136 ui32_t item_count, item_size;
137 if ( ! Reader->ReadUi32BE(&item_count) ) return false;
138 if ( ! Reader->ReadUi32BE(&item_size) ) return false;
140 if ( item_count > 0 )
142 if ( this->ItemSize() != item_size ) return false;
146 for ( ui32_t i = 0; i < item_count && result; ++i )
148 typename ContainerType::value_type tmp_item;
149 result = tmp_item.Unarchive(Reader);
153 this->push_back(tmp_item);
160 void Dump(FILE* stream = 0, ui32_t depth = 0) {
162 char identbuf[IdentBufferLen];
169 typename ContainerType::const_iterator i;
170 for ( i = this->begin(); i != this->end(); ++i )
172 fprintf(stream, " %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
178 template <class item_type>
179 class PushSet : public std::set<item_type>
183 virtual ~PushSet() {}
184 void push_back(const item_type& item) { this->insert(item); }
187 template <class ItemType>
188 class Batch : public FixedSizeItemCollection<PushSet<ItemType> >
195 template <class ItemType>
196 class Array : public FixedSizeItemCollection<std::vector<ItemType> >
205 class SimpleArray : public std::list<T>, public Kumu::IArchive
209 virtual ~SimpleArray() {}
212 bool Unarchive(Kumu::MemIOReader* Reader)
216 while ( Reader->Remainder() > 0 && result )
219 result = Tmp.Unarchive(Reader);
223 this->push_back(Tmp);
230 inline bool HasValue() const { return ! this->empty(); }
232 ui32_t ArchiveLength() const {
233 ui32_t arch_size = 0;
235 typename std::list<T>::const_iterator l_i = this->begin();
237 for ( ; l_i != this->end(); l_i++ )
238 arch_size += l_i->ArchiveLength();
244 bool Archive(Kumu::MemIOWriter* Writer) const {
246 typename std::list<T>::const_iterator l_i = this->begin();
248 for ( ; l_i != this->end() && result; l_i++ )
249 result = (*l_i).Archive(Writer);
255 void Dump(FILE* stream = 0, ui32_t depth = 0)
258 char identbuf[IdentBufferLen];
263 typename std::list<T>::iterator i = this->begin();
264 for ( ; i != this->end(); i++ )
265 fprintf(stream, " %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
270 class ISO8String : public std::string, public Kumu::IArchive
274 ISO8String(const char*);
275 ISO8String(const std::string&);
278 const ISO8String& operator=(const char*);
279 const ISO8String& operator=(const std::string&);
281 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
282 inline virtual bool HasValue() const { return ! empty(); }
283 inline virtual ui32_t ArchiveLength() const { return (ui32_t)(sizeof(ui32_t) + size()); }
284 virtual bool Unarchive(Kumu::MemIOReader* Reader);
285 virtual bool Archive(Kumu::MemIOWriter* Writer) const;
289 class UTF16String : public std::string, public Kumu::IArchive
293 UTF16String(const char*);
294 UTF16String(const std::string&);
297 const UTF16String& operator=(const char*);
298 const UTF16String& operator=(const std::string&);
300 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
301 inline virtual bool HasValue() const { return ! empty(); }
302 inline virtual ui32_t ArchiveLength() const { return (ui32_t)(sizeof(ui32_t) + size()); }
303 virtual bool Unarchive(Kumu::MemIOReader* Reader);
304 virtual bool Archive(Kumu::MemIOWriter* Writer) const;
308 class Rational : public ASDCP::Rational, public Kumu::IArchive
314 Rational(const Rational& rhs) : ASDCP::Rational(), IArchive() {
315 Numerator = rhs.Numerator;
316 Denominator = rhs.Denominator;
319 const Rational& operator=(const Rational& rhs) {
320 Numerator = rhs.Numerator;
321 Denominator = rhs.Denominator;
325 Rational(const ASDCP::Rational& rhs) {
326 Numerator = rhs.Numerator;
327 Denominator = rhs.Denominator;
330 const Rational& operator=(const ASDCP::Rational& rhs) {
331 Numerator = rhs.Numerator;
332 Denominator = rhs.Denominator;
337 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
338 snprintf(str_buf, buf_len, "%d/%d", Numerator, Denominator);
342 inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
343 if ( ! Reader->ReadUi32BE((ui32_t*)&Numerator) ) return false;
344 if ( ! Reader->ReadUi32BE((ui32_t*)&Denominator) ) return false;
348 inline virtual bool HasValue() const { return true; }
349 inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*2; }
351 inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
352 if ( ! Writer->WriteUi32BE((ui32_t)Numerator) ) return false;
353 if ( ! Writer->WriteUi32BE((ui32_t)Denominator) ) return false;
359 class LineMapPair : public Kumu::IArchive
365 LineMapPair() : First(0), Second() {}
368 LineMapPair(const ui32_t& first, const ui32_t& second) : IArchive() {
373 LineMapPair(const LineMapPair& rhs) : IArchive() {
378 const LineMapPair& operator=(const LineMapPair& rhs) {
385 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
386 snprintf(str_buf, buf_len, "%d,%d", First, Second);
390 inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
392 if ( ! Reader->ReadUi32BE(&n) ) return false;
393 if ( n != 2 ) return false;
394 if ( ! Reader->ReadUi32BE(&n) ) return false;
395 if ( n != 4 ) return false;
396 if ( ! Reader->ReadUi32BE((ui32_t*)&First) ) return false;
397 if ( ! Reader->ReadUi32BE((ui32_t*)&Second) ) return false;
401 inline virtual bool HasValue() const { return true; }
402 inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*4; }
404 inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
405 if ( ! Writer->WriteUi32BE(2UL) ) return false;
406 if ( ! Writer->WriteUi32BE(4UL) ) return false;
407 if ( ! Writer->WriteUi32BE((ui32_t)First) ) return false;
408 if ( ! Writer->WriteUi32BE((ui32_t)Second) ) return false;
414 class ColorPrimary : public Kumu::IArchive
420 ColorPrimary() : X(0), Y(0) {}
423 ColorPrimary(const ui16_t& x, const ui16_t& y) : X(x), Y(y) {}
425 ColorPrimary(const ColorPrimary& rhs) { Copy(rhs); }
426 const ColorPrimary& operator=(const ColorPrimary& rhs) { Copy(rhs); return *this; }
428 void Copy(const ColorPrimary& rhs) {
434 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
435 snprintf(str_buf, buf_len, "%d,%d", X, Y);
439 inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
440 if ( ! Reader->ReadUi16BE((ui16_t*)&X) ) return false;
441 if ( ! Reader->ReadUi16BE((ui16_t*)&Y) ) return false;
445 inline virtual bool HasValue() const { return X || Y; }
446 inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*2; }
448 inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
449 if ( ! Writer->WriteUi16BE((ui16_t)X) ) return false;
450 if ( ! Writer->WriteUi16BE((ui16_t)Y) ) return false;
456 class ThreeColorPrimaries : public Kumu::IArchive
463 ThreeColorPrimaries() {}
464 ~ThreeColorPrimaries() {}
466 ThreeColorPrimaries(const ColorPrimary& first, const ColorPrimary& second, const ColorPrimary& third) :
467 First(first), Second(second), Third(third) {}
469 ThreeColorPrimaries(const ThreeColorPrimaries& rhs) { Copy(rhs); }
470 const ThreeColorPrimaries& operator=(const ThreeColorPrimaries& rhs) { Copy(rhs); return *this; }
472 void Copy(const ThreeColorPrimaries& rhs) {
479 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
480 snprintf(str_buf, buf_len, "%d,%d;%d,%d;%d,%d", First.X, First.Y, Second.X, Second.Y, Third.X, Third.Y);
484 inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
485 First.Unarchive(Reader);
486 Second.Unarchive(Reader);
487 Third.Unarchive(Reader);
491 inline virtual bool HasValue() const {
492 return First.HasValue() || Second.HasValue() || Third.HasValue();
495 inline virtual ui32_t ArchiveLength() const {
496 return First.ArchiveLength()
497 + Second.ArchiveLength()
498 + Third.ArchiveLength();
501 inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
502 First.Archive(Writer);
503 Second.Archive(Writer);
504 Third.Archive(Writer);
510 class VersionType : public Kumu::IArchive
513 enum Release_t { RL_UNKNOWN, RL_RELEASE, RL_DEVELOPMENT, RL_PATCHED, RL_BETA, RL_PRIVATE, RL_MAX };
520 VersionType() : Major(0), Minor(0), Patch(0), Build(0), Release(RL_UNKNOWN) {}
521 VersionType(const VersionType& rhs) { Copy(rhs); }
522 virtual ~VersionType() {}
524 const VersionType& operator=(const VersionType& rhs) { Copy(rhs); return *this; }
525 void Copy(const VersionType& rhs) {
530 Release = rhs.Release;
533 void Dump(FILE* = 0);
535 const char* EncodeString(char* str_buf, ui32_t buf_len) const {
536 snprintf(str_buf, buf_len, "%hu.%hu.%hu.%hur%hu", Major, Minor, Patch, Build, ui16_t(Release));
540 virtual bool Unarchive(Kumu::MemIOReader* Reader) {
541 if ( ! Reader->ReadUi16BE(&Major) ) return false;
542 if ( ! Reader->ReadUi16BE(&Minor) ) return false;
543 if ( ! Reader->ReadUi16BE(&Patch) ) return false;
544 if ( ! Reader->ReadUi16BE(&Build) ) return false;
546 if ( ! Reader->ReadUi16BE(&tmp_release) ) return false;
547 Release = (Release_t)tmp_release;
551 inline virtual bool HasValue() const { return true; }
552 inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*5; }
554 virtual bool Archive(Kumu::MemIOWriter* Writer) const {
555 if ( ! Writer->WriteUi16BE(Major) ) return false;
556 if ( ! Writer->WriteUi16BE(Minor) ) return false;
557 if ( ! Writer->WriteUi16BE(Patch) ) return false;
558 if ( ! Writer->WriteUi16BE(Build) ) return false;
559 if ( ! Writer->WriteUi16BE((ui16_t)(Release & 0x0000ffffL)) ) return false;
565 The RGBALayout type shall be a fixed-size 8 element sequence with a total length
566 of 16 bytes, where each element shall consist of the RGBAComponent type with the
569 Code (UInt8): Enumerated value specifying component (i.e., component identifier).
570 "0" is the layout terminator.
572 Depth (UInt8): Integer specifying the number of bits occupied (see also G.2.26)
573 1->32 indicates integer depth
574 253 = HALF (floating point 16-bit value)
575 254 = IEEE floating point 32-bit value
576 255 = IEEE floating point 64-bit value
577 0 = RGBALayout terminator
579 A Fill component indicates unused bits. After the components have been specified,
580 the remaining Code and Size fields shall be set to zero (0).
582 For each component in the Pixel, one of the following Codes or the terminator
583 shall be specified (explained below):
588 struct RGBALayoutTableEntry
595 struct RGBALayoutTableEntry const RGBALayoutTable[] = {
596 { 0x52, 'R', "Red component" },
597 { 0x47, 'G', "Green component" },
598 { 0x42, 'B', "Blue component" },
599 { 0x41, 'A', "Alpha component" },
600 { 0x72, 'r', "Red component (LSBs)" },
601 { 0x67, 'g', "Green component (LSBs)" },
602 { 0x62, 'b', "Blue component (LSBs)" },
603 { 0x61, 'a', "Alpha component (LSBs)" },
604 { 0x46, 'F', "Fill component" },
605 { 0x50, 'P', "Palette code" },
606 { 0x55, 'U', "Color Difference Sample (e.g. U, Cb, I etc.)" },
607 { 0x56, 'V', "Color Difference Sample (e.g. V, Cr, Q etc.)" },
608 { 0x57, 'W', "Composite Video" },
609 { 0x58, 'X', "Non co-sited luma component" },
610 { 0x59, 'Y', "Luma component" },
611 { 0x5a, 'Z', "Depth component (SMPTE ST 268 compatible)" },
612 { 0x75, 'u', "Color Difference Sample (e.g. U, Cb, I etc.) (LSBs)" },
613 { 0x76, 'v', "Color Difference Sample (e.g. V, Cr, Q etc.) (LSBs)" },
614 { 0x77, 'w', "Composite Video (LSBs)" },
615 { 0x78, 'x', "Non co-sited luma component (LSBs)" },
616 { 0x79, 'y', "Luma component (LSBs)" },
617 { 0x7a, 'z', "Depth component (LSBs) (SMPTE ST 268 compatible)" },
618 { 0xd8, 'X', "The DCDM X color component (see SMPTE ST 428-1 X')" },
619 { 0xd9, 'Y', "The DCDM Y color component (see SMPTE ST 428-1 Y')" },
620 { 0xda, 'Z', "The DCDM Z color component (see SMPTE ST 428-1 Z')" },
621 { 0x00, '_', "Terminator" }
625 size_t const RGBAValueLength = 16;
627 byte_t const RGBAValue_RGB_10[RGBAValueLength] = { 'R', 10, 'G', 10, 'B', 10, 0, 0 };
628 byte_t const RGBAValue_RGB_8[RGBAValueLength] = { 'R', 8, 'G', 8, 'B', 8, 0, 0 };
629 byte_t const RGBAValue_YUV_10[RGBAValueLength] = { 'Y', 10, 'U', 10, 'V', 10, 0, 0 };
630 byte_t const RGBAValue_YUV_8[RGBAValueLength] = { 'Y', 8, 'U', 8, 'V', 8, 0, 0 };
631 byte_t const RGBAValue_DCDM[RGBAValueLength] = { 0xd8, 10, 0xd9, 10, 0xda, 10, 0, 0 };
634 class RGBALayout : public Kumu::IArchive
636 byte_t m_value[RGBAValueLength];
640 RGBALayout(const byte_t* value);
643 RGBALayout(const RGBALayout& rhs) { Set(rhs.m_value); }
644 const RGBALayout& operator=(const RGBALayout& rhs) { Set(rhs.m_value); return *this; }
646 void Set(const byte_t* value) {
647 memcpy(m_value, value, RGBAValueLength);
650 const char* EncodeString(char* buf, ui32_t buf_len) const;
652 bool HasValue() const { return true; }
653 ui32_t ArchiveLength() const { return RGBAValueLength; }
655 bool Archive(Kumu::MemIOWriter* Writer) const {
656 return Writer->WriteRaw(m_value, RGBAValueLength);
659 bool Unarchive(Kumu::MemIOReader* Reader) {
660 if ( Reader->Remainder() < RGBAValueLength )
665 memcpy(m_value, Reader->CurrentData(), RGBAValueLength);
666 Reader->SkipOffset(RGBAValueLength);
673 class Raw : public Kumu::ByteString
680 virtual bool Unarchive(Kumu::MemIOReader* Reader);
681 virtual bool Archive(Kumu::MemIOWriter* Writer) const;
682 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
686 class J2KExtendedCapabilitiesType : public Kumu::IArchive
690 Array<Kumu::ArchivableUi16> Ccap;
692 bool HasValue() const { return true; }
693 ui32_t ArchiveLength() const { return 0; }
695 bool Archive(Kumu::MemIOWriter* Writer) const;
696 bool Unarchive(Kumu::MemIOReader* Reader);
697 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
704 #endif //_MXFTYPES_H_