Merge pull request #20 from cinecert/htj2c
authorJohn Hurst <jhurst@cinecert.com>
Mon, 30 Dec 2019 22:03:53 +0000 (14:03 -0800)
committerGitHub <noreply@github.com>
Mon, 30 Dec 2019 22:03:53 +0000 (14:03 -0800)
WIP: add support for ST 422:2019

15 files changed:
.gitignore
src/AS_DCP.h
src/AS_DCP_JP2K.cpp
src/JP2K.cpp
src/JP2K.h
src/JP2K_Codestream_Parser.cpp
src/JP2K_Sequence_Parser.cpp
src/KM_util.h
src/MDD.cpp
src/MDD.h
src/MXFTypes.cpp
src/MXFTypes.h
src/Metadata.cpp
src/Metadata.h
src/j2c-test.cpp

index 8aed0ccb51678fec8aa6718d20e2fee8408751c8..ba1f60fac3d28b1cd897e4cbc5fd09778567f457 100644 (file)
 #
 src/.deps
 src/.libs
+/build
+
+###
+# some tool dirs
+#
+
+/.vscode
 
 ###
 # autotools output
index 96d066cac98acbb8485ba92b443d510a7010d2a6..74991f68f47f819463e5e874975b2ded225b2065 100755 (executable)
@@ -1048,6 +1048,12 @@ namespace ASDCP {
       const ui32_t MaxComponents = 3;
       const ui32_t MaxPrecincts = 32; // ISO 15444-1 Annex A.6.1
       const ui32_t MaxDefaults = 256; // made up
+      const ui8_t  MaxCapabilities = 32;
+                       const ui16_t MaxPRFN = 4;
+                       const ui16_t MaxCPFN = 4;
+                       const i8_t NoExtendedCapabilitiesSignaled = -1;
+                       const ui16_t NoPRFSignaled = 0;
+                       const ui16_t NoCPFSignaled = 0;
 
 #pragma pack(1)
       struct ImageComponent_t  // ISO 15444-1 Annex A.5.1
@@ -1085,6 +1091,26 @@ namespace ASDCP {
        ui8_t  SPqcd[MaxDefaults];
        ui8_t  SPqcdLength;
       };
+
+      struct ExtendedCapabilities_t // ISO 15444-1 Annex A.5.2
+      {
+       ui32_t  Pcap; // Pcap = 0 means that no extended capabilities are required
+       i8_t N; // Number of Ccap elements, or NoExtendedCapabilitiesSignaled if no Extended Capabilities are signaled
+       ui16_t  Ccap[MaxCapabilities]; 
+      };
+
+                       struct Profile_t // ISO 15444-1
+      {
+       ui16_t  N; // N = NoPRFSignaled means that Profile is signaled through Rsiz exclusively
+       ui16_t  Pprf[MaxPRFN]; // Pprf^i in ISO/IEC 15444-1 corresponds to Pprf[i -1]
+      };
+
+                       struct CorrespondingProfile_t // ISO 15444-1
+      {
+       ui16_t  N; // N = NoCPFSignaled means that no corresponding profile is signaled
+       ui16_t  Pcpf[MaxCPFN]; // Pcpf^i in ISO/IEC 15444-1 corresponds to Pcpf[i -1]
+      };
+
 #pragma pack()
 
       struct PictureDescriptor
@@ -1108,6 +1134,9 @@ namespace ASDCP {
        ImageComponent_t      ImageComponents[MaxComponents];
        CodingStyleDefault_t  CodingStyleDefault;
        QuantizationDefault_t QuantizationDefault;
+  ExtendedCapabilities_t ExtendedCapabilities;
+  Profile_t   Profile;
+       CorrespondingProfile_t   CorrespondingProfile;    
       };
 
       // Print debugging information to std::ostream
index a4bffc67eeefc4c1af7e0e9e3a2b52bf2e9bfcdf..129f53d97de10fa68a1a5edf76a5ed9b1e9e76c7 100755 (executable)
@@ -32,6 +32,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AS_DCP_internal.h"
 #include <iostream>
 #include <iomanip>
+#include <algorithm>
 
 using namespace ASDCP::JP2K;
 using Kumu::GenRandomValue;
@@ -106,6 +107,46 @@ ASDCP::JP2K::operator << (std::ostream& strm, const PictureDescriptor& PDesc)
   strm << "              SPqcd: " << Kumu::bin2hex(PDesc.QuantizationDefault.SPqcd, PDesc.QuantizationDefault.SPqcdLength, tmp_buf, MaxDefaults*2)
        << std::endl;
 
+  if (PDesc.Profile.N != 0) {
+         strm << "Profile:" << std::endl;
+
+         for (ui16_t i = 0; i < PDesc.Profile.N; i++) {
+                 strm << "              Pprf(" << (i + 1) << "): "
+                         << std::hex << std::showbase << PDesc.Profile.Pprf[i] << std::dec << std::noshowbase
+                         << std::endl;
+         }
+  }
+
+  if (PDesc.CorrespondingProfile.N != 0) {
+         strm << "Corresponding Profile:" << std::endl;
+
+         for (ui16_t i = 0; i < PDesc.CorrespondingProfile.N; i++) {
+
+                 strm << "              Pcpf(" << (i + 1) << "): "
+                         << std::hex << std::showbase <<  PDesc.CorrespondingProfile.Pcpf[i] << std::dec << std::noshowbase
+                         << std::endl;
+         }
+  }
+
+  if (PDesc.ExtendedCapabilities.N != JP2K::NoExtendedCapabilitiesSignaled && PDesc.ExtendedCapabilities.Pcap != 0) {
+
+         strm << "Extended Capabilities:" << std::endl;
+
+
+         strm << "                     Pcap:" << PDesc.ExtendedCapabilities.Pcap << std::endl;
+
+         for (i32_t b = 0, i = 0; b < JP2K::MaxCapabilities; b++) {
+
+                 if ((PDesc.ExtendedCapabilities.Pcap >> b) & 0x1) {
+
+                         strm << "              Ccap(" << (JP2K::MaxCapabilities - b) << "): " <<
+                                 std::hex << std::showbase << PDesc.ExtendedCapabilities.Ccap[i++] << std::dec << std::noshowbase
+                                 << std::endl;
+
+                 }
+         }
+  }
+
   return strm;
 }
 
