You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-10 06:10:52 +02:00
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.
This commit is contained in:
@@ -718,9 +718,17 @@ typedef struct AVStream {
|
|||||||
int64_t duration_gcd;
|
int64_t duration_gcd;
|
||||||
int duration_count;
|
int duration_count;
|
||||||
double duration_error[MAX_STD_TIMEBASES];
|
double duration_error[MAX_STD_TIMEBASES];
|
||||||
int64_t codec_info_duration;
|
|
||||||
int nb_decoded_frames;
|
int nb_decoded_frames;
|
||||||
int found_decoder;
|
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;
|
} *info;
|
||||||
|
|
||||||
int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */
|
int pts_wrap_bits; /**< number of bits in pts (used for wrapping control) */
|
||||||
|
@@ -2288,6 +2288,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
|
|||||||
|
|
||||||
for (i=0; i<ic->nb_streams; i++) {
|
for (i=0; i<ic->nb_streams; i++) {
|
||||||
ic->streams[i]->info->last_dts = AV_NOPTS_VALUE;
|
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;
|
count = 0;
|
||||||
@@ -2395,12 +2397,31 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
|
|||||||
read_size += pkt->size;
|
read_size += pkt->size;
|
||||||
|
|
||||||
st = ic->streams[pkt->stream_index];
|
st = ic->streams[pkt->stream_index];
|
||||||
if (st->codec_info_nb_frames>1) {
|
if (pkt->dts != AV_NOPTS_VALUE && 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) {
|
/* 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");
|
av_log(ic, AV_LOG_WARNING, "max_analyze_duration reached\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
st->info->codec_info_duration += pkt->duration;
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int64_t last = st->info->last_dts;
|
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++) {
|
for(i=0;i<ic->nb_streams;i++) {
|
||||||
st = ic->streams[i];
|
st = ic->streams[i];
|
||||||
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
|
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,
|
av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den,
|
||||||
(st->codec_info_nb_frames-2)*(int64_t)st->time_base.den,
|
delta_packets*(int64_t)st->time_base.den,
|
||||||
st->info->codec_info_duration*(int64_t)st->time_base.num, 60000);
|
delta_dts*(int64_t)st->time_base.num, 60000);
|
||||||
|
}
|
||||||
// the check for tb_unreliable() is not completely correct, since this is not about handling
|
// 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.
|
// a unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
|
||||||
// ipmovie.c produces.
|
// ipmovie.c produces.
|
||||||
|
@@ -22,7 +22,7 @@ FATE_SAMPLES_AVCONV += $(FATE_AMIX)
|
|||||||
|
|
||||||
FATE_ASYNCTS += fate-filter-asyncts
|
FATE_ASYNCTS += fate-filter-asyncts
|
||||||
fate-filter-asyncts: SRC = $(SAMPLES)/nellymoser/nellymoser-discont.flv
|
fate-filter-asyncts: SRC = $(SAMPLES)/nellymoser/nellymoser-discont.flv
|
||||||
fate-filter-asyncts: CMD = pcm -i $(SRC) -af asyncts
|
fate-filter-asyncts: CMD = pcm -analyzeduration 10000000 -i $(SRC) -af asyncts
|
||||||
fate-filter-asyncts: CMP = oneoff
|
fate-filter-asyncts: CMP = oneoff
|
||||||
fate-filter-asyncts: REF = $(SAMPLES)/nellymoser/nellymoser-discont.pcm
|
fate-filter-asyncts: REF = $(SAMPLES)/nellymoser/nellymoser-discont.pcm
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user