Guess DCP container size and resolution when content is added
authorCarl Hetherington <cth@carlh.net>
Mon, 11 May 2020 20:42:32 +0000 (22:42 +0200)
committerCarl Hetherington <cth@carlh.net>
Tue, 12 May 2020 11:13:36 +0000 (13:13 +0200)
or removed such that there is one piece of video content left
in the project.

Container size and resolution are never again guessed once the
user has set them to something.

src/lib/film.cc
src/lib/film.h
src/tools/dcpomatic_create.cc
test/data

index b1dcb46d7e473b34be81dbc3ba83139cf31a07e2..2f631bd89c02173abba3fc0910289d92fc401208 100644 (file)
@@ -164,6 +164,8 @@ Film::Film (optional<boost::filesystem::path> dir)
        , _upload_after_make_dcp (Config::instance()->default_upload_after_make_dcp())
        , _reencode_j2k (false)
        , _user_explicit_video_frame_rate (false)
+       , _user_explicit_container (false)
+       , _user_explicit_resolution (false)
        , _state_version (current_state_version)
        , _dirty (false)
        , _tolerant (false)
@@ -466,6 +468,8 @@ Film::metadata (bool with_content_paths) const
                i.as_xml (root->add_child("Rating"));
        }
        root->add_child("ContentVersion")->add_child_text(_content_version);
+       root->add_child("UserExplicitContainer")->add_child_text(_user_explicit_container ? "1" : "0");
+       root->add_child("UserExplicitResolution")->add_child_text(_user_explicit_resolution ? "1" : "0");
        _playlist->as_xml (root->add_child ("Playlist"), with_content_paths);
 
        return doc;
@@ -615,6 +619,10 @@ Film::read_metadata (optional<boost::filesystem::path> path)
 
        _content_version = f.optional_string_child("ContentVersion").get_value_or("");
 
+       /* Disable guessing for files made in previous DCP-o-matic versions */
+       _user_explicit_container = f.optional_bool_child("UserExplicitContainer").get_value_or(true);
+       _user_explicit_resolution = f.optional_bool_child("UserExplicitResolution").get_value_or(true);
+
        list<string> notes;
        _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version, notes);
 
@@ -969,20 +977,39 @@ Film::set_dcp_content_type (DCPContentType const * t)
        _dcp_content_type = t;
 }
 
+
+/** @param explicit_user true if this is being set because of
+ *  a direct user request, false if it is being done because
+ *  DCP-o-matic is guessing the best container to use.
+ */
 void
-Film::set_container (Ratio const * c)
+Film::set_container (Ratio const * c, bool explicit_user)
 {
        ChangeSignaller<Film> ch (this, CONTAINER);
        _container = c;
+
+       if (explicit_user) {
+               _user_explicit_container = true;
+       }
 }
 
+
+/** @param explicit_user true if this is being set because of
+ *  a direct user request, false if it is being done because
+ *  DCP-o-matic is guessing the best resolution to use.
+ */
 void
-Film::set_resolution (Resolution r)
+Film::set_resolution (Resolution r, bool explicit_user)
 {
        ChangeSignaller<Film> ch (this, RESOLUTION);
        _resolution = r;
+
+       if (explicit_user) {
+               _user_explicit_resolution = true;
+       }
 }
 
+
 void
 Film::set_j2k_bandwidth (int b)
 {
@@ -1267,12 +1294,54 @@ Film::add_content (shared_ptr<Content> c)
        }
 
        _playlist->add (shared_from_this(), c);
