时间基、时间戳
时间基:表示时间单位的分数,用来定义视频或音频流中时间的精度。其形式是一个分数,分子通常为 1,而分母则表示每秒的单位数。
时间戳:代表在时间轴里占了多少个格子,是特定的时间点。
时间基是时间戳的单位,时间戳值乘以时间基,就可得到实际的时刻值。
c
typedef struct AVRational{
int num; //numerator
int den; //denominator
} AVRational;
FFmpeg 中的几种时间基
- tbn:视频流的时间基,time base of stream,AVStream.time_base 的倒数
c
typedef struct AVStream {
...
/**
* This is the fundamental unit of time (in seconds) in terms
* of which frame timestamps are represented.
*
* decoding: set by libavformat
* encoding: May be set by the caller before avformat_write_header() to
* provide a hint to the muxer about the desired timebase. In
* avformat_write_header(), the muxer will overwrite this field
* with the timebase that will actually be used for the timestamps
* written into the file (which may or may not be related to the
* user-provided one, depending on the format).
*/
AVRational time_base;
}
- tbr:帧率,time base of rate
- tbc:视频解码的时间基,time base of codec,AVCodecContext.time_base 的倒数
c
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;
}
- FFmpeg 内部时间基 AV_TIME_BASE
c
#define AV_TIME_BASE 1000000
#define AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE}
使用此时间基计算得到的时间值表示的单位是微秒。
时间值的形式转换
c
/**
* 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 形式转换为 double 形式。将不同时间基的值转成按秒为单位的运算如下:
timestamp(秒) = pts * av_q2d(time_base)
时间基转换函数
c
/**
* Rescale a 64-bit integer by 2 rational numbers.
*
* The operation is mathematically equivalent to `a * bq / cq`.
*
* This function is equivalent to av_rescale_q_rnd() with #AV_ROUND_NEAR_INF.
*
* @see av_rescale(), av_rescale_rnd(), av_rescale_q_rnd()
*/
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const;
将时间值从一种时间基转换为另一种时间基,其计算公式为 a * bq / cq
c
/**
* Rescale a 64-bit integer by 2 rational numbers with specified rounding.
*
* The operation is mathematically equivalent to `a * bq / cq`.
*
* @see av_rescale(), av_rescale_rnd(), av_rescale_q()
*/
int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq,
enum AVRounding rnd) av_const;
同 av_rescale_q 相比增加了一个指定舍入方式的参数
c
/**
* Convert valid timing fields (timestamps / durations) in a packet from one
* timebase to another. Timestamps with unknown values (AV_NOPTS_VALUE) will be
* ignored.
*
* @param pkt packet on which the conversion will be performed
* @param tb_src source timebase, in which the timing fields in pkt are
* expressed
* @param tb_dst destination timebase, to which the timing fields will be
* converted
*/
void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst);
用于将 AVPacket 中各种时间值从一种时间基转换为另一种时间基