Hand-apply bd7102b476c631b1fa9067f18ce938d86073f6c8; single-file hashes.
authorCarl Hetherington <cth@carlh.net>
Tue, 21 Apr 2015 00:00:36 +0000 (01:00 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 21 Apr 2015 00:00:36 +0000 (01:00 +0100)
12 files changed:
ChangeLog
TO_PORT
src/lib/encoded_data.cc
src/lib/film.cc
src/lib/film.h
src/lib/util.cc
src/lib/util.h
src/lib/writer.cc
src/wx/properties_dialog.cc
src/wx/properties_dialog.h
src/wx/wx_util.cc
src/wx/wx_util.h

index d7e922935741719918e52dfe059d4f39f88077b1..05a1738a0389031152b2e01dc3bb3d7da1782a91 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2015-04-20  Carl Hetherington  <cth@carlh.net>
 
 2015-04-20  Carl Hetherington  <cth@carlh.net>
 
+       * Hand-apply 47770097cf6a5d7dbbdded8977da5f3de53dfd33;
+       single-file hashes.
+
        * Hand-apply e1d0d24146592e311d46781a1961fe080f6357cf;
        attempt to fix confusion with the JPEG2000 bandwidth
        control when a user enters a value directly rather than
        * Hand-apply e1d0d24146592e311d46781a1961fe080f6357cf;
        attempt to fix confusion with the JPEG2000 bandwidth
        control when a user enters a value directly rather than
diff --git a/TO_PORT b/TO_PORT
index 826494214c5fa5ca3a0b124407932a0c8e642d17..bb325e1d4a3f6a0fb527b90a6870b34eaee6a4f5 100644 (file)
--- a/TO_PORT
+++ b/TO_PORT
@@ -1,3 +1,3 @@
 Colour conversion fixes between 1.78.1 and 1.78.2
 b6df85a81f9dadb6ce778aaf3290cd39221b6170
 Colour conversion fixes between 1.78.1 and 1.78.2
 b6df85a81f9dadb6ce778aaf3290cd39221b6170
-47770097cf6a5d7dbbdded8977da5f3de53dfd33
+
index 0e8ffd6b5cc088c17fc323c6a807c338263dcc57..4f8aaab4b5b6f62199884eb76855140cc34e0441 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-    Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -91,15 +91,14 @@ EncodedData::write (shared_ptr<const Film> film, int frame, Eyes eyes) const
 }
 
 void
 }
 
 void
-EncodedData::write_info (shared_ptr<const Film> film, int frame, Eyes eyes, dcp::FrameInfo fin) const
+EncodedData::write_info (shared_ptr<const Film> film, int frame, Eyes eyes, dcp::FrameInfo info) const
 {
 {
-       boost::filesystem::path const info = film->info_path (frame, eyes);
-       FILE* h = fopen_boost (info, "w");
-       if (!h) {
-               throw OpenFileError (info);
+       FILE* file = fopen_boost (film->info_file(), "ab");
+       if (!file) {
+               throw OpenFileError (film->info_file ());
        }
        }
-       fin.write (h);
-       fclose (h);
+       write_frame_info (file, frame, eyes, info);
+       fclose (file);
 }
 
 /** Send this data to a socket.
 }
 
 /** Send this data to a socket.
index a7be8aea7857265fb0b6b7aff82c9d8726075569..7dbeaafe9a58bf1b6cde5d0dfb5f46469863efc3 100644 (file)
@@ -207,14 +207,14 @@ Film::video_identifier () const
        return s.str ();
 }
          
        return s.str ();
 }
          
-/** @return The path to the directory to write video frame info files to */
+/** @return The file to write video frame info to */
 boost::filesystem::path
 boost::filesystem::path
-Film::info_dir () const
+Film::info_file () const
 {
        boost::filesystem::path p;
        p /= "info";
        p /= video_identifier ();
 {
        boost::filesystem::path p;
        p /= "info";
        p /= video_identifier ();
-       return dir (p);
+       return file (p);
 }
 
 boost::filesystem::path
 }
 
 boost::filesystem::path
@@ -316,25 +316,6 @@ Film::send_dcp_to_tms ()
        JobManager::instance()->add (j);
 }
 
        JobManager::instance()->add (j);
 }
 
