[Libav-user] When Seeking to specific frame with AVSEEK_FLAG_BACKWARD, libav will seek to exact specified frame

Odiee47 . simula47 at gmail.com
Tue May 5 12:40:20 EEST 2020


Hi all.

I'm currently working on a simple media player that has to seek to exact
specified frame.
I'm currently using av_seek_frame(); function with AVSEEK_FLAG_BACKWARD
flag which will put me to the first
I-Frame back of my specified location and then I calculate the current
frame  based on this function and just the just
decode all frames until my specified frames is reached.

int64_t PtsToFrame(AVStream* pavStream, int64_t pts)
{
    long double timestamp = pts *
av_q2d(videoState->video->ptrVideoStream->time_base);
    long double fps =
av_q2d(videoState->video->ptrVideoStream->r_frame_rate);
    long double est_frame_f = timestamp  * fps;
    long double rounded = round(est_frame_f);
    auto est_frame_i  = static_cast<std::int64_t>(rounded);

    return est_frame_i;
}

I also use this function to calculate PTS from specified frame

int64_t FrameToPts(AVStream* pavStream, int frame)
{
  int64_t target_dts_usecs = (int64_t)round(frame *
(double)pavStream->r_frame_rate.den / pavStream->r_frame_rate.num *
AV_TIME_BASE);
  auto first_dts_usecs = (int64_t)round(pavStream->first_dts *
(double)pavStream->time_base.num / pavStream->time_base.den * AV_TIME_BASE);
  target_dts_usecs += first_dts_usecs;

 return target_dts_usecs;
}

This works perfectly for almost every format. But now I have few *.mpg
files that have incorrect timestamps.
This has also messed up my normal seek-by-slider functionality.

I found that ffplay solves this issue by checking if it is currently
opening a file that allow for timestamp discontinuities
and then use seek_by_bytes flag when seeking through video.

This has fixed my seeking-by-slider issues but now, on these files my
av_seek_frame(videoState->ptrFormatCtx_, -1, seekTarget,
AVSEEK_FLAG_BACKWARD);
will just seek to exact frame (seekTarget) instead of the first I frame
specified.

My PtsToFrame function also returns incorrect frames (adds 10-13 frames).

To further clarify.
Presume that first I frame in the video is frame 1, the second is frame 250

  JumpToFrame(50);
  int64_t seekTarget = FrameToPts(avStream, frame);
  ret = av_seek_frame(videoState_->ptrFormatCtx_, -1, seekTarget,
AVSEEK_FLAG_BACKWARD);   // should jump to frame 1
  if (ret > 0)
    {
     FastForwardToFrame(frame,seekTarget);  // ff to desired frame
     // ... flush queue
    }

  FastForwardToFrame(...)
  {
   // ... decode frame and put result in pFrame
  if (gotFrame)
    {
     current_frame = PtsToFrame(...);
    }
  }

  Current frame at this point will be the exact frame specified, but since
it's not an I frame the picture glitched.
  I can also confirm that it's the exact frame because I processed the
video with ffmpeg and I have a frame number subtitles on the video.

I presume this happens because of the format and incorrect timestamps in
the file, but I just recently started with libav and can't figure out
where the issue is. Perhaps in the FrameToPts() function? Because when I
hard code the seek frame I can get the FastForward function to
run correctly (although still with an incorrect frame offset).

Anyone had an issue like this?
Thanks.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://ffmpeg.org/pipermail/libav-user/attachments/20200505/5aa220cd/attachment.html>


More information about the Libav-user mailing list