From 61153e191b98a68e0ca6466ed260a632a584b619 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 12 Jan 2013 21:09:23 +0000 Subject: [PATCH] Untested support for splitting into multiple reels. Use J2K bandwidth and colour LUT in the J2K path. --- ChangeLog | 5 +++ src/lib/film.cc | 30 +++++++++++++- src/lib/film.h | 10 +++++ src/lib/make_dcp_job.cc | 88 ++++++++++++++++++++++++++++------------- src/lib/make_dcp_job.h | 2 +- src/wx/film_editor.cc | 60 ++++++++++++++++++++++++++++ src/wx/film_editor.h | 5 +++ wscript | 2 +- 8 files changed, 171 insertions(+), 31 deletions(-) diff --git a/ChangeLog b/ChangeLog index f2563ef10..b2d8be18e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2013-01-12 Carl Hetherington + + * Untested support for splitting DCPs + into multiple reels. + 2013-01-09 Carl Hetherington * Try to build with 0.10.4-ish ffmpeg. diff --git a/src/lib/film.cc b/src/lib/film.cc index 4e48a0e73..3985baf04 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -157,6 +157,7 @@ Film::Film (Film const & o) , _scaler (o._scaler) , _dcp_trim_start (o._dcp_trim_start) , _dcp_trim_end (o._dcp_trim_end) + , _reel_size (o._reel_size) , _dcp_ab (o._dcp_ab) , _content_audio_stream (o._content_audio_stream) , _external_audio (o._external_audio) @@ -216,7 +217,9 @@ Film::j2k_dir () const << "_" << content_digest() << "_" << crop().left << "_" << crop().right << "_" << crop().top << "_" << crop().bottom << "_" << f.first << "_" << f.second - << "_" << scaler()->id(); + << "_" << scaler()->id() + << "_" << j2k_bandwidth() + << "_" << boost::lexical_cast (colour_lut()); p /= s.str (); @@ -410,6 +413,9 @@ Film::write_metadata () const f << "scaler " << _scaler->id () << "\n"; f << "dcp_trim_start " << _dcp_trim_start << "\n"; f << "dcp_trim_end " << _dcp_trim_end << "\n"; + if (_reel_size) { + f << "reel_size " << _reel_size.get() << "\n"; + } f << "dcp_ab " << (_dcp_ab ? "1" : "0") << "\n"; if (_content_audio_stream) { f << "selected_content_audio_stream " << _content_audio_stream->to_string() << "\n"; @@ -524,6 +530,8 @@ Film::read_metadata () _dcp_trim_start = atoi (v.c_str ()); } else if (k == "dcp_trim_end") { _dcp_trim_end = atoi (v.c_str ()); + } else if (k == "reel_size") { + _reel_size = boost::lexical_cast (v); } else if (k == "dcp_ab") { _dcp_ab = (v == "1"); } else if (k == "selected_content_audio_stream" || (!version && k == "selected_audio_stream")) { @@ -1085,6 +1093,26 @@ Film::set_dcp_trim_end (int t) signal_changed (DCP_TRIM_END); } +void +Film::set_reel_size (uint64_t s) +{ + { + boost::mutex::scoped_lock lm (_state_mutex); + _reel_size = s; + } + signal_changed (REEL_SIZE); +} + +void +Film::unset_reel_size () +{ + { + boost::mutex::scoped_lock lm (_state_mutex); + _reel_size = boost::optional (); + } + signal_changed (REEL_SIZE); +} + void Film::set_dcp_ab (bool a) { diff --git a/src/lib/film.h b/src/lib/film.h index 467573ae1..02d9cf7d0 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -113,6 +113,7 @@ public: SCALER, DCP_TRIM_START, DCP_TRIM_END, + REEL_SIZE, DCP_AB, CONTENT_AUDIO_STREAM, EXTERNAL_AUDIO, @@ -196,6 +197,11 @@ public: boost::mutex::scoped_lock lm (_state_mutex); return _dcp_trim_end; } + + boost::optional reel_size () const { + boost::mutex::scoped_lock lm (_state_mutex); + return _reel_size; + } bool dcp_ab () const { boost::mutex::scoped_lock lm (_state_mutex); @@ -357,6 +363,8 @@ public: void set_scaler (Scaler const *); void set_dcp_trim_start (int); void set_dcp_trim_end (int); + void set_reel_size (uint64_t); + void unset_reel_size (); void set_dcp_ab (bool); void set_content_audio_stream (boost::shared_ptr); void set_external_audio (std::vector); @@ -435,6 +443,8 @@ private: int _dcp_trim_start; /** Frames to trim off the end of the DCP */ int _dcp_trim_end; + /** Approximate target reel size in bytes; if not set, use a single reel */ + boost::optional _reel_size; /** true to create an A/B comparison DCP, where the left half of the image is the video without any filters or post-processing, and the right half has the specified filters and post-processing. diff --git a/src/lib/make_dcp_job.cc b/src/lib/make_dcp_job.cc index 5272d6bad..34b3e5124 100644 --- a/src/lib/make_dcp_job.cc +++ b/src/lib/make_dcp_job.cc @@ -37,6 +37,7 @@ extern "C" { #include "film.h" using std::string; +using std::cout; using boost::shared_ptr; /** @param f Film we are making the DCP for. @@ -57,9 +58,9 @@ MakeDCPJob::name () const /** @param f DCP frame index */ string -MakeDCPJob::j2c_path (int f) const +MakeDCPJob::j2c_path (int f, int offset) const { - SourceFrame const s = (f * dcp_frame_rate(_film->frames_per_second()).skip) + _film->dcp_trim_start(); + SourceFrame const s = ((f + offset) * dcp_frame_rate(_film->frames_per_second()).skip) + _film->dcp_trim_start(); return _opt->frame_out_path (s, false); } @@ -75,6 +76,8 @@ MakeDCPJob::run () if (!_film->dcp_length()) { throw EncodeError ("cannot make a DCP when the source length is not known"); } + + descend (0.9); string const dcp_path = _film->dir (_film->dcp_name()); @@ -103,45 +106,74 @@ MakeDCPJob::run () dcp.add_cpl (cpl); - descend (0.8); - shared_ptr pa ( - new libdcp::MonoPictureAsset ( - boost::bind (&MakeDCPJob::j2c_path, this, _1), - _film->dir (_film->dcp_name()), - "video.mxf", - &dcp.Progress, - dfr.frames_per_second, - frames, - _opt->out_size.width, - _opt->out_size.height - ) - ); - - ascend (); + int frames_per_reel = 0; + if (_film->reel_size()) { + frames_per_reel = (_film->reel_size().get() / (_film->j2k_bandwidth() / 8)) * dfr.frames_per_second; + } else { + frames_per_reel = frames; + } - shared_ptr sa; + int frames_done = 0; + int reel = 0; - if (_film->audio_channels() > 0) { - descend (0.1); - sa.reset ( - new libdcp::SoundAsset ( - boost::bind (&MakeDCPJob::wav_path, this, _1), + while (frames_done < frames) { + + descend (float (frames_per_reel) / frames); + + int this_time = std::min (frames_per_reel, (frames - frames_done)); + + descend (0.8); + + shared_ptr pa ( + new libdcp::MonoPictureAsset ( + boost::bind (&MakeDCPJob::j2c_path, this, _1, frames_done), _film->dir (_film->dcp_name()), - "audio.mxf", + String::compose ("video_%1.mxf", reel), &dcp.Progress, dfr.frames_per_second, - frames, - dcp_audio_channels (_film->audio_channels()) + this_time, + _opt->out_size.width, + _opt->out_size.height ) ); + + ascend (); + + shared_ptr sa; + + if (_film->audio_channels() > 0) { + descend (0.1); + sa.reset ( + new libdcp::SoundAsset ( + boost::bind (&MakeDCPJob::wav_path, this, _1), + _film->dir (_film->dcp_name()), + String::compose ("audio_%1.mxf", reel), + &dcp.Progress, + dfr.frames_per_second, + this_time, + frames_done, + dcp_audio_channels (_film->audio_channels()) + ) + ); + ascend (); + } + + descend (0.1); + cpl->add_reel (shared_ptr (new libdcp::Reel (pa, sa, shared_ptr ()))); + ascend (); + + frames_done += frames_per_reel; + ++reel; + ascend (); } + ascend (); + descend (0.1); - cpl->add_reel (shared_ptr (new libdcp::Reel (pa, sa, shared_ptr ()))); dcp.write_xml (); ascend (); - + set_progress (1); set_state (FINISHED_OK); } diff --git a/src/lib/make_dcp_job.h b/src/lib/make_dcp_job.h index 1aa906b0a..5e4f78a25 100644 --- a/src/lib/make_dcp_job.h +++ b/src/lib/make_dcp_job.h @@ -38,7 +38,7 @@ public: private: void dcp_progress (float); - std::string j2c_path (int) const; + std::string j2c_path (int, int) const; std::string wav_path (libdcp::Channel) const; boost::shared_ptr _opt; diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index 72f2d4807..17c40c83d 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -149,6 +149,17 @@ FilmEditor::make_film_panel () _film_sizer->Add (s); } + _multiple_reels = new wxCheckBox (_film_panel, wxID_ANY, wxT ("Make multiple reels")); + _film_sizer->Add (_multiple_reels); + + { + wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); + _reel_size = new wxSpinCtrl (_film_panel, wxID_ANY); + s->Add (_reel_size); + add_label_to_sizer (s, _film_panel, "Gb each"); + _film_sizer->Add (s); + } + _dcp_ab = new wxCheckBox (_film_panel, wxID_ANY, wxT ("A/B")); video_control (_dcp_ab); _film_sizer->Add (_dcp_ab, 1); @@ -169,6 +180,8 @@ FilmEditor::make_film_panel () for (vector::const_iterator i = ct.begin(); i != ct.end(); ++i) { _dcp_content_type->Append (std_to_wx ((*i)->pretty_name ())); } + + _reel_size->SetRange(1, 1000); } void @@ -191,6 +204,8 @@ FilmEditor::connect_to_widgets () _still_duration->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::still_duration_changed), 0, this); _dcp_trim_start->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::dcp_trim_start_changed), 0, this); _dcp_trim_end->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::dcp_trim_end_changed), 0, this); + _multiple_reels->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::multiple_reels_toggled), 0, this); + _reel_size->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::reel_size_changed), 0, this); _with_subtitles->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::with_subtitles_toggled), 0, this); _subtitle_offset->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_offset_changed), 0, this); _subtitle_scale->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::subtitle_scale_changed), 0, this); @@ -463,6 +478,32 @@ FilmEditor::trust_content_header_changed (wxCommandEvent &) _film->set_trust_content_header (_trust_content_header->GetValue ()); } +void +FilmEditor::multiple_reels_toggled (wxCommandEvent &) +{ + if (!_film) { + return; + } + + if (_multiple_reels->GetValue()) { + _film->set_reel_size (_reel_size->GetValue() * 1e9); + } else { + _film->unset_reel_size (); + } + + setup_reel_control_sensitivity (); +} + +void +FilmEditor::reel_size_changed (wxCommandEvent &) +{ + if (!_film) { + return; + } + + _film->set_reel_size (static_cast (_reel_size->GetValue()) * 1e9); +} + /** Called when the DCP A/B switch has been toggled */ void FilmEditor::dcp_ab_toggled (wxCommandEvent &) @@ -640,6 +681,15 @@ FilmEditor::film_changed (Film::Property p) case Film::DCP_TRIM_END: checked_set (_dcp_trim_end, _film->dcp_trim_end()); break; + case Film::REEL_SIZE: + if (_film->reel_size()) { + checked_set (_multiple_reels, true); + checked_set (_reel_size, _film->reel_size().get() / 1e9); + } else { + checked_set (_multiple_reels, false); + } + setup_reel_control_sensitivity (); + break; case Film::AUDIO_GAIN: checked_set (_audio_gain, _film->audio_gain ()); break; @@ -763,6 +813,7 @@ FilmEditor::set_film (shared_ptr f) film_changed (Film::SCALER); film_changed (Film::DCP_TRIM_START); film_changed (Film::DCP_TRIM_END); + film_changed (Film::REEL_SIZE); film_changed (Film::DCP_AB); film_changed (Film::CONTENT_AUDIO_STREAM); film_changed (Film::EXTERNAL_AUDIO); @@ -807,6 +858,8 @@ FilmEditor::set_things_sensitive (bool s) _dcp_content_type->Enable (s); _dcp_trim_start->Enable (s); _dcp_trim_end->Enable (s); + _multiple_reels->Enable (s); + _reel_size->Enable (s); _dcp_ab->Enable (s); _colour_lut->Enable (s); _j2k_bandwidth->Enable (s); @@ -817,6 +870,7 @@ FilmEditor::set_things_sensitive (bool s) setup_subtitle_control_sensitivity (); setup_audio_control_sensitivity (); + setup_reel_control_sensitivity (); } /** Called when the `Edit filters' button has been clicked */ @@ -1157,3 +1211,9 @@ FilmEditor::external_audio_changed (wxCommandEvent &) _film->set_external_audio (a); } + +void +FilmEditor::setup_reel_control_sensitivity () +{ + _reel_size->Enable (_multiple_reels->GetValue ()); +} diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h index 8a900f1e4..34e67eef1 100644 --- a/src/wx/film_editor.h +++ b/src/wx/film_editor.h @@ -65,6 +65,8 @@ private: void format_changed (wxCommandEvent &); void dcp_trim_start_changed (wxCommandEvent &); void dcp_trim_end_changed (wxCommandEvent &); + void multiple_reels_toggled (wxCommandEvent &); + void reel_size_changed (wxCommandEvent &); void dcp_content_type_changed (wxCommandEvent &); void dcp_ab_toggled (wxCommandEvent &); void scaler_changed (wxCommandEvent &); @@ -92,6 +94,7 @@ private: void setup_formats (); void setup_subtitle_control_sensitivity (); void setup_audio_control_sensitivity (); + void setup_reel_control_sensitivity (); void setup_streams (); void setup_audio_details (); @@ -167,6 +170,8 @@ private: wxSpinCtrl* _dcp_trim_start; wxSpinCtrl* _dcp_trim_end; + wxCheckBox* _multiple_reels; + wxSpinCtrl* _reel_size; /** Selector to generate an A/B comparison DCP */ wxCheckBox* _dcp_ab; diff --git a/wscript b/wscript index 657ddc1fa..bcd2ed693 100644 --- a/wscript +++ b/wscript @@ -50,7 +50,7 @@ def configure(conf): conf.env.append_value('CXXFLAGS', '-O2') if not conf.options.static: - conf.check_cfg(package = 'libdcp', atleast_version = '0.34', args = '--cflags --libs', uselib_store = 'DCP', mandatory = True) + conf.check_cfg(package = 'libdcp', atleast_version = '0.36', args = '--cflags --libs', uselib_store = 'DCP', mandatory = True) conf.check_cfg(package = 'libavformat', args = '--cflags --libs', uselib_store = 'AVFORMAT', mandatory = True) conf.check_cfg(package = 'libavfilter', args = '--cflags --libs', uselib_store = 'AVFILTER', mandatory = True) conf.check_cfg(package = 'libavcodec', args = '--cflags --libs', uselib_store = 'AVCODEC', mandatory = True) -- 2.30.2