@@ -197,6 +238,42 @@ ASDCP::JP2K::PictureDescriptorDump(const PictureDescriptor& PDesc, FILE* stream)
          Kumu::bin2hex(PDesc.QuantizationDefault.SPqcd, PDesc.QuantizationDefault.SPqcdLength,
                        tmp_buf, MaxDefaults*2)
          );
+
+
+  if (PDesc.Profile.N != 0) {
+         fprintf(stream, "               Profile:\n");
+
+         for (ui16_t i = 0; i < PDesc.Profile.N; i++) {
+
+                 fprintf(stream, "              Pprf(%d): %hx\n", i + 1, PDesc.Profile.Pprf[i]);
+
+         }
+  }
+
+  if (PDesc.CorrespondingProfile.N != 0) {
+         fprintf(stream, "Corresponding Profile:\n");
+
+         for (ui16_t i = 0; i < PDesc.CorrespondingProfile.N; i++) {
+                 fprintf(stream, "              Pcpf(%d): %hx\n", i + 1, PDesc.CorrespondingProfile.Pcpf[i]);
+
+         }
+  }
+
+  if (PDesc.ExtendedCapabilities.N != JP2K::NoExtendedCapabilitiesSignaled) {
+
+         fprintf(stream, "Extended Capabilities: %x\n", PDesc.ExtendedCapabilities.Pcap);
+
+         for (i32_t b = 0, i = 0; b < JP2K::MaxCapabilities && i < PDesc.ExtendedCapabilities.N; b++) {
+
+                 if ((PDesc.ExtendedCapabilities.Pcap >> (JP2K::MaxCapabilities - b - 1)) & 0x1) {
+
+                         fprintf(stream, "           Ccap(%d): %hx\n", b + 1, PDesc.ExtendedCapabilities.Ccap[i++]);
+
+                 }
+         }
+
+  }
+  
 }
 
 
@@ -255,6 +332,58 @@ ASDCP::JP2K_PDesc_to_MD(const JP2K::PictureDescriptor& PDesc,
   EssenceSubDescriptor.QuantizationDefault.get().Length(qdflt_size);
   EssenceSubDescriptor.QuantizationDefault.set_has_value();
 
+  // Profile
+
+  if (PDesc.Profile.N == 0) {
+         EssenceSubDescriptor.J2KProfile.set_has_value(false);
+  } else {
+         EssenceSubDescriptor.J2KProfile.get().resize(PDesc.Profile.N);
+
+         std::copy(PDesc.Profile.Pprf,
+                 PDesc.Profile.Pprf + PDesc.Profile.N,
+                  EssenceSubDescriptor.J2KProfile.get().begin());
+
+         EssenceSubDescriptor.J2KProfile.set_has_value();
+  }
+
+  // Corresponding profile
+
+  if (PDesc.CorrespondingProfile.N == 0) {
+       
+         EssenceSubDescriptor.J2KCorrespondingProfile.set_has_value(false);
+  
+  } else {
+         EssenceSubDescriptor.J2KCorrespondingProfile.get().resize(PDesc.CorrespondingProfile.N);
+
+         std::copy(PDesc.CorrespondingProfile.Pcpf,
+                 PDesc.CorrespondingProfile.Pcpf + PDesc.CorrespondingProfile.N,
+                 EssenceSubDescriptor.J2KCorrespondingProfile.get().begin());
+
+         EssenceSubDescriptor.J2KCorrespondingProfile.set_has_value();
+  }
+
+  // Extended capabilities
+
+  if (PDesc.ExtendedCapabilities.N == JP2K::NoExtendedCapabilitiesSignaled) {
+
+         /* No extended capabilities are signaled */
+
+         EssenceSubDescriptor.J2KExtendedCapabilities.set_has_value(false);
+
+  } else {
+
+         EssenceSubDescriptor.J2KExtendedCapabilities.get().Pcap = PDesc.ExtendedCapabilities.Pcap;
+
+         EssenceSubDescriptor.J2KExtendedCapabilities.get().Ccap.resize(PDesc.ExtendedCapabilities.N);
+
+         std::copy(PDesc.ExtendedCapabilities.Ccap,
+                 PDesc.ExtendedCapabilities.Ccap + PDesc.ExtendedCapabilities.N,
+                 EssenceSubDescriptor.J2KExtendedCapabilities.get().Ccap.begin());
+
+         EssenceSubDescriptor.J2KExtendedCapabilities.set_has_value(true);
+
+  }
+
   return RESULT_OK;
 }
 
