banner updates to 2015
authormschroffel <mschroffel@cinecert.com>
Thu, 19 Feb 2015 22:42:18 +0000 (22:42 +0000)
committermschroffel <>
Thu, 19 Feb 2015 22:42:18 +0000 (22:42 +0000)
26 files changed:
README
configure.ac
src/AS_02.h
src/AS_02_PCM.cpp
src/AS_DCP_MXF.cpp
src/AS_DCP_TimedText.cpp
src/KM_fileio.cpp
src/KM_util.cpp
src/KM_util.h
src/KM_xml.cpp
src/KM_xml.h
src/MXFTypes.cpp
src/MXFTypes.h
src/Metadata.cpp
src/Metadata.h
src/PCMParserList.cpp
src/PCM_Parser.cpp
src/as-02-unwrap.cpp
src/as-02-wrap.cpp
src/asdcp-info.cpp
src/asdcp-test.cpp
src/asdcp-unwrap.cpp
src/asdcp-wrap.cpp
src/phdr-unwrap.cpp
src/phdr-wrap.cpp
win32/Makefile.mak

diff --git a/README b/README
index 2ba249e18de0f4a2e95d6cede21dc7d4c5f86ab6..b49cf34ab2f9d27b006b5821ba3570071a3b33b8 100755 (executable)
--- a/README
+++ b/README
@@ -150,7 +150,46 @@ command-line utilities all respond to -h.
 
 
 Change History
-2015-01-22 - PHDR feature, bug fixes
+
+2015-02-19 - PHDR feature, bug fixes
+  o Modified PCMParser and PCMParserList to return partial frame buffers at the
+    end of a WAV input file.  This was needed to allow wrapping all samples into
+    an AS-02 audio file (which is clip-wrapped) in the case where the input file
+    has an odd number of samples with respect to the frame buffer size being
+    used.  If there is more than one input file the length of the last buffer
+    will be determined by PCMParserList to be the shortest of the input files.
+    Prior to this change, partial samples in an input WAV file have been
+    abandoned (i.e., not written out to the MXF file).  As a result, AS-DCP
+    applications will have to decide whether to abandon the partial last frame
+    (usually detected by testing frame_buffer.Size() != frame_buffer.Capacity())
+    or write it to the MXF file.  Programs written to the old API will write the
+    partial frame (i.e., new behavior.)  This should not be harmful since the
+    remainder of the buffer is zeroed and the output file will contain one
+    additional edit unit compared to the previous version.
+  o asdcp-wrap has been modified to test for the partial buffer and by default
+    will complain and abandon the buffer (i.e., same behavior but with a warning
+    message.)  A new command line switch (-g) alters this behavior and writes
+    the buffer to the MXF file (it still warns the user that this condition is
+    present.)
+  o as-02-wrap now wraps all samples from the input file to the MXF file. There
+    is no padding, the clip is exactly the set of samples from the input.
+  o as-02 unwrap is temporarily restricted to creating wav files that are
+    aligned with the frame buffer size.  This means that the output file will
+    be longer than the original WAV input in the case where the input file has
+    an odd number of samples with respect to the frame buffer size being used.
+    The pad samples are zero (silence).
+  o Modified CalcFramesFromDurationInSamples() to increment the count by one for
+    the case where the input file has an odd number of samples with respect to
+    the frame buffer size being used (previously it truncated the odd samples.)
+  o Fixed ST 429-5 / ST 2067-5 wrapping to increase header space when ancillary
+    resources are present (fixes a bug that cause the header to overflow the
+    allotted space when large numbers of PNG files were present.)
+  o Refactored GetXMLDocType() to use the XML parser.
+  o Added ParseFirstFromString() method to Kumu::XMLElement
+  o Removed Kumu::StringIsXML from the API.
+  o Added ASDCP::MXF::RGBALayout type
+  o Added J2CLayout property to JPEG2000PictureSubDescriptor
+  o Changed km_token_split() to retain empty elements in the output list
   o Added PHDR wrapping for AS-02.
   o Added J2CLayout property to the JPEG2000PictureSubDescriptor.  This
     support is preliminary: the Raw data type is being used instead of
index 19b405774192c3f593c69a49a8f7a701bfe481e7..35a981df39fdd348875f0a5041589e7f7b7c32fe 100644 (file)
@@ -37,7 +37,7 @@ AC_PREREQ([2.59])
 # For example, if asdcplib version 1.0.0 were modified to accomodate changes
 # in file format, and if no changes were made to AS_DCP.h, the new version would be
 # 1.0.1. If changes were also required in AS_DCP.h, the new version would be 1.1.1.
-AC_INIT([asdcplib], [2.3.8], [asdcplib@cinecert.com])
+AC_INIT([asdcplib], [2.4.9], [asdcplib@cinecert.com])
 
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_SRCDIR([src/KM_error.h])
index 02efb9fdeb417626c6579ded815ba2a94db48b35..78f9229d563ceae443251920705b7c80899589e4 100644 (file)
@@ -118,12 +118,18 @@ namespace AS_02
     }
 
     // Returns number of frames for data described by ADesc, given a duration in samples and an edit rate
-    inline ui32_t CalcFramesFromDurationInSamples(const ui32_t durationInSamples, const ASDCP::MXF::WaveAudioDescriptor& d,
+    inline ui32_t CalcFramesFromDurationInSamples(const ui32_t duration_samples, const ASDCP::MXF::WaveAudioDescriptor& d,
                                                  const ASDCP::Rational& edit_rate)
     {
-      return static_cast<ui32_t>(static_cast<ui64_t>(durationInSamples) *
-                                static_cast<ui64_t>(d.AudioSamplingRate.Denominator * edit_rate.Numerator) /
-                                static_cast<ui64_t>(d.AudioSamplingRate.Numerator * edit_rate.Denominator));
+      ui32_t spf = CalcSamplesPerFrame(d, edit_rate);
+      ui32_t frames = duration_samples / spf;
+      
+      if ( duration_samples % spf != 0 )
+       {
+         ++frames;
+       }
+
+      return frames;
     }
 
   } // namespace MXF
index 9a6a98cf937567ca7aa306afbe23ff8fc9465831..f62dcc369e20ebfe20b282a98107dbb713257eb3 100644 (file)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2011-2013, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
+Copyright (c) 2011-2015, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
 John Hurst
 
 All rights reserved.
