1 时间基与时间戳的概念
在FFmpeg中,时间基(time_base)是时间戳(timestamp)的单位,时间戳值乘以时间基,可以得到实际的时刻值(以秒等为单位)。例如,如果一个视频帧的dts是40,pts是160,其time_base是1/1000秒,那么可以计算出此视频帧的解码时刻是40毫秒(40/1000),显示时刻是160毫秒(160/1000)。FFmpeg中时间戳(pts/dts)的类型是int64_t类型,把一个time_base看作一个时钟脉冲,则可把dts/pts看作时钟脉冲的计数。
2 三种时间基tbr、tbn和tbc
不同的封装格式具有不同的时间基。在FFmpeg处理音视频过程中的不同阶段,也会采用不同的时间基。
FFmepg中有三种时间基,命令行中tbr、tbn和tbc的打印值就是这三种时间基的倒数:
tbn:对应容器中的时间基(对应的结构体为AVPacket)。值是AVStream.time_base的倒数
tbc:对应编解码器中的时间基(对应的结构体为AVFrame)。值是AVCodecContext.time_base的倒数
tbr:从视频流中猜算得到,可能是帧率或场率(帧率的2倍)
3 内部时间基AV_TIME_BASE
除以上三种时间基外,FFmpeg还有一个内部时间基AV_TIME_BASE(以及分数形式的AV_TIME_BASE_Q)
#define AV_TIME_BASE 1000000
#define AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE}
AV_TIME_BASE及AV_TIME_BASE_Q用于FFmpeg内部函数处理,使用此时间基计算得到时间值表示的是微秒。
4 时间转换函数
因为数据状态不同,时间基不一样,所以我们必须转换,这就是pts的转换,以下是时间基转换函数。
static inline double av_q2d(AVRational a){
return a.num / (double) a.den;
}
av_q2d 函数负责把AVRational结构转换成double,通过这个函数可以计算出某一帧在视频中的时间位置:
AVStream stream;
AVPacket packet;
packet播放时刻值:timestamp(单位秒) = packet.pts × av_q2d(stream.time_base);
packet播放时长值:duration(单位秒) = packet.duration × av_q2d(stream.time_base);
av_rescale_q 函数:这个函数的作用是计算a*bq / cq来把时间戳从一个时间基调整到另外一个时间基。在进行时间基转换的时候,应该首先这个函数,因为它可以避免溢出的情况发生。
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq) av_const;
av_packet_rescale_ts 用于将AVPacket中各种时间值从一种时间基转换为另一种时间基。
voi