X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Futils.c;h=3630c6f93f3a1976cc0f3aa8b3a46e2c3d00aa43;hb=aba232cfa9b193604ed98f3fa505378d006b1b3b;hp=60ba9840668bf11b6d7fe4faca57aac15b8da62d;hpb=62bebf6edbbccab013062f74a3093ed3ddbe04d8;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index 60ba9840668..3630c6f93f3 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -35,11 +35,10 @@ #include "libavutil/avstring.h" #include "libavutil/mathematics.h" #include "libavutil/parseutils.h" +#include "libavutil/time.h" #include "riff.h" #include "audiointerleave.h" #include "url.h" -#include -#include #include #if CONFIG_NETWORK #include "network.h" @@ -557,7 +556,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma } s->duration = s->start_time = AV_NOPTS_VALUE; - av_strlcpy(s->filename, filename, sizeof(s->filename)); + av_strlcpy(s->filename, filename ? filename : "", sizeof(s->filename)); /* allocate private data */ if (s->iformat->priv_data_size > 0) { @@ -619,13 +618,17 @@ static void probe_codec(AVFormatContext *s, AVStream *st, const AVPacket *pkt) av_log(s, AV_LOG_DEBUG, "probing stream %d\n", st->index); --st->probe_packets; - pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE); - memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size); - pd->buf_size += pkt->size; - memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE); + if (pkt) { + pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE); + memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size); + pd->buf_size += pkt->size; + memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE); + } else { + st->probe_packets = 0; + } - if(av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)){ - //FIXME we do not reduce score to 0 for the case of running out of buffer space in bytes + if (!st->probe_packets || + av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)) { set_codec_from_probe_data(s, st, pd, st->probe_packets > 0 ? AVPROBE_SCORE_MAX/4 : 0); if(st->codec->codec_id != CODEC_ID_PROBE){ pd->buf_size=0; @@ -646,10 +649,14 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) if (pktl) { *pkt = pktl->pkt; - if(s->streams[pkt->stream_index]->codec->codec_id != CODEC_ID_PROBE || - !s->streams[pkt->stream_index]->probe_packets || - s->raw_packet_buffer_remaining_size < pkt->size){ - AVProbeData *pd = &s->streams[pkt->stream_index]->probe_data; + st = s->streams[pkt->stream_index]; + if (st->codec->codec_id != CODEC_ID_PROBE || !st->probe_packets || + s->raw_packet_buffer_remaining_size < pkt->size) { + AVProbeData *pd; + if (st->probe_packets) { + probe_codec(s, st, NULL); + } + pd = &st->probe_data; av_freep(&pd->buf); pd->buf_size = 0; s->raw_packet_buffer = pktl->next; @@ -664,8 +671,12 @@ int ff_read_packet(AVFormatContext *s, AVPacket *pkt) if (ret < 0) { if (!pktl || ret == AVERROR(EAGAIN)) return ret; - for (i = 0; i < s->nb_streams; i++) - s->streams[i]->probe_packets = 0; + for (i = 0; i < s->nb_streams; i++) { + st = s->streams[i]; + if (st->probe_packets) { + probe_codec(s, st, NULL); + } + } continue; } @@ -747,9 +758,9 @@ static void compute_frame_duration(int *pnum, int *pden, AVStream *st, *pden = 0; switch(st->codec->codec_type) { case AVMEDIA_TYPE_VIDEO: - if (st->r_frame_rate.num) { - *pnum = st->r_frame_rate.den; - *pden = st->r_frame_rate.num; + if (st->avg_frame_rate.num) { + *pnum = st->avg_frame_rate.den; + *pden = st->avg_frame_rate.num; } else if(st->time_base.num*1000LL > st->time_base.den) { *pnum = st->time_base.num; *pden = st->time_base.den; @@ -2276,7 +2287,11 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) } for (i=0; inb_streams; i++) { +#if FF_API_R_FRAME_RATE ic->streams[i]->info->last_dts = AV_NOPTS_VALUE; +#endif + ic->streams[i]->info->fps_first_dts = AV_NOPTS_VALUE; + ic->streams[i]->info->fps_last_dts = AV_NOPTS_VALUE; } count = 0; @@ -2303,8 +2318,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (ic->fps_probe_size >= 0) fps_analyze_framecount = ic->fps_probe_size; /* variable fps and no guess at the real fps */ - if( tb_unreliable(st->codec) && !(st->r_frame_rate.num && st->avg_frame_rate.num) - && st->info->duration_count < fps_analyze_framecount + if( tb_unreliable(st->codec) && !st->avg_frame_rate.num + && st->codec_info_nb_frames < fps_analyze_framecount && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) break; if(st->parser && st->parser->parser->split && !st->codec->extradata) @@ -2372,20 +2387,45 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) break; } - pkt= add_to_pktbuf(&ic->packet_buffer, &pkt1, &ic->packet_buffer_end); - if ((ret = av_dup_packet(pkt)) < 0) - goto find_stream_info_err; + if (ic->flags & AVFMT_FLAG_NOBUFFER) { + pkt = &pkt1; + } else { + pkt = add_to_pktbuf(&ic->packet_buffer, &pkt1, + &ic->packet_buffer_end); + if ((ret = av_dup_packet(pkt)) < 0) + goto find_stream_info_err; + } 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; } +#if FF_API_R_FRAME_RATE { int64_t last = st->info->last_dts; @@ -2393,8 +2433,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) int64_t duration= pkt->dts - last; double dur= duration * av_q2d(st->time_base); -// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) -// av_log(NULL, AV_LOG_ERROR, "%f\n", dur); if (st->info->duration_count < 2) memset(st->info->duration_error, 0, sizeof(st->info->duration_error)); for (i=1; iinfo->duration_error); i++) { @@ -2411,6 +2449,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (last == AV_NOPTS_VALUE || st->info->duration_count <= 1) st->info->last_dts = pkt->dts; } +#endif if(st->parser && st->parser->parser->split && !st->codec->extradata){ int i= st->parser->parser->split(st->codec, pkt->data, pkt->size); if (i > 0 && i < FF_MAX_EXTRADATA_SIZE) { @@ -2446,27 +2485,47 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) for(i=0;inb_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; + int best_fps = 0; + double best_error = 0.01; + 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); + + /* round guessed framerate to a "standard" framerate if it's + * within 1% of the original estimate*/ + for (j = 1; j < MAX_STD_TIMEBASES; j++) { + AVRational std_fps = (AVRational){get_std_framerate(j), 12*1001}; + double error = fabs(av_q2d(st->avg_frame_rate) / av_q2d(std_fps) - 1); + + if (error < best_error) { + best_error = error; + best_fps = std_fps.num; + } + } + if (best_fps) { + av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, + best_fps, 12*1001, INT_MAX); + } + } +#if FF_API_R_FRAME_RATE // 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. if (tb_unreliable(st->codec) && st->info->duration_count > 15 && st->info->duration_gcd > 1 && !st->r_frame_rate.num) av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, st->time_base.den, st->time_base.num * st->info->duration_gcd, INT_MAX); if (st->info->duration_count && !st->r_frame_rate.num - && tb_unreliable(st->codec) /*&& - //FIXME we should not special-case MPEG-2, but this needs testing with non-MPEG-2 ... - st->time_base.num*duration_sum[i]/st->info->duration_count*101LL > st->time_base.den*/){ + && tb_unreliable(st->codec)) { int num = 0; double best_error= 2*av_q2d(st->time_base); best_error = best_error*best_error*st->info->duration_count*1000*12*30; for (j=1; jinfo->duration_error); j++) { double error = st->info->duration_error[j] * get_std_framerate(j); -// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) -// av_log(NULL, AV_LOG_ERROR, "%f %f\n", get_std_framerate(j) / 12.0/1001, error); if(error < best_error){ best_error= error; num = get_std_framerate(j); @@ -2476,6 +2535,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (num && (!st->r_frame_rate.num || (double)num/(12*1001) < 1.01 * av_q2d(st->r_frame_rate))) av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, num, 12*1001, INT_MAX); } +#endif }else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { if(!st->codec->bits_per_coded_sample) st->codec->bits_per_coded_sample= av_get_bits_per_sample(st->codec->codec_id); @@ -3289,8 +3349,10 @@ static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_out if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){ if(st->avg_frame_rate.den && st->avg_frame_rate.num) print_fps(av_q2d(st->avg_frame_rate), "fps"); +#if FF_API_R_FRAME_RATE if(st->r_frame_rate.den && st->r_frame_rate.num) print_fps(av_q2d(st->r_frame_rate), "tbr"); +#endif if(st->time_base.den && st->time_base.num) print_fps(1/av_q2d(st->time_base), "tbn"); if(st->codec->time_base.den && st->codec->time_base.num) @@ -3399,12 +3461,12 @@ void av_dump_format(AVFormatContext *ic, av_free(printed); } -int64_t av_gettime(void) +#if FF_API_AV_GETTIME && CONFIG_SHARED && HAVE_SYMVER +FF_SYMVER(int64_t, av_gettime, (void), "LIBAVFORMAT_54") { - struct timeval tv; - gettimeofday(&tv,NULL); - return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; + return av_gettime(); } +#endif uint64_t ff_ntp_time(void) {