Allow single-frame image contents to adjust their video frame rates to that of the...
authorCarl Hetherington <cth@carlh.net>
Fri, 6 Nov 2015 01:10:27 +0000 (01:10 +0000)
committerCarl Hetherington <cth@carlh.net>
Fri, 6 Nov 2015 01:10:27 +0000 (01:10 +0000)
ChangeLog
src/lib/image_examiner.cc
src/lib/playlist.cc
src/lib/video_content.cc
src/lib/video_content.h
src/wx/content_panel.cc
src/wx/timing_panel.cc

index 889de809f62274ce98f60d6ddaa92af382dc07c6..406fc737139ce9bc08a7dd0af0242c83413f5245 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2015-11-06  Carl Hetherington  <cth@carlh.net>
+
+       * Make single-frame image sources adjust their notional
+       frame rate to that of the DCP (#714).
+
 2015-11-05  Carl Hetherington  <cth@carlh.net>
 
        * Correct time display when previewing multi-reel DCP content.
index 7a93b5cd1439a9bfa0757d6946e965ffa32c5788..376491738ef7b004fb2dd5d8dd37ef0c5bf9a96b 100644 (file)
@@ -69,7 +69,7 @@ ImageExaminer::ImageExaminer (shared_ptr<const Film> film, shared_ptr<const Imag
        }
 
        if (content->still ()) {
-               _video_length = Config::instance()->default_still_length() * video_frame_rate().get_value_or (24);
+               _video_length = Config::instance()->default_still_length() * video_frame_rate().get_value_or (film->video_frame_rate ());
        } else {
                _video_length = _image_content->number_of_paths ();
        }
@@ -84,7 +84,7 @@ ImageExaminer::video_size () const
 optional<double>
 ImageExaminer::video_frame_rate () const
 {
-       if (_image_content->video_frame_rate() != 0) {
+       if (_image_content->has_own_video_frame_rate()) {
                /* The content already knows what frame rate it should be */
                return _image_content->video_frame_rate();
        }
index c9de9b88fdd02726ebd41aa0754b5f26501cb16e..c5cd4b02d0149c52fdd2000f9bd994343695e9a3 100644 (file)
@@ -212,7 +212,7 @@ Playlist::best_dcp_frame_rate () const
 {
        list<int> const allowed_dcp_frame_rates = Config::instance()->allowed_dcp_frame_rates ();
 
-       /* Work out what rates we could manage, including those achieved by using skip / repeat. */
+       /* Work out what rates we could manage, including those achieved by using skip / repeat */
        list<FrameRateCandidate> candidates;
 
        /* Start with the ones without skip / repeat so they will get matched in preference to skipped/repeated ones */
@@ -235,7 +235,7 @@ Playlist::best_dcp_frame_rate () const
                float this_error = 0;
                BOOST_FOREACH (shared_ptr<Content> j, _content) {
                        shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (j);
-                       if (!vc) {
+                       if (!vc || !vc->has_own_video_frame_rate()) {
                                continue;
                        }
 
index 1e8b9034a6242463a60389458e810a23df334eb9..f11b40bb44b7b61d800242832ddfa08b263ef3cf 100644 (file)
@@ -67,7 +67,6 @@ using boost::dynamic_pointer_cast;
 VideoContent::VideoContent (shared_ptr<const Film> film)
        : Content (film)
        , _video_length (0)
-       , _video_frame_rate (0)
        , _video_frame_type (VIDEO_FRAME_TYPE_2D)
        , _scale (VideoContentScale (Ratio::from_id ("178")))
        , _fade_in (0)
@@ -79,7 +78,6 @@ VideoContent::VideoContent (shared_ptr<const Film> film)
 VideoContent::VideoContent (shared_ptr<const Film> film, DCPTime s, Frame len)
        : Content (film, s)
        , _video_length (len)
-       , _video_frame_rate (0)
        , _video_frame_type (VIDEO_FRAME_TYPE_2D)
        , _scale (VideoContentScale (Ratio::from_id ("178")))
        , _fade_in (0)
@@ -91,7 +89,6 @@ VideoContent::VideoContent (shared_ptr<const Film> film, DCPTime s, Frame len)
 VideoContent::VideoContent (shared_ptr<const Film> film, boost::filesystem::path p)
        : Content (film, p)
        , _video_length (0)
-       , _video_frame_rate (0)
        , _video_frame_type (VIDEO_FRAME_TYPE_2D)
        , _scale (VideoContentScale (Ratio::from_id ("178")))
        , _fade_in (0)
@@ -105,7 +102,7 @@ VideoContent::VideoContent (shared_ptr<const Film> film, cxml::ConstNodePtr node
 {
        _video_size.width = node->number_child<int> ("VideoWidth");
        _video_size.height = node->number_child<int> ("VideoHeight");
-       _video_frame_rate = node->number_child<double> ("VideoFrameRate");
+       _video_frame_rate = node->optional_number_child<double> ("VideoFrameRate");
        _video_length = node->number_child<Frame> ("VideoLength");
        _video_frame_type = static_cast<VideoFrameType> (node->number_child<int> ("VideoFrameType"));
        _sample_aspect_ratio = node->optional_number_child<double> ("SampleAspectRatio");
@@ -193,7 +190,9 @@ VideoContent::as_xml (xmlpp::Node* node) const
        node->add_child("VideoLength")->add_child_text (raw_convert<string> (_video_length));
        node->add_child("VideoWidth")->add_child_text (raw_convert<string> (_video_size.width));
        node->add_child("VideoHeight")->add_child_text (raw_convert<string> (_video_size.height));
-       node->add_child("VideoFrameRate")->add_child_text (raw_convert<string> (_video_frame_rate));
+       if (_video_frame_rate) {
+               node->add_child("VideoFrameRate")->add_child_text (raw_convert<string> (_video_frame_rate.get()));
+       }
        node->add_child("VideoFrameType")->add_child_text (raw_convert<string> (static_cast<int> (_video_frame_type)));
        if (_sample_aspect_ratio) {
                node->add_child("SampleAspectRatio")->add_child_text (raw_convert<string> (_sample_aspect_ratio.get ()));
@@ -227,8 +226,7 @@ VideoContent::take_from_video_examiner (shared_ptr<VideoExaminer> d)
        {
                boost::mutex::scoped_lock lm (_mutex);
                _video_size = vs;
-               /* Default video frame rate to 24fps if the examiner doesn't know */
-               _video_frame_rate = vfr.get_value_or (24);
+               _video_frame_rate = vfr;
                _video_length = vl;
                _sample_aspect_ratio = ar;
 
@@ -590,3 +588,13 @@ VideoContent::reel_split_points () const
        t.push_back (position().round_up (film->video_frame_rate()));
        return t;
 }
+
+double
+VideoContent::video_frame_rate () const
+{
+       boost::shared_ptr<const Film> film = _film.lock ();
+       DCPOMATIC_ASSERT (film);
+
+       boost::mutex::scoped_lock lm (_mutex);
+       return _video_frame_rate.get_value_or (film->video_frame_rate ());
+}
index c0a609a6ac90ae7891ca9d1cea1d421fb7b30401..aa541fc32b85bd05f870d7a0776ee5a3427e54e5 100644 (file)
@@ -79,7 +79,12 @@ public:
                return _video_size;
        }
 
-       double video_frame_rate () const {
+       double video_frame_rate () const;
+
+       /** @return true if this content has a specific video frame rate, false
+        *  if it should use the DCP's rate.
+        */
+       bool has_own_video_frame_rate () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _video_frame_rate;
        }
@@ -172,7 +177,8 @@ protected:
        void add_properties (std::list<std::pair<std::string, std::string> > &) const;
 
        Frame _video_length;
-       double _video_frame_rate;
+       /** Video frame rate, or not set if this content should use the DCP's frame rate */
+       boost::optional<double> _video_frame_rate;
        boost::optional<ColourConversion> _colour_conversion;
 
 private:
index 8ca0d5b29854bc9ba58611fda2db3f61098027eb..a84698032c673543a4e3ba8c704f73afaad7cd7f 100644 (file)
@@ -526,11 +526,6 @@ ContentPanel::add_files (list<boost::filesystem::path> paths)
        /* XXX: check for lots of files here and do something */
 
        for (list<boost::filesystem::path>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
-               shared_ptr<Content> c = content_factory (_film, *i);
-               shared_ptr<ImageContent> ic = dynamic_pointer_cast<ImageContent> (c);
-               if (ic) {
-                       ic->set_video_frame_rate (24);
-               }
-               _film->examine_and_add_content (c);
+               _film->examine_and_add_content (content_factory (_film, *i));
        }
 }
index e416a671c10bedb74792fd35a86cfe658134a72b..f05268f92434d79626268eebfe936716a9bf35a9 100644 (file)
@@ -267,7 +267,9 @@ TimingPanel::film_content_changed (int property)
 
                }
 
-               if (check_vc.size() == 1 || count_sc == 1) {
+               bool const single_frame_image_content = vc && dynamic_pointer_cast<const ImageContent> (vc) && vc->number_of_paths() == 1;
+
+               if ((check_vc.size() == 1 || count_sc == 1) && !single_frame_image_content) {
                        if (vc) {
                                checked_set (_video_frame_rate, raw_convert<string> (vc->video_frame_rate (), 5));
                        } else if (sc) {