Using -ss 0 to drop frames with negative timestamps is a perfectly valid
use case.
... | ... |
@@ -652,10 +652,11 @@ static int poll_filter(OutputStream *ost) |
652 | 652 |
return ret; |
653 | 653 |
|
654 | 654 |
if (filtered_frame->pts != AV_NOPTS_VALUE) { |
655 |
+ int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; |
|
655 | 656 |
filtered_frame->pts = av_rescale_q(filtered_frame->pts, |
656 | 657 |
ost->filter->filter->inputs[0]->time_base, |
657 | 658 |
ost->st->codec->time_base) - |
658 |
- av_rescale_q(of->start_time, |
|
659 |
+ av_rescale_q(start_time, |
|
659 | 660 |
AV_TIME_BASE_Q, |
660 | 661 |
ost->st->codec->time_base); |
661 | 662 |
} |
... | ... |
@@ -948,7 +949,7 @@ static int check_output_constraints(InputStream *ist, OutputStream *ost) |
948 | 948 |
if (ost->source_index != ist_index) |
949 | 949 |
return 0; |
950 | 950 |
|
951 |
- if (of->start_time && ist->last_dts < of->start_time) |
|
951 |
+ if (of->start_time != AV_NOPTS_VALUE && ist->last_dts < of->start_time) |
|
952 | 952 |
return 0; |
953 | 953 |
|
954 | 954 |
return 1; |
... | ... |
@@ -957,7 +958,8 @@ static int check_output_constraints(InputStream *ist, OutputStream *ost) |
957 | 957 |
static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *pkt) |
958 | 958 |
{ |
959 | 959 |
OutputFile *of = output_files[ost->file_index]; |
960 |
- int64_t ost_tb_start_time = av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); |
|
960 |
+ int64_t start_time = (of->start_time == AV_NOPTS_VALUE) ? 0 : of->start_time; |
|
961 |
+ int64_t ost_tb_start_time = av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base); |
|
961 | 962 |
AVPacket opkt; |
962 | 963 |
|
963 | 964 |
av_init_packet(&opkt); |
... | ... |
@@ -967,7 +969,7 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p |
967 | 967 |
return; |
968 | 968 |
|
969 | 969 |
if (of->recording_time != INT64_MAX && |
970 |
- ist->last_dts >= of->recording_time + of->start_time) { |
|
970 |
+ ist->last_dts >= of->recording_time + start_time) { |
|
971 | 971 |
ost->finished = 1; |
972 | 972 |
return; |
973 | 973 |
} |
... | ... |
@@ -183,7 +183,7 @@ static int insert_trim(OutputStream *ost, AVFilterContext **last_filter, int *pa |
183 | 183 |
char filter_name[128]; |
184 | 184 |
int ret = 0; |
185 | 185 |
|
186 |
- if (of->recording_time == INT64_MAX && !of->start_time) |
|
186 |
+ if (of->recording_time == INT64_MAX && of->start_time == AV_NOPTS_VALUE) |
|
187 | 187 |
return 0; |
188 | 188 |
|
189 | 189 |
trim = avfilter_get_by_name(name); |
... | ... |
@@ -203,7 +203,7 @@ static int insert_trim(OutputStream *ost, AVFilterContext **last_filter, int *pa |
203 | 203 |
ret = av_opt_set_double(ctx, "duration", (double)of->recording_time / 1e6, |
204 | 204 |
AV_OPT_SEARCH_CHILDREN); |
205 | 205 |
} |
206 |
- if (ret >= 0 && of->start_time) { |
|
206 |
+ if (ret >= 0 && of->start_time != AV_NOPTS_VALUE) { |
|
207 | 207 |
ret = av_opt_set_double(ctx, "start", (double)of->start_time / 1e6, |
208 | 208 |
AV_OPT_SEARCH_CHILDREN); |
209 | 209 |
} |
... | ... |
@@ -113,6 +113,7 @@ static void init_options(OptionsContext *o) |
113 | 113 |
memset(o, 0, sizeof(*o)); |
114 | 114 |
|
115 | 115 |
o->mux_max_delay = 0.7; |
116 |
+ o->start_time = AV_NOPTS_VALUE; |
|
116 | 117 |
o->recording_time = INT64_MAX; |
117 | 118 |
o->limit_filesize = UINT64_MAX; |
118 | 119 |
o->chapters_input_file = INT_MAX; |
... | ... |
@@ -658,13 +659,13 @@ static int open_input_file(OptionsContext *o, const char *filename) |
658 | 658 |
exit_program(1); |
659 | 659 |
} |
660 | 660 |
|
661 |
- timestamp = o->start_time; |
|
661 |
+ timestamp = (o->start_time == AV_NOPTS_VALUE) ? 0 : o->start_time; |
|
662 | 662 |
/* add the stream start time */ |
663 | 663 |
if (ic->start_time != AV_NOPTS_VALUE) |
664 | 664 |
timestamp += ic->start_time; |
665 | 665 |
|
666 | 666 |
/* if seeking requested, we execute it */ |
667 |
- if (o->start_time != 0) { |
|
667 |
+ if (o->start_time != AV_NOPTS_VALUE) { |
|
668 | 668 |
ret = av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD); |
669 | 669 |
if (ret < 0) { |
670 | 670 |
av_log(NULL, AV_LOG_WARNING, "%s: could not seek to position %0.3f\n", |
... | ... |
@@ -1212,7 +1213,8 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata) |
1212 | 1212 |
|
1213 | 1213 |
for (i = 0; i < is->nb_chapters; i++) { |
1214 | 1214 |
AVChapter *in_ch = is->chapters[i], *out_ch; |
1215 |
- int64_t ts_off = av_rescale_q(ofile->start_time - ifile->ts_offset, |
|
1215 |
+ int64_t start_time = (ofile->start_time == AV_NOPTS_VALUE) ? 0 : ofile->start_time; |
|
1216 |
+ int64_t ts_off = av_rescale_q(start_time - ifile->ts_offset, |
|
1216 | 1217 |
AV_TIME_BASE_Q, in_ch->time_base); |
1217 | 1218 |
int64_t rt = (ofile->recording_time == INT64_MAX) ? INT64_MAX : |
1218 | 1219 |
av_rescale_q(ofile->recording_time, AV_TIME_BASE_Q, in_ch->time_base); |