[FFmpeg-devel] [PATCH] Wrong duration in TS container (Ticket #1836)

Steven Liu lingjiujianke at gmail.com
Tue Oct 30 11:17:40 CET 2012


2012/10/30 Heesuk Jung <heesuk.jung at lge.com>:
> Hi,
>
> Michael wrote:
>> Ive tested the patch a bit and it breaks finding the correct duration of:
>> https://ffmpeg.org/trac/ffmpeg/raw-attachment/ticket/1186/sync1.ogg
>
> I update patches and did regression test for 472 files include "sync1.ogg".
> (I compared extracted duration value with master version and patch applied
> master.)
>
> Test result is ok and duration of 4 files with patch is more improved than
> original duration.
>
> Thanks !
>
> From 6af199fbd89ecc9441ce84789e4f1a6800128670 Mon Sep 17 00:00:00 2001
> From: Heesuk Jung <heesuk.jung at lge.com>
> Date: Tue, 30 Oct 2012 18:29:47 +0900
> Subject: [PATCH] Wrong duration in TS container (Ticket #1836)
>
> Libavformat somtimes get wrong duration in some TS conatiner.
> Please refer the problem description and file link in Ticket #1836.
> (http://ffmpeg.org/trac/ffmpeg/ticket/1836)
>
> I have just modified 2 points as below.
>
> 1. check if duration estimation is reasonable or not.
>
> examine if estimated duration is valid based on bit rate information.
> The duration is regarded as abnormal value if it is unreasonably bigger
> than file size / average bit rate.
>
> 2. check if PTS time diff is reasonable or not.
>
> Duration is determined comparing PTS time diff with estimated duration.
> (Actually final duration is selected as bigger value in PTS time diff and
> estimated duration) I suggest that don't beleive duration based on PTS time
> diff if time diff is bigger than hueristic value (file size / average bit
> rate * 2).
> ---
>  libavformat/utils.c |   87
> +++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 files changed, 84 insertions(+), 3 deletions(-)
>  mode change 100644 => 100755 ffprobe.c
>  mode change 100644 => 100755 libavformat/utils.c
>
> diff --git a/ffprobe.c b/ffprobe.c
> old mode 100644
> new mode 100755
> diff --git a/libavformat/utils.c b/libavformat/utils.c
> old mode 100644
> new mode 100755
> index fb5742b..cf76cc1
> --- a/libavformat/utils.c
> +++ b/libavformat/utils.c
> @@ -2012,6 +2012,68 @@ int avformat_seek_file(AVFormatContext *s, int
> stream_index, int64_t min_ts, int
>      // try some generic seek like seek_frame_generic() but with new ts
> semantics
>  }
>
> +/**
> + * examine if duration is valid based on bit rate information or not.
> + * Duration is regarded as invlaid value
> + * if duration is unreasonably bigger than file size/average bit rate.
> + * hueristically suggest  limit_filesize_multiple that means double file
> size
> + * @return 1 if duration is valid.
> + *         0 if duration is not valid.
> + */
> +static int check_duration_using_bit_rate(const int64_t duration,
> +                                         const int64_t filesize, int const
> bit_rate)
> +{
> +    const uint8_t limit_filesize_multiple = 3;
> +
> +    if (bit_rate > 0 &&
> +        duration >
> (filesize*8/(bit_rate/1000)*limit_filesize_multiple*1000)) {
> +        return 0;
> +    }
> +    return 1;
> +}
> +
> +/**
> + * examine if estimated duration is valid or not.
> + * Estimated duration is regarded as invalid value
> + * if duration is unreasonably bigger than file size/average bit rate.
> + * @return 1 if duration estimeation is valid.
> + *         0 if duration estimation is not valid.
> + */
> +static int valid_duration_estimation(AVFormatContext *ic)
> +{
> +    const int64_t duration = ic->duration;
> +    const int64_t filesize = avio_size(ic->pb);
> +    const uint8_t limit_bitrate_multiple = 10;
> +    uint8_t i = 0;
> +    int bit_rate = 0;
> +    AVStream *st;
> +
> +    for (i=0; i<ic->nb_streams; i++) {
> +        st = ic->streams[i];
> +        if (st->codec->bit_rate > 0) {
> +            switch (st->codec->codec_type) {
> +            case AVMEDIA_TYPE_VIDEO:
> +                bit_rate += st->codec->bit_rate;
> +                break;
> +            case AVMEDIA_TYPE_AUDIO:
> +                bit_rate += st->codec->bit_rate;
> +                break;
> +            }
> +           }
> +    }
> +    if (ic->bit_rate > 0 &&
> +        bit_rate > ic->bit_rate*limit_bitrate_multiple) {
> +        bit_rate = ic->bit_rate;
> +    }
> +
> +       if (duration == AV_NOPTS_VALUE ||
> +           !check_duration_using_bit_rate(duration, filesize, bit_rate)) {
> +           ic->bit_rate = bit_rate;
> +           return 0;
> +    }
> +       return 1;
> +}
> +
>  /*******************************************************/
>
>  /**
> @@ -2089,11 +2151,16 @@ static void update_stream_timings(AVFormatContext
> *ic)
>              if (ic->nb_programs) {
>                  for (i=0; i<ic->nb_programs; i++) {
>                      p = ic->programs[i];
> -                    if(p->start_time != AV_NOPTS_VALUE && p->end_time >
> p->start_time)
> -                        duration = FFMAX(duration, p->end_time -
> p->start_time);
> +                    if(p->start_time != AV_NOPTS_VALUE && p->end_time >
> p->start_time) {
> +                        if (check_duration_using_bit_rate(p->end_time -
> p->start_time,
> +
> avio_size(ic->pb), ic->bit_rate)) {
> +                            duration = FFMAX(duration, p->end_time -
> p->start_time);
> +                        }
> +                    }
>                  }
> -            } else
> +            } else {
>                  duration = FFMAX(duration, end_time - start_time);
> +            }
>          }
>      }
>      if (duration != INT64_MIN && duration > 0 && ic->duration ==
> AV_NOPTS_VALUE) {
> @@ -2265,6 +2332,20 @@ static void estimate_timings(AVFormatContext *ic,
> int64_t old_offset)
>          estimate_timings_from_bit_rate(ic);
>          ic->duration_estimation_method = AVFMT_DURATION_FROM_BITRATE;
>      }
> +    if ((ic->duration_estimation_method != AVFMT_DURATION_FROM_BITRATE) &&
> +        !valid_duration_estimation(ic)) {
> +        uint8_t i = 0;
> +        AVStream *st;
> +        ic->duration = AV_NOPTS_VALUE;
> +        for (i=0; i<ic->nb_streams; i++) {
> +            st = ic->streams[i];
> +            st->duration = AV_NOPTS_VALUE;
> +        }
> +        av_log(ic, AV_LOG_WARNING, "Estimating duration from bitrate, this
> may be inaccurate\n");
> +        /* less precise: use bitrate info */
> +        estimate_timings_from_bit_rate(ic);
> +        ic->duration_estimation_method = AVFMT_DURATION_FROM_BITRATE;
> +    }
>      update_stream_timings(ic);
>
>      {
> --
> 1.7.0.4


I Have tried your patch , problem is always.

Program terminated with signal 8, Arithmetic exception.
#0  0x000000000059486a in check_duration_using_bit_rate
(ic=0xfffffffffffffb50, options=0x2b85ce0) at libavformat/utils.c:2029
2029            duration >
(filesize*8/(bit_rate/1000)*limit_filesize_multiple*1000)) {
Missing separate debuginfos, use: debuginfo-install
bzip2-libs-1.0.5-7.el6_0.x86_64 glibc-2.12-1.25.el6.x86_64
zlib-1.2.3-25.el6.x86_64
(gdb) p filesize
$1 = <value optimized out>
(gdb) p bit_rate/1000
$2 = 0
(gdb) p bit_rate
$3 = 23
(gdb) p limit_filesize_multiple
$4 = 3 '\003'
(gdb) p duration
$5 = 95444716145
(gdb)


More information about the ffmpeg-devel mailing list