o Added support for SMPTE RDD 47 "ISXD Track File"
[asdcplib.git] / src / MXFTypes.h
index e98a2e9d7946284b312ef35a64ee92261a3a7650..c49fed9b6f07b267e1f5de0621865dc7c65a4db2 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2012, John Hurst
+Copyright (c) 2005-2016, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "KLV.h"
 #include <list>
 #include <vector>
+#include <set>
 #include <map>
 #include <wchar.h>
 
@@ -64,10 +65,10 @@ namespace ASDCP
 
          TLVReader();
          ASDCP_NO_COPY_CONSTRUCT(TLVReader);
-         bool FindTL(const MDDEntry&);
 
        public:
          TLVReader(const byte_t* p, ui32_t c, IPrimerLookup* = 0);
+         bool FindTL(const MDDEntry&);
          Result_t ReadObject(const MDDEntry&, Kumu::IArchive*);
          Result_t ReadUi8(const MDDEntry&, ui8_t*);
          Result_t ReadUi16(const MDDEntry&, ui16_t*);
@@ -96,97 +97,117 @@ namespace ASDCP
        };
 
       //
-      template <class T>
-       class Batch : public std::vector<T>, public Kumu::IArchive
+      template <class ContainerType>
+       class FixedSizeItemCollection : public ContainerType, public Kumu::IArchive
        {
        public:
-         Batch() {}
-         virtual ~Batch() {}
+         FixedSizeItemCollection() {}
+         virtual ~FixedSizeItemCollection() {}
 
-         //
-         virtual bool Unarchive(Kumu::MemIOReader* Reader) {
-           ui32_t ItemCount, ItemSize;
-           if ( ! Reader->ReadUi32BE(&ItemCount) ) return false;
-           if ( ! Reader->ReadUi32BE(&ItemSize) ) return false;
+         ui32_t ItemSize() const {
+           typename ContainerType::value_type tmp_item;
+           return tmp_item.ArchiveLength();
+         }
+
+         bool HasValue() const { return ! this->empty(); }
 
-           if ( ( ItemCount > 65536 ) || ( ItemSize > 1024 ) )
-             return false;
+         ui32_t ArchiveLength() const {
+           return ( sizeof(ui32_t) * 2 ) +  ( (ui32_t)this->size() * this->ItemSize() );
+         }
 
+         bool Archive(Kumu::MemIOWriter* Writer) const {
+           if ( ! Writer->WriteUi32BE((ui32_t)this->size()) ) return false;
+           if ( ! Writer->WriteUi32BE((ui32_t)this->ItemSize()) ) return false;
+           if ( this->empty() ) return true;
+           
+           typename ContainerType::const_iterator i;
            bool result = true;
-           for ( ui32_t i = 0; i < ItemCount && result; i++ )
+           for ( i = this->begin(); i != this->end() && result; ++i )
              {
-               T Tmp;
-               result = Tmp.Unarchive(Reader);
-
-               if ( result )
-                 this->push_back(Tmp);
+               result = i->Archive(Writer);
              }
 
            return result;
          }
 
-         inline virtual bool HasValue() const { return ! this->empty(); }
-
-         virtual ui32_t ArchiveLength() const {
-           ui32_t arch_size = sizeof(ui32_t)*2;
-
-           typename std::vector<T>::const_iterator l_i = this->begin();
-           assert(l_i != this->end());
-
-           for ( ; l_i != this->end(); l_i++ )
-             arch_size += l_i->ArchiveLength();
-           
-           return arch_size;
-         }
-
          //
-         virtual bool Archive(Kumu::MemIOWriter* Writer) const {
-           if ( ! Writer->WriteUi32BE(this->size()) ) return false;
-           byte_t* p = Writer->CurrentData();
+         bool Unarchive(Kumu::MemIOReader* Reader) {
+           ui32_t item_count, item_size;
+           if ( ! Reader->ReadUi32BE(&item_count) ) return false;
+           if ( ! Reader->ReadUi32BE(&item_size) ) return false;
 
-           if ( ! Writer->WriteUi32BE(0) ) return false;
-           if ( this->empty() ) return true;
-           
-           typename std::vector<T>::const_iterator l_i = this->begin();
-           assert(l_i != this->end());
-
-           ui32_t ItemSize = Writer->Remainder();
-           if ( ! (*l_i).Archive(Writer) ) return false;
-           ItemSize -= Writer->Remainder();
-           Kumu::i2p<ui32_t>(KM_i32_BE(ItemSize), p);
-           l_i++;
+           if ( item_count > 0 )
+             {
+               if ( this->ItemSize() != item_size ) return false;
+             }
 
            bool result = true;
-           for ( ; l_i != this->end() && result; l_i++ )
-             result = (*l_i).Archive(Writer);
+           for ( ui32_t i = 0; i < item_count && result; ++i )
+             {
+               typename ContainerType::value_type tmp_item;
+               result = tmp_item.Unarchive(Reader);
+
+               if ( result )
+                 {
+                   this->push_back(tmp_item);
+                 }
+             }
 
            return result;
          }
 
-         //
-         void Dump(FILE* stream = 0, ui32_t depth = 0)
-           {
-             char identbuf[IdentBufferLen];
+         void Dump(FILE* stream = 0, ui32_t depth = 0) {
+           char identbuf[IdentBufferLen];
 
-             if ( stream == 0 )
+           if ( stream == 0 )
+             {
                stream = stderr;
-
-             typename std::vector<T>::iterator i = this->begin();
-             for ( ; i != this->end(); i++ )
+             }
+           
+           typename ContainerType::const_iterator i;
+           for ( i = this->begin(); i != this->end(); ++i )
+             {
                fprintf(stream, "  %s\n", (*i).EncodeString(identbuf, IdentBufferLen));
-           }
+             }
+         }
        };
 
+
+      template <class item_type>
+       class PushSet : public std::set<item_type>
+      {
+      public:
+       PushSet() {}
+       virtual ~PushSet() {}
+       void push_back(const item_type& item) { this->insert(item); }
+      };
+
+      template <class ItemType>
+       class Batch : public FixedSizeItemCollection<PushSet<ItemType> >
+      {
+      public:
+       Batch() {}
+       virtual ~Batch() {}
+      };
+
+      template <class ItemType>
+       class Array : public FixedSizeItemCollection<std::vector<ItemType> >
+      {
+      public:
+       Array() {}
+       virtual ~Array() {}
+      };
+
       //
       template <class T>
-       class Array : public std::list<T>, public Kumu::IArchive
+       class SimpleArray : public std::list<T>, public Kumu::IArchive
        {
        public:
-         Array() {}
-         virtual ~Array() {}
+         SimpleArray() {}
+         virtual ~SimpleArray() {}
 
          //
-         virtual bool Unarchive(Kumu::MemIOReader* Reader)
+         bool Unarchive(Kumu::MemIOReader* Reader)
            {
              bool result = true;
 
@@ -194,15 +215,19 @@ namespace ASDCP
                {
                  T Tmp;
                  result = Tmp.Unarchive(Reader);
-                 this->push_back(Tmp);
+
+                 if ( result )
+                   {
+                     this->push_back(Tmp);
+                   }
                }
 
              return result;
            }
 
-         inline virtual bool HasValue() const { return ! this->empty(); }
+         inline bool HasValue() const { return ! this->empty(); }
 
-         virtual ui32_t ArchiveLength() const {
+         ui32_t ArchiveLength() const {
            ui32_t arch_size = 0;
 
            typename std::list<T>::const_iterator l_i = this->begin();
@@ -214,7 +239,7 @@ namespace ASDCP
          }
 
          //
-         virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+         bool Archive(Kumu::MemIOWriter* Writer) const {
            bool result = true;
            typename std::list<T>::const_iterator l_i = this->begin();
 
@@ -252,7 +277,7 @@ namespace ASDCP
 
          const char* EncodeString(char* str_buf, ui32_t buf_len) const;
          inline virtual bool HasValue() const { return ! empty(); }
-         inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t) + size(); }
+         inline virtual ui32_t ArchiveLength() const { return (ui32_t)(sizeof(ui32_t) + size()); }
          virtual bool Unarchive(Kumu::MemIOReader* Reader);
          virtual bool Archive(Kumu::MemIOWriter* Writer) const;
        };
@@ -271,7 +296,7 @@ namespace ASDCP
 
          const char* EncodeString(char* str_buf, ui32_t buf_len) const;
          inline virtual bool HasValue() const { return ! empty(); }
-         inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t) + size(); }
+         inline virtual ui32_t ArchiveLength() const { return (ui32_t)(sizeof(ui32_t) + size()); }
          virtual bool Unarchive(Kumu::MemIOReader* Reader);
          virtual bool Archive(Kumu::MemIOWriter* Writer) const;
        };
