X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fffmpeg_decoder.cc;h=a67905daeedde17ebc590f6f130b9911508faa4c;hb=ef9801159e02595d906f669f5604789f1103dca0;hp=201fac8aa5a74dabd82ee4e3b577de4b9e239cd1;hpb=c719feb3cc4a5627827f8576a9b34756f701d59d;p=dcpomatic.git diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 201fac8aa..a67905dae 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -293,6 +293,7 @@ FFmpegDecoder::seek (VideoContent::Frame frame, bool accurate) will hopefully then step through to where we want to be. */ int initial = frame; + if (accurate) { initial -= 5; } @@ -303,8 +304,6 @@ FFmpegDecoder::seek (VideoContent::Frame frame, bool accurate) /* Initial seek time in the stream's timebase */ int64_t const initial_vt = ((initial / _ffmpeg_content->video_frame_rate()) - _video_pts_offset) / time_base; - /* Wanted final seek time in the stream's timebase */ - int64_t const final_vt = ((frame / _ffmpeg_content->video_frame_rate()) - _video_pts_offset) / time_base; av_seek_frame (_format_context, _video_stream, initial_vt, AVSEEK_FLAG_BACKWARD); @@ -314,38 +313,39 @@ FFmpegDecoder::seek (VideoContent::Frame frame, bool accurate) } _just_sought = true; - - if (frame == 0) { - /* We're already there; from here on we can only seek non-zero amounts */ + _video_position = frame; + + if (frame == 0 || !accurate) { + /* We're already there, or we're as close as we need to be */ return; } - if (accurate) { - while (1) { - int r = av_read_frame (_format_context, &_packet); - if (r < 0) { - return; - } - - avcodec_get_frame_defaults (_frame); - - if (_packet.stream_index == _video_stream) { - int finished = 0; - 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 >= final_vt) { - _video_position = rint ( - (bet * time_base + _video_pts_offset) * _ffmpeg_content->video_frame_rate() - ); - av_free_packet (&_packet); - break; - } - } + while (1) { + int r = av_read_frame (_format_context, &_packet); + if (r < 0) { + return; + } + + if (_packet.stream_index != _video_stream) { + continue; + } + + avcodec_get_frame_defaults (_frame); + + int finished = 0; + r = avcodec_decode_video2 (video_codec_context(), _frame, &finished, &_packet); + if (r >= 0 && finished) { + _video_position = rint ( + (av_frame_get_best_effort_timestamp (_frame) * time_base + _video_pts_offset) * _ffmpeg_content->video_frame_rate() + ); + + if (_video_position >= (frame - 1)) { + av_free_packet (&_packet); + break; } - - av_free_packet (&_packet); } + + av_free_packet (&_packet); } } @@ -383,7 +383,13 @@ FFmpegDecoder::decode_audio_packet () audio (silence, _audio_position); } } - + + int const data_size = av_samples_get_buffer_size ( + 0, audio_codec_context()->channels, _frame->nb_samples, audio_sample_format (), 1 + ); + + audio (deinterleave_audio (_frame->data, data_size), _audio_position); + copy_packet.data += decode_result; copy_packet.size -= decode_result; } @@ -451,6 +457,8 @@ FFmpegDecoder::decode_video_packet () /* This PTS is more than one frame forward in time of where we think we should be; emit a black frame. */ + + /* XXX: I think this should be a copy of the last frame... */ boost::shared_ptr black ( new Image ( static_cast (_frame->format),