From a30c4d9551863065a0c9c15601a5647341efef0f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Thu, 21 Mar 2019 10:41:59 -0400 Subject: [PATCH] rework ffmpeg_input to not use pkt_duration which doesn't exist in avconv --- src/zm_ffmpeg_input.cpp | 47 +++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/zm_ffmpeg_input.cpp b/src/zm_ffmpeg_input.cpp index d9c7c2fd3..139e6d862 100644 --- a/src/zm_ffmpeg_input.cpp +++ b/src/zm_ffmpeg_input.cpp @@ -214,39 +214,44 @@ AVFrame *FFmpeg_Input::get_frame( int stream_id, double at ) { seek_target = av_rescale_q(seek_target, AV_TIME_BASE_Q, input_format_context->streams[stream_id]->time_base); Debug(1, "Getting frame from stream %d at %" PRId64, stream_id, seek_target); - if ( frame ) { - if ( (frame->pts + frame->pkt_duration) > seek_target ) { - // The current frame is still the valid picture. - Debug(2,"Returning previous frame which is still good"); - return frame; - } - if ( frame->pts < seek_target ) { - Debug(2, "Frame pts %" PRId64 " duration %" PRId64, frame->pts, frame->pkt_duration); - while ( frame && (frame->pts < seek_target) ) { - if ( ! get_frame(stream_id) ) - return frame; - } - return frame; - } - } - int ret; - if ( frame ) { - if ( ( ret = av_seek_frame(input_format_context, stream_id, seek_target, AVSEEK_FLAG_ANY) < 0 ) ) { + + if ( !frame ) { + // Don't have a frame yet, so get a keyframe before the timestamp + if ( ( ret = av_seek_frame( + input_format_context, stream_id, seek_target, AVSEEK_FLAG_FRAME + ) < 0 ) ) { Error("Unable to seek in stream"); return NULL; } + // Have to grab a frame to update our current frame to know where we are + get_frame(stream_id); + } // end if ! frame - } else { - // No previous frame... are we asking for first frame? - // Must go for a keyframe + if ( frame->pts > seek_target ) { + zm_dump_frame(frame, "frame->pts > seek_target, seek backwards"); + // our frame must be beyond our seek target. so go backwards to before it if ( ( ret = av_seek_frame(input_format_context, stream_id, seek_target, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME ) < 0 ) ) { Error("Unable to seek in stream"); return NULL; } + // Have to grab a frame to update our current frame to know where we are + get_frame(stream_id); + zm_dump_frame(frame, "frame->pts > seek_target, got"); + } // end if frame->pts > seek_target + + // Seeking seems to typically seek to a keyframe, so then we have to decode until we get the frame we want. + if ( frame->pts <= seek_target ) { + zm_dump_frame(frame, "pts <= seek_target"); + while ( frame && (frame->pts < seek_target) ) { + if ( ! get_frame(stream_id) ) + return frame; + } + return frame; } + return get_frame(stream_id); } // end AVFrame *FFmpeg_Input::get_frame( int stream_id, struct timeval at)