[FFmpeg-devel] [PATCH] ffmpeg: Add threshold to discard crazy/damaged timestamps.

Michael Niedermayer michaelni at gmx.at
Wed Feb 8 00:50:11 CET 2012


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 at gmx.at>
---
 ffmpeg.c |   27 +++++++++++++++++++++++----
 1 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/ffmpeg.c b/ffmpeg.c
index 9b6c19d..8d4e9dd 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -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;
 
@@ -3021,14 +3022,14 @@ static int transcode(OutputFile *output_files, int nb_output_files,
         //        ist->next_pts,
         //        pkt.dts, input_files[ist->file_index].ts_offset,
         //        ist->st->codec->codec_type);
-        if (pkt.dts != AV_NOPTS_VALUE && ist->next_pts != AV_NOPTS_VALUE
-            && (is->iformat->flags & AVFMT_TS_DISCONT)) {
+        if (pkt.dts != AV_NOPTS_VALUE && ist->next_pts != 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_pts;
-            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",
@@ -3037,6 +3038,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", %"PRId64" invalid droping\n", pkt.dts, ist->next_pts);
+                    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_pts;
+                    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", %"PRId64" invalid droping\n", pkt.pts, ist->next_pts);
+                        pkt.pts = AV_NOPTS_VALUE;
+                    }
+                }
+            }
         }
 
         // fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size);
@@ -4962,6 +4980,7 @@ static const OptionDef options[] = {
     { "copytb", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&copy_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" },
-- 
1.7.5.4



More information about the ffmpeg-devel mailing list