new functions for KM_fileIO
authorjhurst <jhurst@cinecert.com>
Sun, 5 Apr 2009 19:16:53 +0000 (19:16 +0000)
committerjhurst <>
Sun, 5 Apr 2009 19:16:53 +0000 (19:16 +0000)
comment updates in AS_DCP.h
additional frame rates in AS_DCP.h

configure.ac
src/AS_DCP.h
src/KM_error.h
src/KM_fileio.cpp
src/KM_fileio.h

index c2bb969cfe50e926fd7d4cd26bf6a659966cc528..24bca1138e75866c142dbb725236395fc001bd44 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], [1.4.21], [asdcplib@cinecert.com])
+AC_INIT([asdcplib], [1.4.22], [asdcplib@cinecert.com])
 
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_SRCDIR([src/KM_error.h])
index d8d734b6cad78e5c465431c252dac1f53fb0b133..a6be6d296a3d8401bda37e6843594d6a9159c493 100755 (executable)
@@ -28,15 +28,12 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     \version $Id$       
     \brief   AS-DCP library, public interface
 
-The asdcplib library is a set of wrapper objects that offer simplified
-access to files conforming to the file formats proposed by the SMPTE
-D-Cinema packaging working group DC28.20.  The file format, labeled
-AS-DCP, is described in series of separate documents which include but
-may not be limited to:
+The asdcplib library is a set of file access objects that offer simplified
+access to files conforming to the standards published by the SMPTE
+D-Cinema Technology Committee 21DC. The file format, labeled AS-DCP,
+is described in series of separate documents which include but may not
+be be limited to:
 
- o MXF Interop Track File Specification
- o MXF Interop Track File Essence Encryption Specification
- o MXF Interop Operational Constraints Specification
  o SMPTE 429-2-2009 DCP Operational Constraints
  o SMPTE 429-3-2006 Track File Specification
  o SMPTE 429-4-2006 JPEG 2000 for D-Cinema
@@ -54,29 +51,29 @@ may not be limited to:
  o IETF RFC 2104 - HMAC/SHA1
  o NIST FIPS 197 - AES (Rijndael)
 
+ o MXF Interop Track File Specification
+ o MXF Interop Track File Essence Encryption Specification
+ o MXF Interop Operational Constraints Specification
+ - Note: the MXF Interop documents are not formally published.
+   Contact the asdcplib support address to get copies.
+
 The following use cases are supported by the library:
 
- o Write a plaintext MPEG2 Video Elementary Stream to a plaintext ASDCP file
- o Write a plaintext MPEG2 Video Elementary Stream to a ciphertext ASDCP file
- o Read a plaintext MPEG2 Video Elementary Stream from a plaintext ASDCP file
- o Read a plaintext MPEG2 Video Elementary Stream from a ciphertext ASDCP file
- o Read a ciphertext MPEG2 Video Elementary Stream from a ciphertext ASDCP file
- o Write one or more plaintext JPEG 2000 codestreams to a plaintext ASDCP file
- o Write one or more plaintext JPEG 2000 codestreams to a ciphertext ASDCP file
- o Read one or more plaintext JPEG 2000 codestreams from a plaintext ASDCP file
- o Read one or more plaintext JPEG 2000 codestreams from a ciphertext ASDCP file
- o Read one or more ciphertext JPEG 2000 codestreams from a ciphertext ASDCP file
- o Write one or more plaintext JPEG 2000 stereoscopic codestream pairs to a plaintext ASDCP file
- o Write one or more plaintext JPEG 2000 stereoscopic codestream pairs to a ciphertext ASDCP file
- o Read one or more plaintext JPEG 2000 stereoscopic codestream pairs from a plaintext ASDCP file
- o Read one or more plaintext JPEG 2000 stereoscopic codestream pairs from a ciphertext ASDCP file
- o Read one or more ciphertext JPEG 2000 stereoscopic codestream pairs from a ciphertext ASDCP file
- o Write one or more plaintext PCM audio streams to a plaintext ASDCP file
- o Write one or more plaintext PCM audio streams to a ciphertext ASDCP file
- o Read one or more plaintext PCM audio streams from a plaintext ASDCP file
- o Read one or more plaintext PCM audio streams from a ciphertext ASDCP file
- o Read one or more ciphertext PCM audio streams from a ciphertext ASDCP file
- o Read header metadata from an ASDCP file
+ o Write essence to a plaintext or ciphertext AS-DCP file:
+     MPEG2 Video Elementary Stream
+     JPEG 2000 codestreams
+     JPEG 2000 stereoscopic codestream pairs
+     PCM audio streams
+     SMPTE 429-7 Timed Text XML with font and image resources
+
+ o Read essence from a plaintext or ciphertext AS-DCP file:
+     MPEG2 Video Elementary Stream
+     JPEG 2000 codestreams
+     JPEG 2000 stereoscopic codestream pairs
+     PCM audio streams
+     SMPTE 429-7 Timed Text XML with font and image resources
+
+ o Read header metadata from an AS-DCP file
 
 This project depends upon the following libraries:
  - OpenSSL http://www.openssl.org/
