From c6113e09ca546d5a739b36aa0d198581958d9ded Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 18 Jul 2013 12:40:38 +0100 Subject: [PATCH] Speculative 4K support. --- src/lib/film.cc | 26 ++++++++++++++++++++++++-- src/lib/film.h | 11 ++++++++++- src/lib/types.cc | 33 +++++++++++++++++++++++++++++++++ src/lib/types.h | 8 ++++++++ src/wx/film_editor.cc | 31 ++++++++++++++++++++++++++++--- src/wx/film_editor.h | 2 ++ 6 files changed, 105 insertions(+), 6 deletions(-) diff --git a/src/lib/film.cc b/src/lib/film.cc index e76030efd..3ee8a416f 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -88,6 +88,7 @@ Film::Film (string d) , _use_dci_name (true) , _dcp_content_type (Config::instance()->default_dcp_content_type ()) , _container (Config::instance()->default_container ()) + , _resolution (RESOLUTION_2K) , _scaler (Scaler::from_id ("bicubic")) , _with_subtitles (false) , _j2k_bandwidth (Config::instance()->default_j2k_bandwidth ()) @@ -131,6 +132,7 @@ Film::video_identifier () const stringstream s; s << container()->id() + << "_" << resolution_to_string (_resolution) << "_" << _playlist->video_identifier() << "_" << _dcp_video_frame_rate << "_" << scaler()->id() @@ -314,6 +316,7 @@ Film::write_metadata () const root->add_child("Container")->add_child_text (_container->id ()); } + root->add_child("Resolution")->add_child_text (resolution_to_string (_resolution)); root->add_child("Scaler")->add_child_text (_scaler->id ()); root->add_child("WithSubtitles")->add_child_text (_with_subtitles ? "1" : "0"); root->add_child("J2KBandwidth")->add_child_text (lexical_cast (_j2k_bandwidth)); @@ -358,6 +361,7 @@ Film::read_metadata () } } + _resolution = string_to_resolution (f.string_child ("Resolution")); _scaler = Scaler::from_id (f.string_child ("Scaler")); _with_subtitles = f.bool_child ("WithSubtitles"); _j2k_bandwidth = f.number_child ("J2KBandwidth"); @@ -452,7 +456,7 @@ Film::dci_name (bool if_created_now) const } } - d << "_51_2K"; + d << "_51_" << resolution_to_string (_resolution); if (!dm.studio.empty ()) { d << "_" << dm.studio; @@ -535,6 +539,16 @@ Film::set_container (Ratio const * c) signal_changed (CONTAINER); } +void +Film::set_resolution (Resolution r) +{ + { + boost::mutex::scoped_lock lm (_state_mutex); + _resolution = r; + } + signal_changed (RESOLUTION); +} + void Film::set_scaler (Scaler const * s) { @@ -821,5 +835,13 @@ Film::set_sequence_video (bool s) libdcp::Size Film::full_frame () const { - return libdcp::Size (2048, 1080); + switch (_resolution) { + case RESOLUTION_2K: + return libdcp::Size (2048, 1080); + case RESOLUTION_4K: + return libdcp::Size (4096, 2160); + } + + assert (false); + return libdcp::Size (); } diff --git a/src/lib/film.h b/src/lib/film.h index f4065757b..bd9dcc88d 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -47,7 +47,7 @@ class Player; * @brief A representation of some audio and video content, and details of * how they should be presented in a DCP. * - * The content of a Film is held in a Playlist (created and managed by the Film) + * The content of a Film is held in a Playlist (created and managed by the Film). */ class Film : public boost::enable_shared_from_this, public boost::noncopyable { @@ -129,6 +129,7 @@ public: LOOP, DCP_CONTENT_TYPE, CONTAINER, + RESOLUTION, SCALER, WITH_SUBTITLES, J2K_BANDWIDTH, @@ -165,6 +166,11 @@ public: return _container; } + Resolution resolution () const { + boost::mutex::scoped_lock lm (_state_mutex); + return _resolution; + } + Scaler const * scaler () const { boost::mutex::scoped_lock lm (_state_mutex); return _scaler; @@ -206,6 +212,7 @@ public: void remove_content (boost::shared_ptr); void set_dcp_content_type (DCPContentType const *); void set_container (Ratio const *); + void set_resolution (Resolution); void set_scaler (Scaler const *); void set_with_subtitles (bool); void set_j2k_bandwidth (int); @@ -251,6 +258,8 @@ private: DCPContentType const * _dcp_content_type; /** The container to put this Film in (flat, scope, etc.) */ Ratio const * _container; + /** DCP resolution (2K or 4K) */ + Resolution _resolution; /** Scaler algorithm to use */ Scaler const * _scaler; /** True if subtitles should be shown for this film */ diff --git a/src/lib/types.cc b/src/lib/types.cc index 035c8363d..bc4f5f8d9 100644 --- a/src/lib/types.cc +++ b/src/lib/types.cc @@ -21,6 +21,7 @@ using std::max; using std::min; +using std::string; bool operator== (Crop const & a, Crop const & b) { @@ -32,3 +33,35 @@ bool operator!= (Crop const & a, Crop const & b) return !(a == b); } +/** @param r Resolution. + * @return Untranslated string representation. + */ +string +resolution_to_string (Resolution r) +{ + switch (r) { + case RESOLUTION_2K: + return "2K"; + case RESOLUTION_4K: + return "4K"; + } + + assert (false); + return ""; +} + + +Resolution +string_to_resolution (string s) +{ + if (s == "2K") { + return RESOLUTION_2K; + } + + if (s == "4K") { + return RESOLUTION_4K; + } + + assert (false); + return RESOLUTION_2K; +} diff --git a/src/lib/types.h b/src/lib/types.h index fcf45ffa0..aeaa82ec6 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -53,4 +53,12 @@ struct Crop extern bool operator== (Crop const & a, Crop const & b); extern bool operator!= (Crop const & a, Crop const & b); +enum Resolution { + RESOLUTION_2K, + RESOLUTION_4K +}; + +std::string resolution_to_string (Resolution); +Resolution string_to_resolution (std::string); + #endif diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index 90bf79741..669be844b 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington + Copyright (C) 2012-2013 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 @@ -139,7 +139,7 @@ FilmEditor::make_dcp_panel () ++r; { - add_label_to_grid_bag_sizer (grid, _dcp_panel, _("DCP Frame Rate"), true, wxGBPosition (r, 0)); + add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Frame Rate"), true, wxGBPosition (r, 0)); wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL); _dcp_frame_rate = new wxChoice (_dcp_panel, wxID_ANY); s->Add (_dcp_frame_rate, 1, wxALIGN_CENTER_VERTICAL); @@ -149,11 +149,16 @@ FilmEditor::make_dcp_panel () } ++r; - add_label_to_grid_bag_sizer (grid, _dcp_panel, _("DCP audio channels"), true, wxGBPosition (r, 0)); + add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Audio channels"), true, wxGBPosition (r, 0)); _dcp_audio_channels = new wxSpinCtrl (_dcp_panel, wxID_ANY); grid->Add (_dcp_audio_channels, wxGBPosition (r, 1)); ++r; + add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Resolution"), true, wxGBPosition (r, 0)); + _dcp_resolution = new wxChoice (_dcp_panel, wxID_ANY); + grid->Add (_dcp_resolution, wxGBPosition (r, 1)); + ++r; + { add_label_to_grid_bag_sizer (grid, _dcp_panel, _("JPEG2000 bandwidth"), true, wxGBPosition (r, 0)); wxSizer* s = new wxBoxSizer (wxHORIZONTAL); @@ -191,6 +196,9 @@ FilmEditor::make_dcp_panel () _dcp_audio_channels->SetRange (0, MAX_AUDIO_CHANNELS); _j2k_bandwidth->SetRange (50, 250); + + _dcp_resolution->Append (_("2K")); + _dcp_resolution->Append (_("4K")); } void @@ -230,6 +238,8 @@ FilmEditor::connect_to_widgets () _audio_delay->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::audio_delay_changed), 0, this); _audio_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::audio_stream_changed), 0, this); _subtitle_stream->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::subtitle_stream_changed), 0, this); + _dcp_resolution->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_resolution_changed), 0, this); + _audio_mapping->Changed.connect (boost::bind (&FilmEditor::audio_mapping_changed, this, _1)); _start->Changed.connect (boost::bind (&FilmEditor::start_changed, this)); _length->Changed.connect (boost::bind (&FilmEditor::length_changed, this)); @@ -578,6 +588,16 @@ FilmEditor::dcp_audio_channels_changed (wxCommandEvent &) _film->set_dcp_audio_channels (_dcp_audio_channels->GetValue ()); } +void +FilmEditor::dcp_resolution_changed (wxCommandEvent &) +{ + if (!_film) { + return; + } + + _film->set_resolution (_dcp_resolution->GetSelection() == 0 ? RESOLUTION_2K : RESOLUTION_4K); +} + /** Called when the metadata stored in the Film object has changed; * so that we can update the GUI. @@ -626,6 +646,10 @@ FilmEditor::film_changed (Film::Property p) setup_subtitle_control_sensitivity (); setup_dcp_name (); break; + case Film::RESOLUTION: + checked_set (_dcp_resolution, _film->resolution() == RESOLUTION_2K ? 0 : 1); + setup_dcp_name (); + break; case Film::J2K_BANDWIDTH: checked_set (_j2k_bandwidth, double (_film->j2k_bandwidth()) / 1e6); break; @@ -860,6 +884,7 @@ FilmEditor::set_film (shared_ptr f) film_changed (Film::LOOP); film_changed (Film::DCP_CONTENT_TYPE); film_changed (Film::CONTAINER); + film_changed (Film::RESOLUTION); film_changed (Film::SCALER); film_changed (Film::WITH_SUBTITLES); film_changed (Film::J2K_BANDWIDTH); diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h index f2c6745de..c965a7aff 100644 --- a/src/wx/film_editor.h +++ b/src/wx/film_editor.h @@ -97,6 +97,7 @@ private: void length_changed (); void ratio_changed (wxCommandEvent &); void dcp_audio_channels_changed (wxCommandEvent &); + void dcp_resolution_changed (wxCommandEvent &); /* Handle changes to the model */ void film_changed (Film::Property); @@ -173,6 +174,7 @@ private: AudioMappingView* _audio_mapping; Timecode* _start; Timecode* _length; + wxChoice* _dcp_resolution; std::vector _ratios; -- 2.30.2