@@ -327,6 +352,157 @@ namespace ASDCP
          }
        };
 
+      //
+      class LineMapPair : public Kumu::IArchive
+       {
+       public:
+         ui32_t First;
+         ui32_t Second;
+
+       LineMapPair() : First(0), Second() {}
+         ~LineMapPair() {}
+
+       LineMapPair(const ui32_t& first, const ui32_t& second) : IArchive() {
+           First = first;
+           Second = second;
+         }
+
+         LineMapPair(const LineMapPair& rhs) : IArchive() {
+           First = rhs.First;
+           Second = rhs.Second;
+         }
+
+         const LineMapPair& operator=(const LineMapPair& rhs) {
+           First = rhs.First;
+           Second = rhs.Second;
+           return *this;
+         }
+
+         //
+         inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+           snprintf(str_buf, buf_len, "%d,%d", First, Second);
+           return str_buf;
+         }
+
+         inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
+           ui32_t n;
+           if ( ! Reader->ReadUi32BE(&n) ) return false;
+           if ( n != 2 ) return false;
+           if ( ! Reader->ReadUi32BE(&n) ) return false;
+           if ( n != 4 ) return false;
+           if ( ! Reader->ReadUi32BE((ui32_t*)&First) ) return false;
+           if ( ! Reader->ReadUi32BE((ui32_t*)&Second) ) return false;
+           return true;
+         }
+
+         inline virtual bool HasValue() const { return true; }
+         inline virtual ui32_t ArchiveLength() const { return sizeof(ui32_t)*4; }
+
+         inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+           if ( ! Writer->WriteUi32BE(2UL) ) return false;
+           if ( ! Writer->WriteUi32BE(4UL) ) return false;
+           if ( ! Writer->WriteUi32BE((ui32_t)First) ) return false;
+           if ( ! Writer->WriteUi32BE((ui32_t)Second) ) return false;
+           return true;
+         }
+       };
+
+      //
+      class ColorPrimary : public Kumu::IArchive
+       {
+       public:
+         ui16_t X;
+         ui16_t Y;
+
+       ColorPrimary() : X(0), Y(0) {}
+         ~ColorPrimary() {}
+
+         ColorPrimary(const ui16_t& x, const ui16_t& y) : X(x), Y(y) {}
+
+         ColorPrimary(const ColorPrimary& rhs) { Copy(rhs); }
+         const ColorPrimary& operator=(const ColorPrimary& rhs) { Copy(rhs); return *this; }
+         
+         void Copy(const ColorPrimary& rhs) {
+           X = rhs.X;
+           Y = rhs.Y;
+         }
+
+         //
+         inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+           snprintf(str_buf, buf_len, "%d,%d", X, Y);
+           return str_buf;
+         }
+
+         inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
+           if ( ! Reader->ReadUi16BE((ui16_t*)&X) ) return false;
+           if ( ! Reader->ReadUi16BE((ui16_t*)&Y) ) return false;
+           return true;
+         }
+
+         inline virtual bool HasValue() const { return X || Y; }
+         inline virtual ui32_t ArchiveLength() const { return sizeof(ui16_t)*2; }
+
+         inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+           if ( ! Writer->WriteUi16BE((ui16_t)X) ) return false;
+           if ( ! Writer->WriteUi16BE((ui16_t)Y) ) return false;
+           return true;
+         }
+       };
+
+      //
+      class ThreeColorPrimaries : public Kumu::IArchive
+       {
+       public:
+         ColorPrimary First;
+         ColorPrimary Second;
+         ColorPrimary Third;
+
+         ThreeColorPrimaries() {}
+         ~ThreeColorPrimaries() {}
+
+         ThreeColorPrimaries(const ColorPrimary& first, const ColorPrimary& second, const ColorPrimary& third) :
+           First(first), Second(second), Third(third) {}
+
+         ThreeColorPrimaries(const ThreeColorPrimaries& rhs) { Copy(rhs); }
+         const ThreeColorPrimaries& operator=(const ThreeColorPrimaries& rhs) { Copy(rhs); return *this; }
+         
+         void Copy(const ThreeColorPrimaries& rhs) {
+           First = rhs.First;
+           Second = rhs.Second;
+           Third = rhs.Third;
+         }
+
+         //
+         inline const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+           snprintf(str_buf, buf_len, "%d,%d;%d,%d;%d,%d", First.X, First.Y, Second.X, Second.Y, Third.X, Third.Y);
+           return str_buf;
+         }
+
+         inline virtual bool Unarchive(Kumu::MemIOReader* Reader) {
+           First.Unarchive(Reader);
+           Second.Unarchive(Reader);
+           Third.Unarchive(Reader);
+           return true;
+         }
+
+         inline virtual bool HasValue() const {
+           return First.HasValue() || Second.HasValue() || Third.HasValue();
+         }
+
+         inline virtual ui32_t ArchiveLength() const {
+           return First.ArchiveLength()
+             + Second.ArchiveLength()
+             + Third.ArchiveLength();
+         }
+
+         inline virtual bool Archive(Kumu::MemIOWriter* Writer) const {
+           First.Archive(Writer);
+           Second.Archive(Writer);
+           Third.Archive(Writer);
+           return true;
+         }
+       };
+
       //
       class VersionType : public Kumu::IArchive
        {
@@ -354,7 +530,7 @@ namespace ASDCP
          void Dump(FILE* = 0);
 
          const char* EncodeString(char* str_buf, ui32_t buf_len) const {
-           snprintf(str_buf, buf_len, "%hu.%hu.%hu.%hur%hu", Major, Minor, Patch, Build, Release);
+           snprintf(str_buf, buf_len, "%hu.%hu.%hu.%hur%hu", Major, Minor, Patch, Build, ui16_t(Release));
            return str_buf;
          }
 
@@ -382,6 +558,114 @@ namespace ASDCP
          }
        };
 
