ffmpeg -ss 10.800 -i input.flv -t 5 -c copy -vframes 600 -y out.mp4
-ss用于将文件seek到指定的时间点位置。
这条命令中的-ss的单位是什么? 实际命令行中-ss支持的格式 为:
http://ffmpeg.org/ffmpeg-utils.html#time-duration-syntax
The following examples are all valid time duration:
‘55’
55 seconds
‘12:03:45’
12 hours, 03 minutes and 45 seconds
‘23.189’
23.189 seconds
可见-ss中跟的就是真实的时间点。
在ffmpeg代码中 又是以什么单位存在呢?
ffmpeg_opt.c中,OptionDef中
{ "ss", HAS_ARG | OPT_TIME | OPT_OFFSET |
OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(start_time) },
"set the start time offset", "time_off" },
可见-ss对应的变量类型为OPT_TIME,保存在变量start_time中。
typedef struct OptionsContext {
OptionGroup *g;
/* input/output options */
int64_t start_time;
int64_t start_time_eof;
int seek_timestamp;
...
int64_t recording_time;
int64_t stop_time;
...
} OptionsContext;
start_time中保存的是什么呢?
解析参数时:

else if (po->flags & OPT_TIME) {
*(int64_t *)dst = parse_time_or_die(opt, arg, 1);
}
最终调用的用于解析的函数如下:
int av_parse_time(int64_t *timeval, const char *timestr, int duration)
{
...
int today = 0, negative = 0, microseconds = 0, suffix = 1000000;
...
t *= suffix;
t += microseconds;
*timeval = negative ? -t : t;
return 0;
}
可见最终解析的时间转换为1000000为单位,也就是微秒为单位。
其实也就是单位是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}
也就是说OptionsContext中的start_time的单位是AV_TIME_BASE。
同样情况的还有:

所以,只要看到OptionsContext中的以上几个变量,应该知道它们的单位就是AV_TIME_BASE。
只要能和这些变量发生赋值或加减操作的,单位肯定也是AV_TIME_BASE.
比如static int open_input_file(OptionsContext *o, const char *filename)
函数中的
...
if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) {
o->stop_time = INT64_MAX;
av_log(NULL, AV_LOG_WARNING, "-t and -to cannot be used together; using -t.\n");
}
...
if (o->start_time_eof != AV_NOPTS_VALUE) {
if (o->start_time_eof >= 0) {
av_log(NULL, AV_LOG_ERROR, "-sseof value must be negative; aborting\n");
exit_program(1);
}
if (ic->duration > 0) {
// 这里ic->duration可以和o->start_time_eof相加
// 说明它的单位肯定也是AV_TIME_BASE
o->start_time = o->start_time_eof + ic->duration;
if (o->start_time < 0) {
av_log(NULL, AV_LOG_WARNING, "-sseof value seeks to before start of file %s; ignored\n", filename);
o->start_time = AV_NOPTS_VALUE;
}
} else
av_log(NULL, AV_LOG_WARNING, "Cannot use -sseof, duration of %s not known\n", filename);
}
...
// 这里timestamp可被o->start_time赋值
// 说明它的单位肯定也是AV_TIME_BASE
timestamp = (o->start_time == AV_NOPTS_VALUE) ? 0 : o->start_time;
/* add the stream start time */
if (!o->seek_timestamp && ic->start_time != AV_NOPTS_VALUE)
timestamp += ic->start_time;
...
f = av_mallocz(sizeof(*f));
if (!f)
exit_program(1);
input_files[nb_input_files - 1] = f;
f->ctx = ic;
f->ist_index = nb_input_streams - ic->nb_streams;
// 通过以下的赋值操作
// 可以看出InputFile的start_time、recording_time、
// input_ts_offset、ts_offset的单位肯定也是AV_TIME_BASE
f->start_time = o->start_time;
f->recording_time = o->recording_time;
f->input_ts_offset = o->input_ts_offset;
f->ts_offset = o->input_ts_offset - (copy_ts ? (start_at_zero && ic->start_time != AV_NOPTS_VALUE ? ic->start_time : 0) : timestamp);
网友评论