@@ -312,6 +441,67 @@ ASDCP::MD_to_JP2K_PDesc(const ASDCP::MXF::GenericPictureEssenceDescriptor&  Esse
         EssenceSubDescriptor.QuantizationDefault.const_get().Length());
   
   PDesc.QuantizationDefault.SPqcdLength = EssenceSubDescriptor.QuantizationDefault.const_get().Length() - 1;
+
+  // Profile
+
+  std::fill(PDesc.Profile.Pprf, PDesc.Profile.Pprf + JP2K::MaxPRFN, 0);
+
+  if (EssenceSubDescriptor.J2KProfile.empty() ||
+         EssenceSubDescriptor.J2KProfile.const_get().size() == 0) {
+
+         PDesc.Profile.N = 0;
+
+  } else {
+
+         PDesc.Profile.N = EssenceSubDescriptor.J2KProfile.const_get().size();
+
+         std::copy(EssenceSubDescriptor.J2KProfile.const_get().begin(),
+                 EssenceSubDescriptor.J2KProfile.const_get().end(),
+                 PDesc.Profile.Pprf);
+
+  }
+
+  // Corresponding profile
+
+  std::fill(PDesc.CorrespondingProfile.Pcpf, PDesc.CorrespondingProfile.Pcpf + JP2K::MaxCPFN, 0);
+
+  if (EssenceSubDescriptor.J2KCorrespondingProfile.empty() ||
+         EssenceSubDescriptor.J2KCorrespondingProfile.const_get().size() == 0) {
+
+         PDesc.CorrespondingProfile.N = 0;
+
+  }
+  else {
+
+         PDesc.CorrespondingProfile.N = EssenceSubDescriptor.J2KCorrespondingProfile.const_get().size();
+
+         std::copy(EssenceSubDescriptor.J2KCorrespondingProfile.const_get().begin(),
+                 EssenceSubDescriptor.J2KCorrespondingProfile.const_get().end(),
+                 PDesc.CorrespondingProfile.Pcpf);
+
+  }
+
+  // Extended capabilities
+
+  std::fill(PDesc.ExtendedCapabilities.Ccap, PDesc.ExtendedCapabilities.Ccap + JP2K::MaxCapabilities, 0);
+
+  if (EssenceSubDescriptor.J2KExtendedCapabilities.empty()) {
+
+         PDesc.ExtendedCapabilities.Pcap = 0;
+         PDesc.ExtendedCapabilities.N = JP2K::NoExtendedCapabilitiesSignaled;
+
+  }
+  else {
+
+         PDesc.ExtendedCapabilities.Pcap = EssenceSubDescriptor.J2KExtendedCapabilities.const_get().Pcap;
+         PDesc.ExtendedCapabilities.N = EssenceSubDescriptor.J2KExtendedCapabilities.const_get().Ccap.size();
+
+         std::copy(EssenceSubDescriptor.J2KExtendedCapabilities.const_get().Ccap.begin(),
+                 EssenceSubDescriptor.J2KExtendedCapabilities.const_get().Ccap.end(),
+                 PDesc.ExtendedCapabilities.Ccap);
+
+  }
+
   return RESULT_OK;
 }
 
index a0f2a8a124757cf59bcd2b7c6b59aa3343b558d7..4d2c130787acbf289430296076b1279363967fa6 100755 (executable)
@@ -37,45 +37,17 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using Kumu::DefaultLogSink;
 
 
-// when indexed with the second byte of a marker code, this table will procuce one of
-// two values:
-//   0 - the marker is a standalone marker
-//   1 - the marker designates a marker segment
-//
-const byte_t MarkerSegmentMap[] =
-  {
-    /*      0   1   2   3   4   5   6   7      8   9   a   b   c   d   e   f */
-    /* 0 */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // 0
-    /* 1 */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // 1
-    /* 2 */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // 2
-    /* 3 */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // 3
-    /* 4 */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // 4
-    /* 5 */ 0,  1,  1,  1,  1,  1,  0,  1,     1,  0,  0,  0,  1,  1,  1,  1, // 5
-    /* 6 */ 1,  1,  0,  1,  1,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // 6
-    /* 7 */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // 7
-    /* 8 */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // 8
-    /* 9 */ 1,  1,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // 9
-    /* a */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // a
-    /* b */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // b
-    /* c */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // c
-    /* d */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // d
-    /* e */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // e
-    /* f */ 0,  0,  0,  0,  0,  0,  0,  0,     0,  0,  0,  0,  0,  0,  0,  0, // f
-    /*      0   1   2   3   4   5   6   7      8   9   a   b   c   d   e   f */
-  };
-
-
 //
 ASDCP::Result_t
 ASDCP::JP2K::GetNextMarker(const byte_t** buf, JP2K::Marker& Marker)
 {
   assert((buf != 0) && (*buf != 0 ));
   
-  if ( **buf != 0xff )
+  if (*(*buf)++ != 0xff )
     return ASDCP::RESULT_FAIL;
 
-  Marker.m_IsSegment = (MarkerSegmentMap[*(++(*buf))] == 1);
   Marker.m_Type = (Marker_t)(0xff00 | *(*buf)++);
+  Marker.m_IsSegment = Marker.m_Type != MRK_SOC && Marker.m_Type != MRK_SOD && Marker.m_Type != MRK_EOC;
 
   if ( Marker.m_IsSegment )
     {
@@ -86,13 +58,13 @@ ASDCP::JP2K::GetNextMarker(const byte_t** buf, JP2K::Marker& Marker)
       *buf += Marker.m_DataSize;
     }
 
-
+  /* TODO: why is this here?
   if ( Marker.m_DataSize != 0 && Marker.m_DataSize < 3 )
     {
       DefaultLogSink().Error("Illegal data size: %u\n", Marker.m_DataSize);
       return ASDCP::RESULT_FAIL;
     }
-
+       */
   return ASDCP::RESULT_OK;
 }
 