@@ -258,6 +255,14 @@ namespace ASDCP {
   const Rational SampleRate_48k(48000,1);
   const Rational SampleRate_96k(96000,1);
 
+  // Additional frame rates, see SMPTE 428-11
+  // These rates are new and not supported by all systems. Do not assume that a package
+  // made using on of these rates will work just anywhere!
+  const Rational EditRate_25(25,1);
+  const Rational EditRate_30(30,1);
+  const Rational EditRate_50(50,1);
+  const Rational EditRate_60(60,1);
+
   // Non-reference counting container for internal member objects.
   // Please do not use this class for any other purpose.
   template <class T>
index c17fe76ecf57e1c9a5b16ad8e209b5d8c0c4c962..b0d40d11648273fe548d1d842910a9f6a700c90e 100755 (executable)
@@ -88,6 +88,8 @@ namespace Kumu
   const Result_t RESULT_FILEEXISTS (-18,  "Filename already exists.");
   const Result_t RESULT_NOTAFILE   (-19,  "Filename not found.");
   const Result_t RESULT_UNKNOWN    (-20,  "Unknown result code.");
+  const Result_t RESULT_DIR_CREATE (-21, "Unable to create directory.");
 } // namespace Kumu
 
 //--------------------------------------------------------------------------------
index 978f6f9a6d7b6249c53775343155d5c744e2914c..8625e690b2c62cbb237925ff359a537f6b89d3de 100644 (file)
@@ -32,7 +32,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <KM_fileio.h>
 #include <KM_log.h>
 #include <fcntl.h>
+
 #include <assert.h>
+
 #ifdef KM_WIN32
 #include <direct.h>
 #endif
@@ -52,6 +54,13 @@ struct iovec {
   int   iov_len;
 };
 #else
+# if defined(__linux__)
+#   include <sys/statfs.h>
+# else
+#  include <sys/mount.h>
+# endif
+
+#include <sys/stat.h>
 #include <sys/uio.h>
 typedef struct stat     fstat_t;
 #endif
