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. Reviewed-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Andreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>
This commit is contained in:
@@ -2234,12 +2234,6 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom)
|
|||||||
sample_count=avio_rb32(pb);
|
sample_count=avio_rb32(pb);
|
||||||
sample_duration = 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) {
|
if (sample_count < 0) {
|
||||||
av_log(c->fc, AV_LOG_ERROR, "Invalid sample_count=%d\n", sample_count);
|
av_log(c->fc, AV_LOG_ERROR, "Invalid sample_count=%d\n", sample_count);
|
||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
@@ -2439,10 +2433,13 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
|
|||||||
unsigned int distance = 0;
|
unsigned int distance = 0;
|
||||||
unsigned int rap_group_index = 0;
|
unsigned int rap_group_index = 0;
|
||||||
unsigned int rap_group_sample = 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 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);
|
int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0);
|
||||||
|
|
||||||
current_dts -= sc->dts_shift;
|
current_dts -= sc->dts_shift;
|
||||||
|
last_dts = current_dts;
|
||||||
|
|
||||||
if (!sc->sample_count || st->nb_index_entries)
|
if (!sc->sample_count || st->nb_index_entries)
|
||||||
return;
|
return;
|
||||||
@@ -2522,7 +2519,27 @@ static void mov_build_index(MOVContext *mov, AVStream *st)
|
|||||||
|
|
||||||
current_offset += sample_size;
|
current_offset += sample_size;
|
||||||
stream_size += 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;
|
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++;
|
distance++;
|
||||||
stts_sample++;
|
stts_sample++;
|
||||||
current_sample++;
|
current_sample++;
|
||||||
|
|||||||
Reference in New Issue
Block a user