2 Copyright (c) 2005-2016, 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.
42 // used with TLVReader::Read*
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
56 typedef std::pair<ui32_t, ui32_t> ItemInfo;
57 typedef std::map<TagValue, ItemInfo> TagMap;
60 class TLVReader : public Kumu::MemIOReader
64 IPrimerLookup* m_Lookup;
67 ASDCP_NO_COPY_CONSTRUCT(TLVReader);
70 TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* = 0);
71 bool FindTL(const MDDEntry&);
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*);
80 class TLVWriter : public Kumu::MemIOWriter
84 IPrimerLookup* m_Lookup;
87 ASDCP_NO_COPY_CONSTRUCT(TLVWriter);
88 Result_t WriteTag(const MDDEntry&);
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*);
100 template <class ContainerType>
101 class FixedSizeItemCollection : public ContainerType, public Kumu::IArchive
104 FixedSizeItemCollection() {}
105 virtual ~FixedSizeItemCollection() {}
107 ui32_t ItemSize() const {
108 typename ContainerType::value_type tmp_item;
109 return tmp_item.ArchiveLength();
112 bool HasValue() const { return ! this->empty(); }
114 ui32_t ArchiveLength() const {
115 return ( sizeof(ui32_t) * 2 ) + ( (ui32_t)this->size() * this->ItemSize() );
118 bool Archive(Kumu::MemIOWriter* Writer) const {
119 if ( ! Writer->WriteUi32BE((ui32_t)this->size()) ) return false;
120 if ( ! Writer->WriteUi32BE((ui32_t)this->ItemSize()) ) return false;
121 if ( this->empty() ) return true;
123 typename ContainerType::const_iterator i;
125 for ( i = this->begin(); i != this->end() && result; ++i )
127 result = i->Archive(Writer);
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;
139 if ( item_count > 0 )
141 if ( this->ItemSize() != item_size ) return false;
145 for ( ui32_t i = 0; i < item_count && result; ++i )
147 typename ContainerType::value_type tmp_item;
148 result = tmp_item.Unarchive(Reader);
152 this->push_back(tmp_item);
159 void Dump(FILE* stream = 0, ui32_t depth = 0) {
160 char identbuf[IdentBufferLen];
167 typename ContainerType::const_iterator i;
168 for ( i = this->begin(); i != this->end(); ++i )
170 fprintf(stream, " %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
176 template <class item_type>
177 class PushSet : public std::set<item_type>
181 virtual ~PushSet() {}
182 void push_back(const item_type& item) { this->insert(item); }
185 template <class ItemType>
186 class Batch : public FixedSizeItemCollection<PushSet<ItemType> >
193 template <class ItemType>
194 class Array : public FixedSizeItemCollection<std::vector<ItemType> >
203 class SimpleArray : public std::list<T>, public Kumu::IArchive
207 virtual ~SimpleArray() {}
210 bool Unarchive(Kumu::MemIOReader* Reader)
214 while ( Reader->Remainder() > 0 && result )
217 result = Tmp.Unarchive(Reader);
221 this->push_back(Tmp);
228 inline bool HasValue() const { return ! this->empty(); }
230 ui32_t ArchiveLength() const {
231 ui32_t arch_size = 0;
233 typename std::list<T>::const_iterator l_i = this->begin();
235 for ( ; l_i != this->end(); l_i++ )
236 arch_size += l_i->ArchiveLength();
242 bool Archive(Kumu::MemIOWriter* Writer) const {
244 typename std::list<T>::const_iterator l_i = this->begin();
246 for ( ; l_i != this->end() && result; l_i++ )
247 result = (*l_i).Archive(Writer);
253 void Dump(FILE* stream = 0, ui32_t depth = 0)
255 char identbuf[IdentBufferLen];
260 typename std::list<T>::iterator i = this->begin();
261 for ( ; i != this->end(); i++ )
262 fprintf(stream, " %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
267 class ISO8String : public std::string, public Kumu::IArchive
271 ISO8String(const char*);
272 ISO8String(const std::string&);
275 const ISO8String& operator=(const char*);
276 const ISO8String& operator=(const std::string&);
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 (ui32_t)(sizeof(ui32_t) + size()); }
281 virtual bool Unarchive(Kumu::MemIOReader* Reader);
282 virtual bool Archive(Kumu::MemIOWriter* Writer) const;
286 class UTF16String : public std::string, public Kumu::IArchive
290 UTF16String(const char*);
291 UTF16String(const std::string&);
294 const UTF16String& operator=(const char*);
295 const UTF16String& operator=(const std::string&);
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 (ui32_t)(sizeof(ui32_t) + size()); }
300 virtual bool Unarchive(Kumu::MemIOReader* Reader);
301 virtual bool Archive(Kumu::MemIOWriter* Writer) const;
305 class Rational : public ASDCP::Rational, public Kumu::IArchive
311 Rational(const Rational& rhs) : ASDCP::Rational(), IArchive() {
312 Numerator = rhs.Numerator;
313 Denominator = rhs.Denominator;
316 const Rational& operator=(const Rational& rhs) {
317 Numerator = rhs.Numerator;
318 Denominator = rhs.Denominator;
322 Rational(const ASDCP::Rational& rhs) {
323 Numerator = rhs.Numerator;
324 Denominator = rhs.Denominator;
327 const Rational& operator=(const ASDCP::Rational& rhs) {
328 Numerator = rhs.Numerator;
329 Denominator = rhs.Denominator;
334 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
335 snprintf(str_buf, buf_len, "%d/%d", Numerator, Denominator);
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;
345 inline virtual bool HasValue() const { return true; }
346 inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*2; }
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;
356 class LineMapPair : public Kumu::IArchive
362 LineMapPair() : First(0), Second() {}
365 LineMapPair(const ui32_t& first, const ui32_t& second) : IArchive() {
370 LineMapPair(const LineMapPair& rhs) : IArchive() {
375 const LineMapPair& operator=(const LineMapPair& rhs) {
382 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
383 snprintf(str_buf, buf_len, "%d,%d", First, Second);
387 inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
389 if ( ! Reader->ReadUi32BE(&n) ) return false;
390 if ( n != 2 ) return false;
391 if ( ! Reader->ReadUi32BE(&n) ) return false;
392 if ( n != 4 ) return false;
393 if ( ! Reader->ReadUi32BE((ui32_t*)&First) ) return false;
394 if ( ! Reader->ReadUi32BE((ui32_t*)&Second) ) return false;
398 inline virtual bool HasValue() const { return true; }
399 inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*4; }
401 inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
402 if ( ! Writer->WriteUi32BE(2UL) ) return false;
403 if ( ! Writer->WriteUi32BE(4UL) ) return false;
404 if ( ! Writer->WriteUi32BE((ui32_t)First) ) return false;
405 if ( ! Writer->WriteUi32BE((ui32_t)Second) ) return false;
411 class ColorPrimary : public Kumu::IArchive
417 ColorPrimary() : X(0), Y(0) {}
420 ColorPrimary(const ui16_t& x, const ui16_t& y) : X(x), Y(y) {}
422 ColorPrimary(const ColorPrimary& rhs) { Copy(rhs); }
423 const ColorPrimary& operator=(const ColorPrimary& rhs) { Copy(rhs); return *this; }
425 void Copy(const ColorPrimary& rhs) {
431 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
432 snprintf(str_buf, buf_len, "%d,%d", X, Y);
436 inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
437 if ( ! Reader->ReadUi16BE((ui16_t*)&X) ) return false;
438 if ( ! Reader->ReadUi16BE((ui16_t*)&Y) ) return false;
442 inline virtual bool HasValue() const { return X || Y; }
443 inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*2; }
445 inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
446 if ( ! Writer->WriteUi16BE((ui16_t)X) ) return false;
447 if ( ! Writer->WriteUi16BE((ui16_t)Y) ) return false;
453 class ThreeColorPrimaries : public Kumu::IArchive
460 ThreeColorPrimaries() {}
461 ~ThreeColorPrimaries() {}
463 ThreeColorPrimaries(const ColorPrimary& first, const ColorPrimary& second, const ColorPrimary& third) :
464 First(first), Second(second), Third(third) {}
466 ThreeColorPrimaries(const ThreeColorPrimaries& rhs) { Copy(rhs); }
467 const ThreeColorPrimaries& operator=(const ThreeColorPrimaries& rhs) { Copy(rhs); return *this; }
469 void Copy(const ThreeColorPrimaries& rhs) {
476 inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
477 snprintf(str_buf, buf_len, "%d,%d;%d,%d;%d,%d", First.X, First.Y, Second.X, Second.Y, Third.X, Third.Y);
481 inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
482 First.Unarchive(Reader);
483 Second.Unarchive(Reader);
484 Third.Unarchive(Reader);
488 inline virtual bool HasValue() const {
489 return First.HasValue() || Second.HasValue() || Third.HasValue();
492 inline virtual ui32_t ArchiveLength() const {
493 return First.ArchiveLength()
494 + Second.ArchiveLength()
495 + Third.ArchiveLength();
498 inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
499 First.Archive(Writer);
500 Second.Archive(Writer);
501 Third.Archive(Writer);
507 class VersionType : public Kumu::IArchive
510 enum Release_t { RL_UNKNOWN, RL_RELEASE, RL_DEVELOPMENT, RL_PATCHED, RL_BETA, RL_PRIVATE, RL_MAX };
517 VersionType() : Major(0), Minor(0), Patch(0), Build(0), Release(RL_UNKNOWN) {}
518 VersionType(const VersionType& rhs) { Copy(rhs); }
519 virtual ~VersionType() {}
521 const VersionType& operator=(const VersionType& rhs) { Copy(rhs); return *this; }
522 void Copy(const VersionType& rhs) {
527 Release = rhs.Release;
530 void Dump(FILE* = 0);
532 const char* EncodeString(char* str_buf, ui32_t buf_len) const {
533 snprintf(str_buf, buf_len, "%hu.%hu.%hu.%hur%hu", Major, Minor, Patch, Build, ui16_t(Release));
537 virtual bool Unarchive(Kumu::MemIOReader* Reader) {
538 if ( ! Reader->ReadUi16BE(&Major) ) return false;
539 if ( ! Reader->ReadUi16BE(&Minor) ) return false;
540 if ( ! Reader->ReadUi16BE(&Patch) ) return false;
541 if ( ! Reader->ReadUi16BE(&Build) ) return false;
543 if ( ! Reader->ReadUi16BE(&tmp_release) ) return false;
544 Release = (Release_t)tmp_release;
548 inline virtual bool HasValue() const { return true; }
549 inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*5; }
551 virtual bool Archive(Kumu::MemIOWriter* Writer) const {
552 if ( ! Writer->WriteUi16BE(Major) ) return false;
553 if ( ! Writer->WriteUi16BE(Minor) ) return false;
554 if ( ! Writer->WriteUi16BE(Patch) ) return false;
555 if ( ! Writer->WriteUi16BE(Build) ) return false;
556 if ( ! Writer->WriteUi16BE((ui16_t)(Release & 0x0000ffffL)) ) return false;
562 The RGBALayout type shall be a fixed-size 8 element sequence with a total length
563 of 16 bytes, where each element shall consist of the RGBAComponent type with the
566 Code (UInt8): Enumerated value specifying component (i.e., component identifier).
567 "0" is the layout terminator.
569 Depth (UInt8): Integer specifying the number of bits occupied (see also G.2.26)
570 1->32 indicates integer depth
571 253 = HALF (floating point 16-bit value)
572 254 = IEEE floating point 32-bit value
573 255 = IEEE floating point 64-bit value
574 0 = RGBALayout terminator
576 A Fill component indicates unused bits. After the components have been specified,
577 the remaining Code and Size fields shall be set to zero (0).
579 For each component in the Pixel, one of the following Codes or the terminator
580 shall be specified (explained below):
585 struct RGBALayoutTableEntry
592 struct RGBALayoutTableEntry const RGBALayoutTable[] = {
593 { 0x52, 'R', "Red component" },
594 { 0x47, 'G', "Green component" },
595 { 0x42, 'B', "Blue component" },
596 { 0x41, 'A', "Alpha component" },
597 { 0x72, 'r', "Red component (LSBs)" },
598 { 0x67, 'g', "Green component (LSBs)" },
599 { 0x62, 'b', "Blue component (LSBs)" },
600 { 0x61, 'a', "Alpha component (LSBs)" },
601 { 0x46, 'F', "Fill component" },
602 { 0x50, 'P', "Palette code" },
603 { 0x55, 'U', "Color Difference Sample (e.g. U, Cb, I etc.)" },
604 { 0x56, 'V', "Color Difference Sample (e.g. V, Cr, Q etc.)" },
605 { 0x57, 'W', "Composite Video" },
606 { 0x58, 'X', "Non co-sited luma component" },
607 { 0x59, 'Y', "Luma component" },
608 { 0x5a, 'Z', "Depth component (SMPTE ST 268 compatible)" },
609 { 0x75, 'u', "Color Difference Sample (e.g. U, Cb, I etc.) (LSBs)" },
610 { 0x76, 'v', "Color Difference Sample (e.g. V, Cr, Q etc.) (LSBs)" },
611 { 0x77, 'w', "Composite Video (LSBs)" },
612 { 0x78, 'x', "Non co-sited luma component (LSBs)" },
613 { 0x79, 'y', "Luma component (LSBs)" },
614 { 0x7a, 'z', "Depth component (LSBs) (SMPTE ST 268 compatible)" },
615 { 0xd8, 'X', "The DCDM X color component (see SMPTE ST 428-1 X')" },
616 { 0xd9, 'Y', "The DCDM Y color component (see SMPTE ST 428-1 Y')" },
617 { 0xda, 'Z', "The DCDM Z color component (see SMPTE ST 428-1 Z')" },
618 { 0x00, '_', "Terminator" }
622 size_t const RGBAValueLength = 16;
624 byte_t const RGBAValue_RGB_10[RGBAValueLength] = { 'R', 10, 'G', 10, 'B', 10, 0, 0 };
625 byte_t const RGBAValue_RGB_8[RGBAValueLength] = { 'R', 8, 'G', 8, 'B', 8, 0, 0 };
626 byte_t const RGBAValue_YUV_10[RGBAValueLength] = { 'Y', 10, 'U', 10, 'V', 10, 0, 0 };
627 byte_t const RGBAValue_YUV_8[RGBAValueLength] = { 'Y', 8, 'U', 8, 'V', 8, 0, 0 };
628 byte_t const RGBAValue_DCDM[RGBAValueLength] = { 0xd8, 10, 0xd9, 10, 0xda, 10, 0, 0 };
631 class RGBALayout : public Kumu::IArchive
633 byte_t m_value[RGBAValueLength];
637 RGBALayout(const byte_t* value);
640 RGBALayout(const RGBALayout& rhs) { Set(rhs.m_value); }
641 const RGBALayout& operator=(const RGBALayout& rhs) { Set(rhs.m_value); return *this; }
643 void Set(const byte_t* value) {
644 memcpy(m_value, value, RGBAValueLength);
647 const char* EncodeString(char* buf, ui32_t buf_len) const;
649 bool HasValue() const { return true; }
650 ui32_t ArchiveLength() const { return RGBAValueLength; }
652 bool Archive(Kumu::MemIOWriter* Writer) const {
653 return Writer->WriteRaw(m_value, RGBAValueLength);
656 bool Unarchive(Kumu::MemIOReader* Reader) {
657 if ( Reader->Remainder() < RGBAValueLength )
662 memcpy(m_value, Reader->CurrentData(), RGBAValueLength);
663 Reader->SkipOffset(RGBAValueLength);
670 class Raw : public Kumu::ByteString
674 Raw(const Raw& rhs) { Copy(rhs); }
677 const Raw& operator=(const Raw& rhs) { Copy(rhs); return *this; }
678 void Copy(const Raw& rhs) {
679 if ( KM_SUCCESS(Capacity(rhs.Length())) )
686 virtual bool Unarchive(Kumu::MemIOReader* Reader);
687 virtual bool Archive(Kumu::MemIOWriter* Writer) const;
688 const char* EncodeString(char* str_buf, ui32_t buf_len) const;
691 class J2KExtendedCapabilities : public Kumu::IArchive
695 i8_t Ccapi[16]; // this is certainly wrong, need the spec
697 bool HasValue() const { return true; }
698 ui32_t ArchiveLength() const { return 0; }
700 bool Archive(Kumu::MemIOWriter* Writer) const {
704 bool Unarchive(Kumu::MemIOReader* Reader) {
708 const char* EncodeString(char* str_buf, ui32_t buf_len) const
720 #endif //_MXFTYPES_H_