compile fixes
authorjhurst <jhurst@cinecert.com>
Thu, 21 May 2015 00:10:39 +0000 (00:10 +0000)
committerjhurst <>
Thu, 21 May 2015 00:10:39 +0000 (00:10 +0000)
14 files changed:
src/AS_02.h
src/AS_02_TimedText.cpp
src/AS_DCP.h
src/AS_DCP_MXF.cpp
src/MDD.cpp
src/ST2052_TextParser.cpp
src/TimedText_Parser.cpp
src/Wav.cpp
src/Wav.h
src/as-02-unwrap.cpp
src/asdcp-util.cpp
src/asdcp-wrap.cpp
src/klvsplit.cpp
src/phdr-unwrap.cpp

index 78f9229d563ceae443251920705b7c80899589e4..17561fdbc47004d78782037320c25bb5d5e23492 100644 (file)
@@ -333,6 +333,22 @@ namespace AS_02
       using ASDCP::TimedText::TimedTextResourceDescriptor;
       using ASDCP::TimedText::ResourceList_t;
 
+      //
+      class Type5UUIDFilenameResolver : public ASDCP::TimedText::IResourceResolver
+       {
+         typedef std::map<Kumu::UUID, std::string> ResourceMap;
+           
+         ResourceMap m_ResourceMap;
+         std::string m_Dirname;
+         KM_NO_COPY_CONSTRUCT(Type5UUIDFilenameResolver);
+
+       public:
+         Type5UUIDFilenameResolver();
+         virtual ~Type5UUIDFilenameResolver();
+         Result_t OpenRead(const std::string& dirname);
+         Result_t ResolveRID(const byte_t* uuid, ASDCP::TimedText::FrameBuffer& FrameBuf) const;
+       };
+      
       //
       class ST2052_TextParser
        {
index 7faa7ce84365f6dce453fee816a12cead303eb5c..47d3566a340bec697c3645ad954da566856575d2 100644 (file)
@@ -626,7 +626,6 @@ AS_02::TimedText::MXFWriter::h__Writer::Finalize()
     }
 
   m_IndexWriter.m_Duration = m_FramesWritten = m_TDesc.ContainerDuration;
-  fprintf(stderr, "m_IndexWriter.m_Duration=%d\n", m_IndexWriter.m_Duration);
 
   Result_t result = m_State.Goto_FINAL();
 
index 7231fb56776759e7c4e7758e9c332989a4ab21ce..cb78dbc44cdf8d0ddf0529252bfe78a62cb7df19 100755 (executable)
@@ -1485,6 +1485,7 @@ namespace ASDCP {
 
        public:
          LocalFilenameResolver();
+         virtual ~LocalFilenameResolver();
          Result_t OpenRead(const std::string& dirname);
          Result_t ResolveRID(const byte_t* uuid, FrameBuffer& FrameBuf) const;
        };
index b5ad865110d34d37d4e98bd98b32e37d34f94ed0..32225be604499f42199304cc07fd4c0b469f6bd0 100755 (executable)
@@ -310,24 +310,39 @@ ASDCP::RawEssenceType(const std::string& filename, EssenceType_t& type)
            {
              type = ESS_JPEG_2000;
            }
