From: Carl Hetherington Date: Tue, 21 Apr 2015 00:00:36 +0000 (+0100) Subject: Hand-apply bd7102b476c631b1fa9067f18ce938d86073f6c8; single-file hashes. X-Git-Tag: v2.0.48~148 X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=ff96cc9c9e33fbe9dea02ea2d397144f9c9ac8c9 Hand-apply bd7102b476c631b1fa9067f18ce938d86073f6c8; single-file hashes. --- diff --git a/ChangeLog b/ChangeLog index d7e922935..05a1738a0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2015-04-20 Carl Hetherington + * 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 diff --git a/TO_PORT b/TO_PORT index 826494214..bb325e1d4 100644 --- a/TO_PORT +++ b/TO_PORT @@ -1,3 +1,3 @@ Colour conversion fixes between 1.78.1 and 1.78.2 b6df85a81f9dadb6ce778aaf3290cd39221b6170 -47770097cf6a5d7dbbdded8977da5f3de53dfd33 + diff --git a/src/lib/encoded_data.cc b/src/lib/encoded_data.cc index 0e8ffd6b5..4f8aaab4b 100644 --- a/src/lib/encoded_data.cc +++ b/src/lib/encoded_data.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington + Copyright (C) 2012-2015 Carl Hetherington 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 film, int frame, Eyes eyes) const } void -EncodedData::write_info (shared_ptr film, int frame, Eyes eyes, dcp::FrameInfo fin) const +EncodedData::write_info (shared_ptr 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. diff --git a/src/lib/film.cc b/src/lib/film.cc index a7be8aea7..7dbeaafe9 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -207,14 +207,14 @@ Film::video_identifier () const 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 -Film::info_dir () const +Film::info_file () const { boost::filesystem::path p; p /= "info"; p /= video_identifier (); - return dir (p); + return file (p); } boost::filesystem::path @@ -316,25 +316,6 @@ Film::send_dcp_to_tms () 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 Film::metadata () const { @@ -820,32 +801,6 @@ Film::set_isdcf_date_today () _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 { diff --git a/src/lib/film.h b/src/lib/film.h index 3d1c02c93..cca31d306 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -61,9 +61,8 @@ public: 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 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; @@ -82,8 +81,6 @@ public: return _log; } - int encoded_frames () const; - boost::filesystem::path file (boost::filesystem::path f) const; boost::filesystem::path dir (boost::filesystem::path d) const; diff --git a/src/lib/util.cc b/src/lib/util.cc index ab991e76b..1c9968206 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -423,7 +423,7 @@ md5_digest_head_tail (vector files, boost::uintmax_t si } 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; @@ -619,3 +619,47 @@ split_get_request (string url) 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); +} diff --git a/src/lib/util.h b/src/lib/util.h index 97e119389..bf1d0265b 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -29,6 +29,7 @@ #include "exceptions.h" #include "dcpomatic_time.h" #include +#include extern "C" { #include #include @@ -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 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 split_get_request (std::string url); diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 909b1e448..e8a4ac10b 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington + Copyright (C) 2012-2015 Carl Hetherington 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); } - 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; @@ -558,14 +558,14 @@ bool 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; } - 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; @@ -603,19 +603,12 @@ Writer::check_existing_picture_mxf () 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.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)) { diff --git a/src/wx/properties_dialog.cc b/src/wx/properties_dialog.cc index d1627edad..f80d5d693 100644 --- a/src/wx/properties_dialog.cc +++ b/src/wx/properties_dialog.cc @@ -42,9 +42,6 @@ PropertiesDialog::PropertiesDialog (wxWindow* parent, shared_ptr film) 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 (_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) 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 (); -} diff --git a/src/wx/properties_dialog.h b/src/wx/properties_dialog.h index fe814f7ab..d489754ef 100644 --- a/src/wx/properties_dialog.h +++ b/src/wx/properties_dialog.h @@ -21,7 +21,6 @@ #include "table_dialog.h" class Film; -class ThreadedStaticText; class PropertiesDialog : public TableDialog { @@ -29,12 +28,9 @@ public: PropertiesDialog (wxWindow *, boost::shared_ptr); private: - std::string frames_already_encoded () const; - boost::shared_ptr _film; wxStaticText* _frames; wxStaticText* _disk; - ThreadedStaticText* _encoded; boost::signals2::scoped_connection _encoded_connection; }; diff --git a/src/wx/wx_util.cc b/src/wx/wx_util.cc index c4a7fd5bc..0119799d2 100644 --- a/src/wx/wx_util.cc +++ b/src/wx/wx_util.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington + Copyright (C) 2012-2015 Carl Hetherington 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); } -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 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 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) { diff --git a/src/wx/wx_util.h b/src/wx/wx_util.h index f0e20be95..eeb3fee43 100644 --- a/src/wx/wx_util.h +++ b/src/wx/wx_util.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington + Copyright (C) 2012-2015 Carl Hetherington 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); - -/** @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 fn); - ~ThreadedStaticText (); - - /** Emitted in the UI thread when the text has been set up */ - boost::signals2::signal Finished; - -private: - void run (boost::function 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);