@@ -47,17 +47,15 @@ static std::string SOUND_DEF_LABEL = "Sound Track";
 
 class AS_02::PCM::MXFReader::h__Reader : public AS_02::h__AS02Reader
 {
-  ui64_t m_ClipEssenceBegin;
-  ui64_t m_SamplesPerFrame;
-  ui32_t m_BytesPerFrame;
-  ui32_t m_ContainerDuration;
+  ui64_t m_ClipEssenceBegin, m_ClipSize;
+  ui32_t m_ClipDurationFrames, m_BytesPerFrame;
 
   ASDCP_NO_COPY_CONSTRUCT(h__Reader);
   h__Reader();
 
 public:
-  h__Reader(const Dictionary& d) : AS_02::h__AS02Reader(d), m_ClipEssenceBegin(0),
-                                  m_SamplesPerFrame(0), m_BytesPerFrame(0), m_ContainerDuration(0) {}
+  h__Reader(const Dictionary& d) : AS_02::h__AS02Reader(d), m_ClipEssenceBegin(0), m_ClipSize(0),
+                                  m_ClipDurationFrames(0) {}
   virtual ~h__Reader() {}
 
   ASDCP::Result_t    OpenRead(const std::string&, const ASDCP::Rational& edit_rate);
@@ -134,10 +132,14 @@ AS_02::PCM::MXFReader::h__Reader::OpenRead(const std::string& filename, const AS
            }
 
          m_ClipEssenceBegin = m_File.Tell();
-         m_SamplesPerFrame = AS_02::MXF::CalcSamplesPerFrame(*wave_descriptor, edit_rate);
+         m_ClipSize = reader.Length();
          m_BytesPerFrame = AS_02::MXF::CalcFrameBufferSize(*wave_descriptor, edit_rate);
-         m_ContainerDuration = static_cast<ui32_t>(reader.Length() / ( m_SamplesPerFrame * AS_02::MXF::CalcSampleSize(*wave_descriptor)));
+         m_ClipDurationFrames = m_ClipSize / m_BytesPerFrame;
 
+         if ( m_ClipSize % m_BytesPerFrame > 0 )
+           {
+             ++m_ClipDurationFrames; // there is a partial frame at the end
+           }
        }
     }
 
@@ -154,13 +156,14 @@ AS_02::PCM::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, ASDCP::PCM::FrameBu
       return RESULT_INIT;
     }
 
-  if ( FrameNum > m_ContainerDuration )
+  if ( ! ( FrameNum < m_ClipDurationFrames ) )
     {
       return RESULT_RANGE;
     }
 
   assert(m_ClipEssenceBegin);
-  ui64_t position = m_ClipEssenceBegin + ( FrameNum * m_BytesPerFrame );
+  ui64_t offset = FrameNum * m_BytesPerFrame;
+  ui64_t position = m_ClipEssenceBegin + offset;
   Result_t result = RESULT_OK;
 
   if ( m_File.Tell() != position )
