Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions src/VideoReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,19 +338,28 @@ bool VideoReader::seek(int64_t frame_number) {
(frame_number < current_frame_) || (frame_number - current_frame_ > 50);

if (need_keyframe_seek) {
int64_t target_ts;
if (stream->avg_frame_rate.num != 0 && stream->avg_frame_rate.den != 0) {
target_ts = av_rescale_q(frame_number,
av_inv_q(stream->avg_frame_rate),
stream->time_base);
} else {
AVRational fps = stream->r_frame_rate;
if (fps.num == 0 || fps.den == 0) {
fps = {30, 1};
}
target_ts = av_rescale_q(frame_number, av_inv_q(fps), stream->time_base);
// Keyframe seeking needs a frame rate twice: to turn the requested
// frame index into a target timestamp, and to turn the landing
// timestamp back into an index. If the container declares none there
// is no honest way to do either, so fail here rather than proceed on a
// fabricated rate -- getFPS() reports 0.0 in exactly this case, and the
// two must not disagree.
AVRational seek_fps =
(stream->avg_frame_rate.num != 0 && stream->avg_frame_rate.den != 0)
? stream->avg_frame_rate
: stream->r_frame_rate;

if (seek_fps.num == 0 || seek_fps.den == 0) {
detail::log(LogLevel::Error)
<< "framewright::VideoReader: Cannot seek by frame number without a frame rate"
<< std::endl;
return false;
}

const double frame_duration = av_q2d(av_inv_q(seek_fps));
const int64_t target_ts =
av_rescale_q(frame_number, av_inv_q(seek_fps), stream->time_base);

auto seek_to_keyframe = [&]() -> bool {
int ret =
av_seek_frame(formatCtx_, videoStreamIndex_, target_ts, AVSEEK_FLAG_BACKWARD);
Expand All @@ -376,11 +385,6 @@ bool VideoReader::seek(int64_t frame_number) {
return false;
}

AVRational seek_fps =
stream->avg_frame_rate.num != 0 ? stream->avg_frame_rate : stream->r_frame_rate;
double frame_duration =
(seek_fps.num != 0 && seek_fps.den != 0) ? av_q2d(av_inv_q(seek_fps)) : 0.0;

// Without a usable timestamp there is no way to know where we landed.
// Rewind to the start so the reader is left in a position it can
// honestly report, then fail.
Expand Down
Loading