[FFmpeg-devel] [PATCH] mov: fix DTS calculation for samples with negative stts duration

Andreas Cadhalpun andreas.cadhalpun at googlemail.com
Thu May 28 00:11:00 CEST 2015


A negative sample duration is invalid according to the spec, but there
are samples that use it for the DTS calculation, e.g.:
http://files.1f0.de/samples/mp4-negative-stts-problem.mp4

These currently get out of A/V sync.

Also change the logging type to AV_LOG_WARNING, because decoding the
sample can continue.

Signed-off-by: Andreas Cadhalpun <Andreas.Cadhalpun at googlemail.com>
---
 libavformat/mov.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/libavformat/mov.c b/libavformat/mov.c
index 51cdd21..730f097 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -2234,12 +2234,6 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
         sample_count=avio_rb32(pb);
         sample_duration = avio_rb32(pb);
 
-        /* sample_duration < 0 is invalid based on the spec */
-        if (sample_duration < 0) {
-            av_log(c->fc, AV_LOG_ERROR, "Invalid SampleDelta %d in STTS, at %d st:%d\n",
-                   sample_duration, i, c->fc->nb_streams-1);
-            sample_duration = 1;
-        }
         if (sample_count < 0) {
             av_log(c->fc, AV_LOG_ERROR, "Invalid sample_count=%d\n", sample_count);
             return AVERROR_INVALIDDATA;
@@ -2439,6 +2433,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
         unsigned int distance = 0;
         unsigned int rap_group_index = 0;
         unsigned int rap_group_sample = 0;
+        int64_t dts_correction = 0;
         int rap_group_present = sc->rap_group_count && sc->rap_group;
         int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
 
@@ -2522,6 +2517,19 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
 
                 current_offset += sample_size;
                 stream_size += sample_size;
+                current_dts += dts_correction;
+                /* A negative sample duration is invalid based on the spec,
+                 * but some samples need it to correct the DTS. */
+                if (sc->stts_data[stts_index].duration < 0) {
+                    av_log(mov->fc, AV_LOG_WARNING,
+                           "Invalid SampleDelta %d in STTS, at %d st:%d\n",
+                           sc->stts_data[stts_index].duration, stts_index,
+                           st->index);
+                    dts_correction = sc->stts_data[stts_index].duration - 1;
+                    sc->stts_data[stts_index].duration = 1;
+                } else {
+                    dts_correction = 0;
+                }
                 current_dts += sc->stts_data[stts_index].duration;
                 distance++;
                 stts_sample++;
-- 
2.1.4


More information about the ffmpeg-devel mailing list