[Libav-user] use AVPacket.pts with av_seek_frame()
amillett at matrox.com
Tue Jul 17 15:16:25 CEST 2012
> As an experiment, I am first reading through all the packets, so that
> I know that I have an X number of packets. Each packet has a pts
> value, from 1 to X.
Be careful with this. It is not expected for a video to have it's packet
in increments of 1. I just checked a sample mp4 (h264) file with my code
and the packets were output with this sequence of pts: 0, 24, 48, 72,
etc. In this case, AVPacket->duration == 24.
> const int64_t pti = pFormatContext.duration / (int64_t)X; // duration
> of a packet
This is the same as AVPacket->duration, is it not?
In this case there may be a problem if you try opening a file that has
frames with variable duration.
> const int64_t packetTimestamp = Y * pti;
> av_seek_frame(pFormatCtx, videoStream, packetTimestamp * AV_TIME_BASE,
Okay, so we're back to what seems like AVStream->time_base units and
this is what we want. Have you tried removing the AV_TIME_BASE ? The
best way to debug would be to go in debug mode and to check the flow of
the code line by line to see if packetTimestamp has the value of the
targeted AVPacket's pts (since you already read all the packets, you can
easily see the this value).
Speaking of which, I do believe you should not try to make up pts with
formulas, but rather store them on the first read-up and use them later.
The way I would do it would be like this :
- Loop all the packets with av_read_frame().
- Use avcodec_decode_video2() for each packet. When a frame is returned,
store the pts in ptsArray[i] and then increment i (starting from 0).
Since avcodec_decode_video2 will always return the frames in their
presentation order, you know that ptsArray[Y] will be the the pts value
of the packet you want to show the frame Y.
- When you want to go to the frame Y: av_seek_frame(pFormatCtx,
videoStream, ptsArray[Y], backwardFlag) (maybe with the *AV_TIME_BASE,
but I would guess not).
- av_read_frame() and avcodec_decode_video2().
You could test it easily by just storing one pts value (hardcoding it if
you have to) and then checking if you can access the frame.
Also I don't believe you said you were using av_read_frame() after using
av_seek_frame()... could it be that you are calling
avcodec_decode_video2() with the last packet you read in the first loop?
Hope this helps you...
More information about the Libav-user