+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
--- /dev/null
+#!/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]
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;
};
/*
- 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
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.
if (pass (PASS_REASON_VIDEO, accurate)) {
/* The decoder has nothing more for us */
+ _no_data_frame = frame;
break;
}
}
}
- /* 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 ();
}
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