Merge pull request #20 from cinecert/htj2c
[asdcplib.git] / src / JP2K_Codestream_Parser.cpp
index 32a53167a81201e123d84753a652ccf649765347..9d5540911a699b4e774447479144eaf6579d7927 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2004-2006, John Hurst
+Copyright (c) 2004-2013, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -55,9 +55,8 @@ public:
 
   ~h__CodestreamParser() {}
 
-  Result_t OpenReadFrame(const char* filename, FrameBuffer& FB)
+  Result_t OpenReadFrame(const std::string& filename, FrameBuffer& FB)
   {
-    ASDCP_TEST_NULL_STR(filename);
     m_File.Close();
     Result_t result = m_File.OpenRead(filename);
 
@@ -82,88 +81,174 @@ public:
 
     if ( ASDCP_SUCCESS(result) )
       {
-       Marker NextMarker;
-       ui32_t i;
-       const byte_t* p = FB.RoData();
-       const byte_t* end_p = p + FB.Size();
+       byte_t start_of_data = 0; // out param
+       result = ParseMetadataIntoDesc(FB, m_PDesc, &start_of_data);
 
-       while ( p < end_p && ASDCP_SUCCESS(result) )
-         {
-           result = GetNextMarker(&p, NextMarker);
+       if ( ASDCP_SUCCESS(result) )
+         FB.PlaintextOffset(start_of_data);
+      }
 
-           if ( ASDCP_FAILURE(result) )
-             {
-               result = RESULT_RAW_ESS;
-               break;
-             }
-#if 0
-           fprintf(stderr, "%s Length: %u\n",
-                   GetMarkerString(NextMarker.m_Type), NextMarker.m_DataSize);
-#endif
+    return result;
+  }
+};
 
