diff options
| author | Carl Hetherington <cth@carlh.net> | 2017-05-09 16:38:36 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2017-05-09 16:38:36 +0100 |
| commit | 6a11232620e0006f6a2b1e8d2b56e56d84229d5c (patch) | |
| tree | 5ea8d25d95aac54dbf7e45fa72c50215ff5fc437 /src | |
| parent | 837a54744277a5252a1a69b0690305e9a669124d (diff) | |
Basic GUI for export.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/encoder.cc | 22 | ||||
| -rw-r--r-- | src/lib/encoder.h | 10 | ||||
| -rw-r--r-- | src/lib/event_history.cc | 56 | ||||
| -rw-r--r-- | src/lib/event_history.h | 41 | ||||
| -rw-r--r-- | src/lib/ffmpeg_transcoder.cc | 25 | ||||
| -rw-r--r-- | src/lib/ffmpeg_transcoder.h | 12 | ||||
| -rw-r--r-- | src/lib/wscript | 1 | ||||
| -rw-r--r-- | src/tools/dcpomatic.cc | 22 | ||||
| -rw-r--r-- | src/wx/config_dialog.cc | 2 | ||||
| -rw-r--r-- | src/wx/export_dialog.cc | 62 | ||||
| -rw-r--r-- | src/wx/export_dialog.h | 39 | ||||
| -rw-r--r-- | src/wx/file_picker_ctrl.cc | 12 | ||||
| -rw-r--r-- | src/wx/file_picker_ctrl.h | 4 | ||||
| -rw-r--r-- | src/wx/wscript | 1 |
14 files changed, 271 insertions, 38 deletions
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 276ef8d3a..e82c4af7e 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -54,14 +54,13 @@ using boost::weak_ptr; using boost::optional; using dcp::Data; -int const Encoder::_history_size = 200; - /** @param film Film that we are encoding. * @param writer Writer that we are using. */ Encoder::Encoder (shared_ptr<const Film> film, shared_ptr<Writer> writer) : _film (film) , _writer (writer) + , _history (200) { servers_list_changed (); } @@ -152,15 +151,7 @@ Encoder::end () float Encoder::current_encoding_rate () const { - boost::mutex::scoped_lock lock (_state_mutex); - if (int (_time_history.size()) < _history_size) { - return 0; - } - - struct timeval now; - gettimeofday (&now, 0); - - return _history_size / (seconds (now) - seconds (_time_history.back ())); + return _history.rate (); } /** @return Number of video frames that have been queued for encoding */ @@ -178,14 +169,7 @@ Encoder::video_frames_enqueued () const void Encoder::frame_done () { - boost::mutex::scoped_lock lock (_state_mutex); - - struct timeval tv; - gettimeofday (&tv, 0); - _time_history.push_front (tv); - if (int (_time_history.size()) > _history_size) { - _time_history.pop_back (); - } + _history.event (); } /** Called to request encoding of the next video frame in the DCP. This is called in order, diff --git a/src/lib/encoder.h b/src/lib/encoder.h index fe18f8b2d..7e9bd497a 100644 --- a/src/lib/encoder.h +++ b/src/lib/encoder.h @@ -27,6 +27,7 @@ #include "util.h" #include "cross.h" +#include "event_history.h" #include "exception_store.h" #include <boost/shared_ptr.hpp> #include <boost/thread/mutex.hpp> @@ -84,14 +85,7 @@ private: /** Film that we are encoding */ boost::shared_ptr<const Film> _film; - /** Mutex for _time_history */ - mutable boost::mutex _state_mutex; - /** List of the times of completion of the last _history_size frames; - first is the most recently completed. - */ - std::list<struct timeval> _time_history; - /** Number of frames that we should keep history for */ - static int const _history_size; + EventHistory _history; /** Mutex for _threads */ mutable boost::mutex _threads_mutex; diff --git a/src/lib/event_history.cc b/src/lib/event_history.cc new file mode 100644 index 000000000..eb3438aab --- /dev/null +++ b/src/lib/event_history.cc @@ -0,0 +1,56 @@ +/* + Copyright (C) 2017 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "event_history.h" +#include "util.h" +#include <boost/thread/mutex.hpp> + +EventHistory::EventHistory (int size) + : _size (size) +{ + +} + +float +EventHistory::rate () const +{ + boost::mutex::scoped_lock lock (_mutex); + if (int (_history.size()) < _size) { + return 0; + } + + struct timeval now; + gettimeofday (&now, 0); + + return _size / (seconds (now) - seconds (_history.back ())); +} + +void +EventHistory::event () +{ + boost::mutex::scoped_lock lock (_mutex); + + struct timeval tv; + gettimeofday (&tv, 0); + _history.push_front (tv); + if (int (_history.size()) > _size) { + _history.pop_back (); + } +} diff --git a/src/lib/event_history.h b/src/lib/event_history.h new file mode 100644 index 000000000..5b0f9a6a3 --- /dev/null +++ b/src/lib/event_history.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2017 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <boost/thread/mutex.hpp> +#include <list> + +class EventHistory +{ +public: + EventHistory (int size); + + float rate () const; + void event (); + +private: + /** Mutex for _history */ + mutable boost::mutex _mutex; + /** List of the times of the last _history_size events + first is the most recently completed. + */ + std::list<struct timeval> _history; + /** Number of events that we should keep history for */ + int const _size; +}; diff --git a/src/lib/ffmpeg_transcoder.cc b/src/lib/ffmpeg_transcoder.cc index 21a626462..3ebd0e817 100644 --- a/src/lib/ffmpeg_transcoder.cc +++ b/src/lib/ffmpeg_transcoder.cc @@ -26,11 +26,13 @@ #include "log.h" #include "image.h" #include "compose.hpp" +#include <iostream> #include "i18n.h" using std::string; using std::runtime_error; +using std::cout; using boost::shared_ptr; using boost::bind; using boost::weak_ptr; @@ -44,6 +46,7 @@ force_pixel_format (AVPixelFormat, AVPixelFormat out) FFmpegTranscoder::FFmpegTranscoder (shared_ptr<const Film> film, weak_ptr<Job> job) : Transcoder (film, job) , _pixel_format (AV_PIX_FMT_YUV422P10) + , _history (1000) { } @@ -73,7 +76,7 @@ FFmpegTranscoder::go () _codec_context->flags |= CODEC_FLAG_QSCALE | CODEC_FLAG_GLOBAL_HEADER; boost::filesystem::path filename = _film->file(_film->isdcf_name(true) + ".mov"); - avformat_alloc_output_context2 (&_format_context, 0, 0, filename.string().c_str()); + avformat_alloc_output_context2 (&_format_context, 0, 0, _output.string().c_str()); if (!_format_context) { throw runtime_error ("could not allocate FFmpeg format context"); } @@ -161,7 +164,11 @@ FFmpegTranscoder::video (shared_ptr<PlayerVideo> video, DCPTime time) frame->width = image->size().width; frame->height = image->size().height; frame->format = _pixel_format; - frame->pts = time.frames_round(_film->video_frame_rate()) / (_film->video_frame_rate() * av_q2d (_video_stream->time_base)); + { + boost::mutex::scoped_lock lm (_mutex); + _last_frame = time.frames_round(_film->video_frame_rate()); + frame->pts = _last_frame / (_film->video_frame_rate() * av_q2d (_video_stream->time_base)); + } AVPacket packet; av_init_packet (&packet); @@ -181,6 +188,13 @@ FFmpegTranscoder::video (shared_ptr<PlayerVideo> video, DCPTime time) } av_frame_free (&frame); + + _history.event (); + + shared_ptr<Job> job = _job.lock (); + if (job) { + job->set_progress (float(time.get()) / _film->length().get()); + } } void @@ -198,13 +212,12 @@ FFmpegTranscoder::subtitle (PlayerSubtitles subs, DCPTimePeriod period) float FFmpegTranscoder::current_encoding_rate () const { - /* XXX */ - return 1; + return _history.rate (); } int FFmpegTranscoder::video_frames_enqueued () const { - /* XXX */ - return 1; + boost::mutex::scoped_lock lm (_mutex); + return _last_frame; } diff --git a/src/lib/ffmpeg_transcoder.h b/src/lib/ffmpeg_transcoder.h index aa65b5933..02f0bb82e 100644 --- a/src/lib/ffmpeg_transcoder.h +++ b/src/lib/ffmpeg_transcoder.h @@ -19,6 +19,7 @@ */ #include "transcoder.h" +#include "event_history.h" extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> @@ -37,6 +38,10 @@ public: return false; } + void set_output (boost::filesystem::path o) { + _output = o; + } + private: void video (boost::shared_ptr<PlayerVideo>, DCPTime); void audio (boost::shared_ptr<AudioBuffers>, DCPTime); @@ -46,4 +51,11 @@ private: AVFormatContext* _format_context; AVStream* _video_stream; AVPixelFormat _pixel_format; + + mutable boost::mutex _mutex; + Frame _last_frame; + + EventHistory _history; + + boost::filesystem::path _output; }; diff --git a/src/lib/wscript b/src/lib/wscript index 6f57736b7..22f104a14 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -71,6 +71,7 @@ sources = """ encode_server_finder.cc encoded_log_entry.cc environment_info.cc + event_history.cc examine_content_job.cc exceptions.cc file_group.cc diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index 6543db551..ccaa44edb 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -41,6 +41,7 @@ #include "wx/save_template_dialog.h" #include "wx/templates_dialog.h" #include "wx/nag_dialog.h" +#include "wx/export_dialog.h" #include "lib/film.h" #include "lib/config.h" #include "lib/util.h" @@ -63,6 +64,8 @@ #include "lib/dcpomatic_socket.h" #include "lib/hints.h" #include "lib/dcp_content.h" +#include "lib/ffmpeg_transcoder.h" +#include "lib/transcode_job.h" #include <dcp/exceptions.h> #include <dcp/raw_convert.h> #include <wx/generic/aboutdlgg.h> @@ -192,6 +195,7 @@ enum { ID_jobs_make_dcp_batch, ID_jobs_make_kdms, ID_jobs_make_self_dkdm, + ID_jobs_export, ID_jobs_send_dcp_to_tms, ID_jobs_show_dcp, ID_tools_video_waveform, @@ -269,6 +273,7 @@ public: Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_kdms, this), ID_jobs_make_kdms); Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_dcp_batch, this), ID_jobs_make_dcp_batch); Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_self_dkdm, this), ID_jobs_make_self_dkdm); + Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_export, this), ID_jobs_export); Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_send_dcp_to_tms, this), ID_jobs_send_dcp_to_tms); Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_show_dcp, this), ID_jobs_show_dcp); Bind (wxEVT_MENU, boost::bind (&DOMFrame::tools_video_waveform, this), ID_tools_video_waveform); @@ -697,6 +702,19 @@ private: d->Destroy (); } + void jobs_export () + { + ExportDialog* d = new ExportDialog (this); + if (d->ShowModal() == wxID_OK) { + shared_ptr<TranscodeJob> job (new TranscodeJob (_film)); + shared_ptr<FFmpegTranscoder> tx (new FFmpegTranscoder (_film, job)); + tx->set_output (d->path ()); + job->set_transcoder (tx); + JobManager::instance()->add (job); + } + d->Destroy (); + } + void content_scale_to_fit_width () { ContentList vc = _film_editor->content_panel()->selected_video (); @@ -981,8 +999,12 @@ private: wxMenu* jobs_menu = new wxMenu; add_item (jobs_menu, _("&Make DCP\tCtrl-M"), ID_jobs_make_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION); add_item (jobs_menu, _("Make DCP in &batch converter\tCtrl-B"), ID_jobs_make_dcp_batch, NEEDS_FILM | NOT_DURING_DCP_CREATION); + jobs_menu->AppendSeparator (); add_item (jobs_menu, _("Make &KDMs...\tCtrl-K"), ID_jobs_make_kdms, NEEDS_FILM); add_item (jobs_menu, _("Make DKDM for DCP-o-matic..."), ID_jobs_make_self_dkdm, NEEDS_FILM); + jobs_menu->AppendSeparator (); + add_item (jobs_menu, _("Export..."), ID_jobs_export, NEEDS_FILM); + jobs_menu->AppendSeparator (); add_item (jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL); add_item (jobs_menu, _("S&how DCP"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION | NEEDS_CPL); diff --git a/src/wx/config_dialog.cc b/src/wx/config_dialog.cc index 49a8a6849..63ce57823 100644 --- a/src/wx/config_dialog.cc +++ b/src/wx/config_dialog.cc @@ -205,7 +205,7 @@ private: ++r; add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0)); - _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml"); + _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true); table->Add (_cinemas_file, wxGBPosition (r, 1)); ++r; diff --git a/src/wx/export_dialog.cc b/src/wx/export_dialog.cc new file mode 100644 index 000000000..e21a49e8a --- /dev/null +++ b/src/wx/export_dialog.cc @@ -0,0 +1,62 @@ +/* + Copyright (C) 2017 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "export_dialog.h" +#include "file_picker_ctrl.h" +#include "wx_util.h" +#include <boost/bind.hpp> + +using boost::bind; + +ExportDialog::ExportDialog (wxWindow* parent) + : TableDialog (parent, _("Export film"), 2, 1, true) +{ + add (_("Format"), true); + _format = new wxChoice (this, wxID_ANY); + add (_format); + add (_("Output file"), true); + _file = new FilePickerCtrl (this, _("Select output file"), _("MOV files (*.mov)|*.mov"), false); + add (_file); + + _format->Append (_("ProRes 422")); + _format->SetSelection (0); + + _format->Bind (wxEVT_CHOICE, bind (&ExportDialog::format_changed, this)); + + layout (); +} + +void +ExportDialog::format_changed () +{ + switch (_format->GetSelection()) { + case 0: + _file->SetWildcard (_("MOV files (*.mov)")); + break; + } + + _file->SetPath (""); +} + +boost::filesystem::path +ExportDialog::path () const +{ + return wx_to_std (_file->GetPath ()); +} diff --git a/src/wx/export_dialog.h b/src/wx/export_dialog.h new file mode 100644 index 000000000..8f0be7194 --- /dev/null +++ b/src/wx/export_dialog.h @@ -0,0 +1,39 @@ +/* + Copyright (C) 2017 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "table_dialog.h" +#include <wx/wx.h> +#include <boost/filesystem.hpp> + +class FilePickerCtrl; + +class ExportDialog : public TableDialog +{ +public: + ExportDialog (wxWindow* parent); + + boost::filesystem::path path () const; + +private: + void format_changed (); + + wxChoice* _format; + FilePickerCtrl* _file; +}; diff --git a/src/wx/file_picker_ctrl.cc b/src/wx/file_picker_ctrl.cc index 03b2880fe..4cd843feb 100644 --- a/src/wx/file_picker_ctrl.cc +++ b/src/wx/file_picker_ctrl.cc @@ -28,10 +28,11 @@ using namespace std; using namespace boost; -FilePickerCtrl::FilePickerCtrl (wxWindow* parent, wxString prompt, wxString wildcard) +FilePickerCtrl::FilePickerCtrl (wxWindow* parent, wxString prompt, wxString wildcard, bool open) : wxPanel (parent) , _prompt (prompt) , _wildcard (wildcard) + , _open (open) { _sizer = new wxBoxSizer (wxHORIZONTAL); @@ -43,7 +44,6 @@ FilePickerCtrl::FilePickerCtrl (wxWindow* parent, wxString prompt, wxString wild _sizer->Add (_file, 1, wxEXPAND, 0); SetSizerAndFit (_sizer); - _file->Bind (wxEVT_BUTTON, boost::bind (&FilePickerCtrl::browse_clicked, this)); } @@ -71,10 +71,16 @@ FilePickerCtrl::GetPath () const void FilePickerCtrl::browse_clicked () { - wxFileDialog* d = new wxFileDialog (this, _prompt, wxEmptyString, wxEmptyString, _wildcard); + wxFileDialog* d = new wxFileDialog (this, _prompt, wxEmptyString, wxEmptyString, _wildcard, _open ? wxFD_OPEN : wxFD_SAVE | wxFD_OVERWRITE_PROMPT); d->SetPath (_path); if (d->ShowModal () == wxID_OK) { SetPath (d->GetPath ()); } d->Destroy (); } + +void +FilePickerCtrl::SetWildcard (wxString w) +{ + _wildcard = w; +} diff --git a/src/wx/file_picker_ctrl.h b/src/wx/file_picker_ctrl.h index 61e7bd55f..d0c4d56c8 100644 --- a/src/wx/file_picker_ctrl.h +++ b/src/wx/file_picker_ctrl.h @@ -23,10 +23,11 @@ class FilePickerCtrl : public wxPanel { public: - FilePickerCtrl (wxWindow* parent, wxString prompt, wxString wildcard); + FilePickerCtrl (wxWindow* parent, wxString prompt, wxString wildcard, bool open); wxString GetPath () const; void SetPath (wxString); + void SetWildcard (wxString); private: void browse_clicked (); @@ -36,4 +37,5 @@ private: wxSizer* _sizer; wxString _prompt; wxString _wildcard; + bool _open; }; diff --git a/src/wx/wscript b/src/wx/wscript index 8297f37c9..abe657341 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -49,6 +49,7 @@ sources = """ dolby_doremi_certificate_panel.cc download_certificate_dialog.cc download_certificate_panel.cc + export_dialog.cc file_picker_ctrl.cc film_editor.cc film_name_location_dialog.cc |