@@ -227,6 +199,78 @@ ASDCP::JP2K::Accessor::COM::Dump(FILE* stream) const
     }
 }
 
+//
+void
+ASDCP::JP2K::Accessor::PRF::Dump(FILE* stream) const
+{
+  if ( stream == 0 )
+    stream = stderr;
+
+  fprintf(stream, "PRF: \n");
+
+  if (N() == 0) {
+
+         fprintf(stream, "     N/A");
+
+  } else {
+
+         for (ui16_t i = 1; i <= N(); i++) {
+                 fprintf(stream, "pprf(%d): %d\n", i, pprf(i));
+         }
+
+  }
+}
+
+//
+void
+ASDCP::JP2K::Accessor::CPF::Dump(FILE* stream) const
+{
+  if ( stream == 0 )
+    stream = stderr;
+
+  fprintf(stream, "CPF: \n");
+
+  if (N() == 0) {
+
+         fprintf(stream, "     N/A");
+
+  } else {
+
+         for (ui16_t i = 1; i <= N(); i++) {
+                 fprintf(stream, "pcpf(%d): %d\n", i, pcpf(i));
+         }
+
+  }
+}
+
+
+//
+void
+ASDCP::JP2K::Accessor::CAP::Dump(FILE* stream) const
+{
+  if ( stream == 0 )
+    stream = stderr;
+
+  fprintf(stream, "CAP: \n");
+
+  ui32_t pcap = this->pcap();
+
+  if (pcap == 0) {
+
+         fprintf(stream, "     None");
+
+  } else {
+
+         for (i32_t b = 32, i = 1; b > 0; b--) {
+
+                 if ((pcap >> (32 - b)) & 0x1) {
+
+                         fprintf(stream, "     ccap(%d): %d\n", b, this->ccap(i++));
+
+                 }
+         }
+  }
+}
 
 //-------------------------------------------------------------------------------------------------------
 //
@@ -274,6 +318,9 @@ ASDCP::JP2K::GetMarkerString(Marker_t m)
     case MRK_EPH: return "EPH: End of packet header"; break;
     case MRK_CRG: return "CRG: Component registration"; break;
     case MRK_COM: return "COM: Comment"; break;
+    case MRK_CPF: return "CPF: Corresponding profile"; break;
+    case MRK_CAP: return "CAP: Capabilities"; break;
+    case MRK_PRF: return "PRF: Profile"; break;
     }
 
   return "Unknown marker code";
index b043dfc8de36eca354bb80941cb162a84b042b66..8128de5367f6e15f8b03c5e3992aeb6056c041a7 100755 (executable)
@@ -54,9 +54,12 @@ namespace JP2K
       MRK_SOT = 0xff90, // Start of tile-part
       MRK_SOD = 0xff93, // Start of data
       MRK_EOC = 0xffd9, // End of codestream
+      MRK_CAP = 0xff50,  // Extended capabilities
       MRK_SIZ = 0xff51, // Image and tile size
       MRK_COD = 0xff52, // Coding style default
       MRK_COC = 0xff53, // Coding style component
+      MRK_PRF = 0xff56, // Profile
+      MRK_CPF = 0xff59, // Corresponding profile
       MRK_RGN = 0xff5e, // Region of interest
       MRK_QCD = 0xff5c, // Quantization default
       MRK_QCC = 0xff5d, // Quantization component
@@ -219,6 +222,90 @@ namespace JP2K
          inline ui32_t CommentSize() const { return m_DataSize; }
          void Dump(FILE* stream = 0) const;
        };
