summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2012-06-28 15:49:51 +0200
committerAnton Khirnov <anton@khirnov.net>2012-07-29 08:04:42 +0200
commitfe1c1198e670242f3cf9e3e1eef27cff77f3ee23 (patch)
treec528c326d45f92f823bf0db3b06721104308d59d /libavformat
parent681ed0009905a088aae2a5caf2308d89aaa80562 (diff)
lavf: use dts difference instead of AVPacket.duration in find_stream_info()
AVPacket.duration is mostly made up and thus completely useless, this is especially true for video streams. Therefore use dts difference for framerate estimation and the max_analyze_duration check. The asyncts test now needs -analyzeduration, because the default is 5 seconds and the audio stream in the sample appears at ~10 seconds.
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/avformat.h10
-rw-r--r--libavformat/utils.c38
2 files changed, 41 insertions, 7 deletions
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 7c97ada2c8..0e50487414 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -718,9 +718,17 @@ typedef struct AVStream {
int64_t duration_gcd;
int duration_count;
double duration_error[MAX_STD_TIMEBASES];
- int64_t codec_info_duration;
int nb_decoded_frames;
int found_decoder;
+
+ /**
+ * Those are used for average framerate estimation.
+ */
+ int64_t fps_first_dts;
+ int fps_first_dts_idx;
+ int64_t fps_last_dts;
+ int fps_last_dts_idx;
+
} *info;
int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 149913cb04..bd94f7d7a7 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -2288,6 +2288,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
for (i=0; i<ic->nb_streams; i++) {
ic->streams[i]->info->last_dts = AV_NOPTS_VALUE;
+ ic->streams[i]->info->fps_first_dts = AV_NOPTS_VALUE;
+ ic->streams[i]->info->fps_last_dts = AV_NOPTS_VALUE;
}
count = 0;
@@ -2395,12 +2397,31 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
read_size += pkt->size;
st = ic->streams[pkt->stream_index];
- if (st->codec_info_nb_frames>1) {
- if (av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) {
+ if (pkt->dts != AV_NOPTS_VALUE && st->codec_info_nb_frames > 1) {
+ /* check for non-increasing dts */
+ if (st->info->fps_last_dts != AV_NOPTS_VALUE &&
+ st->info->fps_last_dts >= pkt->dts) {
+ av_log(ic, AV_LOG_WARNING, "Non-increasing DTS in stream %d: "
+ "packet %d with DTS %"PRId64", packet %d with DTS "
+ "%"PRId64"\n", st->index, st->info->fps_last_dts_idx,
+ st->info->fps_last_dts, st->codec_info_nb_frames, pkt->dts);
+ st->info->fps_first_dts = st->info->fps_last_dts = AV_NOPTS_VALUE;
+ }
+
+ /* update stored dts values */
+ if (st->info->fps_first_dts == AV_NOPTS_VALUE) {
+ st->info->fps_first_dts = pkt->dts;
+ st->info->fps_first_dts_idx = st->codec_info_nb_frames;
+ }
+ st->info->fps_last_dts = pkt->dts;
+ st->info->fps_last_dts_idx = st->codec_info_nb_frames;
+
+ /* check max_analyze_duration */
+ if (av_rescale_q(pkt->dts - st->info->fps_first_dts, st->time_base,
+ AV_TIME_BASE_Q) >= ic->max_analyze_duration) {
av_log(ic, AV_LOG_WARNING, "max_analyze_duration reached\n");
break;
}
- st->info->codec_info_duration += pkt->duration;
}
{
int64_t last = st->info->last_dts;
@@ -2460,10 +2481,15 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
for(i=0;i<ic->nb_streams;i++) {
st = ic->streams[i];
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- if (st->codec_info_nb_frames>2 && !st->avg_frame_rate.num && st->info->codec_info_duration)
+ /* estimate average framerate if not set by demuxer */
+ if (!st->avg_frame_rate.num && st->info->fps_last_dts != st->info->fps_first_dts) {
+ int64_t delta_dts = st->info->fps_last_dts - st->info->fps_first_dts;
+ int delta_packets = st->info->fps_last_dts_idx - st->info->fps_first_dts_idx;
+
av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
- (st->codec_info_nb_frames-2)*(int64_t)st->time_base.den,
- st->info->codec_info_duration*(int64_t)st->time_base.num, 60000);
+ delta_packets*(int64_t)st->time_base.den,
+ delta_dts*(int64_t)st->time_base.num, 60000);
+ }
// the check for tb_unreliable() is not completely correct, since this is not about handling
// a unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
// ipmovie.c produces.