X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Futils.c;h=ab7345ede2022cd5795e5ceb111b381049a3ae6a;hb=42610c4983c14cf320267ad4fad5db7c95f203b5;hp=d062948b4c8cb37714e8e88f78e8bb3b83776dae;hpb=e19fbbec9520caf4817ffb8875322ab558611a18;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index d062948b4c8..ab7345ede20 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -417,8 +417,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, if (!fmt || must_open_file) { /* if no file needed do not try to open one */ - if (url_fopen(pb, filename, URL_RDONLY) < 0) { - err = AVERROR_IO; + if ((err=url_fopen(pb, filename, URL_RDONLY)) < 0) { goto fail; } file_opened = 1; @@ -429,7 +428,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, for(probe_size= PROBE_BUF_MIN; probe_size<=PROBE_BUF_MAX && !fmt; probe_size<<=1){ int score= probe_size < PROBE_BUF_MAX ? AVPROBE_SCORE_MAX/4 : 0; /* read probe data */ - pd->buf= av_realloc(pd->buf, probe_size); + pd->buf= av_realloc(pd->buf, probe_size + AVPROBE_PADDING_SIZE); pd->buf_size = get_buffer(pb, pd->buf, probe_size); if (url_fseek(pb, 0, SEEK_SET) < 0) { url_fclose(pb); @@ -452,7 +451,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, } /* XXX: suppress this hack for redirectors */ -#ifdef CONFIG_NETWORK +#ifdef CONFIG_REDIR_DEMUXER if (fmt == &redir_demuxer) { err = redir_open(ic_ptr, pb); url_fclose(pb); @@ -484,6 +483,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, int av_read_packet(AVFormatContext *s, AVPacket *pkt) { + av_init_packet(pkt); return s->iformat->read_packet(s, pkt); } @@ -584,6 +584,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, AVCodecParserContext *pc, AVPacket *pkt) { int num, den, presentation_delayed, delay, i; + int64_t offset; /* handle wrapping */ if(st->cur_dts != AV_NOPTS_VALUE){ if(pkt->pts != AV_NOPTS_VALUE) @@ -599,6 +600,16 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, } } + /* correct timestamps with byte offset if demuxers only have timestamps on packet boundaries */ + if(pc && st->need_parsing == AVSTREAM_PARSE_TIMESTAMPS && pkt->size){ + /* this will estimate bitrate based on this frame's duration and size */ + offset = av_rescale(pc->offset, pkt->duration, pkt->size); + if(pkt->pts != AV_NOPTS_VALUE) + pkt->pts += offset; + if(pkt->dts != AV_NOPTS_VALUE) + pkt->dts += offset; + } + if(is_intra_only(st->codec)) pkt->flags |= PKT_FLAG_KEY; @@ -691,6 +702,8 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) AVStream *st; int len, ret, i; + av_init_packet(pkt); + for(;;) { /* select current input stream component */ st = s->cur_st; @@ -715,6 +728,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) /* return packet if any */ if (pkt->size) { got_packet: + pkt->pos = s->cur_pkt.pos; // Isn't quite accurate but close. pkt->duration = 0; pkt->stream_index = st->index; pkt->pts = st->parser->pts; @@ -771,8 +785,8 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) st->parser = av_parser_init(st->codec->codec_id); if (!st->parser) { /* no parser available : just output the raw packets */ - st->need_parsing = 0; - }else if(st->need_parsing == 2){ + st->need_parsing = AVSTREAM_PARSE_NONE; + }else if(st->need_parsing == AVSTREAM_PARSE_HEADERS){ st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; } if(st->parser && (s->iformat->flags & AVFMT_GENERIC_INDEX)){ @@ -1203,6 +1217,10 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i #ifdef DEBUG_SEEK av_log(s, AV_LOG_DEBUG, "%"PRId64" %"PRId64" %"PRId64" / %"PRId64" %"PRId64" %"PRId64" target:%"PRId64" limit:%"PRId64" start:%"PRId64" noc:%d\n", pos_min, pos, pos_max, ts_min, ts, ts_max, target_ts, pos_limit, start_pos, no_change); #endif + if(ts == AV_NOPTS_VALUE){ + av_log(s, AV_LOG_ERROR, "read_timestamp() failed in the middle\n"); + return -1; + } assert(ts != AV_NOPTS_VALUE); if (target_ts <= ts) { pos_limit = start_pos - 1; @@ -1265,7 +1283,7 @@ static int av_seek_frame_generic(AVFormatContext *s, index = av_index_search_timestamp(st, timestamp, flags); - if(index < 0){ + if(index < 0 || index==st->nb_index_entries-1){ int i; AVPacket pkt; @@ -1465,7 +1483,21 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse int64_t end_time; int64_t filesize, offset, duration; - av_read_frame_flush(ic); + /* free previous packet */ + if (ic->cur_st && ic->cur_st->parser) + av_free_packet(&ic->cur_pkt); + ic->cur_st = NULL; + + /* flush packet queue */ + flush_packet_queue(ic); + + for(i=0;inb_streams;i++) { + st = ic->streams[i]; + if (st->parser) { + av_parser_close(st->parser); + st->parser= NULL; + } + } /* we read the first packets to get the first PTS (not fully accurate, but it is enough now) */ @@ -1641,6 +1673,20 @@ static int try_decode_frame(AVStream *st, const uint8_t *data, int size) return ret; } +static int set_codec_from_probe_data(AVStream *st, AVProbeData *pd, int score) +{ + AVInputFormat *fmt; + fmt = av_probe_input_format2(pd, 1, &score); + + if (fmt) { + if (strncmp(fmt->name, "mp3", 3) == 0) + st->codec->codec_id = CODEC_ID_MP3; + else if (strncmp(fmt->name, "ac3", 3) == 0) + st->codec->codec_id = CODEC_ID_AC3; + } + return !!fmt; +} + /* absolute maximum size we read until we abort */ #define MAX_READ_SIZE 5000000 @@ -1662,6 +1708,8 @@ int av_find_stream_info(AVFormatContext *ic) offset_t old_offset = url_ftell(&ic->pb); int64_t codec_info_duration[MAX_STREAMS]={0}; int codec_info_nb_frames[MAX_STREAMS]={0}; + AVProbeData probe_data[MAX_STREAMS]; + int codec_identified[MAX_STREAMS]={0}; duration_error = av_mallocz(MAX_STREAMS * sizeof(*duration_error)); if (!duration_error) return AVERROR_NOMEM; @@ -1677,7 +1725,7 @@ int av_find_stream_info(AVFormatContext *ic) //only for the split stuff if (!st->parser) { st->parser = av_parser_init(st->codec->codec_id); - if(st->need_parsing == 2 && st->parser){ + if(st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser){ st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES; } } @@ -1687,6 +1735,7 @@ int av_find_stream_info(AVFormatContext *ic) last_dts[i]= AV_NOPTS_VALUE; } + memset(probe_data, 0, sizeof(probe_data)); count = 0; read_size = 0; ppktl = &ic->packet_buffer; @@ -1702,6 +1751,9 @@ int av_find_stream_info(AVFormatContext *ic) break; if(st->parser && st->parser->parser->split && !st->codec->extradata) break; + if (st->codec->codec_type == CODEC_TYPE_AUDIO && + st->codec->codec_id == CODEC_ID_NONE) + break; } if (i == ic->nb_streams) { /* NOTE: if the format has no header, then we need to read @@ -1787,6 +1839,13 @@ int av_find_stream_info(AVFormatContext *ic) } if(last == AV_NOPTS_VALUE || duration_count[index]<=1) last_dts[pkt->stream_index]= pkt->dts; + + if (st->codec->codec_id == CODEC_ID_NONE) { + AVProbeData *pd = &(probe_data[st->index]); + pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size); + memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size); + pd->buf_size += pkt->size; + } } if(st->parser && st->parser->parser->split && !st->codec->extradata){ int i= st->parser->parser->split(st->codec, pkt->data, pkt->size); @@ -1866,12 +1925,28 @@ int av_find_stream_info(AVFormatContext *ic) } } }else if(st->codec->codec_type == CODEC_TYPE_AUDIO) { + if (st->codec->codec_id == CODEC_ID_NONE) { + codec_identified[st->index] = set_codec_from_probe_data(st, &(probe_data[st->index]), 0); + if (codec_identified[st->index]) { + st->need_parsing = AVSTREAM_PARSE_FULL; + } + } if(!st->codec->bits_per_sample) st->codec->bits_per_sample= av_get_bits_per_sample(st->codec->codec_id); } } av_estimate_timings(ic, old_offset); + + for(i=0;inb_streams;i++) { + st = ic->streams[i]; + if (codec_identified[st->index]) { + av_read_frame_flush(ic); + av_seek_frame(ic, st->index, 0.0, 0); + url_fseek(&ic->pb, ic->data_offset, SEEK_SET); + } + } + #if 0 /* correct DTS for b frame streams with no timestamps */ for(i=0;inb_streams;i++) { @@ -1898,6 +1973,9 @@ int av_find_stream_info(AVFormatContext *ic) #endif av_free(duration_error); + for(i=0;icur_dts && st->cur_dts != AV_NOPTS_VALUE && st->cur_dts >= pkt->dts){ - av_log(NULL, AV_LOG_ERROR, "error, non monotone timestamps %"PRId64" >= %"PRId64" st:%d\n", st->cur_dts, pkt->dts, st->index); + av_log(NULL, AV_LOG_ERROR, "error, non monotone timestamps %"PRId64" >= %"PRId64"\n", st->cur_dts, pkt->dts); return -1; } if(pkt->dts != AV_NOPTS_VALUE && pkt->pts != AV_NOPTS_VALUE && pkt->pts < pkt->dts){ - av_log(NULL, AV_LOG_ERROR, "error, pts < dts (%"PRId64" < %"PRId64")\n", - pkt->pts, pkt->dts); + av_log(NULL, AV_LOG_ERROR, "error, pts < dts\n"); return -1; } @@ -2413,6 +2490,30 @@ static AbvEntry frame_abvs[] = { { "qcif", 176, 144, 0, 0 }, { "cif", 352, 288, 0, 0 }, { "4cif", 704, 576, 0, 0 }, + { "qqvga", 160, 120, 0, 0 }, + { "qvga", 320, 240, 0, 0 }, + { "vga", 640, 480, 0, 0 }, + { "svga", 800, 600, 0, 0 }, + { "xga", 1024, 768, 0, 0 }, + { "uxga", 1600,1200, 0, 0 }, + { "qxga", 2048,1536, 0, 0 }, + { "sxga", 1280,1024, 0, 0 }, + { "qsxga", 2560,2048, 0, 0 }, + { "hsxga", 5120,4096, 0, 0 }, + { "wvga", 852, 480, 0, 0 }, + { "wxga", 1366, 768, 0, 0 }, + { "wsxga", 1600,1024, 0, 0 }, + { "wuxga", 1920,1200, 0, 0 }, + { "woxga", 2560,1600, 0, 0 }, + { "wqsxga", 3200,2048, 0, 0 }, + { "wquxga", 3840,2400, 0, 0 }, + { "whsxga", 6400,4096, 0, 0 }, + { "whuxga", 7680,4800, 0, 0 }, + { "cga", 320, 200, 0, 0 }, + { "ega", 640, 350, 0, 0 }, + { "hd480", 852, 480, 0, 0 }, + { "hd720", 1280, 720, 0, 0 }, + { "hd1080", 1920,1080, 0, 0 }, }; int parse_image_size(int *width_ptr, int *height_ptr, const char *str) @@ -2480,7 +2581,6 @@ int parse_frame_rate(int *frame_rate, int *frame_rate_base, const char *arg) return 0; } -#ifndef CONFIG_WINCE int64_t parse_date(const char *datestr, int duration) { const char *p; @@ -2588,7 +2688,6 @@ int64_t parse_date(const char *datestr, int duration) } return negative ? -t : t; } -#endif /* CONFIG_WINCE */ int find_info_tag(char *arg, int arg_size, const char *tag1, const char *info) {