+
+      // Corresponding Profile
+      class CPF {
+
+          const ui16_t* m_Data;
+                 ui16_t m_N;
+
+          KM_NO_COPY_CONSTRUCT(CPF);
+          CPF();
+
+      public:
+          CPF(const Marker& M) {
+              assert(M.m_Type == MRK_CPF);
+
+              m_Data = (ui16_t*) M.m_Data;
+                         m_N = M.m_DataSize >> 1;
+          }
+
+          ~CPF() {}
+
+          inline ui16_t N() const { return m_N; }
+
+          inline ui16_t pcpf(ui16_t i) const { return KM_i16_BE(m_Data[2 * (i - 1)]); }
+
+          void Dump(FILE* stream = 0) const;
+      };
+
+      // Profile
+      class PRF {
+
+          const ui16_t* m_Data;
+                 ui16_t m_N;
+
+          KM_NO_COPY_CONSTRUCT(PRF);
+          PRF();
+
+      public:
+          PRF(const Marker& M) {
+              assert(M.m_Type == MRK_PRF);
+
+                         m_Data = (ui16_t*) M.m_Data;
+                         m_N = M.m_DataSize >> 1;
+                 }
+
+          ~PRF() {}
+
+          inline ui16_t N() const { return m_N; }
+
+          inline ui16_t pprf(ui16_t i) const { return KM_i16_BE(m_Data[2 * (i - 1)]); }
+
+          void Dump(FILE* stream = 0) const;
+      };
+
+      // Extended capabilities
+      class CAP {
+
+          const ui16_t* m_Data;
+
+                 ui32_t m_Pcap;
+
+                 i8_t m_N;
+
+          KM_NO_COPY_CONSTRUCT(CAP);
+          CAP();
+
+      public:
+          CAP(const Marker& M) {
+              assert(M.m_Type == MRK_CAP);
+
+              m_Data = (ui16_t *) (M.m_Data + 4);
+                         m_Pcap = KM_i32_BE(*(ui32_t*)(M.m_Data));
+                         m_N = (M.m_DataSize - 4) >> 1;
+          }
+
+          ~CAP() {}
+
+          inline ui32_t pcap() const { return m_Pcap; }
+
+                 inline i8_t N() const { return m_N; }
+
+          inline ui16_t ccap(ui16_t i) const { return KM_i16_BE(m_Data[2 * (i - 1)]); }
+
+          void Dump(FILE* stream = 0) const;
+      };
     } // namespace Accessor
 } // namespace JP2K
 } // namespace ASDCP