@@ -170,12 +173,19 @@ AS_02::PCM::MXFReader::h__Reader::ReadFrame(ui32_t FrameNum, ASDCP::PCM::FrameBu
 
   if ( KM_SUCCESS(result) )
     {
-      result = m_File.Read(FrameBuf.Data(), m_BytesPerFrame);
-    }
+      ui64_t remainder = m_ClipSize - offset;
+      ui32_t read_size = ( remainder < m_BytesPerFrame ) ? remainder : m_BytesPerFrame;
+      result = m_File.Read(FrameBuf.Data(), read_size);
 
-  if ( KM_SUCCESS(result) )
-    {
-      FrameBuf.Size(m_BytesPerFrame);
+      if ( KM_SUCCESS(result) )
+       {
+         FrameBuf.Size(read_size);
+
+         if ( read_size < FrameBuf.Capacity() )
+           {
+             memset(FrameBuf.Data() + FrameBuf.Size(), 0, FrameBuf.Capacity() - FrameBuf.Size());
+           }
+       }
     }
 
   return result;
@@ -319,10 +329,9 @@ class AS_02::PCM::MXFWriter::h__Writer : public AS_02::h__AS02WriterClip
 public:
   ASDCP::MXF::WaveAudioDescriptor *m_WaveAudioDescriptor;
   byte_t m_EssenceUL[SMPTE_UL_LENGTH];
-  ui32_t m_BytesPerFrame;
-  ui32_t m_SamplesPerFrame;
-
-  h__Writer(const Dictionary& d) : AS_02::h__AS02WriterClip(d), m_WaveAudioDescriptor(0), m_BytesPerFrame(0), m_SamplesPerFrame(0)
+  ui32_t m_BytesPerSample;
+  
+  h__Writer(const Dictionary& d) : AS_02::h__AS02WriterClip(d), m_WaveAudioDescriptor(0), m_BytesPerSample(0)
   {
     memset(m_EssenceUL, 0, SMPTE_UL_LENGTH);
   }
@@ -406,10 +415,7 @@ AS_02::PCM::MXFWriter::h__Writer::SetSourceStream(const ASDCP::Rational& edit_ra
   if ( KM_SUCCESS(result) )
     {
       assert(m_WaveAudioDescriptor);
-      m_BytesPerFrame = AS_02::MXF::CalcFrameBufferSize(*m_WaveAudioDescriptor, edit_rate);
-      m_SamplesPerFrame = AS_02::MXF::CalcSamplesPerFrame(*m_WaveAudioDescriptor, edit_rate);
-      m_WaveAudioDescriptor->ContainerDuration = 0;
-      assert(m_BytesPerFrame);
+      m_BytesPerSample = AS_02::MXF::CalcSampleSize(*m_WaveAudioDescriptor);
       result = WriteAS02Header(PCM_PACKAGE_LABEL, UL(m_Dict->ul(MDD_WAVWrappingClip)),
                               SOUND_DEF_LABEL, UL(m_EssenceUL), UL(m_Dict->ul(MDD_SoundDataDef)),
                               m_EssenceDescriptor->SampleRate, derive_timecode_rate_from_edit_rate(edit_rate));
@@ -437,12 +443,6 @@ AS_02::PCM::MXFWriter::h__Writer::WriteFrame(const FrameBuffer& frame_buf, AESEn
       return RESULT_PARAM;
     }
 
-  if ( frame_buf.Size() % m_BytesPerFrame != 0 )
-    {
-      DefaultLogSink().Error("The frame buffer does not contain an integral number of sample sets.\n");
-      return RESULT_AS02_FORMAT;
-    }
-
   Result_t result = RESULT_OK;
 
   if ( m_State.Test_READY() )
@@ -462,7 +462,7 @@ AS_02::PCM::MXFWriter::h__Writer::WriteFrame(const FrameBuffer& frame_buf, AESEn
 
   if ( KM_SUCCESS(result) )
     {
-      m_FramesWritten += m_SamplesPerFrame;
+      m_FramesWritten += frame_buf.Size() / m_BytesPerSample;
     }
 
   return result;
@@ -482,7 +482,7 @@ AS_02::PCM::MXFWriter::h__Writer::Finalize()
 
   if ( KM_SUCCESS(result) )
     {
-      m_IndexWriter.m_Duration = m_FramesWritten;
+      m_WaveAudioDescriptor->ContainerDuration = m_IndexWriter.m_Duration = m_FramesWritten;
       WriteAS02Footer();
     }
 
index 82ec81c8445df8cdfe5ee3266be6a5b0cf42feb6..0197275b16a96dbf7acdad377c7fc5a53cc282f4 100755 (executable)
@@ -258,6 +258,16 @@ ASDCP::EssenceType(const std::string& filename, EssenceType_t& type)
   return result;
 }
 
+//
+static bool
+string_is_xml(const ASDCP::FrameBuffer& buffer)
+{
+  std::string ns_prefix, type_name, namespace_name;
+  Kumu::AttributeList doc_attr_list;
+  return GetXMLDocType(buffer.RoData(), buffer.Size(),
+                      ns_prefix, type_name, namespace_name, doc_attr_list);
+}
+
 //
 ASDCP::Result_t
 ASDCP::RawEssenceType(const std::string& filename, EssenceType_t& type)
@@ -324,7 +334,7 @@ ASDCP::RawEssenceType(const std::string& filename, EssenceType_t& type)
            {
              type = ESS_PCM_24b_48k;
            }
-         else if ( Kumu::StringIsXML((const char*)FB.RoData(), FB.Size()) )
+         else if ( string_is_xml(FB) )
            {
              type = ESS_TIMED_TEXT;
            }
index e4619e09e64888078f557a050c74e88e9b328726..6b5282344c3d25695420412ce6a3a6d4d0ffa322 100644 (file)
@@ -569,6 +569,7 @@ ASDCP::TimedText::MXFWriter::h__Writer::SetSourceStream(ASDCP::TimedText::TimedT
       resourceSubdescriptor->EssenceStreamID = m_EssenceStreamID++;
       m_EssenceSubDescriptorList.push_back((FileDescriptor*)resourceSubdescriptor);
       m_EssenceDescriptor->SubDescriptors.push_back(resourceSubdescriptor->InstanceUID);
+      m_HeaderSize += resourceSubdescriptor->MIMEMediaType.ArchiveLength() + 20; // 20 == sizeof uuid + sizeof int32
     }
 
   m_EssenceStreamID = 10;
@@ -585,7 +586,7 @@ ASDCP::TimedText::MXFWriter::h__Writer::SetSourceStream(ASDCP::TimedText::TimedT
        }
       else
        {
-         DefaultLogSink().Error("Unable to write Interop timed-text MXF file.  Use SMOTE DCP options instead.\n");
+         DefaultLogSink().Error("Unable to write Interop timed-text MXF file.  Use SMPTE DCP options instead.\n");
          return RESULT_FORMAT;
        }
 
index a7de3c22543bb615422c59581a36eac0579558e6..5149d3524fec598f4162c2087dd2e92a94765499 100644 (file)
@@ -235,12 +235,22 @@ Kumu::PathsAreEquivalent(const std::string& lhs, const std::string& rhs)
 
 //
 Kumu::PathCompList_t&
-Kumu::PathToComponents(const std::string& Path, PathCompList_t& CList, char separator)
+Kumu::PathToComponents(const std::string& path, PathCompList_t& component_list, char separator)
 {
   std::string s;
   s = separator;
-  CList = km_token_split(Path, s);
-  return CList;
+  PathCompList_t tmp_list = km_token_split(path, std::string(s));
+  PathCompList_t::const_iterator i;
+
+  for ( i = tmp_list.begin(); i != tmp_list.end(); ++i )
+    {
+      if ( ! i->empty() )
+       {
+         component_list.push_back(*i);
+       }
+    }
+
+  return component_list;
 }
 
 //
index 8f8107f6875371c54a4d239c4970409a5ba5c2a0..29c3802ab5225e3588915170dabd2d5bc6c67b40 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2012, John Hurst
+Copyright (c) 2005-2015, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -1178,18 +1178,14 @@ Kumu::km_token_split(const std::string& str, const std::string& separator)
   while ( r != 0 )
     {
       assert(r >= pstr);
-      if ( r > pstr )
-       {
-         std::string tmp_str;
-         tmp_str.assign(pstr, r - pstr);
-         components.push_back(tmp_str);
-       }
-
+      std::string tmp_str;
+      tmp_str.assign(pstr, r - pstr);
+      components.push_back(tmp_str);
       pstr = r + separator.size();
       r = strstr(pstr, separator.c_str());
     }
       
-  if ( strlen(pstr) > 0 )
+  if ( strlen(pstr) >= 0 )
     {
       components.push_back(std::string(pstr));
     }
index 3e99bbfccb8f6d61403909806c5705f996644d95..2ca17935d7b662fa47e5b1e0c242460c5c040bf5 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2012, John Hurst
+Copyright (c) 2005-2015, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -540,7 +540,8 @@ namespace Kumu
   const char *km_strnstr(const char *s1, const char *s2, size_t n);
 
   // Split the input string into tokens using the given separator. If the separator is not found the
-  // entire string will be returned as a single-item list.
+  // entire string will be returned as a single-item list.  Empty items will be recorded for
+  // adjacent instances of the separator. E.g., "/foo//bar/" will return ["", "foo", "", "bar", ""].
   std::list<std::string> km_token_split(const std::string& str, const std::string& separator);
 
 } // namespace Kumu
index dcb35a3a4e60a427353839a4a280b3866b9d50f4..936fcb5c88c7d7c1abdf31a6a2d7740c26780dc1 100644 (file)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2010, John Hurst
+Copyright (c) 2005-2015, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -399,6 +399,20 @@ Kumu::XMLElement::ParseString(const std::string& document)
   return ParseString(document.c_str(), document.size());
 }
 
+//
+bool
+Kumu::XMLElement::ParseFirstFromString(const ByteString& document)
+{
+  return ParseFirstFromString((const char*)document.RoData(), document.Length());
+}
+
+//
+bool
+Kumu::XMLElement::ParseFirstFromString(const std::string& document)
+{
+  return ParseFirstFromString(document.c_str(), document.size());
+}
+
 
 //----------------------------------------------------------------------------------------------------
 
@@ -525,6 +539,11 @@ xph_namespace_start(void* p, const XML_Char* ns_prefix, const XML_Char* ns_name)
 bool
 Kumu::XMLElement::ParseString(const char* document, ui32_t doc_len)
 {
+  if ( doc_len == 0 )
+    {
+      return false;
+    }
+
   XML_Parser Parser = XML_ParserCreateNS("UTF-8", '|');
 
   if ( Parser == 0 )
@@ -551,45 +570,33 @@ Kumu::XMLElement::ParseString(const char* document, ui32_t doc_len)
   XML_ParserFree(Parser);
 
   if ( ! Ctx.Namespaces->empty() )
-    m_NamespaceOwner = (void*)Ctx.Namespaces;
+    {
+      m_NamespaceOwner = (void*)Ctx.Namespaces;
+    }
 
   return true;
 }
 
-//------------------------------------------------------------------------------------------
-
-struct xph_test_wrapper
-{
-  XML_Parser Parser;
-  bool  Status;
-
-  xph_test_wrapper(XML_Parser p) : Parser(p), Status(false) {}
-};
-
-// expat wrapper functions, map callbacks to IASAXHandler
+// expat wrapper functions
 // 
 static void
-xph_test_start(void* p, const XML_Char* name, const XML_Char** attrs)
+xph_start_one_shot(void* p, const XML_Char* name, const XML_Char** attrs)
 {
-  assert(p);
-  xph_test_wrapper* Wrapper = (xph_test_wrapper*)p;
-
-  Wrapper->Status = true;
-  XML_StopParser(Wrapper->Parser, false);
+  xph_start(p, name, attrs);
+  XML_Parser parser = (XML_Parser)p;
+  XML_StopParser(parser, false);
 }
 
-
 //
 bool
-Kumu::StringIsXML(const char* document, ui32_t len)
+Kumu::XMLElement::ParseFirstFromString(const char* document, ui32_t doc_len)
 {
-  if ( document == 0 )
-    return false;
-
-  if ( len == 0 )
-    len = strlen(document);
+  if ( doc_len == 0 )
+    {
+      return false;
+    }
 
-  XML_Parser Parser = XML_ParserCreate("UTF-8");
+  XML_Parser Parser = XML_ParserCreateNS("UTF-8", '|');
 
   if ( Parser == 0 )
     {
@@ -597,15 +604,33 @@ Kumu::StringIsXML(const char* document, ui32_t len)
       return false;
     }
 
-  xph_test_wrapper Wrapper(Parser);
-  XML_SetUserData(Parser, (void*)&Wrapper);
-  XML_SetStartElementHandler(Parser, xph_test_start);
+  ExpatParseContext Ctx(this);
+  XML_SetUserData(Parser, (void*)&Ctx);
+  XML_SetElementHandler(Parser, xph_start_one_shot, xph_end);
+  XML_SetCharacterDataHandler(Parser, xph_char);
+  XML_SetStartNamespaceDeclHandler(Parser, xph_namespace_start);
+
+  if ( ! XML_Parse(Parser, document, doc_len, 1) )
+    {
+      DefaultLogSink().Error("XML Parse error on line %d: %s\n",
+                            XML_GetCurrentLineNumber(Parser),
+                            XML_ErrorString(XML_GetErrorCode(Parser)));
+      XML_ParserFree(Parser);
+      return false;
+    }
 
-  XML_Parse(Parser, document, len, 1);
   XML_ParserFree(Parser);
-  return Wrapper.Status;
+
+  if ( ! Ctx.Namespaces->empty() )
+    {
+      m_NamespaceOwner = (void*)Ctx.Namespaces;
+    }
+
+  return true;
 }
 
+
+
 #endif
 
 //----------------------------------------------------------------------------------------------------
@@ -905,7 +930,9 @@ bool
 Kumu::XMLElement::ParseString(const char* document, ui32_t doc_len)
 {
   if ( doc_len == 0 )
-    return false;
+    {
+      return false;
+    }
 
   init_xml_dom();
 
@@ -958,37 +985,69 @@ Kumu::XMLElement::ParseString(const char* document, ui32_t doc_len)
 
 //
 bool
-Kumu::StringIsXML(const char* document, ui32_t len)
+Kumu::XMLElement::ParseFirstFromString(const char* document, ui32_t doc_len)
 {
-  if ( document == 0 || *document == 0 )
-    return false;
+  if ( doc_len == 0 )
+    {
+      return false;
+    }
 
   init_xml_dom();
 
-  if ( len == 0 )
-    len = strlen(document);
+  int errorCount = 0;
+  SAXParser* parser = new SAXParser();
 
-  SAXParser parser;
+  parser->setValidationScheme(SAXParser::Val_Always);
+  parser->setDoNamespaces(true);    // optional
+
+  MyTreeHandler* docHandler = new MyTreeHandler(this);
+  parser->setDocumentHandler(docHandler);
+  parser->setErrorHandler(docHandler);
   XMLPScanToken token;
-  bool status = false;
 
   try
     {
       MemBufInputSource xmlSource(reinterpret_cast<const XMLByte*>(document),
-                                 static_cast<const unsigned int>(len),
+                                 static_cast<const unsigned int>(doc_len),
                                  "pidc_rules_file");
 
-      if ( parser.parseFirst(xmlSource, token) )
+      if ( ! parser->parseFirst(xmlSource, token) )
        {
-         if ( parser.parseNext(token) )
-           status = true;
+         ++errorCount;
+       }
+
+      if ( ! parser->parseNext(token) )
+       {
+         ++errorCount;
        }
     }
+  catch (const XMLException& e)
+    {
+      char* message = XMLString::transcode(e.getMessage());
+      DefaultLogSink().Error("Parser error: %s\n", message);
+      XMLString::release(&message);
+      errorCount++;
+    }
+  catch (const SAXParseException& e)
+    {
+      char* message = XMLString::transcode(e.getMessage());
+      DefaultLogSink().Error("Parser error: %s at line %d\n", message, e.getLineNumber());
+      XMLString::release(&message);
+      errorCount++;
+    }
   catch (...)
     {
+      DefaultLogSink().Error("Unexpected XML parser error\n");
+      errorCount++;
     }
   
-  return status;
+  if ( errorCount == 0 )
+    m_NamespaceOwner = (void*)docHandler->TakeNamespaceMap();
+
+  delete parser;
+  delete docHandler;
+
+  return errorCount > 0 ? false : true;
 }
 
 
@@ -1006,9 +1065,8 @@ Kumu::XMLElement::ParseString(const char* document, ui32_t doc_len)
   return false;
 }
 
-//
 bool
-Kumu::StringIsXML(const char* document, ui32_t len)
+Kumu::XMLElement::ParseFirstFromString(const char* document, ui32_t doc_len)
 {
   DefaultLogSink().Error("Kumu compiled without XML parser support.\n");
   return false;
@@ -1040,124 +1098,27 @@ bool
 Kumu::GetXMLDocType(const byte_t* buf, ui32_t buf_len, std::string& ns_prefix, std::string& type_name, std::string& namespace_name,
                    AttributeList& doc_attr_list)
 {
-  assert(buf);
-  const byte_t *p1 = buf, *p2;
-  const byte_t *end_p = buf + buf_len;
+  XMLElement tmp_element("tmp");
 
-  while ( p1 < end_p && *p1 )
+  if ( ! tmp_element.ParseFirstFromString((const char*)buf, buf_len) )
     {
-      if ( *p1 == '<' && isalpha(p1[1]) )
-        {
-          p2 = ++p1;
-
-          // collect element name
-          while ( p2 < end_p && *p2 && ! ( isspace(*p2) || *p2 == '>' ) )
-            ++p2;
-
-          if ( p2 < end_p )
-            {
-              const byte_t* separator = (byte_t*)strchr(reinterpret_cast<const char*>(p1), ':');
-              if ( separator != 0 && separator < p2 )
-                {
-                  ns_prefix.assign(reinterpret_cast<const char*>(p1), separator - p1);
-                  p1 = separator + 1;
-                }
-
-              type_name.assign(reinterpret_cast<const char*>(p1), p2 - p1);
-              break;
-            }
-        }
-      else if ( *p1 == '<' && ( ( p1 + 3 ) < end_p ) && p1[1] == '!' && p1[2] == '-' && p1[3] == '-' )
-       {
-          p1 += 4;
-
-         for (;;)
-           {
-             while ( *p1 != '>' && p1 < end_p )
-               {
-                 ++p1;
-               }
-
-             if ( *(p1-2) == '-' && *(p1-1) == '-' && *p1 == '>' )
-               {
-                 break;
-               }
-
-             ++p1;
-           }
-       }
-      else
-       {
-         ++p1;
-       }
+      return false;
     }
 
-  if ( isspace(*p2) )
-    {
-      const byte_t *p3 = p2+1;
-      while ( p3 < end_p && *p3 && *p3 != '>'  )
-       {       
-         ++p3;
-       }
-
-      if ( *p3 != '>' )
-       {
-         return false; // not well-formed XML
-       }
-
-      std::string attr_str;
-      attr_str.assign(reinterpret_cast<const char*>(p2+1), p3 - p2 - 1);
-      
-      // normalize whitespace so the subesquent split works properly
-      for ( int j = 0; j < attr_str.length(); ++j )
-       {
-         if ( attr_str[j] != ' ' && isspace(attr_str[j]) )
-           {
-             attr_str[j] = ' ';
-           }
-       }
-
-      std::list<std::string> doc_attr_nvpairs = km_token_split(attr_str, " ");
-      
-      std::list<std::string>::iterator i;
-      std::map<std::string, std::string> ns_map;
-
-      for ( i = doc_attr_nvpairs.begin(); i != doc_attr_nvpairs.end(); ++i )
-        {
-         // trim leading and trailing whitespace an right-most character, i.e., \"
-         std::string trimmed = i->substr(i->find_first_not_of(" "), i->find_last_not_of(" \r\n\t"));
-          std::list<std::string> nv_tokens = km_token_split(trimmed, "=\"");
+  const XMLNamespace* ns = tmp_element.Namespace();
 
-          if ( nv_tokens.size() != 2 )
-           {
-             continue;
-           }
-
-         NVPair nv_pair;
-         nv_pair.name = nv_tokens.front();
-         nv_pair.value = nv_tokens.back();
-         doc_attr_list.push_back(nv_pair);
-          ns_map.insert(std::map<std::string,std::string>::value_type(nv_pair.name, nv_pair.value));
-        }
-
-      std::string doc_ns_name_selector = ns_prefix.empty() ? "xmlns" : "xmlns:"+ns_prefix;
-      std::map<std::string,std::string>::iterator j = ns_map.find(doc_ns_name_selector);
-
-      if ( j != ns_map.end() )
-        {
-          namespace_name = j->second;
-        }
+  if ( ns != 0 )
+    {
+      ns_prefix = ns->Prefix();
+      namespace_name = ns->Name();
     }
- else if ( *p2 != '>' )
-   {
-     return false; // not well-formed XML
-   }
 
-  return ! type_name.empty();
+  type_name = tmp_element.GetName();
+  doc_attr_list = tmp_element.GetAttributes();
+  return true;
 }
 
 
-
 //
 // end KM_xml.cpp
 //
index 0f8ba3cd553741ebd3e972ed1528a40822bb1b2c..0c84e563c17035f098c4f96dc6b5a6896e83c187 100644 (file)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2011, John Hurst
+Copyright (c) 2005-2015, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -41,9 +41,6 @@ namespace Kumu
 {
   class XMLElement;
 
-  // Return true if the given string contains an XML document (or the start of one).
-  bool StringIsXML(const char* document, ui32_t len = 0);
-
   //
   struct NVPair
   {
@@ -109,6 +106,10 @@ namespace Kumu
       bool        ParseString(const ByteString& document);
       bool        ParseString(const std::string& document);
 
+      bool        ParseFirstFromString(const char* document, ui32_t doc_len);
+      bool        ParseFirstFromString(const ByteString& document);
+      bool        ParseFirstFromString(const std::string& document);
+
       // building
       void        SetName(const char* name);
       void        SetBody(const std::string& value);
index c575b963472bcbf13514a5478fd62567aba55162..46ddf612b7c5a261772c2dca28ad0c0885702718 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2012, John Hurst
+Copyright (c) 2005-2015, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -665,6 +665,63 @@ ASDCP::MXF::TLVWriter::WriteUi64(const MDDEntry& Entry, ui64_t* value)
 }
 
 
+//----------------------------------------------------------------------------------------------------
+//
+
+
+ASDCP::MXF::RGBALayout::RGBALayout()
+{
+  memset(m_value, 0, RGBAValueLength);
+}
+
+ASDCP::MXF::RGBALayout::RGBALayout(const byte_t* value)
+{
+  memcpy(m_value, value, RGBAValueLength);
+}
+
+ASDCP::MXF::RGBALayout::~RGBALayout()
+{
+}
+
+static char
+get_char_for_code(byte_t c)
+{
+  for ( int i = 0; ASDCP::MXF::RGBALayoutTable[i].code != 0; ++i )
+    {
+      if ( ASDCP::MXF::RGBALayoutTable[i].code == c )
+       {
+         return ASDCP::MXF::RGBALayoutTable[i].symbol;
+       }
+    }
+
+  return '_';
+}
+
+//
+const char*
+ASDCP::MXF::RGBALayout::EncodeString(char* buf, ui32_t buf_len) const
+{
+  std::string tmp_str;
+  char tmp_buf[64];
+
+  for ( int i = 0; i < RGBAValueLength && m_value[i] != 0; i += 2 )
+    {
+      snprintf(tmp_buf, 64, "%c(%d)", get_char_for_code(m_value[i]), m_value[i+1]);
+
+      if ( ! tmp_str.empty() )
+       {
+         tmp_str += " ";
+       }
+
+      tmp_str += tmp_buf;
+    }
+
+  assert(tmp_str.size() < buf_len);
+  strncpy(buf, tmp_str.c_str(), tmp_str.size());
+  return buf;
+}
+
+
 //----------------------------------------------------------------------------------------------------
 //
 
index fbf303875e7c13bc78babfd0f2a2c5519f3e6eae..77c0f5fdf8cb1a240c71b0efe3c0dbcf6769f210 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2014, John Hurst
+Copyright (c) 2005-2015, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -382,6 +382,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
        {
index 2ab26351d5b992141cccb8326779bd82f9bb772e..bec2530049e24a03729ce5e81e74598b87a86823 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2015, John Hurst
+Copyright (c) 2005-2012, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
index b8d16dcfb5908bd52d3c29ad6e4e0da1b73cc55b..d76c477eb3071eb6b9af79588aadfce8d29b8d1c 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2005-2015, John Hurst
+Copyright (c) 2005-2012, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -564,7 +564,7 @@ namespace ASDCP
           optional_property<Raw> PictureComponentSizing;
           optional_property<Raw> CodingStyleDefault;
           optional_property<Raw> QuantizationDefault;
-         optional_property<Raw> J2CLayout;
+          optional_property<RGBALayout> J2CLayout;
 
       JPEG2000PictureSubDescriptor(const Dictionary*& d);
       JPEG2000PictureSubDescriptor(const JPEG2000PictureSubDescriptor& rhs);
index 4f43c4eb584152c5da8084389ffd7823b0adf6d8..0ae22cc53bb31143358027b3d485734122fa0baf 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2004-2014, John Hurst
+Copyright (c) 2004-2015, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -72,11 +72,18 @@ ASDCP::ParserInstance::PutSample(byte_t* p)
 {
   ASDCP_TEST_NULL(p);
 
-  memcpy(p, m_p, m_SampleSize);
-  m_p += m_SampleSize;
-  return RESULT_OK;
-}
+  if ( m_p != 0 )
+    {
+      if ( m_p < ( FB.RoData() + FB.Size() ) )
+       {
+         memcpy(p, m_p, m_SampleSize);
+         m_p += m_SampleSize;
+         return RESULT_OK;
+       }
+    }
 
+  return RESULT_ENDOFFILE;
+}
 
 //
 Result_t
@@ -247,21 +254,23 @@ ASDCP::PCMParserList::ReadFrame(PCM::FrameBuffer& OutFB)
   Result_t result = RESULT_OK;
 
   if ( size() == 1 )
-    return front()->Parser.ReadFrame(OutFB);
+    {
+      return front()->Parser.ReadFrame(OutFB);
+    }
 
   PCMParserList::iterator self_i;
   assert(PCM::CalcFrameBufferSize(m_ADesc) <= OutFB.Capacity());
 
   for ( self_i = begin(); self_i != end() && ASDCP_SUCCESS(result) ; self_i++ )
-    result = (*self_i)->ReadFrame();
+    {
+      result = (*self_i)->ReadFrame();
+    }
 
   if ( ASDCP_SUCCESS(result) )
     {
-      OutFB.Size(PCM::CalcFrameBufferSize(m_ADesc));
-
-      //      ui32_t sample_size = (PCM::CalcSampleSize(m_ADesc));
       byte_t* Out_p = OutFB.Data();
-      byte_t* End_p = Out_p + OutFB.Size();
+      byte_t* End_p = Out_p + OutFB.Capacity();
+      ui64_t total_sample_bytes = 0;
 
       while ( Out_p < End_p && ASDCP_SUCCESS(result) )
        {
@@ -270,12 +279,22 @@ ASDCP::PCMParserList::ReadFrame(PCM::FrameBuffer& OutFB)
          while ( self_i != end() && ASDCP_SUCCESS(result) )
            {
              result = (*self_i)->PutSample(Out_p);
-             Out_p += (*self_i)->SampleSize();
-             self_i++;
+
+             if ( ASDCP_SUCCESS(result) )
+               {
+                 Out_p += (*self_i)->SampleSize();
+                 total_sample_bytes += (*self_i)->SampleSize();
+                 self_i++;
+               }
            }
        }
 
-      assert(Out_p == End_p);
+      OutFB.Size(total_sample_bytes);
+
+      if ( result == RESULT_ENDOFFILE )
+       {
+         result = RESULT_OK;
+       }
     }
 
   return result;
index 30e5d2884ece6122322b732d03a04284bfa88509..2700aa4b8b409fdd57f908b0397c4b60d3caf045 100755 (executable)
@@ -128,22 +128,22 @@ ASDCP::PCM::WAVParser::h__WAVParser::OpenRead(const std::string& filename, const
              m_ADesc.ChannelFormat = PCM::CF_NONE;
              Reset();
            }
-      else
-        {
-          SimpleRF64Header RF64Header;
-          m_FileReader.Seek(0);
-          result = RF64Header.ReadFromFile(m_FileReader, &m_DataStart);
-
-          if ( ASDCP_SUCCESS(result) )
-            {
-                RF64Header.FillADesc(m_ADesc, PictureRate);
-                m_FrameBufferSize = ASDCP::PCM::CalcFrameBufferSize(m_ADesc);
-                m_DataLength = RF64Header.data_len;
-                m_ADesc.ContainerDuration = m_DataLength / m_FrameBufferSize;
-                m_ADesc.ChannelFormat = PCM::CF_NONE;
-                Reset();
-            }
-        }
+         else
+           {
+             SimpleRF64Header RF64Header;
+             m_FileReader.Seek(0);
+             result = RF64Header.ReadFromFile(m_FileReader, &m_DataStart);
+
+             if ( ASDCP_SUCCESS(result) )
+               {
+                 RF64Header.FillADesc(m_ADesc, PictureRate);
+                 m_FrameBufferSize = ASDCP::PCM::CalcFrameBufferSize(m_ADesc);
+                 m_DataLength = RF64Header.data_len;
+                 m_ADesc.ContainerDuration = m_DataLength / m_FrameBufferSize;
+                 m_ADesc.ChannelFormat = PCM::CF_NONE;
+                 Reset();
+               }
+           }
        }
     }
 
@@ -156,8 +156,10 @@ ASDCP::PCM::WAVParser::h__WAVParser::ReadFrame(FrameBuffer& FB)
 {
   FB.Size(0);
 
-  if ( m_EOF || m_ReadCount >= m_DataLength )
-    return RESULT_ENDOFFILE;
+  if ( m_EOF )
+    {
+      return RESULT_ENDOFFILE;
+    }
 
   if ( FB.Capacity() < m_FrameBufferSize )
     {
@@ -174,7 +176,9 @@ ASDCP::PCM::WAVParser::h__WAVParser::ReadFrame(FrameBuffer& FB)
       m_EOF = true;
 
       if ( read_count > 0 )
-       result = RESULT_OK;
+       {
+         result = RESULT_OK;
+       }
     }
 
   if ( ASDCP_SUCCESS(result) )
@@ -182,6 +186,11 @@ ASDCP::PCM::WAVParser::h__WAVParser::ReadFrame(FrameBuffer& FB)
       m_ReadCount += read_count;
       FB.Size(read_count);
       FB.FrameNumber(m_FramesRead++);
+
+      if ( read_count < FB.Capacity() )
+       {
+         memset(FB.Data() + FB.Size(), 0, FB.Capacity() - FB.Size());
+       }
     }
 
   return result;
index bf69ba32f5845939df81f39db4eb356de47cc76d..148946b6d6af235eed7e84a0cca044e87934f75f 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2011-2014, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
+Copyright (c) 2011-2015, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
 John Hurst
 
 All rights reserved.
@@ -69,7 +69,7 @@ banner(FILE* stream = stdout)
 {
   fprintf(stream, "\n\
 %s (asdcplib %s)\n\n\
-Copyright (c) 2011-2014, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst\n\n\
+Copyright (c) 2011-2015, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst\n\n\
 asdcplib may be copied only under the terms of the license found at\n\
 the top of every file in the asdcplib distribution kit.\n\n\
 Specify the -h (help) option for further information about %s\n\n",
@@ -550,6 +550,13 @@ read_PCM_file(CommandOptions& Options)
              FrameBuffer.Dump(stderr, Options.fb_dump_size);
            }
 
+         if ( FrameBuffer.Size() != FrameBuffer.Capacity() )
+           {
+             fprintf(stderr, "Last frame is incomplete, padding with zeros.\n");
+             // actually, it has already been zeroed for us, we just need to recognize the appropriate size
+             FrameBuffer.Size(FrameBuffer.Capacity());
+           }
+
          result = OutWave.WriteFrame(FrameBuffer);
        }
     }
@@ -597,7 +604,7 @@ main(int argc, const char** argv)
          break;
 
        default:
-         fprintf(stderr, "%s: Unknown file type, not ASDCP essence.\n", Options.input_filename);
+         fprintf(stderr, "%s: Unknown file type, not AS-02 essence.\n", Options.input_filename);
          return 5;
        }
     }