-/** Count the number of frames that have been encoded for this film.
- *  @return frame count.
- */
-int
-Film::encoded_frames () const
-{
-       if (container() == 0) {
-               return 0;
-       }
-
-       int N = 0;
-       for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator (info_dir ()); i != boost::filesystem::directory_iterator(); ++i) {
-               ++N;
-               boost::this_thread::interruption_point ();
-       }
-
-       return N;
-}
-
 shared_ptr<xmlpp::Document>
 Film::metadata () const
 {
 shared_ptr<xmlpp::Document>
 Film::metadata () const
 {
@@ -820,32 +801,6 @@ Film::set_isdcf_date_today ()
        _isdcf_date = boost::gregorian::day_clock::local_day ();
 }
 
        _isdcf_date = boost::gregorian::day_clock::local_day ();
 }
 
-boost::filesystem::path
-Film::info_path (int f, Eyes e) const
-{
-       boost::filesystem::path p;
-       p /= info_dir ();
-
-       SafeStringStream s;
-       s.width (8);
-       s << setfill('0') << f;
-
-       if (e == EYES_LEFT) {
-               s << ".L";
-       } else if (e == EYES_RIGHT) {
-               s << ".R";
-       }
-
-       s << ".md5";
-       
-       p /= s.str();
-
-       /* info_dir() will already have added any initial bit of the path,
-          so don't call file() on this.
-       */
-       return p;
-}
-
 boost::filesystem::path
 Film::j2c_path (int f, Eyes e, bool t) const
 {
 boost::filesystem::path
 Film::j2c_path (int f, Eyes e, bool t) const
 {
index 3d1c02c93a7db30b95ecd3140a7919b46aabffa6..cca31d3061ce3e116581fc7612e129beb4788648 100644 (file)
@@ -61,9 +61,8 @@ public:
        Film (boost::filesystem::path, bool log = true);
        ~Film ();
 
        Film (boost::filesystem::path, bool log = true);
        ~Film ();
 
-       boost::filesystem::path info_dir () const;
+       boost::filesystem::path info_file () const;
        boost::filesystem::path j2c_path (int, Eyes, bool) const;
        boost::filesystem::path j2c_path (int, Eyes, bool) const;
-       boost::filesystem::path info_path (int, Eyes) const;
        boost::filesystem::path internal_video_mxf_dir () const;
        boost::filesystem::path internal_video_mxf_filename () const;
        boost::filesystem::path audio_analysis_dir () const;
        boost::filesystem::path internal_video_mxf_dir () const;
        boost::filesystem::path internal_video_mxf_filename () const;
        boost::filesystem::path audio_analysis_dir () const;
@@ -82,8 +81,6 @@ public:
                return _log;
        }
 
                return _log;
        }
 
-       int encoded_frames () const;
-       
        boost::filesystem::path file (boost::filesystem::path f) const;
        boost::filesystem::path dir (boost::filesystem::path d) const;
 
        boost::filesystem::path file (boost::filesystem::path f) const;
        boost::filesystem::path dir (boost::filesystem::path d) const;
 
index ab991e76b19e58b28bd06373a2ae61673f73e8fa..1c99682063ff76d19279d0f8c73e0a6c5d7aa7cc 100644 (file)
@@ -423,7 +423,7 @@ md5_digest_head_tail (vector<boost::filesystem::path> files, boost::uintmax_t si
                }
 
                boost::uintmax_t this_time = min (to_do, boost::filesystem::file_size (files[i]));
                }
 
                boost::uintmax_t this_time = min (to_do, boost::filesystem::file_size (files[i]));
-               fseek (f, -this_time, SEEK_END);
+               dcpomatic_fseek (f, -this_time, SEEK_END);
                fread (p, 1, this_time, f);
                p += this_time;
                to_do -= this_time;
                fread (p, 1, this_time, f);
                p += this_time;
                to_do -= this_time;
@@ -619,3 +619,47 @@ split_get_request (string url)
 
        return r;
 }
 
        return r;
 }