index 0ed26492e82e4f8ccce9295d92c3247a219108e0..9d5540911a699b4e774447479144eaf6579d7927 100755 (executable)
@@ -101,6 +101,12 @@ ASDCP::JP2K::ParseMetadataIntoDesc(const FrameBuffer& FB, PictureDescriptor& PDe
   const byte_t* p = FB.RoData();
   const byte_t* end_p = p + FB.Size();
 
+  /* initialize optional items */
+
+  PDesc.ExtendedCapabilities.N = JP2K::NoExtendedCapabilitiesSignaled;
+  PDesc.Profile.N = 0;
+  PDesc.CorrespondingProfile.N = 0;
+
   while ( p < end_p && ASDCP_SUCCESS(result) )
     {
       result = GetNextMarker(&p, NextMarker);
@@ -178,6 +184,66 @@ ASDCP::JP2K::ParseMetadataIntoDesc(const FrameBuffer& FB, PictureDescriptor& PDe
          memcpy(&PDesc.QuantizationDefault, NextMarker.m_Data, NextMarker.m_DataSize);
          PDesc.QuantizationDefault.SPqcdLength = NextMarker.m_DataSize - 1;
          break;
+
+       case MRK_CAP:
+         {
+           Accessor::CAP CAP_(NextMarker);
+           
+                       PDesc.ExtendedCapabilities.Pcap = CAP_.pcap();
+
+                       PDesc.ExtendedCapabilities.N = CAP_.N();
+
+                       for (i32_t i = 0; i < CAP_.N(); i++) {
+
+                               PDesc.ExtendedCapabilities.Ccap[i] = CAP_.ccap(i);
+
+                       }
+
+         }
+         break;
+
+               case MRK_PRF:
+         {
+           Accessor::PRF PRF_(NextMarker);
+
+               ui16_t n = PRF_.N();
+
+               if ( n > MaxPRFN )
+           {
+             DefaultLogSink().Error("Number (%d) of Pprf^i exceeds maximum supported\n", n);
+             return RESULT_RAW_FORMAT;
+           }
+
+                       PDesc.Profile.N = n;
+
+                       for(i32_t i = 0; i < n ; i++) {
+
+                               PDesc.Profile.Pprf[i] = PRF_.pprf(i+1);
+                       }
+         }
+         break;
+
+               case MRK_CPF:
+         {
+           Accessor::CPF CPF_(NextMarker);
+
+               ui16_t n = CPF_.N();
+
+               if ( n > MaxCPFN )
+           {
+             DefaultLogSink().Error("Number (%d) of Pcpf^i exceeds maximum supported\n", n);
+             return RESULT_RAW_FORMAT;
+           }
+
+                       PDesc.CorrespondingProfile.N = n;
+
+                       for(i32_t i = 0; i < n; i++) {
+
+                               PDesc.CorrespondingProfile.Pcpf[i] = CPF_.pcpf(i+1);
+                       }
+         }
+         break;
+
        }
     }
 
index a08044000ba1df1ab804b0fb27da31112fe4b485..c5610337fd3fedbd863b792b5632a1810cec9d63 100755 (executable)
@@ -249,6 +249,57 @@ operator==(const ASDCP::JP2K::CodingStyleDefault_t& lhs, const ASDCP::JP2K::Codi
   return true;
 }
 
+//
+bool
+operator==(const ASDCP::JP2K::ExtendedCapabilities_t& lhs, const ASDCP::JP2K::ExtendedCapabilities_t& rhs)
+{
+       if (lhs.N != rhs.N) return false;
+
+       if (lhs.N != JP2K::NoExtendedCapabilitiesSignaled) {
+
+               if (lhs.Pcap != rhs.Pcap) return false;
+
+               for (ui32_t i = 0; i < lhs.N; i++)
+               {
+                       if (lhs.Ccap[i] != rhs.Ccap[i])
+                               return false;
+               }
+
+       }
+
+       return true;
+}
+
+//
+bool
+operator==(const ASDCP::JP2K::CorrespondingProfile_t& lhs, const ASDCP::JP2K::CorrespondingProfile_t& rhs)
+{
+       if (lhs.N != rhs.N) return false;
+
+       for (ui32_t i = 0; i < lhs.N; i++)
+       {
+               if (lhs.Pcpf[i] != rhs.Pcpf[i])
+                       return false;
+       }
+
+       return true;
+}
+
+//
+bool
+operator==(const ASDCP::JP2K::Profile_t& lhs, const ASDCP::JP2K::Profile_t& rhs)
+{
+       if (lhs.N != rhs.N) return false;
+
+       for (ui32_t i = 0; i < lhs.N; i++)
+       {
+               if (lhs.Pprf[i] != rhs.Pprf[i])
+                       return false;
+       }
+
+       return true;
+}
+
 //
 bool
 operator==(const ASDCP::JP2K::PictureDescriptor& lhs, const ASDCP::JP2K::PictureDescriptor& rhs)
@@ -271,6 +322,9 @@ operator==(const ASDCP::JP2K::PictureDescriptor& lhs, const ASDCP::JP2K::Picture
   if ( lhs.Csize != rhs.Csize ) return false;
   if ( ! ( lhs.CodingStyleDefault == rhs.CodingStyleDefault ) ) return false;
   if ( ! ( lhs.QuantizationDefault == rhs.QuantizationDefault ) ) return false;
+  if (!(lhs.Profile == rhs.Profile)) return false;
+  if (!(lhs.CorrespondingProfile == rhs.CorrespondingProfile)) return false;
+  if (!(lhs.ExtendedCapabilities == rhs.ExtendedCapabilities)) return false;
   
   for ( ui32_t i = 0; i < JP2K::MaxComponents; i++ )
     {
index f3f60f187b3715b9a1d50e7af4412a3254047d8f..f6a8935fda44d54297df3db6bd5b0e717e606412 100755 (executable)
@@ -256,6 +256,37 @@ namespace Kumu
       }
     };
 
+  //
+  class ArchivableUi16 : public Kumu::IArchive
+    {
+    public:
+      ui16_t value;
+
+      ArchivableUi16() : value(0) {}
+      ArchivableUi16(const ui16_t& val) : value(val) {}
+      virtual ~ArchivableUi16() {}
+
+      bool   HasValue() const { return true; }
+      ui32_t ArchiveLength() const { return sizeof(ui16_t); }
+
+         operator ui16_t() const { return value; }
+
+      bool   Archive(MemIOWriter* Writer) const {
+       if ( Writer == 0 ) return false;
+       return Writer->WriteUi16BE(value);
+      }
+
+      bool   Unarchive(MemIOReader* Reader) {
+       if ( Reader == 0 ) return false;
+       return Reader->ReadUi16BE(&value);
+      }
+
+      const char* EncodeString(char* str_buf, ui32_t buf_len) const {
+       snprintf(str_buf, buf_len, "%hu", value);
+       return str_buf;
+      }
+    };
+
   //
   typedef Kumu::ArchivableList<ArchivableString> StringList;
 
index a2c691fa3ea597451014ed1b4cae5319d74abf00..06d0fde760eea6a748bd18b8f78b81caa4868232 100644 (file)
@@ -1608,8 +1608,26 @@ static const ASDCP::MDDEntry s_MDD_Table[] = {
      {0}, false, "ACESFrameWrappedEssence" },
    { { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, // 518
        0x03, 0x02, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00 },
-     {0}, false, "DCAudioChannel_FSKSyncSignalChannel" },   
-   { { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, // 519
+     {0}, false, "DCAudioChannel_FSKSyncSignalChannel" },
+   { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e,
+       0x04, 0x01, 0x06, 0x03, 0x0f, 0x00, 0x00, 0x00 },
+     {0}, false, "JPEG2000PictureSubDescriptor_J2KExtendedCapabilities" }, // 519
+   { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e,
+       0x04, 0x01, 0x06, 0x03, 0x10, 0x00, 0x00, 0x00 },
+     {0}, false, "JPEG2000PictureSubDescriptor_J2KProfile" }, // 520
+   { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e,
+       0x04, 0x01, 0x06, 0x03, 0x11, 0x00, 0x00, 0x00 },
+     {0}, false, "JPEG2000PictureSubDescriptor_J2KCorrespondingProfile" }, // 521
+   { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x04, 0x01, 0x01,
+       0x03, 0x01, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00 },
+     {0}, false, "J2KExtendedCapabilities" }, // 522
+   { { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0D,
+       0x04, 0x01, 0x02, 0x02, 0x03, 0x01, 0x08, 0x00 },
+     {0}, false, "HTJ2KPictureCodingScheme" }, // 523
+   { { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0D,
+       0x04, 0x01, 0x02, 0x02, 0x03, 0x01, 0x08, 0x01 },
+     {0}, false, "HTJ2KPictureCodingSchemeGeneric" }, // 524
+   { { 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x0d, // 525
        0x0d, 0x0f, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00 },
      {0}, false, "AudioChannelSLVS" },
    { {0}, {0}, false, 0 },
