Optional progress reporting when making MXF hashes.
authorCarl Hetherington <cth@carlh.net>
Thu, 29 Aug 2013 13:24:09 +0000 (14:24 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 29 Aug 2013 13:24:09 +0000 (14:24 +0100)
src/asset.cc
src/asset.h
src/cpl.cc
src/util.cc
src/util.h

index fb21580e32651ce4be73e5b3947dd68cb8d3367e..06b87953e4631dd42a1cff4a2b680bb0cafc2ba5 100644 (file)
@@ -88,12 +88,22 @@ string
 Asset::digest () const
 {
        if (_digest.empty ()) {
-               _digest = make_digest (path().string());
+               _digest = make_digest (path().string(), 0);
        }
 
        return _digest;
 }
 
+void
+Asset::compute_digest (boost::function<void (float)> progress)
+{
+       if (!_digest.empty ()) {
+               return;
+       }
+
+       _digest = make_digest (path().string(), &progress);
+}
+
 bool
 Asset::equals (shared_ptr<const Asset> other, EqualityOptions, boost::function<void (NoteType, string)> note) const
 {
index 44d088a3121695f9bba809fa0775c3f396b398b0..c6ff7e830f6971ab2793dd1f26dda28d04792f1b 100644 (file)
@@ -73,6 +73,14 @@ public:
         */
        void write_to_assetmap (xmlpp::Node *) const;
 
+       /** Compute the digest for this asset.  Calling this is optional: if
+        *  it is not called, the digest will be computed when required.  However,
+        *  calling this method allows the caller to see the progress of the
+        *  computation, which can be long for large assets.
+        *  @param Called with progress between 0 and 1.
+        */
+       void compute_digest (boost::function<void (float)> progress);
+
        std::string uuid () const {
                return _uuid;
        }
index e4f36fed092f907af48c1985134104bdb54c04df..561cc9898af4af4ce05590c1b95cc8a6a11fd7ff 100644 (file)
@@ -252,7 +252,7 @@ CPL::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<Encryptio
 
        doc.write_to_file_formatted (p.string (), "UTF-8");
 
-       _digest = make_digest (p.string ());
+       _digest = make_digest (p.string (), 0);
        _length = boost::filesystem::file_size (p.string ());
 }
 
index 875693bf70ceaef75fc8c5e331db32ba177476f4..d7b4f9809dd58288f539e12386502cb22db74bae 100644 (file)
@@ -70,10 +70,12 @@ libdcp::make_uuid ()
 
 /** Create a digest for a file.
  *  @param filename File name.
+ *  @param progress Pointer to a progress reporting function, or 0.  The function will be called
+ *  with a progress value between 0 and 1.
  *  @return Digest.
  */
 string
-libdcp::make_digest (string filename)
+libdcp::make_digest (string filename, boost::function<void (float)>* progress)
 {
        Kumu::FileReader reader;
        if (ASDCP_FAILURE (reader.OpenRead (filename.c_str ()))) {
@@ -82,8 +84,12 @@ libdcp::make_digest (string filename)
        
        SHA_CTX sha;
        SHA1_Init (&sha);
-       
-       Kumu::ByteString read_buffer (65536);
+
+       int const buffer_size = 65536;
+       Kumu::ByteString read_buffer (buffer_size);
+
+       Kumu::fsize_t done = 0;
+       Kumu::fsize_t const size = reader.Size ();
        while (1) {
                ui32_t read = 0;
                Kumu::Result_t r = reader.Read (read_buffer.Data(), read_buffer.Capacity(), &read);
@@ -95,6 +101,11 @@ libdcp::make_digest (string filename)
                }
                
                SHA1_Update (&sha, read_buffer.Data(), read);
+
+               if (progress) {
+                       (*progress) (float (done) / size);
+                       done += read;
+               }
        }
 
        byte_t byte_buffer[20];
index 9153dbdaafcbd4689f494b802fc15249123bb089..586d197f73f2e5a9fa4979d66b8fc49198eb8dd6 100644 (file)
@@ -27,6 +27,7 @@
 #include <string>
 #include <stdint.h>
 #include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
 #include <openjpeg.h>
 #include "types.h"
 
@@ -60,7 +61,7 @@ extern bool operator== (Size const & a, Size const & b);
 extern bool operator!= (Size const & a, Size const & b);
 
 extern std::string make_uuid ();
-extern std::string make_digest (std::string filename);
+extern std::string make_digest (std::string filename, boost::function<void (float)> *);
 extern std::string content_kind_to_string (ContentKind kind);
 extern ContentKind content_kind_from_string (std::string kind);
 extern bool empty_or_white_space (std::string s);