FFmpeg中有Video, Audio, Subtitle等各种数据,它们根据自己的特性有不同的时间单位。FFmpeg还有基本的接口,也有自己的时间单位。这里说明了各种时间单位,和各种单位之间的转换。
1. 使用者惯用的时间
使用者习惯用1秒作为时间单位。
2. AV_TIME_BASE
FFmpeg使用AV_TIME_BASE度量时间,它的倒数AV_TIME_BASE_Q是它的时间单位。FFmpeg将AV_TIME_BASE_Q定义为1微秒。
#define AV_TIME_BASE 1000000
#define AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE}
typedef struct AVRational
{
int num; //numerator
int den; //denominator
} AVRational;
使用AV_TIME_BASE的接口如:
- AVFormatContext.duration
- AVStream.duration
- avformat_seek_file()
3. 帧的pts
有些时间依赖具体的封装格式。
如MP4格式中,有专门的字段规定了pts的度量基础,如:
- Movie Header Box(mvhd)中的time scale字段
- Media Header Box(mdhd)中的time scale字段
都用来规定1秒内的时间单元数,也就是时间单位是1 / time scale。FFmpeg把这个值保存在AVStream.time_base中。
使用av_read_frame()读到帧AVPacket。AVPacket.pts是FFmpeg从MP4文件中读来的,没有转换,所以时间单位是AVStream.time_base。
时间也依赖封装的数据类型。不同数据类型的Stream,它的time_base不同,比如Subtitle stream就与Video stream不同。
4. 时间转换
av_rescale_q ()用于把时间从一种时间单位调整到另外一个时间单位。这个函数的实质是计算(a * bq / cq)。它可以避免溢出的情况。
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
如下的例子将帧的pts从MP4文件的时间转换成微秒:
AVPacket* pkt = ...;
AVStream* st = ...;
pkt->pts = av_rescale_q (pkt->pts, st->time_base, AV_TIME_BASE_Q);
参考资料
ffmpeg中的时间
https://www.cnblogs.com/yinxiangpei/articles/3892982.html
网友评论