diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-02-07 23:43:10 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-02-10 05:40:42 +0100 |
commit | 29034e65039ef6b1854ceeb76ffe4092992d9fd5 (patch) | |
tree | 5ae156f7fd22e31d3a3d71d4f2f64247b4508f92 | |
parent | 789d6b73cf8120fc411a8862c4ffb7e533607245 (diff) | |
download | ffmpeg-29034e65039ef6b1854ceeb76ffe4092992d9fd5.tar.gz |
ffmpeg: Add threshold to discard crazy/damaged timestamps.
The added tests are limited to the case where timestamp discontinuities
are not allowed. The default is 30 hours which is arbitrarily picked and
quite conservative.
This prevents a out of memory condition due to duplicating a frame
millions of times.
Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | ffmpeg.c | 27 |
1 files changed, 23 insertions, 4 deletions
@@ -171,6 +171,7 @@ static int nb_frames_drop = 0; static int input_sync; static float dts_delta_threshold = 10; +static float dts_error_threshold = 3600*30; static int print_stats = 1; @@ -3020,14 +3021,14 @@ static int transcode(OutputFile *output_files, int nb_output_files, // ist->next_dts, // ist->dts, av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q), input_files[ist->file_index].ts_offset, // ist->st->codec->codec_type); - if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE - && (is->iformat->flags & AVFMT_TS_DISCONT)) { + if (pkt.dts != AV_NOPTS_VALUE && ist->next_dts != AV_NOPTS_VALUE && !copy_ts) { int64_t pkt_dts = av_rescale_q(pkt.dts, ist->st->time_base, AV_TIME_BASE_Q); int64_t delta = pkt_dts - ist->next_dts; - if((delta < -1LL*dts_delta_threshold*AV_TIME_BASE || + if (is->iformat->flags & AVFMT_TS_DISCONT) { + if(delta < -1LL*dts_delta_threshold*AV_TIME_BASE || (delta > 1LL*dts_delta_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) || - pkt_dts+1<ist->pts)&& !copy_ts){ + pkt_dts+1<ist->pts){ input_files[ist->file_index].ts_offset -= delta; av_log(NULL, AV_LOG_DEBUG, "timestamp discontinuity %"PRId64", new offset= %"PRId64"\n", @@ -3036,6 +3037,23 @@ static int transcode(OutputFile *output_files, int nb_output_files, if (pkt.pts != AV_NOPTS_VALUE) pkt.pts-= av_rescale_q(delta, AV_TIME_BASE_Q, ist->st->time_base); } + } else { + if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || + (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE) || + pkt_dts+1<ist->pts){ + av_log(NULL, AV_LOG_WARNING, "DTS %"PRId64", next:%"PRId64" st:%d invalid droping\n", pkt.dts, ist->next_dts, pkt.stream_index); + pkt.dts = AV_NOPTS_VALUE; + } + if (pkt.pts != AV_NOPTS_VALUE){ + int64_t pkt_pts = av_rescale_q(pkt.pts, ist->st->time_base, AV_TIME_BASE_Q); + delta = pkt_pts - ist->next_dts; + if ( delta < -1LL*dts_error_threshold*AV_TIME_BASE || + (delta > 1LL*dts_error_threshold*AV_TIME_BASE && ist->st->codec->codec_type != AVMEDIA_TYPE_SUBTITLE)) { + av_log(NULL, AV_LOG_WARNING, "PTS %"PRId64", next:%"PRId64" invalid droping st:%d\n", pkt.pts, ist->next_dts, pkt.stream_index); + pkt.pts = AV_NOPTS_VALUE; + } + } + } } // fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size); @@ -4960,6 +4978,7 @@ static const OptionDef options[] = { { "copytb", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)©_tb}, "copy input stream time base when stream copying", "source" }, { "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, // { "dts_delta_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_delta_threshold}, "timestamp discontinuity delta threshold", "threshold" }, + { "dts_error_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&dts_error_threshold}, "timestamp error delta threshold", "threshold" }, { "xerror", OPT_BOOL, {(void*)&exit_on_error}, "exit on error", "error" }, { "copyinkf", OPT_BOOL | OPT_EXPERT | OPT_SPEC, {.off = OFFSET(copy_initial_nonkeyframes)}, "copy initial non-keyframes" }, { "frames", OPT_INT64 | HAS_ARG | OPT_SPEC, {.off = OFFSET(max_frames)}, "set the number of frames to record", "number" }, |