As per ISO 14496-12, sample duration of 0 is invalid except for the last entry. However, some files may use it to stall dts progress in order to recover from a desync.
In addition, catch and fix 0 value for sample count. --- v2: adjust dts if 0 duration is encountered libavformat/mov.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 351ecde770..7e90e24bd5 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2970,16 +2970,22 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n", sample_count, sample_duration); + if (!sample_count) { + av_log(c->fc, AV_LOG_WARNING, "invalid sample count of 0 in stts for st %d at entry %u; changing to 1.\n", + c->fc->nb_streams-1, i); + sc->stts_data[i].count = sample_count = 1; + } + /* STTS sample offsets are uint32 but some files store it as int32 * with negative values used to correct DTS delays. There may be abnormally large values as well. */ - if (sample_duration > c->max_stts_delta) { + if (sample_duration > c->max_stts_delta || !sample_duration) { // assume high delta is a correction if negative when cast as int32 int32_t delta_magnitude = (int32_t)sample_duration; - av_log(c->fc, AV_LOG_WARNING, "Too large sample offset %u in stts entry %u with count %u in st:%d. Clipping to 1.\n", + av_log(c->fc, AV_LOG_WARNING, "Too large or zero sample offset %u in stts entry %u with count %u in st:%d. Setting to 1.\n", sample_duration, i, sample_count, st->index); sc->stts_data[i].duration = 1; - corrected_dts += (delta_magnitude < 0 ? (int64_t)delta_magnitude : 1) * sample_count; + corrected_dts += (delta_magnitude <= 0 ? (int64_t)delta_magnitude : 1) * sample_count; } else { corrected_dts += sample_duration * sample_count; } @@ -2987,7 +2993,7 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) current_dts += sc->stts_data[i].duration * sample_count; if (current_dts > corrected_dts) { - int64_t drift = (current_dts - corrected_dts)/FFMAX(sample_count, 1); + int64_t drift = (current_dts - corrected_dts)/sample_count; uint32_t correction = (sc->stts_data[i].duration > drift) ? drift : sc->stts_data[i].duration - 1; current_dts -= correction * sample_count; sc->stts_data[i].duration -= correction; -- 2.33.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".