Ticket #1836: 0001-Wrong-duration-in-TS-container-Ticket-1836.2.patch
| File 0001-Wrong-duration-in-TS-container-Ticket-1836.2.patch, 5.5 KB (added by Heesuk Jung, 7 months ago) |
|---|
-
libavformat/utils.c
From 6af199fbd89ecc9441ce84789e4f1a6800128670 Mon Sep 17 00:00:00 2001 From: Heesuk Jung <heesuk.jung@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 b int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int 2012 2012 // try some generic seek like seek_frame_generic() but with new ts semantics 2013 2013 } 2014 2014 2015 /** 2016 * examine if duration is valid based on bit rate information or not. 2017 * Duration is regarded as invlaid value 2018 * if duration is unreasonably bigger than file size/average bit rate. 2019 * hueristically suggest limit_filesize_multiple that means double file size 2020 * @return 1 if duration is valid. 2021 * 0 if duration is not valid. 2022 */ 2023 static int check_duration_using_bit_rate(const int64_t duration, 2024 const int64_t filesize, int const bit_rate) 2025 { 2026 const uint8_t limit_filesize_multiple = 3; 2027 2028 if (bit_rate > 0 && 2029 duration > (filesize*8/(bit_rate/1000)*limit_filesize_multiple*1000)) { 2030 return 0; 2031 } 2032 return 1; 2033 } 2034 2035 /** 2036 * examine if estimated duration is valid or not. 2037 * Estimated duration is regarded as invalid value 2038 * if duration is unreasonably bigger than file size/average bit rate. 2039 * @return 1 if duration estimeation is valid. 2040 * 0 if duration estimation is not valid. 2041 */ 2042 static int valid_duration_estimation(AVFormatContext *ic) 2043 { 2044 const int64_t duration = ic->duration; 2045 const int64_t filesize = avio_size(ic->pb); 2046 const uint8_t limit_bitrate_multiple = 10; 2047 uint8_t i = 0; 2048 int bit_rate = 0; 2049 AVStream *st; 2050 2051 for (i=0; i<ic->nb_streams; i++) { 2052 st = ic->streams[i]; 2053 if (st->codec->bit_rate > 0) { 2054 switch (st->codec->codec_type) { 2055 case AVMEDIA_TYPE_VIDEO: 2056 bit_rate += st->codec->bit_rate; 2057 break; 2058 case AVMEDIA_TYPE_AUDIO: 2059 bit_rate += st->codec->bit_rate; 2060 break; 2061 } 2062 } 2063 } 2064 if (ic->bit_rate > 0 && 2065 bit_rate > ic->bit_rate*limit_bitrate_multiple) { 2066 bit_rate = ic->bit_rate; 2067 } 2068 2069 if (duration == AV_NOPTS_VALUE || 2070 !check_duration_using_bit_rate(duration, filesize, bit_rate)) { 2071 ic->bit_rate = bit_rate; 2072 return 0; 2073 } 2074 return 1; 2075 } 2076 2015 2077 /*******************************************************/ 2016 2078 2017 2079 /** … … static void update_stream_timings(AVFormatContext *ic) 2089 2151 if (ic->nb_programs) { 2090 2152 for (i=0; i<ic->nb_programs; i++) { 2091 2153 p = ic->programs[i]; 2092 if(p->start_time != AV_NOPTS_VALUE && p->end_time > p->start_time) 2093 duration = FFMAX(duration, p->end_time - p->start_time); 2154 if(p->start_time != AV_NOPTS_VALUE && p->end_time > p->start_time) { 2155 if (check_duration_using_bit_rate(p->end_time - p->start_time, 2156 avio_size(ic->pb), ic->bit_rate)) { 2157 duration = FFMAX(duration, p->end_time - p->start_time); 2158 } 2159 } 2094 2160 } 2095 } else 2161 } else { 2096 2162 duration = FFMAX(duration, end_time - start_time); 2163 } 2097 2164 } 2098 2165 } 2099 2166 if (duration != INT64_MIN && duration > 0 && ic->duration == AV_NOPTS_VALUE) { … … static void estimate_timings(AVFormatContext *ic, int64_t old_offset) 2265 2332 estimate_timings_from_bit_rate(ic); 2266 2333 ic->duration_estimation_method = AVFMT_DURATION_FROM_BITRATE; 2267 2334 } 2335 if ((ic->duration_estimation_method != AVFMT_DURATION_FROM_BITRATE) && 2336 !valid_duration_estimation(ic)) { 2337 uint8_t i = 0; 2338 AVStream *st; 2339 ic->duration = AV_NOPTS_VALUE; 2340 for (i=0; i<ic->nb_streams; i++) { 2341 st = ic->streams[i]; 2342 st->duration = AV_NOPTS_VALUE; 2343 } 2344 av_log(ic, AV_LOG_WARNING, "Estimating duration from bitrate, this may be inaccurate\n"); 2345 /* less precise: use bitrate info */ 2346 estimate_timings_from_bit_rate(ic); 2347 ic->duration_estimation_method = AVFMT_DURATION_FROM_BITRATE; 2348 } 2268 2349 update_stream_timings(ic); 2269 2350 2270 2351 {
