X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Futils.c;h=1a34049c2109a357c83763b72ed518a36a1c0013;hb=ca75a92325f77aaadb234e947c6242c3344233e7;hp=8700e9e4e527359395152388603b45be72b9e1c8;hpb=15afa396e4461e3ecabfecb13afb7ab95cf5aa9d;p=ffmpeg diff --git a/libavformat/utils.c b/libavformat/utils.c index 8700e9e4e52..1a34049c210 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -41,6 +41,18 @@ AVInputFormat *first_iformat = NULL; /** head of registered output format linked list. */ AVOutputFormat *first_oformat = NULL; +AVInputFormat *av_iformat_next(AVInputFormat *f) +{ + if(f) return f->next; + else return first_iformat; +} + +AVOutputFormat *av_oformat_next(AVOutputFormat *f) +{ + if(f) return f->next; + else return first_oformat; +} + void av_register_input_format(AVInputFormat *format) { AVInputFormat **p; @@ -311,6 +323,7 @@ static const AVOption options[]={ {"track", " set the track number", OFFSET(track), FF_OPT_TYPE_INT, DEFAULT, 0, INT_MAX, E}, {"year", "set the year", OFFSET(year), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, E}, {"analyzeduration", "how many microseconds are analyzed to estimate duration", OFFSET(max_analyze_duration), FF_OPT_TYPE_INT, 3*AV_TIME_BASE, 0, INT_MAX, D}, +{"cryptokey", "decryption key", OFFSET(key), FF_OPT_TYPE_BINARY, 0, 0, 0, D}, {NULL}, }; @@ -361,8 +374,7 @@ int av_open_input_stream(AVFormatContext **ic_ptr, goto fail; } ic->iformat = fmt; - if (pb) - ic->pb = *pb; + ic->pb = pb; ic->duration = AV_NOPTS_VALUE; ic->start_time = AV_NOPTS_VALUE; av_strlcpy(ic->filename, filename, sizeof(ic->filename)); @@ -383,7 +395,7 @@ int av_open_input_stream(AVFormatContext **ic_ptr, goto fail; if (pb && !ic->data_offset) - ic->data_offset = url_ftell(&ic->pb); + ic->data_offset = url_ftell(ic->pb); *ic_ptr = ic; return 0; @@ -405,11 +417,10 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, int buf_size, AVFormatParameters *ap) { - int err, must_open_file, file_opened, probe_size; + int err, probe_size; AVProbeData probe_data, *pd = &probe_data; - ByteIOContext pb1, *pb = &pb1; + ByteIOContext *pb = NULL; - file_opened = 0; pd->filename = ""; if (filename) pd->filename = filename; @@ -423,18 +434,11 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, /* do not open file if the format does not need it. XXX: specific hack needed to handle RTSP/TCP */ - must_open_file = 1; - if (fmt && (fmt->flags & AVFMT_NOFILE)) { - must_open_file = 0; - pb= NULL; //FIXME this or memset(pb, 0, sizeof(ByteIOContext)); otherwise it is uninitialized - } - - if (!fmt || must_open_file) { + if (!fmt || !(fmt->flags & AVFMT_NOFILE)) { /* if no file needed do not try to open one */ - if ((err=url_fopen(pb, filename, URL_RDONLY)) < 0) { + if ((err=url_fopen(&pb, filename, URL_RDONLY)) < 0) { goto fail; } - file_opened = 1; if (buf_size > 0) { url_setbufsize(pb, buf_size); } @@ -447,8 +451,8 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE); if (url_fseek(pb, 0, SEEK_SET) < 0) { url_fclose(pb); - if (url_fopen(pb, filename, URL_RDONLY) < 0) { - file_opened = 0; + if (url_fopen(&pb, filename, URL_RDONLY) < 0) { + pb = NULL; err = AVERROR(EIO); goto fail; } @@ -465,16 +469,6 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, goto fail; } - /* XXX: suppress this hack for redirectors */ -#ifdef CONFIG_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; - } -#endif - /* check filename in case of an image number is expected */ if (fmt->flags & AVFMT_NEEDNUMBER) { if (!av_filename_number_test(filename)) { @@ -488,7 +482,7 @@ int av_open_input_file(AVFormatContext **ic_ptr, const char *filename, return 0; fail: av_freep(&pd->buf); - if (file_opened) + if (pb) url_fclose(pb); *ic_ptr = NULL; return err; @@ -647,9 +641,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 +717,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) @@ -1131,7 +1124,7 @@ int av_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts return -1; /* do the seek */ - url_fseek(&s->pb, pos, SEEK_SET); + url_fseek(s->pb, pos, SEEK_SET); av_update_cur_dts(s, st, ts); @@ -1156,7 +1149,7 @@ int64_t av_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, i if(ts_max == AV_NOPTS_VALUE){ int step= 1024; - filesize = url_fsize(&s->pb); + filesize = url_fsize(s->pb); pos_max = filesize - 1; do{ pos_max -= step; @@ -1262,12 +1255,12 @@ static int av_seek_frame_byte(AVFormatContext *s, int stream_index, int64_t pos, #endif pos_min = s->data_offset; - pos_max = url_fsize(&s->pb) - 1; + pos_max = url_fsize(s->pb) - 1; if (pos < pos_min) pos= pos_min; else if(pos > pos_max) pos= pos_max; - url_fseek(&s->pb, pos, SEEK_SET); + url_fseek(s->pb, pos, SEEK_SET); #if 0 av_update_cur_dts(s, st, ts); @@ -1292,10 +1285,10 @@ static int av_seek_frame_generic(AVFormatContext *s, if(st->index_entries && st->nb_index_entries){ ie= &st->index_entries[st->nb_index_entries-1]; - url_fseek(&s->pb, ie->pos, SEEK_SET); + url_fseek(s->pb, ie->pos, SEEK_SET); av_update_cur_dts(s, st, ie->timestamp); }else - url_fseek(&s->pb, 0, SEEK_SET); + url_fseek(s->pb, 0, SEEK_SET); for(i=0;; i++) { int ret = av_read_frame(s, &pkt); @@ -1318,7 +1311,7 @@ static int av_seek_frame_generic(AVFormatContext *s, return 0; } ie = &st->index_entries[index]; - url_fseek(&s->pb, ie->pos, SEEK_SET); + url_fseek(s->pb, ie->pos, SEEK_SET); av_update_cur_dts(s, st, ie->timestamp); @@ -1510,7 +1503,7 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse /* we read the first packets to get the first PTS (not fully accurate, but it is enough now) */ - url_fseek(&ic->pb, 0, SEEK_SET); + url_fseek(ic->pb, 0, SEEK_SET); read_size = 0; for(;;) { if (read_size >= DURATION_MAX_READ_SIZE) @@ -1543,7 +1536,7 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse if (offset < 0) offset = 0; - url_fseek(&ic->pb, offset, SEEK_SET); + url_fseek(ic->pb, offset, SEEK_SET); read_size = 0; for(;;) { if (read_size >= DURATION_MAX_READ_SIZE) @@ -1569,7 +1562,7 @@ static void av_estimate_timings_from_pts(AVFormatContext *ic, offset_t old_offse fill_all_stream_timings(ic); - url_fseek(&ic->pb, old_offset, SEEK_SET); + url_fseek(ic->pb, old_offset, SEEK_SET); for(i=0; inb_streams; i++){ st= ic->streams[i]; st->cur_dts= st->first_dts; @@ -1585,7 +1578,7 @@ static void av_estimate_timings(AVFormatContext *ic, offset_t old_offset) if (ic->iformat->flags & AVFMT_NOFILE) { file_size = 0; } else { - file_size = url_fsize(&ic->pb); + file_size = url_fsize(ic->pb); if (file_size < 0) file_size = 0; } @@ -1593,7 +1586,7 @@ static void av_estimate_timings(AVFormatContext *ic, offset_t old_offset) if ((!strcmp(ic->iformat->name, "mpeg") || !strcmp(ic->iformat->name, "mpegts")) && - file_size && !ic->pb.is_streamed) { + file_size && !ic->pb->is_streamed) { /* get accurate estimate from the PTSes */ av_estimate_timings_from_pts(ic, old_offset); } else if (av_has_duration(ic)) { @@ -1638,7 +1631,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) @@ -1758,7 +1751,7 @@ int av_find_stream_info(AVFormatContext *ic) int64_t last_dts[MAX_STREAMS]; int duration_count[MAX_STREAMS]={0}; double (*duration_error)[MAX_STD_TIMEBASES]; - offset_t old_offset = url_ftell(&ic->pb); + 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]; @@ -1803,9 +1796,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; } @@ -1993,7 +1983,7 @@ int av_find_stream_info(AVFormatContext *ic) } st->cur_dts= st->first_dts; } - url_fseek(&ic->pb, ic->data_offset, SEEK_SET); + url_fseek(ic->pb, ic->data_offset, SEEK_SET); } #if 0 @@ -2033,21 +2023,25 @@ int av_find_stream_info(AVFormatContext *ic) int av_read_play(AVFormatContext *s) { - if (!s->iformat->read_play) - return AVERROR(ENOSYS); - return s->iformat->read_play(s); + if (s->iformat->read_play) + return s->iformat->read_play(s); + if (s->pb && s->pb->read_play) + return av_url_read_fplay(s->pb); + return AVERROR(ENOSYS); } int av_read_pause(AVFormatContext *s) { - if (!s->iformat->read_pause) - return AVERROR(ENOSYS); - return s->iformat->read_pause(s); + if (s->iformat->read_pause) + return s->iformat->read_pause(s); + if (s->pb && s->pb->read_pause) + return av_url_read_fpause(s->pb); + return AVERROR(ENOSYS); } void av_close_input_file(AVFormatContext *s) { - int i, must_open_file; + int i; AVStream *st; /* free previous packet */ @@ -2070,16 +2064,12 @@ void av_close_input_file(AVFormatContext *s) 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) { - must_open_file = 0; - } - if (must_open_file) { - url_fclose(&s->pb); - } + if (!(s->iformat->flags & AVFMT_NOFILE)) + url_fclose(s->pb); av_freep(&s->priv_data); av_free(s); } @@ -2346,7 +2336,7 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt) ret= s->oformat->write_packet(s, pkt); if(!ret) - ret= url_ferror(&s->pb); + ret= url_ferror(s->pb); return ret; } @@ -2447,8 +2437,8 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt){ if(ret<0) return ret; - if(url_ferror(&s->pb)) - return url_ferror(&s->pb); + if(url_ferror(s->pb)) + return url_ferror(s->pb); } } @@ -2471,7 +2461,7 @@ int av_write_trailer(AVFormatContext *s) if(ret<0) goto fail; - if(url_ferror(&s->pb)) + if(url_ferror(s->pb)) goto fail; } @@ -2479,22 +2469,70 @@ int av_write_trailer(AVFormatContext *s) ret = s->oformat->write_trailer(s); fail: if(ret == 0) - ret=url_ferror(&s->pb); + ret=url_ferror(s->pb); for(i=0;inb_streams;i++) av_freep(&s->streams[i]->priv_data); av_freep(&s->priv_data); 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 tb(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 tb(m)", 1/av_q2d(st->time_base));*/ + else + av_log(NULL, AV_LOG_INFO, ", %5.2f tb(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", @@ -2532,35 +2570,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) @@ -2878,68 +2898,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,