X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Futils.c;h=2b378ab712e4a1720b466fbcd47c264808812351;hb=488eec10443c4a498a926fa4f57f74be892c461a;hp=17b342e8ad333ed3a1e3964c7a1ec45240e05caf;hpb=5cc2530fc24bc2acddeb03687a9efa5ca8fb02f0;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index 17b342e8ad3..2b378ab712e 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -32,12 +32,12 @@ #include "id3v2.h" #include "libavutil/avstring.h" #include "libavutil/mathematics.h" +#include "libavutil/parseutils.h" #include "riff.h" #include "audiointerleave.h" #include "url.h" #include #include -#include #include #if CONFIG_NETWORK #include "network.h" @@ -169,7 +169,7 @@ int av_match_ext(const char *filename, const char *extensions) while (*p != '\0' && *p != ',' && q-ext1extensions && av_match_ext(lpd.filename, fmt->extensions)) { *score_max = AVPROBE_SCORE_MAX/4; @@ -347,6 +347,14 @@ AVInputFormat *av_probe_input_format2(AVProbeData *pd, int is_opened, int *score } } + if (!fmt && id3 && *score_max < AVPROBE_SCORE_MAX/4-1) { + while ((fmt = av_iformat_next(fmt))) + if (fmt->extensions && av_match_ext("mp3", fmt->extensions)) { + *score_max = AVPROBE_SCORE_MAX/4-1; + break; + } + } + return fmt; } @@ -568,7 +576,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, #endif /* open input file and probe the format if necessary */ -static int init_input(AVFormatContext *s, const char *filename) +static int init_input(AVFormatContext *s, const char *filename, AVDictionary **options) { int ret; AVProbeData pd = {filename, NULL, 0}; @@ -586,7 +594,8 @@ static int init_input(AVFormatContext *s, const char *filename) (!s->iformat && (s->iformat = av_probe_input_format(&pd, 0)))) return 0; - if ((ret = avio_open(&s->pb, filename, AVIO_FLAG_READ)) < 0) + if ((ret = avio_open2(&s->pb, filename, AVIO_FLAG_READ, + &s->interrupt_callback, options)) < 0) return ret; if (s->iformat) return 0; @@ -611,7 +620,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma if ((ret = av_opt_set_dict(s, &tmp)) < 0) goto fail; - if ((ret = init_input(s, filename)) < 0) + if ((ret = init_input(s, filename, &tmp)) < 0) goto fail; /* check filename in case an image number is expected */ @@ -725,6 +734,7 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_WARNING, "Dropped corrupted packet (stream = %d)\n", pkt->stream_index); + av_free_packet(pkt); continue; } @@ -954,11 +964,6 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, delay= st->codec->has_b_frames; presentation_delayed = 0; - // ignore delay caused by frame threading so that the mpeg2-without-dts - // warning will not trigger - if (delay && st->codec->active_thread_type&FF_THREAD_FRAME) - delay -= st->codec->thread_count-1; - /* XXX: need has_b_frame, but cannot get it if the codec is not initialized */ if (delay && @@ -1374,7 +1379,15 @@ void ff_read_frame_flush(AVFormatContext *s) } } -void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp){ +#if FF_API_SEEK_PUBLIC +void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp) +{ + ff_update_cur_dts(s, ref_st, timestamp); +} +#endif + +void ff_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp) +{ int i; for(i = 0; i < s->nb_streams; i++) { @@ -1494,7 +1507,14 @@ int av_index_search_timestamp(AVStream *st, int64_t wanted_timestamp, wanted_timestamp, flags); } +#if FF_API_SEEK_PUBLIC int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags){ + return ff_seek_frame_binary(s, stream_index, target_ts, flags); +} +#endif + +int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts, int flags) +{ AVInputFormat *avif= s->iformat; int64_t av_uninit(pos_min), av_uninit(pos_max), pos, pos_limit; int64_t ts_min, ts_max, ts; @@ -1541,7 +1561,7 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts } } - pos= av_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit, ts_min, ts_max, flags, &ts, avif->read_timestamp); + pos= ff_gen_search(s, stream_index, target_ts, pos_min, pos_max, pos_limit, ts_min, ts_max, flags, &ts, avif->read_timestamp); if(pos<0) return -1; @@ -1549,12 +1569,28 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts if ((ret = avio_seek(s->pb, pos, SEEK_SET)) < 0) return ret; - av_update_cur_dts(s, st, ts); + ff_update_cur_dts(s, st, ts); return 0; } -int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, int64_t pos_min, int64_t pos_max, int64_t pos_limit, int64_t ts_min, int64_t ts_max, int flags, int64_t *ts_ret, int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )){ +#if FF_API_SEEK_PUBLIC +int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, + int64_t pos_min, int64_t pos_max, int64_t pos_limit, + int64_t ts_min, int64_t ts_max, int flags, int64_t *ts_ret, + int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )) +{ + return ff_gen_search(s, stream_index, target_ts, pos_min, pos_max, + pos_limit, ts_min, ts_max, flags, ts_ret, + read_timestamp); +} +#endif + +int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, + int64_t pos_min, int64_t pos_max, int64_t pos_limit, + int64_t ts_min, int64_t ts_max, int flags, int64_t *ts_ret, + int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )) +{ int64_t pos, ts; int64_t start_pos, filesize; int no_change; @@ -1708,7 +1744,7 @@ static int seek_frame_generic(AVFormatContext *s, ie= &st->index_entries[st->nb_index_entries-1]; if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0) return ret; - av_update_cur_dts(s, st, ie->timestamp); + ff_update_cur_dts(s, st, ie->timestamp); }else{ if ((ret = avio_seek(s->pb, s->data_offset, SEEK_SET)) < 0) return ret; @@ -1739,7 +1775,7 @@ static int seek_frame_generic(AVFormatContext *s, ie = &st->index_entries[index]; if ((ret = avio_seek(s->pb, ie->pos, SEEK_SET)) < 0) return ret; - av_update_cur_dts(s, st, ie->timestamp); + ff_update_cur_dts(s, st, ie->timestamp); return 0; } @@ -1749,10 +1785,12 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f int ret; AVStream *st; - ff_read_frame_flush(s); - - if(flags & AVSEEK_FLAG_BYTE) + if (flags & AVSEEK_FLAG_BYTE) { + if (s->iformat->flags & AVFMT_NO_BYTE_SEEK) + return -1; + ff_read_frame_flush(s); return seek_frame_byte(s, stream_index, timestamp, flags); + } if(stream_index < 0){ stream_index= av_find_default_stream_index(s); @@ -1765,18 +1803,22 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f } /* first, we try the format specific seek */ - if (s->iformat->read_seek) + if (s->iformat->read_seek) { + ff_read_frame_flush(s); ret = s->iformat->read_seek(s, stream_index, timestamp, flags); - else + } else ret = -1; if (ret >= 0) { return 0; } - if(s->iformat->read_timestamp && !(s->iformat->flags & AVFMT_NOBINSEARCH)) - return av_seek_frame_binary(s, stream_index, timestamp, flags); - else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) + if (s->iformat->read_timestamp && !(s->iformat->flags & AVFMT_NOBINSEARCH)) { + ff_read_frame_flush(s); + return ff_seek_frame_binary(s, stream_index, timestamp, flags); + } else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) { + ff_read_frame_flush(s); return seek_frame_generic(s, stream_index, timestamp, flags); + } else return -1; } @@ -1786,10 +1828,10 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int if(min_ts > ts || max_ts < ts) return -1; - ff_read_frame_flush(s); - - if (s->iformat->read_seek2) + if (s->iformat->read_seek2) { + ff_read_frame_flush(s); return s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags); + } if(s->iformat->read_timestamp){ //try to seek via read_timestamp() @@ -1831,7 +1873,7 @@ static int has_duration(AVFormatContext *ic) static void update_stream_timings(AVFormatContext *ic) { int64_t start_time, start_time1, end_time, end_time1; - int64_t duration, duration1; + int64_t duration, duration1, filesize; int i; AVStream *st; @@ -1842,33 +1884,28 @@ static void update_stream_timings(AVFormatContext *ic) st = ic->streams[i]; if (st->start_time != AV_NOPTS_VALUE && st->time_base.den) { start_time1= av_rescale_q(st->start_time, st->time_base, AV_TIME_BASE_Q); - if (start_time1 < start_time) - start_time = start_time1; + start_time = FFMIN(start_time, start_time1); if (st->duration != AV_NOPTS_VALUE) { end_time1 = start_time1 + av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q); - if (end_time1 > end_time) - end_time = end_time1; + end_time = FFMAX(end_time, end_time1); } } if (st->duration != AV_NOPTS_VALUE) { duration1 = av_rescale_q(st->duration, st->time_base, AV_TIME_BASE_Q); - if (duration1 > duration) - duration = duration1; + duration = FFMAX(duration, duration1); } } if (start_time != INT64_MAX) { ic->start_time = start_time; - if (end_time != INT64_MIN) { - if (end_time - start_time > duration) - duration = end_time - start_time; - } + if (end_time != INT64_MIN) + duration = FFMAX(duration, end_time - start_time); } if (duration != INT64_MIN) { ic->duration = duration; - if (ic->file_size > 0) { + if (ic->pb && (filesize = avio_size(ic->pb)) > 0) { /* compute the bitrate */ - ic->bit_rate = (double)ic->file_size * 8.0 * AV_TIME_BASE / + ic->bit_rate = (double)filesize * 8.0 * AV_TIME_BASE / (double)ic->duration; } } @@ -1910,9 +1947,8 @@ static void estimate_timings_from_bit_rate(AVFormatContext *ic) /* if duration is already set, we believe it */ if (ic->duration == AV_NOPTS_VALUE && - ic->bit_rate != 0 && - ic->file_size != 0) { - filesize = ic->file_size; + ic->bit_rate != 0) { + filesize = ic->pb ? avio_size(ic->pb) : 0; if (filesize > 0) { for(i = 0; i < ic->nb_streams; i++) { st = ic->streams[i]; @@ -1956,7 +1992,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) /* estimate the end time (duration) */ /* XXX: may need to support wrapping */ - filesize = ic->file_size; + filesize = ic->pb ? avio_size(ic->pb) : 0; end_time = AV_NOPTS_VALUE; do{ offset = filesize - (DURATION_MAX_READ_SIZE<pb); - if (file_size < 0) - file_size = 0; + file_size = FFMAX(0, file_size); } - ic->file_size = file_size; if ((!strcmp(ic->iformat->name, "mpeg") || !strcmp(ic->iformat->name, "mpegts")) && @@ -2066,7 +2100,7 @@ static int has_codec_parameters(AVCodecContext *avctx) avctx->codec_id == CODEC_ID_MP1 || avctx->codec_id == CODEC_ID_MP2 || avctx->codec_id == CODEC_ID_MP3 || - avctx->codec_id == CODEC_ID_SPEEX)) + avctx->codec_id == CODEC_ID_CELT)) return 0; break; case AVMEDIA_TYPE_VIDEO: @@ -2082,7 +2116,7 @@ static int has_codec_parameters(AVCodecContext *avctx) static int has_decode_delay_been_guessed(AVStream *st) { return st->codec->codec_id != CODEC_ID_H264 || - st->codec_info_nb_frames >= 6 + st->codec->has_b_frames; + st->info->nb_decoded_frames >= 6; } static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **options) @@ -2108,6 +2142,8 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option avcodec_get_frame_defaults(&picture); ret = avcodec_decode_video2(st->codec, &picture, &got_picture, avpkt); + if (got_picture) + st->info->nb_decoded_frames++; break; case AVMEDIA_TYPE_AUDIO: data_size = FFMAX(avpkt->size, AVCODEC_MAX_AUDIO_FRAME_SIZE); @@ -2144,7 +2180,7 @@ enum CodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag) return tags[i].id; } for(i=0; tags[i].id != CODEC_ID_NONE; i++) { - if (ff_toupper4(tag) == ff_toupper4(tags[i].tag)) + if (avpriv_toupper4(tag) == avpriv_toupper4(tags[i].tag)) return tags[i].id; } return CODEC_ID_NONE; @@ -2271,7 +2307,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) count = 0; read_size = 0; for(;;) { - if(url_interrupt_cb()){ + if (ff_check_interrupt(&ic->interrupt_callback)){ ret= AVERROR_EXIT; av_log(ic, AV_LOG_DEBUG, "interrupted\n"); break; @@ -2357,9 +2393,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) } { int64_t last = st->info->last_dts; - int64_t duration= pkt->dts - last; - if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && duration>0){ + if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && pkt->dts > last){ + int64_t duration= pkt->dts - last; double dur= duration * av_q2d(st->time_base); // if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) @@ -2369,7 +2405,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) for (i=1; iinfo->duration_error); i++) { int framerate= get_std_framerate(i); int ticks= lrintf(dur*framerate/(1001*12)); - double error= dur - ticks*1001*12/(double)framerate; + double error = dur - (double)ticks*1001*12 / framerate; st->info->duration_error[i] += error*error; } st->info->duration_count++; @@ -2418,9 +2454,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) (st->codec_info_nb_frames-2)*(int64_t)st->time_base.den, st->info->codec_info_duration*(int64_t)st->time_base.num, 60000); if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample) - st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt); - // 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. @@ -2655,7 +2688,17 @@ void av_close_input_file(AVFormatContext *s) avio_close(pb); } +#if FF_API_NEW_STREAM AVStream *av_new_stream(AVFormatContext *s, int id) +{ + AVStream *st = avformat_new_stream(s, NULL); + if (st) + st->id = id; + return st; +} +#endif + +AVStream *avformat_new_stream(AVFormatContext *s, AVCodec *c) { AVStream *st; int i; @@ -2676,13 +2719,12 @@ AVStream *av_new_stream(AVFormatContext *s, int id) return NULL; } - st->codec = avcodec_alloc_context3(NULL); + st->codec = avcodec_alloc_context3(c); if (s->iformat) { /* no default bitrate if decoding */ st->codec->bit_rate = 0; } st->index = s->nb_streams; - st->id = id; st->start_time = AV_NOPTS_VALUE; st->duration = AV_NOPTS_VALUE; /* we set the current DTS to 0 so that formats without any timestamps @@ -2729,7 +2771,7 @@ AVProgram *av_new_program(AVFormatContext *ac, int id) return program; } -AVChapter *ff_new_chapter(AVFormatContext *s, int id, AVRational time_base, int64_t start, int64_t end, const char *title) +AVChapter *avpriv_new_chapter(AVFormatContext *s, int id, AVRational time_base, int64_t start, int64_t end, const char *title) { AVChapter *chapter = NULL; int i; @@ -2797,7 +2839,7 @@ static int validate_codec_tag(AVFormatContext *s, AVStream *st) for (n = 0; s->oformat->codec_tag[n]; n++) { avctag = s->oformat->codec_tag[n]; while (avctag->id != CODEC_ID_NONE) { - if (ff_toupper4(avctag->tag) == ff_toupper4(st->codec->codec_tag)) { + if (avpriv_toupper4(avctag->tag) == avpriv_toupper4(st->codec->codec_tag)) { id = avctag->id; if (id == st->codec->codec_id) return 1; @@ -3335,7 +3377,7 @@ void av_dump_format(AVFormatContext *ic, int is_output) { int i; - uint8_t *printed = av_mallocz(ic->nb_streams); + uint8_t *printed = ic->nb_streams ? av_mallocz(ic->nb_streams) : NULL; if (ic->nb_streams && !printed) return; @@ -3896,9 +3938,14 @@ void ff_make_absolute_url(char *buf, int size, const char *base, int64_t ff_iso8601_to_unix_time(const char *datestr) { #if HAVE_STRPTIME - struct tm time = {0}; - strptime(datestr, "%Y - %m - %dT%T", &time); - return mktime(&time); + struct tm time1 = {0}, time2 = {0}; + char *ret1, *ret2; + ret1 = strptime(datestr, "%Y - %m - %d %T", &time1); + ret2 = strptime(datestr, "%Y - %m - %dT%T", &time2); + if (ret2 && !ret1) + return av_timegm(&time2); + else + return av_timegm(&time1); #else av_log(NULL, AV_LOG_WARNING, "strptime() unavailable on this system, cannot convert " "the date string.\n"); @@ -3919,3 +3966,24 @@ int avformat_query_codec(AVOutputFormat *ofmt, enum CodecID codec_id, int std_co } return AVERROR_PATCHWELCOME; } + +int avformat_network_init(void) +{ +#if CONFIG_NETWORK + int ret; + ff_network_inited_globally = 1; + if ((ret = ff_network_init()) < 0) + return ret; + ff_tls_init(); +#endif + return 0; +} + +int avformat_network_deinit(void) +{ +#if CONFIG_NETWORK + ff_network_close(); + ff_tls_deinit(); +#endif + return 0; +}