Guess a better optimum frame rate when there is content at 24 and 48 fps (#633).
[dcpomatic.git] / src / lib / playlist.cc
index 1aeed4062a8e2d603f3d09b731e43e499b56879e..e2135a60ed6a9479450f0991430aab819fc16ec6 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
 
     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
@@ -67,11 +67,11 @@ Playlist::content_changed (weak_ptr<Content> content, int property, bool frequen
           - any other position changes will be timeline drags which should not result in content
           being sequenced.
        */
-       
+
        if (property == ContentProperty::LENGTH || property == VideoContentProperty::VIDEO_FRAME_TYPE) {
                maybe_sequence_video ();
        }
-       
+
        ContentChanged (content, property, frequent);
 }
 
@@ -81,9 +81,9 @@ Playlist::maybe_sequence_video ()
        if (!_sequence_video || _sequencing_video) {
                return;
        }
-       
+
        _sequencing_video = true;
-       
+
        DCPTime next_left;
        DCPTime next_right;
        for (ContentList::iterator i = _content.begin(); i != _content.end(); ++i) {
@@ -91,7 +91,7 @@ Playlist::maybe_sequence_video ()
                if (!vc) {
                        continue;
                }
-               
+
                if (vc->video_frame_type() == VIDEO_FRAME_TYPE_3D_RIGHT) {
                        vc->set_position (next_right);
                        next_right = vc->end() + DCPTime::delta ();
@@ -102,7 +102,7 @@ Playlist::maybe_sequence_video ()
        }
 
        /* This won't change order, so it does not need a sort */
-       
+
        _sequencing_video = false;
 }
 
@@ -110,11 +110,14 @@ string
 Playlist::video_identifier () const
 {
        string t;
-       
+
        for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
                shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (*i);
+               shared_ptr<const SubtitleContent> sc = dynamic_pointer_cast<const SubtitleContent> (*i);
                if (vc) {
                        t += vc->identifier ();
+               } else if (sc && sc->burn_subtitles ()) {
+                       t += sc->identifier ();
                }
        }
 
@@ -162,7 +165,7 @@ Playlist::remove (shared_ptr<Content> c)
        while (i != _content.end() && *i != c) {
                ++i;
        }
-       
+
        if (i != _content.end ()) {
                _content.erase (i);
                Changed ();
@@ -179,14 +182,14 @@ Playlist::remove (ContentList c)
                while (j != _content.end() && *j != *i) {
                        ++j;
                }
-       
+
                if (j != _content.end ()) {
                        _content.erase (j);
                }
        }
 
        /* This won't change order, so it does not need a sort */
-       
+
        Changed ();
 }
 
@@ -234,8 +237,14 @@ Playlist::best_dcp_frame_rate () const
                                continue;
                        }
 
+                       /* Best error for this content; we could use the content as-is or double its rate */
+                       float best_error = min (
+                               float (fabs (i->source - vc->video_frame_rate ())),
+                               float (fabs (i->source - vc->video_frame_rate () * 2))
+                               );
+
                        /* Use the largest difference between DCP and source as the "error" */
-                       this_error = max (this_error, float (fabs (i->source - vc->video_frame_rate ())));
+                       this_error = max (this_error, best_error);
                }
 
                if (this_error < error) {
@@ -249,7 +258,7 @@ Playlist::best_dcp_frame_rate () const
        if (!best) {
                return 24;
        }
-       
+
        return best->dcp;
 }
 
@@ -258,7 +267,7 @@ Playlist::length () const
 {
        DCPTime len;
        for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
-               len = max (len, (*i)->end() + DCPTime::delta ());
+               len = max (len, (*i)->end());
        }
 
        return len;
@@ -272,7 +281,7 @@ Playlist::reconnect ()
        }
 
        _content_connections.clear ();
-               
+
        for (ContentList::iterator i = _content.begin(); i != _content.end(); ++i) {
                _content_connections.push_back ((*i)->Changed.connect (bind (&Playlist::content_changed, this, _1, _2, _3)));
        }
@@ -349,7 +358,7 @@ Playlist::repeat (ContentList c, int n)
        }
 
        sort (_content.begin(), _content.end(), ContentSorter ());
-       
+
        reconnect ();
        Changed ();
 }
@@ -358,7 +367,7 @@ void
 Playlist::move_earlier (shared_ptr<Content> c)
 {
        sort (_content.begin(), _content.end(), ContentSorter ());
-       
+
        ContentList::iterator previous = _content.end ();
        ContentList::iterator i = _content.begin();
        while (i != _content.end() && *i != c) {
@@ -371,7 +380,7 @@ Playlist::move_earlier (shared_ptr<Content> c)
                return;
        }
 
-       
+
        DCPTime const p = (*previous)->position ();
        (*previous)->set_position (p + c->length_after_trim ());
        c->set_position (p);
@@ -382,7 +391,7 @@ void
 Playlist::move_later (shared_ptr<Content> c)
 {
        sort (_content.begin(), _content.end(), ContentSorter ());
-       
+
        ContentList::iterator i = _content.begin();
        while (i != _content.end() && *i != c) {
                ++i;