Fix assertion failure with overlapping video content (#666).
authorCarl Hetherington <cth@carlh.net>
Thu, 20 Aug 2015 16:53:46 +0000 (17:53 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 20 Aug 2015 16:53:46 +0000 (17:53 +0100)
ChangeLog
src/lib/player.cc

index 8edb4aca243b4307281f0601983611eccedebc70..77e172b9f571f0edcf53b630696bd9d9b7598d41 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2015-08-20  Carl Hetherington  <cth@carlh.net>
+
+       * Fix assertion failure with overlapping video content (#666).
+
 2015-08-19  Carl Hetherington  <cth@carlh.net>
 
        * Version 2.1.42 released.
index 147f08ae8ef18e62961402893493c24c40a37b44..d55c8d396cc48730c97b3a80b81d90faf6e5d1b4 100644 (file)
@@ -348,7 +348,7 @@ Player::get_video (DCPTime time, bool accurate)
                subtitles = merge (sub_images);
        }
 
-       /* Find video */
+       /* Find pieces containing video which is happening now */
 
        list<shared_ptr<Piece> > ov = overlaps<VideoContent> (
                time,
@@ -361,56 +361,54 @@ Player::get_video (DCPTime time, bool accurate)
                /* No video content at this time */
                pvf.push_back (black_player_video_frame (time));
        } else {
-               /* Decide which pieces of content to use */
-               list<shared_ptr<Piece> > ov_to_use;
-
-               /* Always use the last one */
-               list<shared_ptr<Piece> >::reverse_iterator i = ov.rbegin ();
-               ov_to_use.push_back (*i);
-               VideoFrameType const first_type = dynamic_pointer_cast<VideoContent> ((*i)->content)->video_frame_type ();
-
-               ++i;
-               if (i != ov.rend ()) {
-                       shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*i)->content);
-                       /* Use the second to last if it's the other part of a 3D content pair */
-                       if (
-                               (first_type == VIDEO_FRAME_TYPE_3D_LEFT && vc->video_frame_type() == VIDEO_FRAME_TYPE_3D_RIGHT) ||
-                               (first_type == VIDEO_FRAME_TYPE_3D_RIGHT && vc->video_frame_type() == VIDEO_FRAME_TYPE_3D_LEFT)
-                               ) {
-                               /* Other part of a pair of 3D content */
-                               ov_to_use.push_back (*i);
-                       }
-               }
+               /* Some video content at this time */
+               shared_ptr<Piece> last = *(ov.rbegin ());
+               VideoFrameType const last_type = dynamic_pointer_cast<VideoContent> (last->content)->video_frame_type ();
+
+               /* Get video from appropriate piece(s) */
+               BOOST_FOREACH (shared_ptr<Piece> piece, ov) {
 
-               BOOST_FOREACH (shared_ptr<Piece> piece, ov_to_use) {
                        shared_ptr<VideoDecoder> decoder = dynamic_pointer_cast<VideoDecoder> (piece->decoder);
                        DCPOMATIC_ASSERT (decoder);
                        shared_ptr<VideoContent> video_content = dynamic_pointer_cast<VideoContent> (piece->content);
                        DCPOMATIC_ASSERT (video_content);
 
-                       list<ContentVideo> content_video = decoder->get_video (dcp_to_content_video (piece, time), accurate);
-                       if (content_video.empty ()) {
-                               pvf.push_back (black_player_video_frame (time));
-                       } else {
-                               dcp::Size image_size = video_content->scale().size (video_content, _video_container_size, _film->frame_size ());
-
-                               for (list<ContentVideo>::const_iterator i = content_video.begin(); i != content_video.end(); ++i) {
-                                       pvf.push_back (
-                                               shared_ptr<PlayerVideo> (
-                                                       new PlayerVideo (
-                                                               i->image,
-                                                               content_video_to_dcp (piece, i->frame),
-                                                               video_content->crop (),
-                                                               video_content->fade (i->frame),
-                                                               image_size,
-                                                               _video_container_size,
-                                                               i->eyes,
-                                                               i->part,
-                                                               video_content->colour_conversion ()
+                       bool const use =
+                               /* always use the last video */
+                               piece == last ||
+                               /* with a corresponding L/R eye if appropriate */
+                               (last_type == VIDEO_FRAME_TYPE_3D_LEFT && video_content->video_frame_type() == VIDEO_FRAME_TYPE_3D_RIGHT) ||
+                               (last_type == VIDEO_FRAME_TYPE_3D_RIGHT && video_content->video_frame_type() == VIDEO_FRAME_TYPE_3D_LEFT);
+
+                       if (use) {
+                               /* We want to use this piece */
+                               list<ContentVideo> content_video = decoder->get_video (dcp_to_content_video (piece, time), accurate);
+                               if (content_video.empty ()) {
+                                       pvf.push_back (black_player_video_frame (time));
+                               } else {
+                                       dcp::Size image_size = video_content->scale().size (video_content, _video_container_size, _film->frame_size ());
+
+                                       for (list<ContentVideo>::const_iterator i = content_video.begin(); i != content_video.end(); ++i) {
+                                               pvf.push_back (
+                                                       shared_ptr<PlayerVideo> (
+                                                               new PlayerVideo (
+                                                                       i->image,
+                                                                       content_video_to_dcp (piece, i->frame),
+                                                                       video_content->crop (),
+                                                                       video_content->fade (i->frame),
+                                                                       image_size,
+                                                                       _video_container_size,
+                                                                       i->eyes,
+                                                                       i->part,
+                                                                       video_content->colour_conversion ()
+                                                                       )
                                                                )
-                                                       )
-                                               );
+                                                       );
+                                       }
                                }
+                       } else {
+                               /* Discard unused video */
+                               decoder->get_video (dcp_to_content_video (piece, time), accurate);
                        }
                }
        }