From f3bdfee28332b1ccc794186d91a1f9e082004a1e Mon Sep 17 00:00:00 2001
Date: Mon, 18 Feb 2013 11:55:37 +0000
Subject: [PATCH] Get-stream-durations-using-read_timestamp

---
 libavformat/utils.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/libavformat/utils.c b/libavformat/utils.c
index bdb9d17..3e7dec9 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -2283,6 +2283,41 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic)
 #define DURATION_MAX_READ_SIZE 250000LL
 #define DURATION_MAX_RETRY 4
 
+static void av_estimate_timings_from_pts2(AVFormatContext *ic, int64_t old_offset)
+{
+    AVStream *st;
+    int i, step= 1024;
+    int64_t ts, pos;
+
+    for(i=0;i<ic->nb_streams;i++) {
+        st = ic->streams[i];
+
+        pos = 0;
+        ts = ic->iformat->read_timestamp(ic, i, &pos, DURATION_MAX_READ_SIZE);
+        if (ts == AV_NOPTS_VALUE)
+            continue;
+        if (st->start_time > ts || st->start_time == AV_NOPTS_VALUE)
+            st->start_time = ts;
+
+        pos = avio_size(ic->pb) - 1;
+        do {
+            pos -= step;
+            ts = ic->iformat->read_timestamp(ic, i, &pos, pos + step);
+            step += step;
+        } while (ts == AV_NOPTS_VALUE && pos >= step && step < DURATION_MAX_READ_SIZE);
+
+        if (ts == AV_NOPTS_VALUE)
+            continue;
+
+        if (st->duration < ts - st->start_time || st->duration == AV_NOPTS_VALUE)
+            st->duration = ts - st->start_time;
+    }
+
+    fill_all_stream_timings(ic);
+
+    avio_seek(ic->pb, old_offset, SEEK_SET);
+}
+
 /* only usable for MPEG-PS streams */
 static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
 {
@@ -2382,6 +2417,10 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset)
            the components */
         fill_all_stream_timings(ic);
         ic->duration_estimation_method = AVFMT_DURATION_FROM_STREAM;
+    } else if (ic->iformat->read_timestamp && 
+        file_size && ic->pb->seekable) {
+        /* get accurate estimate from the PTSes */
+        av_estimate_timings_from_pts2(ic, old_offset);
     } else {
         av_log(ic, AV_LOG_WARNING, "Estimating duration from bitrate, this may be inaccurate\n");
         /* less precise: use bitrate info */
-- 
1.7.10.4