+
+long
+frame_info_position (int frame, Eyes eyes)
+{
+       static int const info_size = 48;
+       
+       switch (eyes) {
+       case EYES_BOTH:
+               return frame * info_size;
+       case EYES_LEFT:
+               return frame * info_size * 2;
+       case EYES_RIGHT:
+               return frame * info_size * 2 + info_size;
+       default:
+               DCPOMATIC_ASSERT (false);
+       }
+
+       DCPOMATIC_ASSERT (false);
+}
+
+dcp::FrameInfo
+read_frame_info (FILE* file, int frame, Eyes eyes)
+{
+       dcp::FrameInfo info;
+       dcpomatic_fseek (file, frame_info_position (frame, eyes), SEEK_SET);
+       fread (&info.offset, sizeof (info.offset), 1, file);
+       fread (&info.size, sizeof (info.size), 1, file);
+       
+       char hash_buffer[33];
+       fread (hash_buffer, 1, 32, file);
+       hash_buffer[32] = '\0';
+       info.hash = hash_buffer;
+
+       return info;
+}
+
+void
+write_frame_info (FILE* file, int frame, Eyes eyes, dcp::FrameInfo info)
+{
+       dcpomatic_fseek (file, frame_info_position (frame, eyes), SEEK_SET);
+       fwrite (&info.offset, sizeof (info.offset), 1, file);
+       fwrite (&info.size, sizeof (info.size), 1, file);
+       fwrite (info.hash.c_str(), 1, info.hash.size(), file);
+}
index 97e119389d9462c23181be1ddee453dd92a1e5eb..bf1d0265b0dec3b90da1c0ba57414ed1868f6312 100644 (file)
@@ -29,6 +29,7 @@
 #include "exceptions.h"
 #include "dcpomatic_time.h"
 #include <dcp/util.h>
 #include "exceptions.h"
 #include "dcpomatic_time.h"
 #include <dcp/util.h>
+#include <dcp/picture_mxf_writer.h>
 extern "C" {
 #include <libavcodec/avcodec.h>
 #include <libavfilter/avfilter.h>
 extern "C" {
 #include <libavcodec/avcodec.h>
 #include <libavfilter/avfilter.h>
@@ -75,6 +76,8 @@ extern int round_to (float n, int r);
 extern void* wrapped_av_malloc (size_t);
 extern ContentTimePeriod subtitle_period (AVSubtitle const &);
 extern void set_backtrace_file (boost::filesystem::path);
 extern void* wrapped_av_malloc (size_t);
 extern ContentTimePeriod subtitle_period (AVSubtitle const &);
 extern void set_backtrace_file (boost::filesystem::path);
+extern dcp::FrameInfo read_frame_info (FILE* file, int frame, Eyes eyes);
+extern void write_frame_info (FILE* file, int frame, Eyes eyes, dcp::FrameInfo info);
 extern int64_t video_frames_to_audio_frames (VideoFrame v, float audio_sample_rate, float frames_per_second);
 extern std::map<std::string, std::string> split_get_request (std::string url);
 
 extern int64_t video_frames_to_audio_frames (VideoFrame v, float audio_sample_rate, float frames_per_second);
 extern std::map<std::string, std::string> split_get_request (std::string url);
 
index 909b1e4484d1c19b1cbc56b751131a098215534a..e8a4ac10b4f2192b43140b662aee72ad95d21e7e 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-    Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -189,12 +189,12 @@ Writer::fake_write (int frame, Eyes eyes)
                _full_condition.wait (lock);
        }
        
                _full_condition.wait (lock);
        }
        
-       FILE* ifi = fopen_boost (_film->info_path (frame, eyes), "r");
-       if (!ifi) {
-               throw ReadFileError (_film->info_path (frame, eyes));
+       FILE* file = fopen_boost (_film->info_file (), "rb");
+       if (!file) {
+               throw ReadFileError (_film->info_file ());
        }
        }
-       dcp::FrameInfo info (ifi);
-       fclose (ifi);
+       dcp::FrameInfo info = read_frame_info (file, frame, eyes);
+       fclose (file);
        
        QueueItem qi;
        qi.type = QueueItem::FAKE;
        
        QueueItem qi;
        qi.type = QueueItem::FAKE;
