Guess a better optimum frame rate when there is content at 24 and 48 fps (#633).
[dcpomatic.git] / src / lib / playlist.cc
index 22412da4a3640b5313cd6d75cdb25422a4ee08f6..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
@@ -62,10 +62,16 @@ Playlist::~Playlist ()
 void
 Playlist::content_changed (weak_ptr<Content> content, int property, bool frequent)
 {
+       /* Don't respond to position changes here, as:
+          - sequencing after earlier/later changes is handled by move_earlier/move_later
+          - 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);
 }
 
@@ -75,10 +81,9 @@ Playlist::maybe_sequence_video ()
        if (!_sequence_video || _sequencing_video) {
                return;
        }
-       
+
        _sequencing_video = true;
-       
-       ContentList cl = _content;
+
        DCPTime next_left;
        DCPTime next_right;
        for (ContentList::iterator i = _content.begin(); i != _content.end(); ++i) {
@@ -86,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 ();
@@ -97,7 +102,7 @@ Playlist::maybe_sequence_video ()
        }
 
        /* This won't change order, so it does not need a sort */
-       
+
        _sequencing_video = false;
 }
 
@@ -105,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 ();
                }
        }
 
@@ -157,7 +165,7 @@ Playlist::remove (shared_ptr<Content> c)
        while (i != _content.end() && *i != c) {
                ++i;
        }
-       
+
        if (i != _content.end ()) {
                _content.erase (i);
                Changed ();
@@ -174,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 ();
 }
 
@@ -229,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) {
@@ -244,7 +258,7 @@ Playlist::best_dcp_frame_rate () const
        if (!best) {
                return 24;
        }
-       
+
        return best->dcp;
 }
 
@@ -253,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;
@@ -267,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)));
        }
@@ -344,7 +358,7 @@ Playlist::repeat (ContentList c, int n)
        }
 
        sort (_content.begin(), _content.end(), ContentSorter ());
-       
+
        reconnect ();
        Changed ();
 }
@@ -353,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) {
@@ -361,12 +375,12 @@ Playlist::move_earlier (shared_ptr<Content> c)
                ++i;
        }
 
-       assert (i != _content.end ());
+       DCPOMATIC_ASSERT (i != _content.end ());
        if (previous == _content.end ()) {
                return;
        }
 
-       
+
        DCPTime const p = (*previous)->position ();
        (*previous)->set_position (p + c->length_after_trim ());
        c->set_position (p);
@@ -377,13 +391,13 @@ 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;
        }
 
-       assert (i != _content.end ());
+       DCPOMATIC_ASSERT (i != _content.end ());
 
        ContentList::iterator next = i;
        ++next;
@@ -393,6 +407,6 @@ Playlist::move_later (shared_ptr<Content> c)
        }
 
        (*next)->set_position (c->position ());
-       c->set_position (c->position() + c->length_after_trim ());
+       c->set_position (c->position() + (*next)->length_after_trim ());
        sort (_content.begin(), _content.end(), ContentSorter ());
 }