X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=libavformat%2Futils.c;h=6c985af1a01707727ff7f841e74007423a153169;hb=d5ed5e7d0c1fa46de348db0de4c82b0f621db3d4;hp=7fd7c32f80c1b770f68f52af7a13d33ad28f7de6;hpb=6c65cf58fdeafc1bd7643305e66e0e073429c78d;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index 7fd7c32f80c..6c985af1a01 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -480,7 +480,7 @@ static int init_input(AVFormatContext *s, const char *filename, AVDictionary **o if (s->pb) { s->flags |= AVFMT_FLAG_CUSTOM_IO; if (!s->iformat) - return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, 0); + return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, s->probesize); else if (s->iformat->flags & AVFMT_NOFILE) return AVERROR(EINVAL); return 0; @@ -495,7 +495,7 @@ static int init_input(AVFormatContext *s, const char *filename, AVDictionary **o return ret; if (s->iformat) return 0; - return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, 0); + return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, s->probesize); } static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, @@ -515,10 +515,22 @@ static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt, return &pktl->pkt; } +static void queue_attached_pictures(AVFormatContext *s) +{ + int i; + for (i = 0; i < s->nb_streams; i++) + if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC && + s->streams[i]->discard < AVDISCARD_ALL) { + AVPacket copy = s->streams[i]->attached_pic; + copy.destruct = NULL; + add_to_pktbuf(&s->raw_packet_buffer, ©, &s->raw_packet_buffer_end); + } +} + int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options) { AVFormatContext *s = *ps; - int i, ret = 0; + int ret = 0; AVDictionary *tmp = NULL; ID3v2ExtraMeta *id3v2_extra_meta = NULL; @@ -574,13 +586,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma goto fail; ff_id3v2_free_extra_meta(&id3v2_extra_meta); - /* queue attached pictures */ - for (i = 0; i < s->nb_streams; i++) - if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) { - AVPacket copy = s->streams[i]->attached_pic; - copy.destruct = NULL; - add_to_pktbuf(&s->raw_packet_buffer, ©, &s->raw_packet_buffer_end); - } + queue_attached_pictures(s); if (s->pb && !s->data_offset) s->data_offset = avio_tell(s->pb); @@ -606,7 +612,7 @@ fail: /*******************************************************/ -int av_read_packet(AVFormatContext *s, AVPacket *pkt) +int ff_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret, i; AVStream *st; @@ -692,6 +698,14 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt) } } +#if FF_API_READ_PACKET +int av_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + return ff_read_packet(s, pkt); +} +#endif + + /**********************************************************/ /** @@ -813,7 +827,8 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, st->start_time = pts; } -static void update_initial_durations(AVFormatContext *s, AVStream *st, AVPacket *pkt) +static void update_initial_durations(AVFormatContext *s, AVStream *st, + int stream_index, int duration) { AVPacketList *pktl= s->packet_buffer; int64_t cur_dts= 0; @@ -821,10 +836,10 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, AVPacket if(st->first_dts != AV_NOPTS_VALUE){ cur_dts= st->first_dts; for(; pktl; pktl= pktl->next){ - if(pktl->pkt.stream_index == pkt->stream_index){ + if(pktl->pkt.stream_index == stream_index){ if(pktl->pkt.pts != pktl->pkt.dts || pktl->pkt.dts != AV_NOPTS_VALUE || pktl->pkt.duration) break; - cur_dts -= pkt->duration; + cur_dts -= duration; } } pktl= s->packet_buffer; @@ -833,15 +848,16 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, AVPacket return; for(; pktl; pktl= pktl->next){ - if(pktl->pkt.stream_index != pkt->stream_index) + if(pktl->pkt.stream_index != stream_index) continue; if(pktl->pkt.pts == pktl->pkt.dts && pktl->pkt.dts == AV_NOPTS_VALUE && !pktl->pkt.duration){ pktl->pkt.dts= cur_dts; if(!st->codec->has_b_frames) pktl->pkt.pts= cur_dts; - cur_dts += pkt->duration; - pktl->pkt.duration= pkt->duration; + cur_dts += duration; + if (st->codec->codec_type != AVMEDIA_TYPE_AUDIO) + pktl->pkt.duration = duration; }else break; } @@ -884,13 +900,13 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, pkt->dts= pkt->pts= AV_NOPTS_VALUE; } - if (pkt->duration == 0) { + if (pkt->duration == 0 && st->codec->codec_type != AVMEDIA_TYPE_AUDIO) { compute_frame_duration(&num, &den, st, pc, pkt); if (den && num) { pkt->duration = av_rescale_rnd(1, num * (int64_t)st->time_base.den, den * (int64_t)st->time_base.num, AV_ROUND_DOWN); if(pkt->duration != 0 && s->packet_buffer) - update_initial_durations(s, st, pkt); + update_initial_durations(s, st, pkt->stream_index, pkt->duration); } } @@ -951,12 +967,29 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, st->last_IP_pts= pkt->pts; /* cannot compute PTS if not present (we can compute it only by knowing the future */ - } else if(pkt->pts != AV_NOPTS_VALUE || pkt->dts != AV_NOPTS_VALUE || pkt->duration){ - if(pkt->pts != AV_NOPTS_VALUE && pkt->duration){ - int64_t old_diff= FFABS(st->cur_dts - pkt->duration - pkt->pts); + } else if (pkt->pts != AV_NOPTS_VALUE || + pkt->dts != AV_NOPTS_VALUE || + pkt->duration || + st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + int duration = pkt->duration; + if (!duration && st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + compute_frame_duration(&num, &den, st, pc, pkt); + if (den && num) { + duration = av_rescale_rnd(1, num * (int64_t)st->time_base.den, + den * (int64_t)st->time_base.num, + AV_ROUND_DOWN); + if (duration != 0 && s->packet_buffer) { + update_initial_durations(s, st, pkt->stream_index, + duration); + } + } + } + + if(pkt->pts != AV_NOPTS_VALUE && duration){ + int64_t old_diff= FFABS(st->cur_dts - duration - pkt->pts); int64_t new_diff= FFABS(st->cur_dts - pkt->pts); - if(old_diff < new_diff && old_diff < (pkt->duration>>3)){ - pkt->pts += pkt->duration; + if(old_diff < new_diff && old_diff < (duration>>3)){ + pkt->pts += duration; // av_log(NULL, AV_LOG_DEBUG, "id:%d old:%"PRId64" new:%"PRId64" dur:%d cur:%"PRId64" size:%d\n", pkt->stream_index, old_diff, new_diff, pkt->duration, st->cur_dts, pkt->size); } } @@ -969,7 +1002,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, pkt->pts = st->cur_dts; pkt->dts = pkt->pts; if(pkt->pts != AV_NOPTS_VALUE) - st->cur_dts = pkt->pts + pkt->duration; + st->cur_dts = pkt->pts + duration; } } @@ -1131,7 +1164,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) AVPacket cur_pkt; /* read next packet */ - ret = av_read_packet(s, &cur_pkt); + ret = ff_read_packet(s, &cur_pkt); if (ret < 0) { if (ret == AVERROR(EAGAIN)) return ret; @@ -1158,7 +1191,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) cur_pkt.size); } if (s->debug & FF_FDEBUG_TS) - av_log(s, AV_LOG_DEBUG, "av_read_packet stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, duration=%d, flags=%d\n", + av_log(s, AV_LOG_DEBUG, "ff_read_packet stream=%d, pts=%"PRId64", dts=%"PRId64", size=%d, duration=%d, flags=%d\n", cur_pkt.stream_index, cur_pkt.pts, cur_pkt.dts, @@ -1288,7 +1321,8 @@ int av_find_default_stream_index(AVFormatContext *s) return -1; for(i = 0; i < s->nb_streams; i++) { st = s->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + !(st->disposition & AV_DISPOSITION_ATTACHED_PIC)) { return i; } if (first_audio_index < 0 && st->codec->codec_type == AVMEDIA_TYPE_AUDIO) @@ -1620,14 +1654,6 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, static int seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, int flags){ int64_t pos_min, pos_max; -#if 0 - AVStream *st; - - if (stream_index < 0) - return -1; - - st= s->streams[stream_index]; -#endif pos_min = s->data_offset; pos_max = avio_size(s->pb) - 1; @@ -1637,9 +1663,6 @@ static int seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, in avio_seek(s->pb, pos, SEEK_SET); -#if 0 - av_update_cur_dts(s, st, ts); -#endif return 0; } @@ -1702,7 +1725,8 @@ static int seek_frame_generic(AVFormatContext *s, return 0; } -int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +static int seek_frame_internal(AVFormatContext *s, int stream_index, + int64_t timestamp, int flags) { int ret; AVStream *st; @@ -1745,14 +1769,29 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f return -1; } +int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +{ + int ret = seek_frame_internal(s, stream_index, timestamp, flags); + + if (ret >= 0) + queue_attached_pictures(s); + + return ret; +} + int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int64_t ts, int64_t max_ts, int flags) { if(min_ts > ts || max_ts < ts) return -1; if (s->iformat->read_seek2) { + int ret; ff_read_frame_flush(s); - return s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags); + ret = s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags); + + if (ret >= 0) + queue_attached_pictures(s); + return ret; } if(s->iformat->read_timestamp){ @@ -1925,7 +1964,7 @@ static void estimate_timings_from_pts(AVFormatContext *ic, int64_t old_offset) break; do { - ret = av_read_packet(ic, pkt); + ret = ff_read_packet(ic, pkt); } while(ret == AVERROR(EAGAIN)); if (ret != 0) break; @@ -2007,15 +2046,20 @@ static void estimate_timings(AVFormatContext *ic, int64_t old_offset) } } -static int has_codec_parameters(AVCodecContext *avctx) +static int has_codec_parameters(AVStream *st) { + AVCodecContext *avctx = st->codec; int val; switch (avctx->codec_type) { case AVMEDIA_TYPE_AUDIO: - val = avctx->sample_rate && avctx->channels && avctx->sample_fmt != AV_SAMPLE_FMT_NONE; + val = avctx->sample_rate && avctx->channels; + if (st->info->found_decoder >= 0 && avctx->sample_fmt == AV_SAMPLE_FMT_NONE) + return 0; break; case AVMEDIA_TYPE_VIDEO: - val = avctx->width && avctx->pix_fmt != PIX_FMT_NONE; + val = avctx->width; + if (st->info->found_decoder >= 0 && avctx->pix_fmt == PIX_FMT_NONE) + return 0; break; default: val = 1; @@ -2038,14 +2082,16 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option AVFrame picture; AVPacket pkt = *avpkt; - if (!avcodec_is_open(st->codec)) { + if (!avcodec_is_open(st->codec) && !st->info->found_decoder) { AVDictionary *thread_opt = NULL; codec = st->codec->codec ? st->codec->codec : avcodec_find_decoder(st->codec->codec_id); - if (!codec) + if (!codec) { + st->info->found_decoder = -1; return -1; + } /* force thread count to 1 since the h264 decoder will not extract SPS * and PPS to extradata during multi-threaded decoding */ @@ -2053,13 +2099,20 @@ static int try_decode_frame(AVStream *st, AVPacket *avpkt, AVDictionary **option ret = avcodec_open2(st->codec, codec, options ? options : &thread_opt); if (!options) av_dict_free(&thread_opt); - if (ret < 0) + if (ret < 0) { + st->info->found_decoder = -1; return ret; - } + } + st->info->found_decoder = 1; + } else if (!st->info->found_decoder) + st->info->found_decoder = 1; + + if (st->info->found_decoder < 0) + return -1; while ((pkt.size > 0 || (!pkt.data && got_picture)) && ret >= 0 && - (!has_codec_parameters(st->codec) || + (!has_codec_parameters(st) || !has_decode_delay_been_guessed(st) || (!st->codec_info_nb_frames && st->codec->codec->capabilities & CODEC_CAP_CHANNEL_CONF))) { got_picture = 0; @@ -2210,7 +2263,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) : &thread_opt); //try to just open decoders, in case this is enough to get parameters - if(!has_codec_parameters(st->codec)){ + if (!has_codec_parameters(st)) { if (codec && !st->codec->codec) avcodec_open2(st->codec, codec, options ? &options[i] : &thread_opt); @@ -2237,7 +2290,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) int fps_analyze_framecount = 20; st = ic->streams[i]; - if (!has_codec_parameters(st->codec)) + if (!has_codec_parameters(st)) break; /* if the timebase is coarse (like the usual millisecond precision of mkv), we need to analyze more frames to reliably arrive at @@ -2283,7 +2336,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (ret < 0) { /* EOF or error*/ AVPacket empty_pkt = { 0 }; - int err; + int err = 0; av_init_packet(&empty_pkt); ret = -1; /* we could not have all the codec parameters before EOF */ @@ -2291,16 +2344,18 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) st = ic->streams[i]; /* flush the decoders */ - do { - err = try_decode_frame(st, &empty_pkt, - (options && i < orig_nb_streams) ? - &options[i] : NULL); - } while (err > 0 && !has_codec_parameters(st->codec)); + if (st->info->found_decoder == 1) { + do { + err = try_decode_frame(st, &empty_pkt, + (options && i < orig_nb_streams) ? + &options[i] : NULL); + } while (err > 0 && !has_codec_parameters(st)); + } if (err < 0) { av_log(ic, AV_LOG_WARNING, "decoding for stream %d failed\n", st->index); - } else if (!has_codec_parameters(st->codec)){ + } else if (!has_codec_parameters(st)) { char buf[256]; avcodec_string(buf, sizeof(buf), st->codec, 0); av_log(ic, AV_LOG_WARNING, @@ -2320,7 +2375,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) st = ic->streams[pkt->stream_index]; if (st->codec_info_nb_frames>1) { - if (st->time_base.den > 0 && av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) { + if (av_rescale_q(st->info->codec_info_duration, st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) { av_log(ic, AV_LOG_WARNING, "max_analyze_duration reached\n"); break; } @@ -2385,11 +2440,11 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) } for(i=0;inb_streams;i++) { st = ic->streams[i]; - if (st->codec_info_nb_frames>2 && !st->avg_frame_rate.num && st->info->codec_info_duration) - 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); 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) + 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); // 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. @@ -2439,31 +2494,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) compute_chapters_end(ic); -#if 0 - /* correct DTS for B-frame streams with no timestamps */ - for(i=0;inb_streams;i++) { - st = ic->streams[i]; - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - if(b-frames){ - ppktl = &ic->packet_buffer; - while(ppkt1){ - if(ppkt1->stream_index != i) - continue; - if(ppkt1->pkt->dts < 0) - break; - if(ppkt1->pkt->pts != AV_NOPTS_VALUE) - break; - ppkt1->pkt->dts -= delta; - ppkt1= ppkt1->next; - } - if(ppkt1) - continue; - st->cur_dts -= delta; - } - } - } -#endif - find_stream_info_err: for (i=0; i < ic->nb_streams; i++) { if (ic->streams[i]->codec) @@ -3038,7 +3068,9 @@ static int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacke return comp > 0; } -int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush){ +int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, + AVPacket *pkt, int flush) +{ AVPacketList *pktl; int stream_count=0; int i; @@ -3068,6 +3100,14 @@ int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pk } } +#if FF_API_INTERLEAVE_PACKET +int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, + AVPacket *pkt, int flush) +{ + return ff_interleave_packet_per_dts(s, out, pkt, flush); +} +#endif + /** * Interleave an AVPacket correctly so it can be muxed. * @param out the interleaved packet will be output here @@ -3084,7 +3124,7 @@ static int interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *in, in av_free_packet(in); return ret; } else - return av_interleave_packet_per_dts(s, out, in, flush); + return ff_interleave_packet_per_dts(s, out, in, flush); } int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){