+
+       maybe_set_container_and_resolution ();
+}
+
+
+void
+Film::maybe_set_container_and_resolution ()
+{
+       /* Get the only piece of video content, if there is only one */
+       shared_ptr<VideoContent> video;
+       BOOST_FOREACH (shared_ptr<const Content> i, _playlist->content()) {
+               if (i->video) {
+                       if (!video) {
+                               video = i->video;
+                       } else {
+                               video.reset ();
+                       }
+               }
+       }
+
+       if (video) {
+               /* This is the only piece of video content in this Film.  Use it to make a guess for
+                * DCP container size and resolution, unless the user has already explicitly set these
+                * things.
+                */
+               if (!_user_explicit_container) {
+                       if (video->size().ratio() > 2.3) {
+                               set_container (Ratio::from_id("239"), false);
+                       } else {
+                               set_container (Ratio::from_id("185"), false);
+                       }
+               }
+
+               if (!_user_explicit_resolution) {
+                       if (video->size_after_crop().width > 2048 || video->size_after_crop().height > 1080) {
+                               set_resolution (RESOLUTION_4K, false);
+                       } else {
+                               set_resolution (RESOLUTION_2K, false);
+                       }
+               }
+       }
 }
 
 void
 Film::remove_content (shared_ptr<Content> c)
 {
        _playlist->remove (c);
+       maybe_set_container_and_resolution ();
 }
 
 void
index 40d366f8f68c8a331ee7840c9bf37ee944515f89..b03b0258e7f074316b9c3560911a14f55dec1120 100644 (file)
@@ -351,8 +351,8 @@ public:
        void move_content_earlier (boost::shared_ptr<Content>);
        void move_content_later (boost::shared_ptr<Content>);
        void set_dcp_content_type (DCPContentType const *);
-       void set_container (Ratio const *);
-       void set_resolution (Resolution);
+       void set_container (Ratio const *, bool user_explicit = true);
+       void set_resolution (Resolution, bool user_explicit = true);
        void set_signed (bool);
        void set_encrypted (bool);
        void set_key (dcp::Key key);
@@ -409,6 +409,7 @@ private:
        void maybe_add_content (boost::weak_ptr<Job>, boost::weak_ptr<Content>, bool disable_audio_analysis);
        void audio_analysis_finished ();
        void check_settings_consistency ();
+       void maybe_set_container_and_resolution ();
 
        static std::string const metadata_file;
 
@@ -462,6 +463,8 @@ private:
        bool _reencode_j2k;
        /** true if the user has ever explicitly set the video frame rate of this film */
        bool _user_explicit_video_frame_rate;
+       bool _user_explicit_container;
+       bool _user_explicit_resolution;
        std::map<dcp::Marker, dcpomatic::DCPTime> _markers;
        std::vector<dcp::Rating> _ratings;
        std::string _content_version;
index bcfc2f68b8ba4fa66e50db1640de2153d1e12b82..857359117c3c64309b2c4a35f0c1fcba452bfa5f 100644 (file)
@@ -96,14 +96,18 @@ main (int argc, char* argv[])
                }
                film->set_name (cc.name);
 
-               film->set_container (cc.container_ratio);
+               if (cc.container_ratio) {
+                       film->set_container (cc.container_ratio);
+               }
                film->set_dcp_content_type (cc.dcp_content_type);
                film->set_interop (cc.standard == dcp::INTEROP);
                film->set_use_isdcf_name (!cc.no_use_isdcf_name);
                film->set_signed (!cc.no_sign);
                film->set_encrypted (cc.encrypt);
                film->set_three_d (cc.threed);
-               film->set_resolution (cc.fourk ? RESOLUTION_4K : RESOLUTION_2K);
+               if (cc.fourk) {
+                       film->set_resolution (RESOLUTION_4K);
+               }
                if (cc.j2k_bandwidth) {
                        film->set_j2k_bandwidth (*cc.j2k_bandwidth);
                }
index 9ec245b7f59b65ad6dd6d0f717686931ff66d748..3b21196b894bfbc096a5e90ee11dcf5f50bd4bf9 160000 (submodule)
--- a/test/data
+++ b/test/data
@@ -1 +1 @@
-Subproject commit 9ec245b7f59b65ad6dd6d0f717686931ff66d748
+Subproject commit 3b21196b894bfbc096a5e90ee11dcf5f50bd4bf9