[Libav-user] use AVPacket.pts with av_seek_frame()

Alexandre Millette amillett at matrox.com
Tue Jul 17 15:16:25 CEST 2012

Hello again.
> 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, 
> backwardFlag).
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...
Alex M

More information about the Libav-user mailing list