Stop trying to get frames from a video source when an attempt
authorCarl Hetherington <cth@carlh.net>
Sun, 24 Jan 2016 23:40:32 +0000 (23:40 +0000)
committerCarl Hetherington <cth@carlh.net>
Sun, 24 Jan 2016 23:40:32 +0000 (23:40 +0000)
to get an earlier frame has already failed because the decoder
said it has no more data.  Before this the VideoDecoder would
repeatedly seek to try to get a frame which does not exist.

This happens when the header of a file is wrong, it would seem;
in the file that triggered the bug the header (as read by DoM or ffprobe)
has a length of 137275 frames but the last frame in the file
(according to DoM or ffprobe -show_frames) is 136207 (44.5s earlier).

ChangeLog
src/lib/video_decoder.cc
src/lib/video_decoder.h

index 427c362943e9908f5f0edf8e083dfd26e56e5f73..c2d05c5eb0ba8bb71486a7019a60002e7574a5d1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2016-01-24  Carl Hetherington  <cth@carlh.net>
+
+       * Fix encodes getting stuck in some cases (#783).
+
 2016-01-23  Carl Hetherington  <cth@carlh.net>
 
        * Fix estimate of required disk space to take referencing
index fd5779a657f0304124a28ef27980a62a85a1945a..1de2cd8060a3e0616ff152914e1ccd835934f95f 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2016 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
@@ -70,6 +70,10 @@ VideoDecoder::decoded_video (Frame frame)
 list<ContentVideo>
 VideoDecoder::get_video (Frame frame, bool accurate)
 {
+       if (_no_data_frame && frame >= _no_data_frame.get()) {
+               return list<ContentVideo> ();
+       }
+       
        /* At this stage, if we have get_video()ed before, _decoded_video will contain the last frame that this
           method returned (and possibly a few more).  If the requested frame is not in _decoded_video and it is not the next
           one after the end of _decoded_video we need to seek.
@@ -100,6 +104,7 @@ VideoDecoder::get_video (Frame frame, bool accurate)
 
                        if (pass (PASS_REASON_VIDEO, accurate)) {
                                /* The decoder has nothing more for us */
+                               _no_data_frame = frame;
                                break;
                        }
 
@@ -121,9 +126,9 @@ VideoDecoder::get_video (Frame frame, bool accurate)
                }
        }
 
-       /* Clean up _decoded_video; keep the frame we are returning (which may have two images
+       /* Clean up _decoded_video; keep the frame we are returning, if any (which may have two images
           for 3D), but nothing before that */
-       while (!_decoded_video.empty() && _decoded_video.front().frame < dec.front().frame) {
+       while (!_decoded_video.empty() && !dec.empty() && _decoded_video.front().frame < dec.front().frame) {
                _decoded_video.pop_front ();
        }
 
index 42cfc49063de396fa5043f193430ccffc6279eb0..af24b93bc9ca1c016f74f29169a53e59daa68d10 100644 (file)
@@ -70,9 +70,12 @@ protected:
        boost::shared_ptr<Image> _black_image;
        boost::optional<ContentTime> _last_seek_time;
        bool _last_seek_accurate;
-
        /** true if this decoder should ignore all video; i.e. never produce any */
        bool _ignore_video;
+       /** if set, this is a frame for which we got no data because the Decoder said
+        *  it has no more to give.
+        */
+       boost::optional<Frame> _no_data_frame;
 };
 
 #endif