X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Futils.c;h=c91102c6ce9ea12cb0b56b9352eadb67c90f80ee;hb=3240941b2552ec9b6373163240bb89a4bab40c50;hp=0e323831d3d75081d258ac1bec4cbe9f47f01f89;hpb=9fcbcca60a6d838924d662df95b194525254f0ac;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index 0e323831d3d..c91102c6ce9 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "avformat.h" -#include "allformats.h" #include "opt.h" #include "avstring.h" #include "riff.h" @@ -468,7 +467,8 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, /* XXX: suppress this hack for redirectors */ #ifdef CONFIG_REDIR_DEMUXER - if (fmt == &redir_demuxer) { + if (!strcmp(fmt->name, "redir")) { + int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f); err = redir_open(ic_ptr, pb); url_fclose(pb); return err; @@ -647,9 +647,6 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, pkt->dts += offset; } - if(is_intra_only(st->codec)) - pkt->flags |= PKT_FLAG_KEY; - /* do we have a video B frame ? */ delay= st->codec->has_b_frames; presentation_delayed = 0; @@ -726,7 +723,9 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, // av_log(NULL, AV_LOG_ERROR, "OUTdelayed:%d/%d pts:%"PRId64", dts:%"PRId64" cur_dts:%"PRId64"\n", presentation_delayed, delay, pkt->pts, pkt->dts, st->cur_dts); /* update flags */ - if (pc) { + if(is_intra_only(st->codec)) + pkt->flags |= PKT_FLAG_KEY; + else if (pc) { pkt->flags = 0; /* key frame computation */ if (pc->pict_type == FF_I_TYPE) @@ -1364,19 +1363,18 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f /*******************************************************/ /** - * Returns TRUE if the stream has accurate timings in any stream. + * Returns TRUE if the stream has accurate duration in any stream. * - * @return TRUE if the stream has accurate timings for at least one component. + * @return TRUE if the stream has accurate duration for at least one component. */ -static int av_has_timings(AVFormatContext *ic) +static int av_has_duration(AVFormatContext *ic) { int i; AVStream *st; for(i = 0;i < ic->nb_streams; i++) { st = ic->streams[i]; - if (st->start_time != AV_NOPTS_VALUE && - st->duration != AV_NOPTS_VALUE) + if (st->duration != AV_NOPTS_VALUE) return 1; } return 0; @@ -1390,11 +1388,13 @@ static int av_has_timings(AVFormatContext *ic) static void av_update_stream_timings(AVFormatContext *ic) { int64_t start_time, start_time1, end_time, end_time1; + int64_t duration, duration1; int i; AVStream *st; start_time = INT64_MAX; end_time = INT64_MIN; + duration = INT64_MIN; for(i = 0;i < ic->nb_streams; i++) { st = ic->streams[i]; if (st->start_time != AV_NOPTS_VALUE) { @@ -1408,19 +1408,27 @@ static void av_update_stream_timings(AVFormatContext *ic) 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; + } } if (start_time != INT64_MAX) { ic->start_time = start_time; if (end_time != INT64_MIN) { - ic->duration = end_time - start_time; - if (ic->file_size > 0) { - /* compute the bit rate */ - ic->bit_rate = (double)ic->file_size * 8.0 * AV_TIME_BASE / - (double)ic->duration; - } + if (end_time - start_time > duration) + duration = end_time - start_time; + } + } + if (duration != INT64_MIN) { + ic->duration = duration; + if (ic->file_size > 0) { + /* compute the bit rate */ + ic->bit_rate = (double)ic->file_size * 8.0 * AV_TIME_BASE / + (double)ic->duration; } } - } static void fill_all_stream_timings(AVFormatContext *ic) @@ -1564,6 +1572,7 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse for(i=0; inb_streams; i++){ st= ic->streams[i]; st->cur_dts= st->first_dts; + st->last_IP_pts = AV_NOPTS_VALUE; } } @@ -1586,7 +1595,7 @@ static void av_estimate_timings(AVFormatContext *ic, offset_t old_offset) file_size && !ic->pb.is_streamed) { /* get accurate estimate from the PTSes */ av_estimate_timings_from_pts(ic, old_offset); - } else if (av_has_timings(ic)) { + } else if (av_has_duration(ic)) { /* at least one components has timings - we use them for all the components */ fill_all_stream_timings(ic); @@ -1628,7 +1637,7 @@ static int has_codec_parameters(AVCodecContext *enc) val = 1; break; } - return (val != 0); + return (enc->codec_id != CODEC_ID_NONE && val != 0); } static int try_decode_frame(AVStream *st, const uint8_t *data, int size) @@ -1793,9 +1802,6 @@ 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(st->first_dts == AV_NOPTS_VALUE) break; } @@ -2057,6 +2063,12 @@ void av_close_input_file(AVFormatContext *s) av_free(st->codec); av_free(st); } + for(i=s->nb_programs-1; i>=0; i--) { + av_freep(&s->programs[i]->provider_name); + av_freep(&s->programs[i]->name); + av_freep(&s->programs[i]->stream_index); + av_freep(&s->programs[i]); + } flush_packet_queue(s); must_open_file = 1; if (s->iformat->flags & AVFMT_NOFILE) { @@ -2103,6 +2115,43 @@ AVStream *av_new_stream(AVFormatContext *s, int id) return st; } +AVProgram *av_new_program(AVFormatContext *ac, int id) +{ + AVProgram *program=NULL; + int i; + +#ifdef DEBUG_SI + av_log(ac, AV_LOG_DEBUG, "new_program: id=0x%04x\n", id); +#endif + + for(i=0; inb_programs; i++) + if(ac->programs[i]->id == id) + program = ac->programs[i]; + + if(!program){ + program = av_mallocz(sizeof(AVProgram)); + if (!program) + return NULL; + dynarray_add(&ac->programs, &ac->nb_programs, program); + program->discard = AVDISCARD_NONE; + } + program->id = id; + + return program; +} + +void av_set_program_name(AVProgram *program, char *provider_name, char *name) +{ + assert(!provider_name == !name); + if(name){ + av_free(program->provider_name); + av_free(program-> name); + program->provider_name = av_strdup(provider_name); + program-> name = av_strdup( name); + } +} + + /************************************************************/ /* output media file */ @@ -2434,15 +2483,63 @@ fail: return ret; } +void av_program_add_stream_index(AVFormatContext *ac, int progid, unsigned int idx) +{ + int i, j; + AVProgram *program=NULL; + void *tmp; + + for(i=0; inb_programs; i++){ + if(ac->programs[i]->id != progid) + continue; + program = ac->programs[i]; + for(j=0; jnb_stream_indexes; j++) + if(program->stream_index[j] == idx) + return; + + tmp = av_realloc(program->stream_index, sizeof(unsigned int)*(program->nb_stream_indexes+1)); + if(!tmp) + return; + program->stream_index = tmp; + program->stream_index[program->nb_stream_indexes++] = idx; + return; + } +} + /* "user interface" functions */ +static void dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) +{ + char buf[256]; + int flags = (is_output ? ic->oformat->flags : ic->iformat->flags); + AVStream *st = ic->streams[i]; + int g = ff_gcd(st->time_base.num, st->time_base.den); + avcodec_string(buf, sizeof(buf), st->codec, is_output); + av_log(NULL, AV_LOG_INFO, " Stream #%d.%d", index, i); + /* the pid is an important information, so we display it */ + /* XXX: add a generic system */ + if (flags & AVFMT_SHOW_IDS) + av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id); + if (strlen(st->language) > 0) + av_log(NULL, AV_LOG_INFO, "(%s)", st->language); + av_log(NULL, AV_LOG_DEBUG, ", %d/%d", st->time_base.num/g, st->time_base.den/g); + av_log(NULL, AV_LOG_INFO, ": %s", buf); + if(st->codec->codec_type == CODEC_TYPE_VIDEO){ + if(st->r_frame_rate.den && st->r_frame_rate.num) + av_log(NULL, AV_LOG_INFO, ", %5.2f fps(r)", av_q2d(st->r_frame_rate)); +/* else if(st->time_base.den && st->time_base.num) + av_log(NULL, AV_LOG_INFO, ", %5.2f fps(m)", 1/av_q2d(st->time_base));*/ + else + av_log(NULL, AV_LOG_INFO, ", %5.2f fps(c)", 1/av_q2d(st->codec->time_base)); + } + av_log(NULL, AV_LOG_INFO, "\n"); +} void dump_format(AVFormatContext *ic, int index, const char *url, int is_output) { - int i, flags; - char buf[256]; + int i; av_log(NULL, AV_LOG_INFO, "%s #%d, %s, %s '%s':\n", is_output ? "Output" : "Input", @@ -2480,35 +2577,17 @@ void dump_format(AVFormatContext *ic, } av_log(NULL, AV_LOG_INFO, "\n"); } - for(i=0;inb_streams;i++) { - AVStream *st = ic->streams[i]; - int g= ff_gcd(st->time_base.num, st->time_base.den); - avcodec_string(buf, sizeof(buf), st->codec, is_output); - av_log(NULL, AV_LOG_INFO, " Stream #%d.%d", index, i); - /* the pid is an important information, so we display it */ - /* XXX: add a generic system */ - if (is_output) - flags = ic->oformat->flags; - else - flags = ic->iformat->flags; - if (flags & AVFMT_SHOW_IDS) { - av_log(NULL, AV_LOG_INFO, "[0x%x]", st->id); - } - if (strlen(st->language) > 0) { - av_log(NULL, AV_LOG_INFO, "(%s)", st->language); - } - av_log(NULL, AV_LOG_DEBUG, ", %d/%d", st->time_base.num/g, st->time_base.den/g); - av_log(NULL, AV_LOG_INFO, ": %s", buf); - if(st->codec->codec_type == CODEC_TYPE_VIDEO){ - if(st->r_frame_rate.den && st->r_frame_rate.num) - av_log(NULL, AV_LOG_INFO, ", %5.2f fps(r)", av_q2d(st->r_frame_rate)); -/* else if(st->time_base.den && st->time_base.num) - av_log(NULL, AV_LOG_INFO, ", %5.2f fps(m)", 1/av_q2d(st->time_base));*/ - else - av_log(NULL, AV_LOG_INFO, ", %5.2f fps(c)", 1/av_q2d(st->codec->time_base)); - } - av_log(NULL, AV_LOG_INFO, "\n"); - } + if(ic->nb_programs) { + int j, k; + for(j=0; jnb_programs; j++) { + av_log(NULL, AV_LOG_INFO, " Program %d %s\n", ic->programs[j]->id, + ic->programs[j]->name ? ic->programs[j]->name : ""); + for(k=0; kprograms[j]->nb_stream_indexes; k++) + dump_stream_format(ic, ic->programs[j]->stream_index[k], index, is_output); + } + } else + for(i=0;inb_streams;i++) + dump_stream_format(ic, i, index, is_output); } int parse_image_size(int *width_ptr, int *height_ptr, const char *str) @@ -2569,6 +2648,7 @@ int64_t parse_date(const char *datestr, int duration) p = datestr; q = NULL; if (!duration) { + /* parse the year-month-day part */ for (i = 0; i < sizeof(date_fmt) / sizeof(date_fmt[0]); i++) { q = small_strptime(p, date_fmt[i], &dt); if (q) { @@ -2576,6 +2656,8 @@ int64_t parse_date(const char *datestr, int duration) } } + /* if the year-month-day part is missing, then take the + * current year-month-day time */ if (!q) { if (is_utc) { dt = *gmtime(&now); @@ -2590,6 +2672,7 @@ int64_t parse_date(const char *datestr, int duration) if (*p == 'T' || *p == 't' || *p == ' ') p++; + /* parse the hour-minute-second part */ for (i = 0; i < sizeof(time_fmt) / sizeof(time_fmt[0]); i++) { q = small_strptime(p, time_fmt[i], &dt); if (q) { @@ -2597,13 +2680,19 @@ int64_t parse_date(const char *datestr, int duration) } } } else { + /* parse datestr as a duration */ if (p[0] == '-') { negative = 1; ++p; } + /* parse datestr as HH:MM:SS */ q = small_strptime(p, time_fmt[0], &dt); if (!q) { + /* parse datestr as S+ */ dt.tm_sec = strtol(p, (char **)&q, 10); + if (q == p) + /* the parsing didn't succeed */ + return INT64_MIN; dt.tm_min = 0; dt.tm_hour = 0; } @@ -2611,10 +2700,7 @@ int64_t parse_date(const char *datestr, int duration) /* Now we have all the fields that we can get */ if (!q) { - if (duration) - return 0; - else - return now * INT64_C(1000000); + return INT64_MIN; } if (duration) { @@ -2630,6 +2716,7 @@ int64_t parse_date(const char *datestr, int duration) t *= 1000000; + /* parse the .m... part */ if (*q == '.') { int val, n; q++; @@ -2818,68 +2905,58 @@ void url_split(char *proto, int proto_size, char *path, int path_size, const char *url) { - const char *p; - char *q; - int port; + const char *p, *ls, *at, *col, *brk, *q; - port = -1; + if (port_ptr) *port_ptr = -1; + if (proto_size > 0) proto[0] = 0; + if (authorization_size > 0) authorization[0] = 0; + if (hostname_size > 0) hostname[0] = 0; + if (path_size > 0) path[0] = 0; - p = url; - q = proto; - while (*p != ':' && *p != '\0') { - if ((q - proto) < proto_size - 1) - *q++ = *p; - p++; - } - if (proto_size > 0) - *q = '\0'; - if (authorization_size > 0) - authorization[0] = '\0'; - if (*p == '\0') { - if (proto_size > 0) - proto[0] = '\0'; - if (hostname_size > 0) - hostname[0] = '\0'; - p = url; + /* parse protocol */ + if ((p = strchr(url, ':'))) { + av_strlcpy(proto, url, FFMIN(proto_size, p + 1 - url)); + p++; /* skip ':' */ + if (*p == '/') p++; + if (*p == '/') p++; } else { - char *at,*slash; // PETR: position of '@' character and '/' character + /* no protocol means plain filename */ + av_strlcpy(path, url, path_size); + return; + } - p++; - if (*p == '/') - p++; - if (*p == '/') - p++; - at = strchr(p,'@'); // PETR: get the position of '@' - slash = strchr(p,'/'); // PETR: get position of '/' - end of hostname - if (at && slash && at > slash) at = NULL; // PETR: not interested in '@' behind '/' - - q = at ? authorization : hostname; // PETR: if '@' exists starting with auth. - - while ((at || *p != ':') && *p != '/' && *p != '?' && *p != '\0') { // PETR: - if (*p == '@') { // PETR: passed '@' - if (authorization_size > 0) - *q = '\0'; - q = hostname; - at = NULL; - } else if (!at) { // PETR: hostname - if ((q - hostname) < hostname_size - 1) - *q++ = *p; - } else { - if ((q - authorization) < authorization_size - 1) - *q++ = *p; - } - p++; - } - if (hostname_size > 0) - *q = '\0'; - if (*p == ':') { - p++; - port = strtoul(p, (char **)&p, 10); - } + /* separate path from hostname */ + if ((ls = strchr(p, '/'))) { + if ((q = strchr(ls, '?'))) + av_strlcpy(path, ls, FFMIN(path_size, q - ls + 1)); + else + av_strlcpy(path, ls, path_size); + } else if (!(ls = strchr(p, '?'))) + ls = &p[strlen(p)]; // XXX + + /* the rest is hostname, use that to parse auth/port */ + if (ls != p) { + /* authorization (user[:pass]@hostname) */ + if ((at = strchr(p, '@')) && at < ls) { + av_strlcpy(authorization, p, + FFMIN(authorization_size, at + 1 - p)); + p = at + 1; /* skip '@' */ + } + + if (*p == '[' && (brk = strchr(p, ']')) && brk < ls) { + /* [host]:port */ + av_strlcpy(hostname, p + 1, + FFMIN(hostname_size, brk - p)); + if (brk[1] == ':' && port_ptr) + *port_ptr = atoi(brk + 2); + } else if ((col = strchr(p, ':')) && col < ls) { + av_strlcpy(hostname, p, + FFMIN(col + 1 - p, hostname_size)); + if (port_ptr) *port_ptr = atoi(col + 1); + } else + av_strlcpy(hostname, p, + FFMIN(ls + 1 - p, hostname_size)); } - if (port_ptr) - *port_ptr = port; - av_strlcpy(path, p, path_size); } void av_set_pts_info(AVStream *s, int pts_wrap_bits,