index 6d7b702ab3c51d5f184339eed4dde2c2c2bc0da8..d704217945aa433abc9e998a495a39f1bd0c3024 100755 (executable)
--- a/src/MDD.h
+++ b/src/MDD.h
@@ -554,7 +554,13 @@ namespace ASDCP {
        MDD_ACESUncompressedMonoscopicWithAlpha, // 516
        MDD_ACESFrameWrappedEssence, // 517
        MDD_DCAudioChannel_FSKSyncSignalChannel, // 518
-       MDD_AudioChannelSLVS, // 519
+       MDD_JPEG2000PictureSubDescriptor_J2KExtendedCapabilities, // 519
+       MDD_JPEG2000PictureSubDescriptor_J2KProfile, // 520
+       MDD_JPEG2000PictureSubDescriptor_J2KCorrespondingProfile, // 521
+       MDD_J2KExtendedCapabilities, // 522
+       MDD_HTJ2KPictureCodingScheme, // 523
+       MDD_HTJ2KPictureCodingSchemeGeneric, // 524
+       MDD_AudioChannelSLVS, // 525
        MDD_Max
     }; // enum MDD_t
 
index a98a4d2fd701f42c4eb17d6d3156df56000b5f0f..39d928b8ad73d6b22ba632eee2eeb9c0233af428 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2016, John Hurst
+Copyright (c) 2005-2019, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -774,6 +774,63 @@ ASDCP::MXF::Raw::EncodeString(char* str_buf, ui32_t buf_len) const
   return str_buf;
 }
 
+
+//
+bool
+ASDCP::MXF::J2KExtendedCapabilities::Archive(Kumu::MemIOWriter* Writer) const {
+  if ( ! Writer->WriteUi32BE(Pcap) )
+    {
+      return false;
+    }
+
+    if ( ! Ccap.Archive(Writer) )
+    {
+        return false;
+    }
+
+  return true;
+}
+
+//
+bool
+ASDCP::MXF::J2KExtendedCapabilities::Unarchive(Kumu::MemIOReader* Reader) {
+  if ( ! Reader->ReadUi32BE(&Pcap) )
+    {
+      return false;
+    }
+
+ if ( ! Ccap.Unarchive(Reader) )
+    {
+        return false;
+    }
+
+  return true;
+}
+
+//
+const char*
+ASDCP::MXF::J2KExtendedCapabilities::EncodeString(char* str_buf, ui32_t buf_len) const
+{
+  const int str_len = ( sizeof(ui16_t) + 1 ) * JP2K::MaxCapabilities;
+
+  if ( Pcap != 0 && buf_len > str_len )
+    {
+      for ( int i = 0; i < Ccap.size(); ++i )
+        {
+         snprintf(str_buf+(i*3), 4, "%02hx.", Ccap[i]);
+        }
+
+      str_buf[str_len-1] = 0;
+    }
+  else
+    {
+      str_buf[0] = 0;
+    }
+
+  return str_buf;
+}
+
+
 //
 // end MXFTypes.cpp
 //
index c49fed9b6f07b267e1f5de0621865dc7c65a4db2..eb8b3dfe0b52e83144f77570c421afcfbae7a18e 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2016, John Hurst
+Copyright (c) 2005-2019, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define _MXFTYPES_H_
 
 #include "KLV.h"
+#include "AS_DCP.h"
 #include <list>
 #include <vector>
 #include <set>
@@ -688,6 +689,21 @@ namespace ASDCP
          const char* EncodeString(char* str_buf, ui32_t buf_len) const;
        };
 
+      //
+      class J2KExtendedCapabilities : public Kumu::IArchive
+        {
+        public:
+         ui32_t Pcap;
+         Array<Kumu::ArchivableUi16> Ccap;
+       
+         bool HasValue() const { return true; }
+         ui32_t ArchiveLength() const { return 0; }
+
+         bool Archive(Kumu::MemIOWriter* Writer) const;
+         bool Unarchive(Kumu::MemIOReader* Reader);
+         const char* EncodeString(char* str_buf, ui32_t buf_len) const;
+      };
+
     } // namespace MXF
 } // namespace ASDCP
 
index 2a1e1f2b2c57847b9abff0e84caf5e194c18a390..9b7f95e285116c589ae529e2971a8b102b642fc3 100755 (executable)
@@ -2125,6 +2125,18 @@ JPEG2000PictureSubDescriptor::InitFromTLVSet(TLVReader& TLVSet)
     result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(JPEG2000PictureSubDescriptor, J2CLayout));
     J2CLayout.set_has_value( result == RESULT_OK );
   }
