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

Hee Suk Jung heesuk.jung at lge.com
Tue Oct 30 14:44:00 CET 2012


Hi Hendrik

Thanks for your feedback.
I comment my opinion for your question and update new patch.

Hendrik wrote:
> The way the calculation is written, it will always result in a
> division by zero if bitrate is < 10000.
> I would recommend to re-order the calcuation into this form:
>
> (filesize * 8) / bitrate * limit_filesize_multiple * 1000000
>
> As an alternative, move one factor 1000 into the filesize
> multiplication, to preserve a bit more accuracy in these integer
> division.
 --> Yes, root casuse of problem is that bit rate is under 1 kbps.
     And so I change calculation order as your suggestion.

>
> Personally, i think this check can also easily go wrong. What if only
> the audio stream in a file has a determined bitrate, and the video
> does not?
> It would trigger this, and discard a possibly perfectly valid duration.
 --> I don't think so.
     We suppose that bit rate of video stream is NULL and audio bit rate is 500kbps.
     Total bit rate of streams is too smaller than actual bit rate.
     When estimated duration is bigger than refernce duration,
     we use new duration.
     (reference duration : (filesize * 8) / bitrate * limit_filesize_multiple * 1000000 )
     And so duration is not changed becasue very small bit rate (<< actual bit rate) make
     so big reference duration.

I hope your feedback.

Thanks.

>From 8beba62059f0139d85a9142d8ec99958685323fb Mon Sep 17 00:00:00 2001
From: Heesuk Jung
Date: Tue, 30 Oct 2012 05:42:36 -0700
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 file 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..9f88076
--- 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 > (limit_filesize_multiple*filesize*8/bit_rate*1000000)) {
+        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; inb_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; inb_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; inb_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.9.5



More information about the ffmpeg-devel mailing list