-           switch ( NextMarker.m_Type )
+ASDCP::Result_t
+ASDCP::JP2K::ParseMetadataIntoDesc(const FrameBuffer& FB, PictureDescriptor& PDesc, byte_t* start_of_data)
+{
+  Result_t result = RESULT_OK;
+  Marker NextMarker;
+  ui32_t i;
+  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);
+
+      if ( ASDCP_FAILURE(result) )
+       {
+         result = RESULT_RAW_ESS;
+         break;
+       }
+
+      switch ( NextMarker.m_Type )
+       {
+       case MRK_SOD:
+         if ( start_of_data != 0 )
+           *start_of_data = p - FB.RoData();
+
+         p = end_p;
+         break;
+
+       case MRK_SIZ:
+         {
+           Accessor::SIZ SIZ_(NextMarker);
+           PDesc.StoredWidth = SIZ_.Xsize();
+           PDesc.StoredHeight = SIZ_.Ysize();
+           PDesc.AspectRatio = Rational(SIZ_.Xsize(), SIZ_.Ysize());
+           PDesc.Rsize = SIZ_.Rsize();
+           PDesc.Xsize = SIZ_.Xsize();
+           PDesc.Ysize = SIZ_.Ysize();
+           PDesc.XOsize = SIZ_.XOsize();
+           PDesc.YOsize = SIZ_.YOsize();
+           PDesc.XTsize = SIZ_.XTsize();
+           PDesc.YTsize = SIZ_.YTsize();
+           PDesc.XTOsize = SIZ_.XTOsize();
+           PDesc.YTOsize = SIZ_.YTOsize();
+           PDesc.Csize = SIZ_.Csize();
+
+           if ( PDesc.Csize != 3 )
              {
-             case MRK_SOD:
-               FB.PlaintextOffset(p - FB.RoData());
-               p = end_p;
-               break;
-
-             case MRK_SIZ:
-               {
-                 Accessor::SIZ SIZ_(NextMarker);
-                 m_PDesc.StoredWidth = SIZ_.Xsize();
-                 m_PDesc.StoredHeight = SIZ_.Ysize();
-                 m_PDesc.AspectRatio = Rational(SIZ_.Xsize(), SIZ_.Ysize());
-                 m_PDesc.Rsize = SIZ_.Rsize();
-                 m_PDesc.Xsize = SIZ_.Xsize();
-                 m_PDesc.Ysize = SIZ_.Ysize();
-                 m_PDesc.XOsize = SIZ_.XOsize();
-                 m_PDesc.YOsize = SIZ_.YOsize();
-                 m_PDesc.XTsize = SIZ_.XTsize();
-                 m_PDesc.YTsize = SIZ_.YTsize();
-                 m_PDesc.XTOsize = SIZ_.XTOsize();
-                 m_PDesc.YTOsize = SIZ_.YTOsize();
-                 m_PDesc.Csize = SIZ_.Csize();
-
-                 if ( m_PDesc.Csize != 3 )
-                   {
-                     DefaultLogSink().Error("Unexpected number of components: %u\n", m_PDesc.Csize);
-                     return RESULT_RAW_FORMAT;
-                   }
-
-                 for ( i = 0; i < m_PDesc.Csize; i++ )
-                   SIZ_.ReadComponent(i, m_PDesc.ImageComponents[i]);
-               }
-               break;
-
-             case MRK_COD:
-               if ( NextMarker.m_DataSize > DefaultCodingDataLength )
-                 {
-                   DefaultLogSink().Error("Unexpectedly large CodingStyle data: %u\n", NextMarker.m_DataSize);
-                   return RESULT_RAW_FORMAT;
-                 }
-
-               m_PDesc.CodingStyleLength = NextMarker.m_DataSize;
-               memcpy(m_PDesc.CodingStyle, NextMarker.m_Data, m_PDesc.CodingStyleLength);
-               break;
-
-             case MRK_QCD:
-               if ( NextMarker.m_DataSize > DefaultCodingDataLength )
-                 {
-                   DefaultLogSink().Error("Unexpectedly large QuantDefault data: %u\n", NextMarker.m_DataSize);
-                   return RESULT_RAW_FORMAT;
-                 }
-
-               m_PDesc.QuantDefaultLength = NextMarker.m_DataSize;
-               memcpy(m_PDesc.QuantDefault, NextMarker.m_Data, m_PDesc.QuantDefaultLength);
-               break;
+               DefaultLogSink().Error("Unexpected number of components: %u\n", PDesc.Csize);
+               return RESULT_RAW_FORMAT;
              }
+           
+           for ( i = 0; i < PDesc.Csize; i++ )
+             SIZ_.ReadComponent(i, PDesc.ImageComponents[i]);
          }
-      }
+         break;
+
+       case MRK_COD:
+         memset(&PDesc.CodingStyleDefault, 0, sizeof(CodingStyleDefault_t));
+
+         if ( NextMarker.m_DataSize > sizeof(CodingStyleDefault_t) )
+           {
+             DefaultLogSink().Error("Unexpectedly large CodingStyle data: %u\n", NextMarker.m_DataSize);
+             return RESULT_RAW_FORMAT;
+           }
+         
+         memcpy(&PDesc.CodingStyleDefault, NextMarker.m_Data, NextMarker.m_DataSize);
+         break;
+
+       case MRK_QCD:
+         memset(&PDesc.QuantizationDefault, 0, sizeof(QuantizationDefault_t));
+
+         if ( NextMarker.m_DataSize < 3 ) // ( Sqcd = 8 bits, SPqcd = 8 bits ) == 2 bytes, error if not greater
+           {
+             DefaultLogSink().Error("No quantization signaled. QCD size=%s.\n", NextMarker.m_DataSize);
+             return RESULT_RAW_FORMAT;
+           }
+         
+         if ( NextMarker.m_DataSize > MaxDefaults )
+           {
+             DefaultLogSink().Error("Quantization Default length exceeds maximum %d\n", NextMarker.m_DataSize);
+             return RESULT_RAW_FORMAT;
+           }
+
+         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();
 
-    return result;
-  }
-};
+                       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;
+
+       }
+    }
+
+  return result;
+}
 
 //------------------------------------------------------------------------------------------
 
@@ -178,7 +263,7 @@ ASDCP::JP2K::CodestreamParser::~CodestreamParser()
 // Opens the stream for reading, parses enough data to provide a complete
 // set of stream metadata for the MXFWriter below.
 ASDCP::Result_t
-ASDCP::JP2K::CodestreamParser::OpenReadFrame(const char* filename, FrameBuffer& FB) const
+ASDCP::JP2K::CodestreamParser::OpenReadFrame(const std::string& filename, FrameBuffer& FB) const
 {
   const_cast<ASDCP::JP2K::CodestreamParser*>(this)->m_Parser = new h__CodestreamParser;
   return m_Parser->OpenReadFrame(filename, FB);