From aac495a25fc0ceb17eabbcd73c6519b7dcb9da30 Mon Sep 17 00:00:00 2001
From: Heesuk Jung <heesuk.jung@lge.com>
Date: Fri, 16 Nov 2012 16:26:04 +0900
Subject: [PATCH] Wrong duration in TS container (Ticket #1836)

Sometimes TS container file has unreasonbly big PTS in last frame.
In this case, we use previous last PTS value to decide stream dueation.

Fix 2nd promlematic file cas in Ticket #1836
link : https://docs.google.com/open?id=0B6r7ZfWFIypCNFVuWHowMFBBN0E
---
 libavformat/utils.c |   13 ++++++++++++-
 1 files changed, 12 insertions(+), 1 deletions(-)

diff --git a/libavformat/utils.c b/libavformat/utils.c
index 4072ac8..fb55477 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -2161,6 +2161,7 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic)
 
 #define DURATION_MAX_READ_SIZE 250000LL
 #define DURATION_MAX_RETRY 4
+#define DURATION_MULTIPLE_LIMIT 8
 
 /* only usable for MPEG-PS streams */
 static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
@@ -2170,6 +2171,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
     int read_size, i, ret;
     int64_t end_time;
     int64_t filesize, offset, duration;
+    int64_t ref_duration, pre_duration;
     int retry=0;
 
     /* flush packet queue */
@@ -2190,6 +2192,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
     /* XXX: may need to support wrapping */
     filesize = ic->pb ? avio_size(ic->pb) : 0;
     end_time = AV_NOPTS_VALUE;
+    ref_duration = AV_NOPTS_VALUE;
     do{
         offset = filesize - (DURATION_MAX_READ_SIZE<<retry);
         if (offset < 0)
@@ -2219,8 +2222,16 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset)
                 if (duration < 0)
                     duration += 1LL<<st->pts_wrap_bits;
                 if (duration > 0) {
-                    if (st->duration == AV_NOPTS_VALUE || st->duration < duration)
+                    if (st->duration == AV_NOPTS_VALUE || st->duration < duration) {
+                        pre_duration = st->duration;
                         st->duration = duration;
+                        if (ref_duration == AV_NOPTS_VALUE) {
+                            ref_duration = st->duration;
+                        } else if (st->duration/DURATION_MULTIPLE_LIMIT > ref_duration) {
+                            st->duration = pre_duration;
+                            break;
+                        }
+                    }
                 }
             }
             av_free_packet(pkt);
-- 
1.7.0.4