@@ -1125,6 +1134,57 @@ Kumu::WriteObjectIntoFile(const Kumu::IArchive& Object, const std::string& Filen
 //------------------------------------------------------------------------------------------
 //
 
+//
+Result_t
+Kumu::ReadFileIntoBuffer(const std::string& Filename, Kumu::ByteString& Buffer, ui32_t max_size)
+{
+  ui32_t file_size = FileSize(Filename);
+  Result_t result = Buffer.Capacity(file_size);
+
+  if ( KM_SUCCESS(result) )
+    {
+      ui32_t read_count = 0;
+      FileWriter Reader;
+
+      result = Reader.OpenRead(Filename.c_str());
+
+      if ( KM_SUCCESS(result) )
+       result = Reader.Read(Buffer.Data(), file_size, &read_count);
+    
+      if ( KM_SUCCESS(result) )
+       {
+         if ( file_size != read_count) 
+           return RESULT_READFAIL;
+
+         Buffer.Length(read_count);
+       }
+    }
+  
+  return result;
+}
+
+//
+Result_t
+Kumu::WriteBufferIntoFile(const Kumu::ByteString& Buffer, const std::string& Filename)
+{
+  ui32_t write_count = 0;
+  FileWriter Writer;
+
+  Result_t result = Writer.OpenWrite(Filename.c_str());
+
+  if ( KM_SUCCESS(result) )
+    result = Writer.Write(Buffer.RoData(), Buffer.Length(), &write_count);
+
+  if ( KM_SUCCESS(result) && Buffer.Length() != write_count) 
+    return RESULT_WRITEFAIL;
+
+  return result;
+}
+
+//------------------------------------------------------------------------------------------
+//
+
+
 // Win32 directory scanner
 //
 #ifdef KM_WIN32
@@ -1277,6 +1337,181 @@ Kumu::DirScanner::GetNext(char* filename)
 #endif // KM_WIN32
 
 
+//------------------------------------------------------------------------------------------
+
+// note: when moving to KM_fileio, don't forget to write the Win32 versions
+// note: add error messages and remove RESULT_FAIL form DirScanner
+
+#ifdef KM_WIN32
+#else // KM_WIN32
+
+// given a path string, create any missing directories so that PathIsDirectory(Path) is true.
+//
+Result_t
+Kumu::CreateDirectoriesInPath(const std::string& Path)
+{
+  bool abs = PathIsAbsolute(Path);
+  assert(abs);
+  PathCompList_t PathComps, TmpPathComps;
+
+  PathToComponents(Path, PathComps);
+
+  while ( ! PathComps.empty() )
+    {
+      TmpPathComps.push_back(PathComps.front());
+      PathComps.pop_front();
+      std::string tmp_path = abs ? ComponentsToAbsolutePath(TmpPathComps) : ComponentsToPath(TmpPathComps);
+
+      if ( ! PathIsDirectory(tmp_path) )
+       {
+         if ( mkdir(tmp_path.c_str(), 0775) != 0 )
+           {
+             DefaultLogSink().Error("CreateDirectoriesInPath mkdir %s: %s\n",
+                                    tmp_path.c_str(), strerror(errno));
+             return RESULT_DIR_CREATE;
+           }
+       }
+    }
+
+  return RESULT_OK;
+}
+#endif // KM_WIN32
+
+
+#ifdef KM_WIN32
+#else // KM_WIN32
+
+//
+Result_t
+Kumu::DeleteFile(const std::string& filename)
+{
+  if ( unlink(filename.c_str()) == 0 )
+    return RESULT_OK;
+
+  switch ( errno )
+    {
+    case ENOENT:
+    case ENOTDIR: return RESULT_NOTAFILE;
+
+    case EROFS:
+    case EBUSY:
+    case EACCES:
+    case EPERM:   return RESULT_NO_PERM;
+    }
+
+  DefaultLogSink().Error("DeleteFile %s: %s\n", filename.c_str(), strerror(errno));
+  return RESULT_FAIL;
+}
+
+//
+Result_t
+h__DeletePath(const std::string& pathname)
+{
+  fprintf(stderr, "h__DeletePath %s\n", pathname.c_str());
+  Result_t result = RESULT_OK;
+
+  if ( ! PathIsDirectory(pathname) )
+    {
+      result = DeleteFile(pathname);
+    }
+  else
+    {
+      {
+       DirScanner TestDir;
+       char       next_file[Kumu::MaxFilePath];
+       result = TestDir.Open(pathname.c_str());
+
+       while ( KM_SUCCESS(result) && KM_SUCCESS(TestDir.GetNext(next_file)) )
+         {
+           if ( next_file[0] == '.' )
+             {
+               if ( next_file[1] ==  0 )
+                 continue; // don't delete 'this'
+               
+               if ( next_file[1] == '.' && next_file[2] ==  0 )
+                 continue; // don't delete 'this' parent
+             }
+
+           result = h__DeletePath(pathname + std::string("/") + next_file);
+         }
+      }
+
+      if ( rmdir(pathname.c_str()) != 0 )
+       {
+         switch ( errno )
+           {
+           case ENOENT:
+           case ENOTDIR:
+             result = RESULT_NOTAFILE;
+             break;
+
+           case EROFS:
+           case EBUSY:
+           case EACCES:
+           case EPERM:
+             result = RESULT_NO_PERM;
+             break;
+
+           default:
+             DefaultLogSink().Error("DeletePath %s: %s\n", pathname.c_str(), strerror(errno));
+             result = RESULT_FAIL;
+           }
+       }
+    }
+
+  return result;
+}
+
+//
+Result_t
+Kumu::DeletePath(const std::string& pathname)
+{
+  std::string c_pathname = PathMakeAbsolute(PathMakeCanonical(pathname));
+  DefaultLogSink().Debug("DeletePath (%s) c(%s)\n", pathname.c_str(), c_pathname.c_str());
+  return h__DeletePath(c_pathname);
+}
+
+#endif // KM_WIN32
+
+//------------------------------------------------------------------------------------------
+//
+
+
+#ifdef KM_WIN32
+#else // KM_WIN32
+
+//
+Result_t
+Kumu::FreeSpaceForPath(const std::string& path, Kumu::fsize_t& free_space, Kumu::fsize_t& total_space)
+{
+  struct statfs s;
+
+  if ( statfs(path.c_str(), &s) == 0 )
+    {
+      if ( s.f_blocks < 1 )
+       {
+         DefaultLogSink().Error("File system %s has impossible size: %ld\n",
+                                path.c_str(), s.f_blocks);
+         return RESULT_FAIL;
+       }
+
+      free_space = (Kumu::fsize_t)s.f_bsize * (Kumu::fsize_t)s.f_bavail;
+      total_space = (Kumu::fsize_t)s.f_bsize * (Kumu::fsize_t)s.f_blocks;
+      return RESULT_OK;
+    }
+
+  switch ( errno )
+    {
+    case ENOENT:
+    case ENOTDIR: return RESULT_NOTAFILE;
+    case EACCES:  return RESULT_NO_PERM;
+    }
+
+  DefaultLogSink().Error("FreeSpaceForPath statfs %s: %s\n", path.c_str(), strerror(errno));
+  return RESULT_FAIL;
+} 
+
+#endif // KM_WIN32
 
 //
 // end KM_fileio.cpp
index 448cf76f01f9db423163cf98591ddc01d92fede7..738a3162f9cb93fb91ef185375232244d87036ec 100755 (executable)
@@ -119,18 +119,26 @@ namespace Kumu
 
   const ui32_t MaxFilePath = Kilobyte;
 
+
+  //------------------------------------------------------------------------------------------
   // Path Manglers
-  //
+  //------------------------------------------------------------------------------------------
+
+  // types
   typedef std::list<std::string> PathCompList_t; // a list of path components
   typedef std::list<std::string> PathList_t; // a list of paths
 
+  // tests
   bool        PathExists(const std::string& Path); // true if the path exists in the filesystem
   bool        PathIsFile(const std::string& Path); // true if the path exists in the filesystem and is a file
   bool        PathIsDirectory(const std::string& Path); // true if the path exists in the filesystem and is a directory
   fsize_t     FileSize(const std::string& Path); // returns the size of a regular file, 0 for a directory or device
   bool        PathsAreEquivalent(const std::string& lhs, const std::string& rhs); // true if paths point to the same filesystem entry
 
-  // split and reassemble pats as lists of path components
+  // Returns free space and total space available for the given path
+  Result_t   FreeSpaceForPath(const std::string& path, Kumu::fsize_t& free_space, Kumu::fsize_t& total_space);
+
+  // split and reassemble paths as lists of path components
   PathCompList_t& PathToComponents(const std::string& Path, PathCompList_t& CList, char separator = '/'); // removes '//'
   std::string ComponentsToPath(const PathCompList_t& CList, char separator = '/');
   std::string ComponentsToAbsolutePath(const PathCompList_t& CList, char separator = '/'); // add separator to the front
@@ -141,12 +149,18 @@ namespace Kumu
   std::string PathMakeLocal(const std::string& Path, const std::string& Parent); // remove Parent from front of Path, if it exists
   std::string PathMakeCanonical(const std::string& Path, char separator = '/'); // remove '.' and '..'
 
+  // common operations
   std::string PathBasename(const std::string& Path, char separator = '/'); // returns right-most path element (list back())
   std::string PathDirname(const std::string& Path, char separator = '/'); // returns everything but the right-most element
   std::string PathGetExtension(const std::string& Path); // returns everything in the right-most element following the right-most '.'
   std::string PathSetExtension(const std::string& Path, const std::string& Extension); // empty extension removes '.' as well
 
-  //
+
+  //------------------------------------------------------------------------------------------
+  // Path Search
+  //------------------------------------------------------------------------------------------
+
+  // An interface for a path matching function, used by FindInPath() and FindInPaths() below
   //
   class IPathMatch
   {
@@ -155,6 +169,7 @@ namespace Kumu
     virtual bool Match(const std::string& s) const = 0;
   };
 
+  // matches any pathname
  class PathMatchAny : public IPathMatch
   {
   public:
@@ -163,6 +178,7 @@ namespace Kumu
   };
 
 #ifndef KM_WIN32
+  // matches pathnames using a regular expression
  class PathMatchRegex : public IPathMatch
   {
     regex_t m_regex;
@@ -176,6 +192,7 @@ namespace Kumu
     bool Match(const std::string& s) const;
   };
 
+  // matches pathnames using a Bourne shell glob expression
  class PathMatchGlob : public IPathMatch
   {
     regex_t m_regex;
@@ -198,6 +215,22 @@ namespace Kumu
   PathList_t& FindInPaths(const IPathMatch& Pattern, const PathList_t& SearchPaths,
                          PathList_t& FoundPaths, bool one_shot = false, char separator = '/');
 
+  //------------------------------------------------------------------------------------------
+  // Directory Manipulation
+  //------------------------------------------------------------------------------------------
+
+  // Create a directory, creates intermediate directories as necessary
+  Result_t CreateDirectoriesInPath(const std::string& Path);
+
+  // Delete a file (fails if the path points to a directory)
+  Result_t DeleteFile(const std::string& filename);
+
+  // Recursively remove a file or directory
+  Result_t DeletePath(const std::string& pathname);
+
+  //------------------------------------------------------------------------------------------
+  // File I/O Wrappers
+  //------------------------------------------------------------------------------------------
 
   // Instant IO for strings
   //
@@ -215,6 +248,20 @@ namespace Kumu
   // Archives an object into a file
   Result_t WriteObjectIntoFile(const IArchive& Object, const std::string& Filename);
 
+  // Instant IO for memory buffers
+  //
+  // Unarchives a file into a buffer
+  Result_t ReadFileIntoBuffer(const std::string& Filename, Kumu::ByteString& Buffer,
+                             ui32_t max_size = 8 * Kumu::Megabyte);
+
+  // Archives a buffer into a file
+  Result_t WriteBufferIntoFile(const Kumu::ByteString& Buffer, const std::string& Filename);
+
+
+  //------------------------------------------------------------------------------------------
+  // File I/O
+  //------------------------------------------------------------------------------------------
+
   //
   class FileReader
     {
@@ -274,6 +321,11 @@ namespace Kumu
       Result_t Write(const byte_t*, ui32_t, ui32_t* = 0);            // write buffer to disk
    };
 
+  Result_t CreateDirectoriesInPath(const std::string& Path);
+  Result_t FreeSpaceForPath(const std::string& path, Kumu::fsize_t& free_space, Kumu::fsize_t& total_space);
+  Result_t DeleteFile(const std::string& filename);
+  Result_t DeletePath(const std::string& pathname);
+
 } // namespace Kumu