+      /*
+       The RGBALayout type shall be a fixed-size 8 element sequence with a total length
+       of 16 bytes, where each element shall consist of the RGBAComponent type with the
+       following fields:
+
+       Code (UInt8): Enumerated value specifying component (i.e., component identifier).
+       "0" is the layout terminator.
+
+       Depth (UInt8): Integer specifying the number of bits occupied (see also G.2.26) 
+         1->32 indicates integer depth
+         253 = HALF (floating point 16-bit value)
+         254 = IEEE floating point 32-bit value
+         255 = IEEE floating point 64-bit value
+         0 = RGBALayout terminator
+
+       A Fill component indicates unused bits. After the components have been specified,
+       the remaining Code and Size fields shall be set to zero (0).
+
+       For each component in the Pixel, one of the following Codes or the terminator
+       shall be specified (explained below):
+
+       Code    ASCII
+
+      */
+      struct RGBALayoutTableEntry
+      {
+       byte_t code;
+       char symbol;
+       const char* label;
+      };
+
+      struct RGBALayoutTableEntry const RGBALayoutTable[] = {
+       { 0x52, 'R', "Red component" },
+       { 0x47, 'G', "Green component" },
+       { 0x42, 'B', "Blue component" },
+       { 0x41, 'A', "Alpha component" },
+       { 0x72, 'r', "Red component (LSBs)" },
+       { 0x67, 'g', "Green component (LSBs)" },
+       { 0x62, 'b', "Blue component (LSBs)" },
+       { 0x61, 'a', "Alpha component (LSBs)" },
+       { 0x46, 'F', "Fill component" },
+       { 0x50, 'P', "Palette code" },
+       { 0x55, 'U', "Color Difference Sample (e.g. U, Cb, I etc.)" },
+       { 0x56, 'V', "Color Difference Sample (e.g. V, Cr, Q etc.)" },
+       { 0x57, 'W', "Composite Video" },
+       { 0x58, 'X', "Non co-sited luma component" },
+       { 0x59, 'Y', "Luma component" },
+       { 0x5a, 'Z', "Depth component (SMPTE ST 268 compatible)" },
+       { 0x75, 'u', "Color Difference Sample (e.g. U, Cb, I etc.) (LSBs)" },
+       { 0x76, 'v', "Color Difference Sample (e.g. V, Cr, Q etc.) (LSBs)" },
+       { 0x77, 'w', "Composite Video (LSBs)" },
+       { 0x78, 'x', "Non co-sited luma component (LSBs)" },
+       { 0x79, 'y', "Luma component (LSBs)" },
+       { 0x7a, 'z', "Depth component (LSBs) (SMPTE ST 268 compatible)" },
+       { 0xd8, 'X', "The DCDM X color component (see SMPTE ST 428-1 X')" },
+       { 0xd9, 'Y', "The DCDM Y color component (see SMPTE ST 428-1 Y')" },
+       { 0xda, 'Z', "The DCDM Z color component (see SMPTE ST 428-1 Z')" },
+       { 0x00, '_', "Terminator" }
+      };
+
+
+      size_t const RGBAValueLength = 16;
+
+      byte_t const RGBAValue_RGB_10[RGBAValueLength] = { 'R', 10, 'G', 10, 'B', 10, 0, 0 };
+      byte_t const RGBAValue_RGB_8[RGBAValueLength]  = { 'R', 8,  'G', 8,  'B', 8,  0, 0 };
+      byte_t const RGBAValue_YUV_10[RGBAValueLength] = { 'Y', 10, 'U', 10, 'V', 10, 0, 0 };
+      byte_t const RGBAValue_YUV_8[RGBAValueLength]  = { 'Y', 8,  'U', 8,  'V', 8,  0, 0 };
+      byte_t const RGBAValue_DCDM[RGBAValueLength] = { 0xd8, 10, 0xd9, 10, 0xda, 10, 0, 0 };
+
+
+      class RGBALayout : public Kumu::IArchive
+       {
+         byte_t m_value[RGBAValueLength];
+
+       public:
+         RGBALayout();
+         RGBALayout(const byte_t* value);
+         ~RGBALayout();
+
+         RGBALayout(const RGBALayout& rhs) { Set(rhs.m_value); }
+         const RGBALayout& operator=(const RGBALayout& rhs) { Set(rhs.m_value); return *this; }
+         
+         void Set(const byte_t* value) {
+           memcpy(m_value, value, RGBAValueLength);
+         }
+
+         const char* EncodeString(char* buf, ui32_t buf_len) const;
+
+         bool HasValue() const { return true; }
+         ui32_t ArchiveLength() const { return RGBAValueLength; }
+
+         bool Archive(Kumu::MemIOWriter* Writer) const {
+           return Writer->WriteRaw(m_value, RGBAValueLength);
+         }
+
+         bool Unarchive(Kumu::MemIOReader* Reader) {
+           if ( Reader->Remainder() < RGBAValueLength )
+             {
+               return false;
+             }
+
+           memcpy(m_value, Reader->CurrentData(), RGBAValueLength);
+           Reader->SkipOffset(RGBAValueLength);
+           return true;
+         }
+       };
+
+
       //
       class Raw : public Kumu::ByteString
        {