看到ffmpeg中很多时间单位都是AV_TIME_BASE units
, 这个是个什么单位呢?
ffmpeg中的内部计时单位(时间基),ffmepg中的所有时间都是于它为一个单位,比如AVStream中的duration即以为着这个流的长度为duration个AV_TIME_BASE。
/**
* Internal time base represented as integer
*/
#define AV_TIME_BASE 1000000
/**
* Internal time base represented as fractional value
*/
#define AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE}
可见ffmpeg内部时间单位为微秒 (μs), 即AV_TIME_BASE units
单位是1us。
AV_TIME_BASE_Q是AV_TIME_BASE的倒数。
int hours, mins, secs, us;
...
secs = FFABS(pts) / AV_TIME_BASE;
us = FFABS(pts) % AV_TIME_BASE;
举一些以AV_TIME_BASE units为单位的例子:
- InputStream
typedef struct InputStream {
int file_index;
AVStream *st;
...
int64_t start; /* time when read started */
/* predicted dts of the next packet read for this stream or (when there are
* several frames in a packet) of the next frame in current packet (in AV_TIME_BASE units) */
int64_t next_dts;
int64_t dts; ///< dts of the last packet read for this stream (in AV_TIME_BASE units)
int64_t next_pts; ///< synthetic pts for the next decode frame (in AV_TIME_BASE units)
int64_t pts; ///< current pts of the decoded frame (in AV_TIME_BASE units)
...
}
- OutputFile
typedef struct OutputFile {
...
int64_t recording_time; ///< desired length of the resulting file in microseconds == AV_TIME_BASE units
int64_t start_time; ///< start time in microseconds == AV_TIME_BASE units
...
} OutputFile;
时间基转换公式
timestamp(ffmpeg内部时间戳) = AV_TIME_BASE * time(秒)
time(秒) = AV_TIME_BASE_Q * timestamp(ffmpeg内部时间戳)
所以当需要把视频跳转到N秒的时候可以使用下面的方法:
int64_t timestamp = N * AV_TIME_BASE;
av_seek_frame(fmtctx, index_of_video, timestamp, AVSEEK_FLAG_BACKWARD);
av_rescale_q
ffmpeg同样为我们提供了不同时间基之间的转换函数
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
这个函数的作用是计算a * bq / cq,来把时间戳从一个时基调整到另外一个时基。在进行时基转换的时候,我们应该首选这个函数,因为它可以避免溢出的情况发生。
References:
https://www.cnblogs.com/yinxiangpei/articles/3892982.html
https://blog.csdn.net/matrix_laboratory/article/details/53159511
https://www.suninf.net/2018/02/ffmpeg-timestamps.html
https://www.jianshu.com/p/bf323cee3b8e