时间基、时间戳
时间基:表示时间单位的分数,用来定义视频或音频流中时间的精度。其形式是一个分数,分子通常为 1,而分母则表示每秒的单位数。
时间戳:代表在时间轴里占了多少个格子,是特定的时间点。
时间基是时间戳的单位,时间戳值乘以时间基,就可得到实际的时刻值。
typedef struct AVRational{int num; //numeratorint den; //denominator
} AVRational;
FFmpeg 中的几种时间基
- tbn:视频流的时间基,time base of stream,AVStream.time_base 的倒数
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 的倒数
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
#define AV_TIME_BASE 1000000
#define AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE}
使用此时间基计算得到的时间值表示的单位是微秒。
时间值的形式转换
/*** 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)
时间基转换函数
/*** 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
/*** 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 相比增加了一个指定舍入方式的参数
/*** 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 中各种时间值从一种时间基转换为另一种时间基