Various fixes to resampling.
[dcpomatic.git] / src / lib / film.cc
index 6bf8fee84d6e4f189f29ac67c5812e77bc2dc369..583a15e19cc472af6ae2ecca5c73077b174ecd17 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <stdexcept>
 #include <iostream>
+#include <algorithm>
 #include <fstream>
 #include <cstdlib>
 #include <sstream>
@@ -47,6 +48,7 @@
 #include "scaler.h"
 #include "decoder_factory.h"
 #include "config.h"
+#include "check_hashes_job.h"
 
 using namespace std;
 using namespace boost;
@@ -68,7 +70,7 @@ Film::Film (string d, bool must_exist)
        
        filesystem::path p (filesystem::system_complete (d));
        filesystem::path result;
-       for(filesystem::path::iterator i = p.begin(); i != p.end(); ++i) {
+       for (filesystem::path::iterator i = p.begin(); i != p.end(); ++i) {
                if (*i == "..") {
                        if (filesystem::is_symlink (result) || result.filename() == "..") {
                                result /= *i;
@@ -88,7 +90,7 @@ Film::Film (string d, bool must_exist)
 
        read_metadata ();
 
-       _log = new Log (_state.file ("log"));
+       _log = new FileLog (_state.file ("log"));
 }
 
 /** Copy constructor */
@@ -122,6 +124,10 @@ Film::read_metadata ()
                        continue;
                }
 
+               if (line[line.size() - 1] == '\r') {
+                       line = line.substr (0, line.size() - 1);
+               }
+
                size_t const s = line.find (' ');
                if (s == string::npos) {
                        continue;
@@ -165,7 +171,24 @@ Film::set_name (string n)
 void
 Film::set_content (string c)
 {
-       if (filesystem::path(c).has_root_directory () && starts_with (c, _state.directory)) {
+       string check = _state.directory;
+
+#if BOOST_FILESYSTEM_VERSION == 3
+       filesystem::path slash ("/");
+       string platform_slash = slash.make_preferred().string ();
+#else
+#ifdef DVDOMATIC_WINDOWS
+       string platform_slash = "\\";
+#else
+       string platform_slash = "/";
+#endif
+#endif 
+
+       if (!ends_with (check, platform_slash)) {
+               check += platform_slash;
+       }
+       
+       if (filesystem::path(c).has_root_directory () && starts_with (c, check)) {
                c = c.substr (_state.directory.length() + 1);
        }
 
@@ -190,6 +213,7 @@ Film::set_content (string c)
        _state.audio_sample_rate = d->audio_sample_rate ();
        _state.audio_sample_format = d->audio_sample_format ();
 
+       _state.content_digest = md5_digest (s->content_path ());
        _state.content = c;
        
        signal_changed (SIZE);
@@ -222,48 +246,48 @@ Film::set_dcp_content_type (DCPContentType const * t)
 void
 Film::set_left_crop (int c)
 {
-       if (c == _state.left_crop) {
+       if (c == _state.crop.left) {
                return;
        }
        
-       _state.left_crop = c;
-       signal_changed (LEFT_CROP);
+       _state.crop.left = c;
+       signal_changed (CROP);
 }
 
 /** Set the number of pixels by which to crop the right of the source video */
 void
 Film::set_right_crop (int c)
 {
-       if (c == _state.right_crop) {
+       if (c == _state.crop.right) {
                return;
        }
 
-       _state.right_crop = c;
-       signal_changed (RIGHT_CROP);
+       _state.crop.right = c;
+       signal_changed (CROP);
 }
 
 /** Set the number of pixels by which to crop the top of the source video */
 void
 Film::set_top_crop (int c)
 {
-       if (c == _state.top_crop) {
+       if (c == _state.crop.top) {
                return;
        }
        
-       _state.top_crop = c;
-       signal_changed (TOP_CROP);
+       _state.crop.top = c;
+       signal_changed (CROP);
 }
 
 /** Set the number of pixels by which to crop the bottom of the source video */
 void
 Film::set_bottom_crop (int c)
 {
-       if (c == _state.bottom_crop) {
+       if (c == _state.crop.bottom) {
                return;
        }
        
-       _state.bottom_crop = c;
-       signal_changed (BOTTOM_CROP);
+       _state.crop.bottom = c;
+       signal_changed (CROP);
 }
 
 /** Set the filters to apply to the image when generating thumbnails
@@ -409,10 +433,10 @@ Film::j2k_dir () const
 {
        assert (format());
 
-       stringstream s;
+       filesystem::path p;
 
        /* Start with j2c */
-       s << "j2c/";
+       p /= "j2c";
 
        pair<string, string> f = Filter::ffmpeg_strings (filters ());
 
@@ -420,19 +444,24 @@ Film::j2k_dir () const
           so that we don't get confused about J2K files generated using different
           settings.
        */
-       s << _state.format->nickname()
-         << "_" << _state.content
-         << "_" << left_crop() << "_" << right_crop() << "_" << top_crop() << "_" << bottom_crop()
+       stringstream s;
+       s << _state.format->id()
+         << "_" << _state.content_digest
+         << "_" << crop().left << "_" << crop().right << "_" << crop().top << "_" << crop().bottom
          << "_" << f.first << "_" << f.second
          << "_" << _state.scaler->id();
 
+       p /= s.str ();
+
        /* Similarly for the A/B case */
        if (dcp_ab()) {
+               stringstream s;
                pair<string, string> fa = Filter::ffmpeg_strings (Config::instance()->reference_filters());
-               s << "/ab_" << Config::instance()->reference_scaler()->id() << "_" << fa.first << "_" << fa.second;
+               s << "ab_" << Config::instance()->reference_scaler()->id() << "_" << fa.first << "_" << fa.second;
+               p /= s.str ();
        }
        
-       return _state.dir (s.str ());
+       return _state.dir (p.string ());
 }
 
 /** Handle a change to the Film's metadata */
@@ -516,7 +545,8 @@ Film::make_dcp (bool transcode, int freq)
                        JobManager::instance()->add (shared_ptr<Job> (new TranscodeJob (fs, o, log ())));
                }
        }
-       
+
+       JobManager::instance()->add (shared_ptr<Job> (new CheckHashesJob (fs, o, log ())));
        JobManager::instance()->add (shared_ptr<Job> (new MakeDCPJob (fs, o, log ())));
 }
 
@@ -577,13 +607,6 @@ Film::set_scaler (Scaler const * s)
        signal_changed (SCALER);
 }
 
-void
-Film::set_frames_per_second (float f)
-{
-       _state.frames_per_second = f;
-       signal_changed (FRAMES_PER_SECOND);
-}
-
 /** @return full paths to any audio files that this Film has */
 vector<string>
 Film::audio_files () const
@@ -624,3 +647,18 @@ Film::copy_from_dvd ()
        JobManager::instance()->add (j);
 }
 
+int
+Film::encoded_frames () const
+{
+       if (format() == 0) {
+               return 0;
+       }
+
+       int N = 0;
+       for (filesystem::directory_iterator i = filesystem::directory_iterator (j2k_dir ()); i != filesystem::directory_iterator(); ++i) {
+               ++N;
+               this_thread::interruption_point ();
+       }
+
+       return N;
+}