summaryrefslogtreecommitdiff
path: root/src/lib/ffmpeg_decoder.cc
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-07-12 23:52:35 +0100
committerCarl Hetherington <cth@carlh.net>2013-07-12 23:52:35 +0100
commitbc5253cec3293a3cde39f5b9fea491a6be720640 (patch)
tree81ef03eb0c83a2acd5e626825f99ca6cd03eda3d /src/lib/ffmpeg_decoder.cc
parent33dd911e6c2cc3c42425d4260bd22dbe462d01be (diff)
Try to improve refetching of last frame and seek backwards.
Diffstat (limited to 'src/lib/ffmpeg_decoder.cc')
-rw-r--r--src/lib/ffmpeg_decoder.cc20
1 files changed, 17 insertions, 3 deletions
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index 27009114c..c77cb71c0 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -264,8 +264,22 @@ void
FFmpegDecoder::seek (VideoContent::Frame frame, bool accurate)
{
double const time_base = av_q2d (_format_context->streams[_video_stream]->time_base);
- int64_t const vt = frame / (_ffmpeg_content->video_frame_rate() * time_base);
- av_seek_frame (_format_context, _video_stream, vt, AVSEEK_FLAG_BACKWARD);
+
+ /* If we are doing an accurate seek, our initial shot will be 5 frames (5 being
+ a number plucked from the air) earlier than we want to end up. The loop below
+ will hopefully then step through to where we want to be.
+ */
+ int initial = frame;
+ if (accurate) {
+ initial -= 5;
+ }
+
+ /* Initial seek time in the stream's timebase */
+ int64_t const initial_vt = initial / (_ffmpeg_content->video_frame_rate() * time_base);
+ /* Wanted final seek time in the stream's timebase */
+ int64_t const final_vt = frame / (_ffmpeg_content->video_frame_rate() * time_base);
+
+ av_seek_frame (_format_context, _video_stream, initial_vt, AVSEEK_FLAG_BACKWARD);
avcodec_flush_buffers (video_codec_context());
if (_subtitle_codec_context) {
@@ -293,7 +307,7 @@ FFmpegDecoder::seek (VideoContent::Frame frame, bool accurate)
int const r = avcodec_decode_video2 (video_codec_context(), _frame, &finished, &_packet);
if (r >= 0 && finished) {
int64_t const bet = av_frame_get_best_effort_timestamp (_frame);
- if (bet >= vt) {
+ if (bet >= final_vt) {
_video_position = rint (
(bet * time_base + _pts_offset) * _ffmpeg_content->video_frame_rate()
);