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) {
161 char identbuf[IdentBufferLen];
168 typename ContainerType::const_iterator i;
169 for ( i = this->begin(); i != this->end(); ++i )
171 fprintf(stream, " %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
177 template <class item_type>
178 class PushSet : public std::set<item_type>
182 virtual ~PushSet() {}
183 void push_back(const item_type& item) { this->insert(item); }
186 template <class ItemType>
187 class Batch : public FixedSizeItemCollection<PushSet<ItemType> >
194 template <class ItemType>
195 class Array : public FixedSizeItemCollection<std::vector<ItemType> >
204 class SimpleArray : public std::list<T>, public Kumu::IArchive
208 virtual ~SimpleArray() {}
211 bool Unarchive(Kumu::MemIOReader* Reader)
215 while ( Reader->Remainder() > 0 && result )
218 result = Tmp.Unarchive(Reader);
222 this->push_back(Tmp);
229 inline bool HasValue() const { return ! this->empty(); }
231 ui32_t ArchiveLength() const {
232 ui32_t arch_size = 0;
234 typename std::list<T>::const_iterator l_i = this->begin();
236 for ( ; l_i != this->end(); l_i++ )
237 arch_size += l_i->ArchiveLength();
243 bool Archive(Kumu::MemIOWriter* Writer) const {
245 typename std::list<T>::const_iterator l_i = this->begin();
247 for ( ; l_i != this->end() && result; l_i++ )
248 result = (*l_i).Archive(Writer);
254 void Dump(FILE* stream = 0, ui32_t depth = 0)
256 char identbuf[IdentBufferLen];
261 typename std::list<T>::iterator i = this->begin();
262 for ( ; i != this->end(); i++ )
263 fprintf(stream, " %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
268 class ISO8String : public std::string, public Kumu::IArchive
272 ISO8String(const char*);
273 ISO8String(const std::string&);
276 const ISO8String& operator=(const char*);
277 const ISO8String& operator=(const std::string&);
279 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
280 inline virtual bool HasValue() const { return ! empty(); }
281 inline virtual ui32_t ArchiveLength() const { return (ui32_t)(sizeof(ui32_t) + size()); }
282 virtual bool Unarchive(Kumu::MemIOReader* Reader);
283 virtual bool Archive(Kumu::MemIOWriter* Writer) const;
287 class UTF16String : public std::string, public Kumu::IArchive
291 UTF16String(const char*);
292 UTF16String(const std::string&);
295 const UTF16String& operator=(const char*);
296 const UTF16String& operator=(const std::string&);
298 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
299 inline virtual bool HasValue() const { return ! empty(); }
300 inline virtual ui32_t ArchiveLength() const { return (ui32_t)(sizeof(ui32_t) + size()); }
301 virtual bool Unarchive(Kumu::MemIOReader* Reader);
302 virtual bool Archive(Kumu::MemIOWriter* Writer) const;
306 class Rational : public ASDCP::Rational, public Kumu::IArchive
312 Rational(const Rational& rhs) : ASDCP::Rational(), IArchive() {
313 Numerator = rhs.Numerator;
314 Denominator = rhs.Denominator;
317 const Rational& operator=(const Rational& rhs) {
318 Numerator = rhs.Numerator;
319 Denominator = rhs.Denominator;
323 Rational(const ASDCP::Rational& rhs) {
324 Numerator = rhs.Numerator;
325 Denominator = rhs.Denominator;
328 const Rational& operator=(const ASDCP::Rational& rhs) {
329 Numerator = rhs.Numerator;
330 Denominator = rhs.Denominator;
335 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
336 snprintf(str_buf, buf_len, "%d/%d", Numerator, Denominator);
340 inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
341 if ( ! Reader->ReadUi32BE((ui32_t*)&Numerator) ) return false;
342 if ( ! Reader->ReadUi32BE((ui32_t*)&Denominator) ) return false;
346 inline virtual bool HasValue() const { return true; }
347 inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*2; }
349 inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
350 if ( ! Writer->WriteUi32BE((ui32_t)Numerator) ) return false;
351 if ( ! Writer->WriteUi32BE((ui32_t)Denominator) ) return false;
357 class LineMapPair : public Kumu::IArchive
363 LineMapPair() : First(0), Second() {}
366 LineMapPair(const ui32_t& first, const ui32_t& second) : IArchive() {
371 LineMapPair(const LineMapPair& rhs) : IArchive() {
376 const LineMapPair& operator=(const LineMapPair& rhs) {
383 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
384 snprintf(str_buf, buf_len, "%d,%d", First, Second);
388 inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
390 if ( ! Reader->ReadUi32BE(&n) ) return false;
391 if ( n != 2 ) return false;
392 if ( ! Reader->ReadUi32BE(&n) ) return false;
393 if ( n != 4 ) return false;
394 if ( ! Reader->ReadUi32BE((ui32_t*)&First) ) return false;
395 if ( ! Reader->ReadUi32BE((ui32_t*)&Second) ) return false;
399 inline virtual bool HasValue() const { return true; }
400 inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*4; }
402 inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
403 if ( ! Writer->WriteUi32BE(2UL) ) return false;
404 if ( ! Writer->WriteUi32BE(4UL) ) return false;
405 if ( ! Writer->WriteUi32BE((ui32_t)First) ) return false;
406 if ( ! Writer->WriteUi32BE((ui32_t)Second) ) return false;
412 class ColorPrimary : public Kumu::IArchive
418 ColorPrimary() : X(0), Y(0) {}
421 ColorPrimary(const ui16_t& x, const ui16_t& y) : X(x), Y(y) {}
423 ColorPrimary(const ColorPrimary& rhs) { Copy(rhs); }
424 const ColorPrimary& operator=(const ColorPrimary& rhs) { Copy(rhs); return *this; }
426 void Copy(const ColorPrimary& rhs) {
432 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
433 snprintf(str_buf, buf_len, "%d,%d", X, Y);
437 inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
438 if ( ! Reader->ReadUi16BE((ui16_t*)&X) ) return false;
439 if ( ! Reader->ReadUi16BE((ui16_t*)&Y) ) return false;
443 inline virtual bool HasValue() const { return X || Y; }
444 inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*2; }
446 inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
447 if ( ! Writer->WriteUi16BE((ui16_t)X) ) return false;
448 if ( ! Writer->WriteUi16BE((ui16_t)Y) ) return false;
454 class ThreeColorPrimaries : public Kumu::IArchive
461 ThreeColorPrimaries() {}
462 ~ThreeColorPrimaries() {}
464 ThreeColorPrimaries(const ColorPrimary& first, const ColorPrimary& second, const ColorPrimary& third) :
465 First(first), Second(second), Third(third) {}
467 ThreeColorPrimaries(const ThreeColorPrimaries& rhs) { Copy(rhs); }
468 const ThreeColorPrimaries& operator=(const ThreeColorPrimaries& rhs) { Copy(rhs); return *this; }
470 void Copy(const ThreeColorPrimaries& rhs) {
477 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
478 snprintf(str_buf, buf_len, "%d,%d;%d,%d;%d,%d", First.X, First.Y, Second.X, Second.Y, Third.X, Third.Y);
482 inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
483 First.Unarchive(Reader);
484 Second.Unarchive(Reader);
485 Third.Unarchive(Reader);
489 inline virtual bool HasValue() const {
490 return First.HasValue() || Second.HasValue() || Third.HasValue();
493 inline virtual ui32_t ArchiveLength() const {
494 return First.ArchiveLength()
495 + Second.ArchiveLength()
496 + Third.ArchiveLength();
499 inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
500 First.Archive(Writer);
501 Second.Archive(Writer);
502 Third.Archive(Writer);
508 class VersionType : public Kumu::IArchive
511 enum Release_t { RL_UNKNOWN, RL_RELEASE, RL_DEVELOPMENT, RL_PATCHED, RL_BETA, RL_PRIVATE, RL_MAX };
518 VersionType() : Major(0), Minor(0), Patch(0), Build(0), Release(RL_UNKNOWN) {}
519 VersionType(const VersionType& rhs) { Copy(rhs); }
520 virtual ~VersionType() {}
522 const VersionType& operator=(const VersionType& rhs) { Copy(rhs); return *this; }
523 void Copy(const VersionType& rhs) {
528 Release = rhs.Release;
531 void Dump(FILE* = 0);
533 const char* EncodeString(char* str_buf, ui32_t buf_len) const {
534 snprintf(str_buf, buf_len, "%hu.%hu.%hu.%hur%hu", Major, Minor, Patch, Build, ui16_t(Release));
538 virtual bool Unarchive(Kumu::MemIOReader* Reader) {
539 if ( ! Reader->ReadUi16BE(&Major) ) return false;
540 if ( ! Reader->ReadUi16BE(&Minor) ) return false;
541 if ( ! Reader->ReadUi16BE(&Patch) ) return false;
542 if ( ! Reader->ReadUi16BE(&Build) ) return false;
544 if ( ! Reader->ReadUi16BE(&tmp_release) ) return false;
545 Release = (Release_t)tmp_release;
549 inline virtual bool HasValue() const { return true; }
550 inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*5; }
552 virtual bool Archive(Kumu::MemIOWriter* Writer) const {
553 if ( ! Writer->WriteUi16BE(Major) ) return false;
554 if ( ! Writer->WriteUi16BE(Minor) ) return false;
555 if ( ! Writer->WriteUi16BE(Patch) ) return false;
556 if ( ! Writer->WriteUi16BE(Build) ) return false;
557 if ( ! Writer->WriteUi16BE((ui16_t)(Release & 0x0000ffffL)) ) return false;
563 The RGBALayout type shall be a fixed-size 8 element sequence with a total length
564 of 16 bytes, where each element shall consist of the RGBAComponent type with the
567 Code (UInt8): Enumerated value specifying component (i.e., component identifier).
568 "0" is the layout terminator.
570 Depth (UInt8): Integer specifying the number of bits occupied (see also G.2.26)
571 1->32 indicates integer depth
572 253 = HALF (floating point 16-bit value)
573 254 = IEEE floating point 32-bit value
574 255 = IEEE floating point 64-bit value
575 0 = RGBALayout terminator
577 A Fill component indicates unused bits. After the components have been specified,
578 the remaining Code and Size fields shall be set to zero (0).
580 For each component in the Pixel, one of the following Codes or the terminator
581 shall be specified (explained below):
586 struct RGBALayoutTableEntry
593 struct RGBALayoutTableEntry const RGBALayoutTable[] = {
594 { 0x52, 'R', "Red component" },
595 { 0x47, 'G', "Green component" },
596 { 0x42, 'B', "Blue component" },
597 { 0x41, 'A', "Alpha component" },
598 { 0x72, 'r', "Red component (LSBs)" },
599 { 0x67, 'g', "Green component (LSBs)" },
600 { 0x62, 'b', "Blue component (LSBs)" },
601 { 0x61, 'a', "Alpha component (LSBs)" },
602 { 0x46, 'F', "Fill component" },
603 { 0x50, 'P', "Palette code" },
604 { 0x55, 'U', "Color Difference Sample (e.g. U, Cb, I etc.)" },
605 { 0x56, 'V', "Color Difference Sample (e.g. V, Cr, Q etc.)" },
606 { 0x57, 'W', "Composite Video" },
607 { 0x58, 'X', "Non co-sited luma component" },
608 { 0x59, 'Y', "Luma component" },
609 { 0x5a, 'Z', "Depth component (SMPTE ST 268 compatible)" },
610 { 0x75, 'u', "Color Difference Sample (e.g. U, Cb, I etc.) (LSBs)" },
611 { 0x76, 'v', "Color Difference Sample (e.g. V, Cr, Q etc.) (LSBs)" },
612 { 0x77, 'w', "Composite Video (LSBs)" },
613 { 0x78, 'x', "Non co-sited luma component (LSBs)" },
614 { 0x79, 'y', "Luma component (LSBs)" },
615 { 0x7a, 'z', "Depth component (LSBs) (SMPTE ST 268 compatible)" },
616 { 0xd8, 'X', "The DCDM X color component (see SMPTE ST 428-1 X')" },
617 { 0xd9, 'Y', "The DCDM Y color component (see SMPTE ST 428-1 Y')" },
618 { 0xda, 'Z', "The DCDM Z color component (see SMPTE ST 428-1 Z')" },
619 { 0x00, '_', "Terminator" }
623 size_t const RGBAValueLength = 16;
625 byte_t const RGBAValue_RGB_10[RGBAValueLength] = { 'R', 10, 'G', 10, 'B', 10, 0, 0 };
626 byte_t const RGBAValue_RGB_8[RGBAValueLength] = { 'R', 8, 'G', 8, 'B', 8, 0, 0 };
627 byte_t const RGBAValue_YUV_10[RGBAValueLength] = { 'Y', 10, 'U', 10, 'V', 10, 0, 0 };
628 byte_t const RGBAValue_YUV_8[RGBAValueLength] = { 'Y', 8, 'U', 8, 'V', 8, 0, 0 };
629 byte_t const RGBAValue_DCDM[RGBAValueLength] = { 0xd8, 10, 0xd9, 10, 0xda, 10, 0, 0 };
632 class RGBALayout : public Kumu::IArchive
634 byte_t m_value[RGBAValueLength];
638 RGBALayout(const byte_t* value);
641 RGBALayout(const RGBALayout& rhs) { Set(rhs.m_value); }
642 const RGBALayout& operator=(const RGBALayout& rhs) { Set(rhs.m_value); return *this; }
644 void Set(const byte_t* value) {
645 memcpy(m_value, value, RGBAValueLength);
648 const char* EncodeString(char* buf, ui32_t buf_len) const;
650 bool HasValue() const { return true; }
651 ui32_t ArchiveLength() const { return RGBAValueLength; }
653 bool Archive(Kumu::MemIOWriter* Writer) const {
654 return Writer->WriteRaw(m_value, RGBAValueLength);
657 bool Unarchive(Kumu::MemIOReader* Reader) {
658 if ( Reader->Remainder() < RGBAValueLength )
663 memcpy(m_value, Reader->CurrentData(), RGBAValueLength);
664 Reader->SkipOffset(RGBAValueLength);
671 class Raw : public Kumu::ByteString
675 Raw(const Raw& rhs) { Copy(rhs); }
678 const Raw& operator=(const Raw& rhs) { Copy(rhs); return *this; }
679 void Copy(const Raw& rhs) {
680 if ( KM_SUCCESS(Capacity(rhs.Length())) )
687 virtual bool Unarchive(Kumu::MemIOReader* Reader);
688 virtual bool Archive(Kumu::MemIOWriter* Writer) const;
689 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
693 class J2KExtendedCapabilities : public Kumu::IArchive
697 Array<Kumu::ArchivableUi16> Ccap;
699 bool HasValue() const { return true; }
700 ui32_t ArchiveLength() const { return 0; }
702 bool Archive(Kumu::MemIOWriter* Writer) const;
703 bool Unarchive(Kumu::MemIOReader* Reader);
704 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
711 #endif //_MXFTYPES_H_