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

Heesuk Jung heesuk.jung at lge.com
Mon Oct 22 12:57:37 CEST 2012


>From cdac9ec5ec8a3e66f7f818d1a27fefee4e2e611b Mon Sep 17 00:00:00 2001
From: Heesuk Jung <heesuk.jung at lge.com>
Date: Mon, 22 Oct 2012 19:33:27 +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 |   74
+++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 72 insertions(+), 2 deletions(-)
 mode change 100644 => 100755 libavformat/utils.c

diff --git a/libavformat/utils.c b/libavformat/utils.c
old mode 100644
new mode 100755
index f27104e..7cdcddc
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -2012,6 +2012,57 @@ 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 considered 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 = 2;
+
+    if (bit_rate > 0) {
+        if (duration >
(filesize*8/bit_rate*limit_filesize_multiple*1000000)) {
+            return 0;
+        }
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+/**
+ * examine if estimated duration is valid based on bit rate information or
not.
+ * Estimated duration is considered if duration is unreasonably bigger than
file size/average bit rate.
+ * @return 1 if duration is valid.
+ *         0 if duration is not valid.
+ */
+static int valid_duration_estimation(AVFormatContext *ic)
+{
+    const int64_t duration = ic->duration;
+    const int64_t filesize = avio_size(ic->pb);
+    int bit_rate = 0;
+    int i = 0;
+    AVStream *st;
+
+    for (i=0; i<ic->nb_streams; i++) {
+        st = ic->streams[i];
+        if (st->codec->bit_rate > 0)
+            bit_rate += st->codec->bit_rate;
+    }
+
+    if (bit_rate != 0) {
+        if ((duration == AV_NOPTS_VALUE) ||
+            !check_duration_using_bit_rate(duration, filesize, bit_rate)) {
+            ic->bit_rate = bit_rate;
+            return 0;
+        }
+    }
+    return 1;
+}
+
 /*******************************************************/
 
 /**
@@ -2077,8 +2128,12 @@ static void update_stream_timings(AVFormatContext
*ic)
 
     if (start_time != INT64_MAX) {
         ic->start_time = start_time;
-        if (end_time != INT64_MIN)
-            duration = FFMAX(duration, end_time - start_time);
+        if (end_time != INT64_MIN) {
+            int64_t duration_time_diff = end_time - start_time;
+            if (check_duration_using_bit_rate(duration_time_diff,
avio_size(ic->pb), ic->bit_rate)) {
+                duration = FFMAX(duration, duration_time_diff);
+            }
+        }
     }
     if (duration != INT64_MIN && duration > 0 && ic->duration ==
AV_NOPTS_VALUE) {
         ic->duration = duration;
@@ -2249,6 +2304,21 @@ 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

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Wrong-duration-in-TS-container-Ticket-1836.patch
Type: application/octet-stream
Size: 4773 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20121022/bcfa80d8/attachment.obj>


More information about the ffmpeg-devel mailing list