-         else if ( ASDCP_SUCCESS(WavHeader.ReadFromBuffer(FB.RoData(), read_count, &data_offset)) )
+         else if ( std::string((const char*)FB.RoData() + 8, 4) == "WAVE" )
            {
-             switch ( WavHeader.samplespersec )
+             if ( std::string((const char*)FB.RoData(), 4) == "RIFF" )
                {
-               case 48000: type = ESS_PCM_24b_48k; break;
-               case 96000: type = ESS_PCM_24b_96k; break;
-               default:
-                 return RESULT_FORMAT;
+                 result = WavHeader.ReadFromBuffer(FB.RoData(), read_count, &data_offset);
+
+                 if ( ASDCP_SUCCESS(result) )
+                   {
+                     switch ( WavHeader.samplespersec )
+                       {
+                       case 48000: type = ESS_PCM_24b_48k; break;
+                       case 96000: type = ESS_PCM_24b_96k; break;
+                       default:
+                         DefaultLogSink().Error("Unexpected sample rate: %d\n", WavHeader.samplespersec);
+                         result = RESULT_FORMAT;
+                       }
+                   }
                }
-           }
-         else if ( ASDCP_SUCCESS(RF64Header.ReadFromBuffer(FB.RoData(), read_count, &data_offset)) )
-           {
-             switch ( RF64Header.samplespersec )
+             else
                {
-               case 48000: type = ESS_PCM_24b_48k; break;
-               case 96000: type = ESS_PCM_24b_96k; break;
-               default:
-                 return RESULT_FORMAT;
+                 result = RF64Header.ReadFromBuffer(FB.RoData(), read_count, &data_offset);
+               
+                 if ( ASDCP_SUCCESS(result) )
+                   {
+                     switch ( RF64Header.samplespersec )
+                       {
+                       case 48000: type = ESS_PCM_24b_48k; break;
+                       case 96000: type = ESS_PCM_24b_96k; break;
+                       default:
+                         DefaultLogSink().Error("Unexpected sample rate: %d\n", WavHeader.samplespersec);
+                         result = RESULT_FORMAT;
+                       }
+                   }
                }
            }
          else if ( ASDCP_SUCCESS(AIFFHeader.ReadFromBuffer(FB.RoData(), read_count, &data_offset)) )
index cae083dc6900adec24f024263cf6c47ae4485372..7698ff514df016136c2ecf550c5d3a9637db3c5e 100644 (file)
@@ -1124,16 +1124,16 @@ static const ASDCP::MDDEntry s_MDD_Table[] = {
   { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 362
       0x04, 0x01, 0x03, 0x02, 0x0b, 0x00, 0x00, 0x00 },
       {0}, false, "GenericPictureEssenceDescriptor_AlternativeCenterCuts" },
-  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x01, // 363
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 363
       0x04, 0x01, 0x05, 0x01, 0x13, 0x00, 0x00, 0x00 },
       {0x32, 0x05}, true, "GenericPictureEssenceDescriptor_ActiveHeight" },
-  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x01, // 364
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 364
       0x04, 0x01, 0x05, 0x01, 0x14, 0x00, 0x00, 0x00 },
       {0x32, 0x04}, true, "GenericPictureEssenceDescriptor_ActiveWidth" },
-  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x01, // 365
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 365
       0x04, 0x01, 0x05, 0x01, 0x15, 0x00, 0x00, 0x00 },
       {0x32, 0x06}, true, "GenericPictureEssenceDescriptor_ActiveXOffset" },