+  if ( ASDCP_SUCCESS(result) ) {
+    result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(JPEG2000PictureSubDescriptor, J2KExtendedCapabilities));
+    J2KExtendedCapabilities.set_has_value( result == RESULT_OK );
+  }
+  if ( ASDCP_SUCCESS(result) ) {
+    result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(JPEG2000PictureSubDescriptor, J2KProfile));
+    J2KProfile.set_has_value( result == RESULT_OK );
+  }
+  if ( ASDCP_SUCCESS(result) ) {
+    result = TLVSet.ReadObject(OBJ_READ_ARGS_OPT(JPEG2000PictureSubDescriptor, J2KCorrespondingProfile));
+    J2KCorrespondingProfile.set_has_value( result == RESULT_OK );
+  }
   return result;
 }
 
@@ -2148,6 +2160,9 @@ JPEG2000PictureSubDescriptor::WriteToTLVSet(TLVWriter& TLVSet)
   if ( ASDCP_SUCCESS(result)  && ! CodingStyleDefault.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(JPEG2000PictureSubDescriptor, CodingStyleDefault));
   if ( ASDCP_SUCCESS(result)  && ! QuantizationDefault.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(JPEG2000PictureSubDescriptor, QuantizationDefault));
   if ( ASDCP_SUCCESS(result)  && ! J2CLayout.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(JPEG2000PictureSubDescriptor, J2CLayout));
+  if ( ASDCP_SUCCESS(result)  && ! J2KExtendedCapabilities.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(JPEG2000PictureSubDescriptor, J2KExtendedCapabilities));
+  if ( ASDCP_SUCCESS(result)  && ! J2KProfile.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(JPEG2000PictureSubDescriptor, J2KProfile));
+  if ( ASDCP_SUCCESS(result)  && ! J2KCorrespondingProfile.empty() ) result = TLVSet.WriteObject(OBJ_WRITE_ARGS_OPT(JPEG2000PictureSubDescriptor, J2KCorrespondingProfile));
   return result;
 }
 
@@ -2170,6 +2185,9 @@ JPEG2000PictureSubDescriptor::Copy(const JPEG2000PictureSubDescriptor& rhs)
   CodingStyleDefault = rhs.CodingStyleDefault;
   QuantizationDefault = rhs.QuantizationDefault;
   J2CLayout = rhs.J2CLayout;
+  J2KExtendedCapabilities = rhs.J2KExtendedCapabilities;
+  J2KProfile = rhs.J2KProfile;
+  J2KCorrespondingProfile = rhs.J2KCorrespondingProfile;
 }
 
 //
@@ -2205,6 +2223,17 @@ JPEG2000PictureSubDescriptor::Dump(FILE* stream)
   if ( ! J2CLayout.empty() ) {
     fprintf(stream, "  %22s = %s\n",  "J2CLayout", J2CLayout.get().EncodeString(identbuf, IdentBufferLen));
   }
+  if ( ! J2KExtendedCapabilities.empty() ) {
+    fprintf(stream, "  %22s = %s\n",  "J2KExtendedCapabilities", J2KExtendedCapabilities.get().EncodeString(identbuf, IdentBufferLen));
+  }
+  if ( ! J2KProfile.empty() ) {
+    fprintf(stream, "  %22s:\n",  "J2KProfile");
+  J2KProfile.get().Dump(stream);
+  }
+  if ( ! J2KCorrespondingProfile.empty() ) {
+    fprintf(stream, "  %22s:\n",  "J2KCorrespondingProfile");
+  J2KCorrespondingProfile.get().Dump(stream);
+  }
 }
 
 //
index 6601d649315af43a440f3e742b3f314ff08b44f6..03b3169ca7ecd56413667678b399bcd1dee78475 100755 (executable)
@@ -571,6 +571,9 @@ namespace ASDCP
           optional_property<Raw > CodingStyleDefault;
           optional_property<Raw > QuantizationDefault;
           optional_property<RGBALayout > J2CLayout;
+          optional_property<J2KExtendedCapabilities > J2KExtendedCapabilities;
+          optional_property<Array<Kumu::ArchivableUi16> > J2KProfile;
+          optional_property<Array<Kumu::ArchivableUi16> > J2KCorrespondingProfile;
 
       JPEG2000PictureSubDescriptor(const Dictionary*& d);
       JPEG2000PictureSubDescriptor(const JPEG2000PictureSubDescriptor& rhs);
index 918498299bb001ef350013cd1cd5756e560cff75..bcf95d086485a94534f01f66f61aed62ba095708 100755 (executable)
@@ -246,6 +246,21 @@ main(int argc, const char** argv)
                {
                  has_tlm = true;
                }
+             else if ( current_marker.m_Type == MRK_CAP )
+               {
+                       Accessor::CAP CAP_(current_marker);
+                       CAP_.Dump(stdout);
+               }
+             else if ( current_marker.m_Type == MRK_PRF )
+               {
+                       Accessor::PRF PRF_(current_marker);
+                       PRF_.Dump(stdout);
+               }
+             else if ( current_marker.m_Type == MRK_CPF )
+               {
+                       Accessor::CPF CPF_(current_marker);
+                       CPF_.Dump(stdout);
+               }
              else
                {
                  fprintf(stderr, "Unprocessed marker - %s\n", GetMarkerString(current_marker.m_Type));