Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ffmpeg time unit explanation and av_seek_frame method

What does time_base mean in ffmpeg? document(here) says it is "frames per second". and I see in a real example that:

AVFormatContext->streams[video_index]->time_base == 1 / 30000

But video's AVCodecContext->time_base == 1001 / 60000

This makes me quite confused, and I don't understand them.

The second question is about av_seek_frame method. If seeking via time stamp (last parameter is AVSEEK_FLAG_BACKWARD or 0), the seek is started from current position read by av_seek_frame? or from the start of the file? or from the start position of decoding after last av_seek_frame call ?

like image 484
Mr.Wang from Next Door Avatar asked Sep 02 '12 09:09

Mr.Wang from Next Door


3 Answers

But video's AVCodecContext->time_base == 1001 / 60000

This makes me quite confused, and I don't understand them.

time_base is of type AVRational, which is a rational number composed of a numerator and a denominator, as opposed to using a decimal point. I assume the reason they don't just use double is that this way you don't lose any precision.

AVRational is defined in the sources as:

typedef struct AVRational{
    int num; ///< numerator
    int den; ///< denominator
} AVRational;

time_base is also reciprocal to frames per second, not equal to it. So if you have 30 fps, this means that time base is 1/30, instead of 30.

like image 168
sashoalm Avatar answered Oct 04 '22 20:10

sashoalm


Do not use r_frame_rate, since it is libavformats guess, not exact. (see http://ffmpeg.org/pipermail/ffmpeg-devel/2005-May/003079.html )

AVCodecContext.time_base gives the exact fps. If ticks_per_frame is 2, downsize the time_base with 1/2. For example, if AVCodecContext.time_base (1, 60) and ticks_per_frame is 1, the fps is 60. If ticks_per_frame is 2, fps is 30.

If AVCodecContext->time_base is (1001, 60000), fps is 60.

The time_base for AVCodecContext is related to fps.

The time_base for AVStream is only for time unit in the methods in AVStream, such as getting the time of one frame, or the .start variable.

There is another time_base for AVPacket. But from ffmpeg-devel, they prefer to make AVPacket.time_base the same as the one for AVStream.

like image 45
user1914692 Avatar answered Oct 04 '22 21:10

user1914692


I tested all of the fields from satuon's comment link with a number of video files, and it appears as though the correct framerate can be calculated thus:

double framerate = av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate);

... where pFormatCtx is your AVFormatContext and videoStream is the index of your video stream, found using this code:

int videoStream = -1;
for (uint i=0; i < pFormatCtx->nb_streams; i++) {
    if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && videoStream < 0) {
        videoStream = i;
    }
}

Using ffmpeg 1.1.

like image 43
njahnke Avatar answered Oct 04 '22 19:10

njahnke