-  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x01, // 366
+  { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 366
       0x04, 0x01, 0x05, 0x01, 0x16, 0x00, 0x00, 0x00 },
       {0x32, 0x07}, true, "GenericPictureEssenceDescriptor_ActiveYOffset" },
   { { 0x06, 0x0e, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x0e, // 367
index 9a8dd2a6203525457005699c188ea75e9f759c80..b00ebe6a9214df189a920baa8fd479055f03209e 100644 (file)
@@ -1,5 +1,5 @@
 /*
-Copyright (c) 2013-2014, John Hurst
+Copyright (c) 2013-2015, John Hurst
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "AS_02_internal.h"
 #include "KM_xml.h"
+#include <openssl/sha.h>
 
 using namespace Kumu;
 using namespace ASDCP;
@@ -40,6 +41,133 @@ using Kumu::DefaultLogSink;
 
 const char* c_tt_namespace_name = "http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt";
 
+
+//------------------------------------------------------------------------------------------
+
+//
+//
+static byte_t s_id_prefix[16] = {
+  // RFC 4122 type 5
+  // 2067-2 5.4.5
+  0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1,
+  0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8
+};
+
+//
+void
+gen_png_name_id(const std::string& image_name, UUID& asset_id)
+{
+  SHA_CTX ctx;
+  SHA1_Init(&ctx);
+  SHA1_Update(&ctx, s_id_prefix, 16);
+  SHA1_Update(&ctx, (byte_t*)image_name.c_str(), image_name.length());
+
+  const ui32_t sha_len = 20;
+  byte_t bin_buf[sha_len];
+  SHA1_Final(bin_buf, &ctx);
+
+  // Derive the asset ID from the digest. Make it a type-5 UUID
+  byte_t buf[UUID_Length];
+  memcpy(buf, bin_buf, UUID_Length);
+  buf[6] &= 0x0f; // clear bits 4-7
+  buf[6] |= 0x50; // set UUID version 'digest'
+  buf[8] &= 0x3f; // clear bits 6&7
+  buf[8] |= 0x80; // set bit 7
+  asset_id.Set(buf);
+}
+
+//------------------------------------------------------------------------------------------
+
+
+AS_02::TimedText::Type5UUIDFilenameResolver::Type5UUIDFilenameResolver() {}
+AS_02::TimedText::Type5UUIDFilenameResolver::~Type5UUIDFilenameResolver() {}
+
+const byte_t PNGMagic[8] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
+const byte_t OpenTypeMagic[5] = { 0x4f, 0x54, 0x54, 0x4f, 0x00 };
+const byte_t TrueTypeMagic[5] = { 0x00, 0x01, 0x00, 0x00, 0x00 };
+
+//
+Result_t
+AS_02::TimedText::Type5UUIDFilenameResolver::OpenRead(const std::string& dirname)
+{
+  DirScannerEx dir_reader;
+  DirectoryEntryType_t ft;
+  std::string next_item;
+  std::string abs_dirname = PathMakeCanonical(dirname);
+  byte_t read_buffer[16];
+
+  if ( abs_dirname.empty() )
+    {
+      abs_dirname = ".";
+    }
+
+  if ( KM_SUCCESS(dir_reader.Open(abs_dirname.c_str())) )
+    {
+      while ( KM_SUCCESS(dir_reader.GetNext(next_item, ft)) )
+        {
+          if ( next_item[0] == '.' ) continue; // no hidden files
+         std::string tmp_path = PathJoin(abs_dirname, next_item);
+
+         if ( ft == DET_FILE )
+           {
+             FileReader reader;
+             Result_t result = reader.OpenRead(tmp_path);
+
+             if ( KM_SUCCESS(result) )
+               {
+                 result = reader.Read(read_buffer, 16);
+               }
+
+             if ( KM_SUCCESS(result) )
+               {
+                 // is it PNG?
+                 if ( memcmp(read_buffer, PNGMagic, sizeof(PNGMagic)) == 0 )
+                   {
+                     UUID asset_id;
+                     gen_png_name_id(next_item, asset_id);
+                     m_ResourceMap.insert(ResourceMap::value_type(asset_id, next_item));
+                   }
+               }
+           }
+       }
+    }
+}
+
+//
+Result_t
+AS_02::TimedText::Type5UUIDFilenameResolver::ResolveRID(const byte_t* uuid, ASDCP::TimedText::FrameBuffer& FrameBuf) const
+{
+  Kumu::UUID tmp_id(uuid);
+  char buf[64];
+
+  ResourceMap::const_iterator i = m_ResourceMap.find(tmp_id);
+
+  if ( i == m_ResourceMap.end() )
+    {
+      return RESULT_NOT_FOUND;
+    }
+
+  FileReader Reader;
+
+  DefaultLogSink().Debug("Retrieving resource %s from file %s\n", tmp_id.EncodeHex(buf, 64), i->second.c_str());
+
+  Result_t result = Reader.OpenRead(i->second.c_str());
+
+  if ( KM_SUCCESS(result) )
+    {
+      ui32_t read_count, read_size = Reader.Size();
+      result = FrameBuf.Capacity(read_size);
+      
+      if ( KM_SUCCESS(result) )
+       result = Reader.Read(FrameBuf.Data(), read_size, &read_count);
+      
+      if ( KM_SUCCESS(result) )
+       FrameBuf.Size(read_count);
+    }
+
+  return result;
+}
+
 //------------------------------------------------------------------------------------------
 
 typedef std::map<Kumu::UUID, ASDCP::TimedText::MIMEType_t> ResourceTypeMap_t;
@@ -56,7 +184,7 @@ public:
   std::string m_Filename;
   std::string m_XMLDoc;
   TimedTextDescriptor  m_TDesc;
-  ASDCP::mem_ptr<ASDCP::TimedText::LocalFilenameResolver> m_DefaultResolver;
+  ASDCP::mem_ptr<ASDCP::TimedText::IResourceResolver> m_DefaultResolver;
 
   h__TextParser() : m_Root("**ParserRoot**")
   {
@@ -69,7 +197,7 @@ public:
   {
     if ( m_DefaultResolver.empty() )
       {
-       ASDCP::TimedText::LocalFilenameResolver *resolver = new ASDCP::TimedText::LocalFilenameResolver;
+       AS_02::TimedText::Type5UUIDFilenameResolver *resolver = new AS_02::TimedText::Type5UUIDFilenameResolver;
        resolver->OpenRead(PathDirname(m_Filename));
        m_DefaultResolver = resolver;
       }
@@ -79,7 +207,7 @@ public:
 
   Result_t OpenRead(const std::string& filename);
   Result_t OpenRead(const std::string& xml_doc, const std::string& filename);
-  Result_t ReadAncillaryResource(const UUID& uuid, ASDCP::TimedText::FrameBuffer& FrameBuf,
+  Result_t ReadAncillaryResource(const byte_t *uuid, ASDCP::TimedText::FrameBuffer& FrameBuf,
                                 const ASDCP::TimedText::IResourceResolver& Resolver) const;
 };
 
@@ -107,12 +235,64 @@ AS_02::TimedText::ST2052_TextParser::h__TextParser::OpenRead(const std::string&
   return OpenRead();
 }
 
+//
+template <class VisitorType>
+bool
+apply_visitor(const XMLElement& element, VisitorType& visitor)
+{
+  const ElementList& l = element.GetChildren();
+  ElementList::const_iterator i;
+
+  for ( i = l.begin(); i != l.end(); ++i )
+    {
+      if ( ! visitor.Element(**i) )
+       {
+         return false;
+       }
+
+      if ( ! apply_visitor(**i, visitor) )
+       {
+         return false;
+       }
+    }
+
+  return true;
+}
+
+//
+class AttributeVisitor
+{
+  std::string attr_name;
+
+public:
+  AttributeVisitor(const std::string& n) : attr_name(n) {}
+  std::set<std::string> value_list;
+
+  bool Element(const XMLElement& e)
+  {
+    const AttributeList& l = e.GetAttributes();
+    AttributeList::const_iterator i;
+    for ( i = l.begin(); i != l.end(); ++i )
+      {
+       if ( i->name == attr_name )
+         {
+           value_list.insert(i->value);
+         }
+      }
+
+    return true;
+  }
+};
+
 //
 Result_t
 AS_02::TimedText::ST2052_TextParser::h__TextParser::OpenRead()
 {
   if ( ! m_Root.ParseString(m_XMLDoc.c_str()) )
-    return RESULT_FORMAT;
+    {
+      return RESULT_FORMAT;
+    }
 
   m_TDesc.EncodingName = "UTF-8"; // the XML parser demands UTF-8
   m_TDesc.ResourceList.clear();
@@ -129,9 +309,63 @@ AS_02::TimedText::ST2052_TextParser::h__TextParser::OpenRead()
       m_TDesc.NamespaceName = ns->Name();
     }
 
+  AttributeVisitor png_visitor("backgroundImage");
+  apply_visitor(m_Root, png_visitor);
+  std::set<std::string>::const_iterator i;
+
+  for ( i = png_visitor.value_list.begin(); i != png_visitor.value_list.end(); ++i )
+    {
+      UUID asset_id;
+      gen_png_name_id(*i, asset_id);
+      TimedTextResourceDescriptor TmpResource;
+      memcpy(TmpResource.ResourceID, asset_id.Value(), UUIDlen);
+      TmpResource.Type = ASDCP::TimedText::MT_PNG;
+      m_TDesc.ResourceList.push_back(TmpResource);
+      m_ResourceTypes.insert(ResourceTypeMap_t::value_type(UUID(TmpResource.ResourceID), ASDCP::TimedText::MT_PNG));
+    }
+
   return RESULT_OK;
 }
 
+//
+Result_t
+AS_02::TimedText::ST2052_TextParser::h__TextParser::ReadAncillaryResource(const byte_t* uuid, ASDCP::TimedText::FrameBuffer& FrameBuf,
+                                                                         const ASDCP::TimedText::IResourceResolver& Resolver) const
+{
+  FrameBuf.AssetID(uuid);
+  UUID TmpID(uuid);
+  char buf[64];
+
+  ResourceTypeMap_t::const_iterator rmi = m_ResourceTypes.find(TmpID);
+
+  if ( rmi == m_ResourceTypes.end() )
+    {
+      DefaultLogSink().Error("Unknown ancillary resource id: %s\n", TmpID.EncodeHex(buf, 64));
+      return RESULT_RANGE;
+    }
+
+  Result_t result = Resolver.ResolveRID(uuid, FrameBuf);
+
+  if ( KM_SUCCESS(result) )
+    {
+      if ( (*rmi).second == ASDCP::TimedText::MT_PNG )
+       {
+         FrameBuf.MIMEType("image/png");
+       }    
+      else if ( (*rmi).second == ASDCP::TimedText::MT_OPENTYPE )
+       {
+         FrameBuf.MIMEType("application/x-font-opentype");
+       }
+      else
+       {
+         FrameBuf.MIMEType("application/octet-stream");
+       }
+    }
+
+  return result;
+}
+
+
 
 //------------------------------------------------------------------------------------------
 
@@ -199,7 +433,13 @@ ASDCP::Result_t
 AS_02::TimedText::ST2052_TextParser::ReadAncillaryResource(const Kumu::UUID& uuid, ASDCP::TimedText::FrameBuffer& FrameBuf,
                                                           const ASDCP::TimedText::IResourceResolver* Resolver) const
 {
-  return RESULT_NOTIMPL;
+  if ( m_Parser.empty() )
+    return RESULT_INIT;
+
+  if ( Resolver == 0 )
+    Resolver = m_Parser->GetDefaultResolver();
+
+  return m_Parser->ReadAncillaryResource(uuid.Value(), FrameBuf, *Resolver);
 }
 
 
index e3916943dd87a973d190ef607378e940377922e2..7ecd0938498c892bacb0cf36309da18a88e14d0c 100644 (file)
@@ -45,6 +45,7 @@ const char* c_dcst_namespace_name = "http://www.smpte-ra.org/schemas/428-7/2007/
 
 
 ASDCP::TimedText::LocalFilenameResolver::LocalFilenameResolver() {}
+ASDCP::TimedText::LocalFilenameResolver::~LocalFilenameResolver() {}
 
 //
 Result_t
index 20776d56190446e5d3004f3d14f863ede950df41..aad4b89ab03d61bac648a7234e7d2df4ec371c1f 100755 (executable)
@@ -175,7 +175,7 @@ ASDCP::Wav::SimpleWaveHeader::ReadFromBuffer(const byte_t* buf, ui32_t buf_len,
        {
          ui16_t format = KM_i16_LE(*(ui16_t*)p); p += 2;
 
-         if ( format != WAVE_FORMAT_PCM && format != WAVE_FORMAT_EXTENSIBLE )
+         if ( format != ASDCP_WAVE_FORMAT_PCM && format != ASDCP_WAVE_FORMAT_EXTENSIBLE )
            {
              DefaultLogSink().Error("Expecting uncompressed PCM data, got format type %hd\n", format);
              return RESULT_RAW_FORMAT;
@@ -564,7 +564,7 @@ ASDCP::RF64::SimpleRF64Header::ReadFromBuffer(const byte_t* buf, ui32_t buf_len,
         {
             ui16_t format = KM_i16_LE(*(ui16_t*)p); p += 2;
 
-            if ( format != Wav::WAVE_FORMAT_PCM && format != Wav::WAVE_FORMAT_EXTENSIBLE )
+            if ( format != Wav::ASDCP_WAVE_FORMAT_PCM && format != Wav::ASDCP_WAVE_FORMAT_EXTENSIBLE )
             {
                 DefaultLogSink().Error("Expecting uncompressed PCM data, got format type %hd\n", format);
                 return RESULT_RAW_FORMAT;
index 683207324f62e20ff8c48c937435df8d85d5f4c9..7e274d8787561f16d588b65f9801e6c0e744d4f7 100755 (executable)
--- a/src/Wav.h
+++ b/src/Wav.h
@@ -89,8 +89,8 @@ namespace ASDCP
       const fourcc FCC_fmt_("fmt ");
       const fourcc FCC_data("data");
 
-      const ui16_t WAVE_FORMAT_PCM = 1;
-      const ui16_t WAVE_FORMAT_EXTENSIBLE = 65534;
+      const ui16_t ASDCP_WAVE_FORMAT_PCM = 1;
+      const ui16_t ASDCP_WAVE_FORMAT_EXTENSIBLE = 65534;
 
       //
       class SimpleWaveHeader
index 148946b6d6af235eed7e84a0cca044e87934f75f..37b458b3aaf0bc35bf9ea45319797a60d0250875 100755 (executable)
@@ -86,7 +86,7 @@ USAGE: %s [-h|-help] [-V]\n\
        %s [-1|-2] [-b <buffer-size>] [-d <duration>]\n\
        [-f <starting-frame>] [-m] [-p <frame-rate>] [-R] [-s <size>] [-v] [-W]\n\
        [-w] <input-file> [<file-prefix>]\n\n",
-         PROGRAM_NAME, PROGRAM_NAME, PROGRAM_NAME);
+         PROGRAM_NAME, PROGRAM_NAME);
 
   fprintf(stream, "\
 Options:\n\
index 6be6c07ec7a9fa663833312b9a19e998bc816913..a3c891d3693563cda5c163c40330c3809233b21d 100755 (executable)
@@ -79,7 +79,7 @@ USAGE: %s [-h|-help] [-V]\n\
        %s -d <input-file>\n\
 \n\
        %s -g | -u\n",
-         PROGRAM_NAME, PROGRAM_NAME, PROGRAM_NAME, PROGRAM_NAME);
+         PROGRAM_NAME, PROGRAM_NAME, PROGRAM_NAME);
 
   fprintf(stream, "\
 Major modes:\n\
index 9388d87ca1e5921d61adc7c732bdfb09e7ac5b56..8d5477292648c3c3444d9846917bb29a66333b1d 100755 (executable)
@@ -1681,8 +1681,7 @@ main(int argc, const char** argv)
        case ESS_DCDATA_UNKNOWN:
          if ( ! Options.aux_data_coding.HasValue() )
            {
-             fprintf(stderr, "Option \"-A <UL>\" is required for Aux Data essence.\n",
-                     Options.filenames.front().c_str());
+             fprintf(stderr, "Option \"-A <UL>\" is required for Aux Data essence.\n");
              return 3;
            }
          else
index 4f77dbb6eb107f832544077c2ef70d57c8b5f25f..5dcd8ed4b6ebb187606256a6ae0179a2ab0e568e 100755 (executable)
@@ -292,7 +292,7 @@ main(int argc, const char** argv)
              snprintf(filename_buf, 1024, "%s%010qu%s", this_prefix.c_str(), item_counter, Options.suffix.c_str());
 
              if ( Options.verbose_flag )
-               fprintf(stderr, "%s (%d bytes)\n", filename_buf, packet.ValueLength());
+               fprintf(stderr, "%s (%llu bytes)\n", filename_buf, packet.ValueLength());
 
              Kumu::FileWriter writer;
              writer.OpenWrite(filename_buf);
index a0ba7c7829db6b3b7270ba2c4b69ed27f25cf778..b759cd713fd30573f3dbd5a7b87fa9748b6d7082 100755 (executable)
@@ -77,7 +77,7 @@ USAGE: %s [-h|-help] [-V]\n\
        %s [-b <buffer-size>] [-d <duration>]\n\
        [-f <starting-frame>] [-m] [-R] [-s <size>] [-v] [-W]\n\
        [-w] <input-file> [<file-prefix>]\n\n",
-         PROGRAM_NAME, PROGRAM_NAME, PROGRAM_NAME);
+         PROGRAM_NAME, PROGRAM_NAME);
 
   fprintf(stream, "\
 Options:\n\