Release me
[asdcplib.git] / src / JP2K_Codestream_Parser.cpp
index 700233f56fc83f6eb5f728d6acb836af0210b721..0ed26492e82e4f8ccce9295d92c3247a219108e0 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);
 
@@ -67,7 +66,7 @@ public:
 
        if ( FB.Capacity() < file_size )
          {
-           DefaultLogSink().Error("FrameBuf.Capacity: %lu frame length: %lu\n", FB.Capacity(), (ui32_t)file_size);
+           DefaultLogSink().Error("FrameBuf.Capacity: %u frame length: %u\n", FB.Capacity(), (ui32_t)file_size);
            return RESULT_SMALLBUF;
          }
       }
@@ -82,83 +81,109 @@ 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 0
-           fprintf(stderr, "%s Length: %lu\n",
-                   GetMarkerString(NextMarker.m_Type), NextMarker.m_DataSize);
-#endif
-
-           switch ( NextMarker.m_Type )
-             {
-             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: %lu\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: %lu\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: %lu\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;
-             }
-         }
+       if ( ASDCP_SUCCESS(result) )
+         FB.PlaintextOffset(start_of_data);
       }
 
     return result;
   }
 };
 
+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();
+
+  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 )
+             {
+               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;
+       }
+    }
+
+  return result;
+}
+
 //------------------------------------------------------------------------------------------
 
 ASDCP::JP2K::CodestreamParser::CodestreamParser()
@@ -172,7 +197,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);