On 29.05.2015 05:03, Michael Niedermayer wrote:
> On Thu, May 28, 2015 at 06:49:02PM +0200, Andreas Cadhalpun wrote:
>> @@ -2522,7 +2519,27 @@ static void mov_build_index(MOVContext *mov, AVStream
>> *st)
>>
>> current_offset += sample_size;
>> stream_size += sample_size;
>> +
>> + /* 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;
>> + }
>> current_dts += sc->stts_data[stts_index].duration;
>> + if (current_dts + dts_correction > last_dts) {
>> + current_dts += dts_correction;
>> + dts_correction = 0;
>> + } else {
>> + /* Avoid creating non-monotonous DTS */
>> + dts_correction += current_dts - last_dts - 1;
>> + current_dts = last_dts + 1;
>
> this would enfore strict monotonicity not just monotoicity
> dts[i-1] == dts[i] was previously left as is
> is there a reason to change this ?
If the dts doesn't change, the packet duration is passed through. This
leads to a wrong packet duration, when dts_correction is in effect.
> Ive not checked what the spec says about it but i suspect there are
> files which have such dts
I haven't found an explicit mentioning of duration 0 in the spec, but
if you think it's better not to change how this was handled previously
for samples which didn't have a negative duration, one can simply
add '!dts_correction ||' before the 'current_dts + dts_correction > last_dts'
check. Attached patch includes this change.
Best regards,
Andreas
>From 266bb402dcc6c53200637c8c37572239192bb0d3 Mon Sep 17 00:00:00 2001
From: Andreas Cadhalpun <[email protected]>
Date: Wed, 27 May 2015 23:57:50 +0200
Subject: [PATCH] mov: fix DTS calculation for samples with negative stts
duration
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 <[email protected]>
---
libavformat/mov.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 6072934..5cea5fd 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,10 +2433,13 @@ 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 last_dts = 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);
current_dts -= sc->dts_shift;
+ last_dts = current_dts;
if (!sc->sample_count || st->nb_index_entries)
return;
@@ -2522,7 +2519,27 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
current_offset += sample_size;
stream_size += sample_size;
+
+ /* 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;
+ }
current_dts += sc->stts_data[stts_index].duration;
+ if (!dts_correction || current_dts + dts_correction > last_dts) {
+ current_dts += dts_correction;
+ dts_correction = 0;
+ } else {
+ /* Avoid creating non-monotonous DTS */
+ dts_correction += current_dts - last_dts - 1;
+ current_dts = last_dts + 1;
+ }
+ last_dts = current_dts;
distance++;
stts_sample++;
current_sample++;
--
2.1.4
_______________________________________________
ffmpeg-devel mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel