ffmpeg # AVRational
用ffmpeg经常用到以下的数据结构:
/**
* Rational number (pair of numerator and denominator).
*/
typedef struct AVRational{
int num; ///< Numerator
int den; ///< Denominator
} AVRational;
Rational是啥意思? 其实这里表示的Rational number。
Rational number
In mathematics, a rational number is any number that can be expressed as the quotient or fraction p/q of two integers, a numerator p and a non-zero denominator q.[1]
Since q may be equal to 1, every integer is a rational number.
rational number就是可以表示成p/q两个整数相除的数。其实就是传说中的有理数。
numberator: 分子
denominator: 分母
可见AVRational中num是numberator的简称,den是denominator的简称。
AVRational time_base
typedef struct AVCodecContext {
...
/**
* This is the fundamental unit of time (in seconds) in terms
* of which frame timestamps are represented. For fixed-fps content,
* timebase should be 1/framerate and timestamp increments should be
* identically 1.
* This often, but not always is the inverse of the frame rate or field rate
* for video. 1/time_base is not the average frame rate if the frame rate is not
* constant.
*
* Like containers, elementary streams also can store timestamps, 1/time_base
* is the unit in which these timestamps are specified.
* As example of such codec time base see ISO/IEC 14496-2:2001(E)
* vop_time_increment_resolution and fixed_vop_rate
* (fixed_vop_rate == 0 implies that it is different from the framerate)
*
* - encoding: MUST be set by user.
* - decoding: the use of this field for decoding is deprecated.
* Use framerate instead.
*/
AVRational time_base;
...
}
帧率为25时
一个需要注意的地方,我们在这里使用了 int64 来存储 PTS,这是因为 PTS 是一个整型值。比如,如果一个视频流的帧率是 24,那么 PTS 为 42 则表示这一帧应该是第 42 帧如果我们 1/24 秒播一帧的话。我们可以用这个值除以帧率来得到以秒为单位的时间。视频流的 time_base 值则是 1/framerate,所以当我们获得 PTS 后,我们要乘上 time_base。
PTS的时间单位为AVRational,所以计算实际的时间时,经常遇到如下代码:
if (frame->pts != AV_NOPTS_VALUE)
dpts = av_q2d(is->video_st->time_base) * frame->pts;
av_q2d是啥?
av_q2d
/**
* Convert an AVRational to a `double`.
* @param a AVRational to convert
* @return `a` in floating-point form
* @see av_d2q()
*/
static inline double av_q2d(AVRational a){
return a.num / (double) a.den;
}
AVRational frame_rate
有时帧率也用AVRational来表示。
static void do_video_out(OutputFile *of,
OutputStream *ost,
AVFrame *next_picture,
double sync_ipts)
{
...
AVRational frame_rate;
...
frame_rate = av_buffersink_get_frame_rate(filter);
if (frame_rate.num > 0 && frame_rate.den > 0)
duration = 1/(av_q2d(frame_rate) * av_q2d(enc->time_base));
....
}
References:
https://en.wikipedia.org/wiki/Rational_number
http://www.samirchen.com/ffmpeg-tutorial-5/