@@ -558,14 +558,14 @@ bool
 Writer::check_existing_picture_mxf_frame (FILE* mxf, int f, Eyes eyes)
 {
        /* Read the frame info as written */
 Writer::check_existing_picture_mxf_frame (FILE* mxf, int f, Eyes eyes)
 {
        /* Read the frame info as written */
-       FILE* ifi = fopen_boost (_film->info_path (f, eyes), "r");
-       if (!ifi) {
+       FILE* file = fopen_boost (_film->info_file (), "rb");
+       if (!file) {
                LOG_GENERAL ("Existing frame %1 has no info file", f);
                return false;
        }
        
                LOG_GENERAL ("Existing frame %1 has no info file", f);
                return false;
        }
        
-       dcp::FrameInfo info (ifi);
-       fclose (ifi);
+       dcp::FrameInfo info = read_frame_info (file, f, eyes);
+       fclose (file);
        if (info.size == 0) {
                LOG_GENERAL ("Existing frame %1 has no info file", f);
                return false;
        if (info.size == 0) {
                LOG_GENERAL ("Existing frame %1 has no info file", f);
                return false;
@@ -603,19 +603,12 @@ Writer::check_existing_picture_mxf ()
                return;
        }
 
                return;
        }
 
-       int N = 0;
-       for (boost::filesystem::directory_iterator i (_film->info_dir ()); i != boost::filesystem::directory_iterator (); ++i) {
-               ++N;
-       }
-
        while (true) {
 
                shared_ptr<Job> job = _job.lock ();
                DCPOMATIC_ASSERT (job);
 
        while (true) {
 
                shared_ptr<Job> job = _job.lock ();
                DCPOMATIC_ASSERT (job);
 
-               if (N > 0) {
-                       job->set_progress (float (_first_nonexistant_frame) / N);
-               }
+               job->set_progress_unknown ();
 
                if (_film->three_d ()) {
                        if (!check_existing_picture_mxf_frame (mxf, _first_nonexistant_frame, EYES_LEFT)) {
 
                if (_film->three_d ()) {
                        if (!check_existing_picture_mxf_frame (mxf, _first_nonexistant_frame, EYES_LEFT)) {
index d1627edad33e7b1b3b3e6336bd3bf9942a325a7f..f80d5d6939f75f9c4c21ed269f8fafea7ee3bd97 100644 (file)
@@ -42,9 +42,6 @@ PropertiesDialog::PropertiesDialog (wxWindow* parent, shared_ptr<Film> film)
        add (_("Disk space required"), true);
        _disk = add (new wxStaticText (this, wxID_ANY, wxT ("")));
 
        add (_("Disk space required"), true);
        _disk = add (new wxStaticText (this, wxID_ANY, wxT ("")));
 
-       add (_("Frames already encoded"), true);
-       _encoded = add (new ThreadedStaticText (this, _("counting..."), boost::bind (&PropertiesDialog::frames_already_encoded, this)));
-       _encoded_connection = _encoded->Finished.connect (boost::bind (&PropertiesDialog::layout, this));
        _frames->SetLabel (std_to_wx (lexical_cast<string> (_film->length().frames (_film->video_frame_rate ()))));
        double const disk = double (_film->required_disk_space()) / 1073741824.0f;
        SafeStringStream s;
        _frames->SetLabel (std_to_wx (lexical_cast<string> (_film->length().frames (_film->video_frame_rate ()))));
        double const disk = double (_film->required_disk_space()) / 1073741824.0f;
        SafeStringStream s;
@@ -53,21 +50,3 @@ PropertiesDialog::PropertiesDialog (wxWindow* parent, shared_ptr<Film> film)
 
        layout ();
 }
 
        layout ();
 }
-
-string
-PropertiesDialog::frames_already_encoded () const
-{
-       SafeStringStream u;
-       try {
-               u << _film->encoded_frames ();
-       } catch (boost::thread_interrupted &) {
-               return "";
-       }
-
-       uint64_t const frames = _film->length().frames (_film->video_frame_rate ());
-       if (frames) {
-               /* XXX: encoded_frames() should check which frames have been encoded */
-               u << " (" << (_film->encoded_frames() * 100 / frames) << "%)";
-       }
-       return u.str ();
-}
index fe814f7abf341341a7ff3480f36a9f5085b730c4..d489754efae4c2247d2ed8e2860594b5266a8fbe 100644 (file)
@@ -21,7 +21,6 @@
 #include "table_dialog.h"
 
 class Film;
 #include "table_dialog.h"
 
 class Film;
-class ThreadedStaticText;
 
 class PropertiesDialog : public TableDialog
 {
 
 class PropertiesDialog : public TableDialog
 {
@@ -29,12 +28,9 @@ public:
        PropertiesDialog (wxWindow *, boost::shared_ptr<Film>);
 
 private:
        PropertiesDialog (wxWindow *, boost::shared_ptr<Film>);
 
 private:
-       std::string frames_already_encoded () const;
-
        boost::shared_ptr<Film> _film;
        wxStaticText* _frames;
        wxStaticText* _disk;
        boost::shared_ptr<Film> _film;
        wxStaticText* _frames;
        wxStaticText* _disk;
-       ThreadedStaticText* _encoded;
 
        boost::signals2::scoped_connection _encoded_connection;
 };
 
        boost::signals2::scoped_connection _encoded_connection;
 };
index c4a7fd5bca9f071b5da875d7a476d0c7d8ce2962..0119799d26aaa3d0c8ff17dde466169877d6fd78 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-    Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -117,50 +117,6 @@ std_to_wx (string s)
        return wxString (s.c_str(), wxConvUTF8);
 }
 
        return wxString (s.c_str(), wxConvUTF8);
 }
 
-int const ThreadedStaticText::_update_event_id = 10000;
-
-/** @param parent Parent for the wxStaticText.
- *  @param initial Initial text for the wxStaticText while the computation is being run.
- *  @param fn Function which works out what the wxStaticText content should be and returns it.
- */
-ThreadedStaticText::ThreadedStaticText (wxWindow* parent, wxString initial, boost::function<string ()> fn)
-       : wxStaticText (parent, wxID_ANY, initial)
-{
-       Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&ThreadedStaticText::thread_finished, this, _1), _update_event_id);
-       _thread = new thread (bind (&ThreadedStaticText::run, this, fn));
-}
-
-ThreadedStaticText::~ThreadedStaticText ()
-{
-       _thread->interrupt ();
-       _thread->join ();
-       delete _thread;
-}
-
-/** Run our thread and post the result to the GUI thread via AddPendingEvent */
-void
-ThreadedStaticText::run (boost::function<string ()> fn)
-try
-{
-       wxCommandEvent ev (wxEVT_COMMAND_TEXT_UPDATED, _update_event_id);
-       ev.SetString (std_to_wx (fn ()));
-       GetEventHandler()->AddPendingEvent (ev);
-}
-catch (...)
-{
-       /* Ignore exceptions; marginally better than the program quitting, but
-          only marginally.
-       */
-}
-
-/** Called in the GUI thread when our worker thread has finished */
-void
-ThreadedStaticText::thread_finished (wxCommandEvent& ev)
-{
-       SetLabel (ev.GetString ());
-       Finished ();
-}
-
 string
 string_client_data (wxClientData* o)
 {
 string
 string_client_data (wxClientData* o)
 {
index f0e20be9598b015cb13fb8700220d0dfc3308d18..eeb3fee4321a76c6e5e18029b93651bffc70f6cc 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -64,31 +64,6 @@ extern std::string wx_to_std (wxString);
 extern wxString std_to_wx (std::string);
 extern void dcpomatic_setup_i18n ();
 extern wxString context_translation (wxString);
 extern wxString std_to_wx (std::string);
 extern void dcpomatic_setup_i18n ();
 extern wxString context_translation (wxString);
-
-/** @class ThreadedStaticText
- *
- *  @brief A wxStaticText whose content is computed in a separate thread, to avoid holding
- *  up the GUI while work is done.
- */
-class ThreadedStaticText : public wxStaticText
-{
-public:
-       ThreadedStaticText (wxWindow* parent, wxString initial, boost::function<std::string ()> fn);
-       ~ThreadedStaticText ();
-
-       /** Emitted in the UI thread when the text has been set up */
-       boost::signals2::signal<void()> Finished;
-
-private:
-       void run (boost::function<std::string ()> fn);
-       void thread_finished (wxCommandEvent& ev);
-
-       /** Thread to do our work in */
-       boost::thread* _thread;
-       
-       static const int _update_event_id;
-};
-
 extern std::string string_client_data (wxClientData* o);
 
 extern void checked_set (wxFilePickerCtrl* widget, std::string value);
 extern std::string string_client_data (wxClientData* o);
 
 extern void checked_set (wxFilePickerCtrl* widget, std::string value);