Merge branch 'master' of ssh://git.carlh.net/home/carl/git/dcpomatic
authorCarl Hetherington <cth@carlh.net>
Sun, 24 Jan 2016 23:53:22 +0000 (23:53 +0000)
committerCarl Hetherington <cth@carlh.net>
Sun, 24 Jan 2016 23:53:22 +0000 (23:53 +0000)
ChangeLog
hacks/check_packets.py [new file with mode: 0644]
src/lib/decoder.h
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
diff --git a/hacks/check_packets.py b/hacks/check_packets.py
new file mode 100644 (file)
index 0000000..916813a
--- /dev/null
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+
+import subprocess
+import shlex
+import sys
+
+last_video_pts = None
+
+def handle(frame):
+    global last_video_pts
+    if frame['media_type'] == 'video':
+        if last_video_pts is not None and frame['pkt_pts_time'] <= last_video_pts:
+            print 'Out of order video frame %f is ahead of %f' % (frame['pkt_pts_time'], last_video_pts)
+        else:
+            print 'OK frame %f' % frame['pkt_pts_time']
+        last_video_pts = frame['pkt_pts_time']
+
+p = subprocess.Popen(shlex.split('ffprobe -show_frames %s' % sys.argv[1]), stdin=None, stdout=subprocess.PIPE)
+frame = dict()
+while True:
+    l = p.stdout.readline()
+    if l == '':
+        break
+
+    l = l.strip()
+
+    if l == '[/FRAME]':
+        handle(frame)
+        frame = dict()
+    elif l != '[FRAME]' and l != '[SIDE_DATA]' and l != '[/SIDE_DATA]':
+        s = l.split('=')
+        if s[0] == 'pkt_pts_time':
+            frame[s[0]] = float(s[1])
+        else:
+            frame[s[0]] = s[1]
index 9867b79b099a12466790c637ce78011a6867a830..10bb4531032e4d0068340b14c985d9b401ac2fb5 100644 (file)
@@ -57,6 +57,7 @@ protected:
                PASS_REASON_SUBTITLE
        };
 
+       /** @return true if this decoder has already returned all its data and will give no more */
        virtual bool pass (PassReason, bool accurate) = 0;
 };
 
index 5d08615a68c9578c1a4283ea1c270ed7b98f80af..38b9e8ced058c77d23dd0396a1621837181a809f 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