index 8aac348e008996b4e529633e2b255eb9de058fca..0973b91af247777a97cc9a7a2611114de4898881 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2011-2014, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
+Copyright (c) 2011-2015, Robert Scheler, Heiko Sparenberg Fraunhofer IIS,
 John Hurst
 
 All rights reserved.
@@ -107,7 +107,7 @@ banner(FILE* stream = stdout)
 {
   fprintf(stream, "\n\
 %s (asdcplib %s)\n\n\
-Copyright (c) 2011-2014, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst\n\n\
+Copyright (c) 2011-2015, Robert Scheler, Heiko Sparenberg Fraunhofer IIS, John Hurst\n\n\
 asdcplib may be copied only under the terms of the license found at\n\
 the top of every file in the asdcplib distribution kit.\n\n\
 Specify the -h (help) option for further information about %s\n\n",
@@ -173,7 +173,7 @@ decode_rational(const char* str_rat)
 {
   assert(str_rat);
   ui32_t Num = atoi(str_rat);
-  ui32_t Den = 0;
+  ui32_t Den = 1;
 
   const char* den_str = strrchr(str_rat, '/');
   if ( den_str != 0 )
@@ -759,14 +759,6 @@ write_PCM_file(CommandOptions& Options)
 
          if ( ASDCP_SUCCESS(result) )
            {
-             if ( FrameBuffer.Size() != FrameBuffer.Capacity() )
-               {
-                 fprintf(stderr, "WARNING: Last frame read was short, PCM input is possibly not frame aligned.\n");
-                 fprintf(stderr, "Expecting %u bytes, got %u.\n", FrameBuffer.Capacity(), FrameBuffer.Size());
-                 result = RESULT_ENDOFFILE;
-                 continue;
-               }
-
              if ( Options.verbose_flag )
                FrameBuffer.Dump(stderr, Options.fb_dump_size);
 
index 448ef421522660533563b39b5f4d243fade54b2b..9b3ea40a7503516eb96b1bdc2a4a973f32616b36 100755 (executable)
@@ -76,7 +76,7 @@ banner(FILE* stream = stdout)
 {
   fprintf(stream, "\n\
 %s (asdcplib %s)\n\n\
-Copyright (c) 2003-2014 John Hurst\n\n\
+Copyright (c) 2003-2015 John Hurst\n\n\
 asdcplib may be copied only under the terms of the license found at\n\
 the top of every file in the asdcplib distribution kit.\n\n\
 Specify the -h (help) option for further information about %s\n\n",
index dc507066eeaef0d7a212aac004c0cf38be02e989..c0ccaa1c99bb2bbb455ac3bc20d5bc09ef4437b2 100755 (executable)
@@ -103,7 +103,7 @@ banner(FILE* stream = stdout)
 {
   fprintf(stream, "\n\
 %s (asdcplib %s)\n\n\
-Copyright (c) 2003-2014 John Hurst\n\n\
+Copyright (c) 2003-2015 John Hurst\n\n\
 asdcplib may be copied only under the terms of the license found at\n\
 the top of every file in the asdcplib distribution kit.\n\n\
 Specify the -h (help) option for further information about %s\n\n",
index e3572f695f3c7d862151d2b8a11bdf735a1b613f..1f7e8d243ff27d4fc9721e66ba6233683d8a7038 100755 (executable)
@@ -61,7 +61,7 @@ banner(FILE* stream = stdout)
 {
   fprintf(stream, "\n\
 %s (asdcplib %s)\n\n\
-Copyright (c) 2003-2014 John Hurst\n\n\
+Copyright (c) 2003-2015 John Hurst\n\n\
 asdcplib may be copied only under the terms of the license found at\n\
 the top of every file in the asdcplib distribution kit.\n\n\
 Specify the -h (help) option for further information about %s\n\n",
index 0a749b0d1dfbec9cfbab4533aabf4f3e2d022302..72dbaea866ed8bd7bdb1b5e834a125bcfe57800a 100755 (executable)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2003-2014, John Hurst
+Copyright (c) 2003-2015, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -113,7 +113,7 @@ banner(FILE* stream = stdout)
 {
   fprintf(stream, "\n\
 %s (asdcplib %s)\n\n\
-Copyright (c) 2003-2014 John Hurst\n\n\
+Copyright (c) 2003-2015 John Hurst\n\n\
 asdcplib may be copied only under the terms of the license found at\n\
 the top of every file in the asdcplib distribution kit.\n\n\
 Specify the -h (help) option for further information about %s\n\n",
@@ -221,6 +221,7 @@ public:
   bool   version_flag;   // true if the version display option was selected
   bool   help_flag;      // true if the help display option was selected
   bool   stereo_image_flag; // if true, expect stereoscopic JP2K input (left eye first)
+  bool   write_partial_pcm_flag; // if true, write the last frame of PCM input even when it is incomplete
   ui32_t start_frame;    // frame number to begin processing
   ui32_t duration;       // number of frames to be processed
   bool   use_smpte_labels; // if true, SMPTE UL values will be written instead of MXF Interop values
@@ -289,7 +290,7 @@ public:
     encrypt_header_flag(true), write_hmac(true),
     verbose_flag(false), fb_dump_size(0),
     no_write_flag(false), version_flag(false), help_flag(false), stereo_image_flag(false),
-    start_frame(0),
+    write_partial_pcm_flag(false), start_frame(0),
     duration(0xffffffff), use_smpte_labels(false), j2c_pedantic(true),
     fb_size(FRAME_BUFFER_SIZE),
     channel_fmt(PCM::CF_NONE),
@@ -364,6 +365,7 @@ public:
                start_frame = abs(atoi(argv[i]));
                break;
 
+             case 'g': write_partial_pcm_flag = true; break;
              case 'h': help_flag = true; break;
 
              case 'j': key_id_flag = true;
@@ -1059,8 +1061,12 @@ write_PCM_file(CommandOptions& Options)
                {
                  fprintf(stderr, "WARNING: Last frame read was short, PCM input is possibly not frame aligned.\n");
                  fprintf(stderr, "Expecting %u bytes, got %u.\n", FrameBuffer.Capacity(), FrameBuffer.Size());
-                 result = RESULT_ENDOFFILE;
-                 continue;
+
+                 if ( Options.write_partial_pcm_flag )
+                   {
+                     result = RESULT_ENDOFFILE;
+                     continue;
+                   }
                }
 
              if ( Options.verbose_flag )
@@ -1188,8 +1194,12 @@ write_PCM_with_ATMOS_sync_file(CommandOptions& Options)
                {
                  fprintf(stderr, "WARNING: Last frame read was short, PCM input is possibly not frame aligned.\n");
                  fprintf(stderr, "Expecting %u bytes, got %u.\n", FrameBuffer.Capacity(), FrameBuffer.Size());
-                 result = RESULT_ENDOFFILE;
-                 continue;
+
+                 if ( Options.write_partial_pcm_flag )
+                   {
+                     result = RESULT_ENDOFFILE;
+                     continue;
+                   }
                }
 
         if ( Options.verbose_flag )
index a7a3afc7a6a055f08cbb7d606f31ecdab1216d41..a0ba7c7829db6b3b7270ba2c4b69ed27f25cf778 100755 (executable)
@@ -60,7 +60,7 @@ banner(FILE* stream = stdout)
 {
   fprintf(stream, "\n\
 %s (asdcplib %s)\n\n\
-Copyright (c) 2011-2014, John Hurst\n\n\
+Copyright (c) 2011-2015, John Hurst\n\n\
 asdcplib may be copied only under the terms of the license found at\n\
 the top of every file in the asdcplib distribution kit.\n\n\
 Specify the -h (help) option for further information about %s\n\n",
index a00d0916b468d5a00b58087ddc5ea474ec445bf9..b7ef2d2487bbdee2f1d7a5eb614ad90ab201f1ab 100755 (executable)
@@ -91,7 +91,7 @@ banner(FILE* stream = stdout)
 {
   fprintf(stream, "\n\
 %s (asdcplib %s)\n\n\
-Copyright (c) 2011-2014, John Hurst\n\n\
+Copyright (c) 2011-2015, John Hurst\n\n\
 asdcplib may be copied only under the terms of the license found at\n\
 the top of every file in the asdcplib distribution kit.\n\n\
 Specify the -h (help) option for further information about %s\n\n",
index 6640d01a1422a128decea9962a6468dc8a0aafd7..ac7be7268307067b20dbf627f0e2bcd439ab61c9 100755 (executable)
@@ -33,11 +33,11 @@ OBJDIR = .
 \r
 !ifdef ENABLE_RANDOM_UUID\r
 CXXFLAGS1 = /nologo /W3 /GR /EHsc /DWIN32 /DKM_WIN32 /D_CONSOLE /I. /I$(SRCDIR) /DASDCP_PLATFORM=\"win32\" \\r
-       /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /DPACKAGE_VERSION=\"2.1.1\" \\r
+       /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /DPACKAGE_VERSION=\"2.4.9\" \\r
        /I"$(WITH_OPENSSL)"\inc32 /DCONFIG_RANDOM_UUID=1\r
 !else\r
 CXXFLAGS1 = /nologo /W3 /GR /EHsc /DWIN32 /DKM_WIN32 /D_CONSOLE /I. /I$(SRCDIR) /DASDCP_PLATFORM=\"win32\" \\r
-       /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /DPACKAGE_VERSION=\"2.1.1\" \\r
+       /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /DPACKAGE_VERSION=\"2.4.9\" \\r
        /I"$(WITH_OPENSSL)"\inc32\r
 !endif\r
 LIB_EXE = lib.exe\r