该接口是ffmpeg媒体打开过程的开始,avformat_open_input()内部处理的逻辑为:
- 输入输出结构体AVIOContext的初始化
- 输入数据的识别:例如RTP?或者是file文件的识别,其通过一套机制来进行,判断后缀或者是文件头数据信息等
- 使用获得评分最高的文件协议对应的URLProtocol,通过函数指针的方式,与ffmpeg进行连接
- 然后调用该URLProtocol的函数进行open,read等操作
int avformat_open_input(AVFormatContext **ps, const char *filename,AVInputFormat *fmt, AVDictionary **options)
{AVFormatContext *s &#61; *ps;int i, ret &#61; 0;AVDictionary *tmp &#61; NULL;ID3v2ExtraMeta *id3v2_extra_meta &#61; NULL;if (!s && !(s &#61; avformat_alloc_context()))return AVERROR(ENOMEM);if (!s->av_class) {av_log(NULL, AV_LOG_ERROR, "Input context has not been properly allocated by avformat_alloc_context() and is not NULL either\n");return AVERROR(EINVAL);}if (fmt)s->iformat &#61; fmt;if (options)av_dict_copy(&tmp, *options, 0);if (s->pb) // must be before any goto fails->flags |&#61; AVFMT_FLAG_CUSTOM_IO;if ((ret &#61; av_opt_set_dict(s, &tmp)) <0)goto fail;if ((ret &#61; init_input(s, filename, &tmp)) <0)goto fail;s->probe_score &#61; ret;if (!s->protocol_whitelist && s->pb && s->pb->protocol_whitelist) {s->protocol_whitelist &#61; av_strdup(s->pb->protocol_whitelist);if (!s->protocol_whitelist) {ret &#61; AVERROR(ENOMEM);goto fail;}}if (!s->protocol_blacklist && s->pb && s->pb->protocol_blacklist) {s->protocol_blacklist &#61; av_strdup(s->pb->protocol_blacklist);if (!s->protocol_blacklist) {ret &#61; AVERROR(ENOMEM);goto fail;}}if (s->format_whitelist && av_match_list(s->iformat->name, s->format_whitelist, &#39;,&#39;) <&#61; 0) {av_log(s, AV_LOG_ERROR, "Format not on whitelist \&#39;%s\&#39;\n", s->format_whitelist);ret &#61; AVERROR(EINVAL);goto fail;}avio_skip(s->pb, s->skip_initial_bytes);/* Check filename in case an image number is expected. */if (s->iformat->flags & AVFMT_NEEDNUMBER) {if (!av_filename_number_test(filename)) {ret &#61; AVERROR(EINVAL);goto fail;}}s->duration &#61; s->start_time &#61; AV_NOPTS_VALUE;av_strlcpy(s->filename, filename ? filename : "", sizeof(s->filename));/* Allocate private data. */if (s->iformat->priv_data_size > 0) {if (!(s->priv_data &#61; av_mallocz(s->iformat->priv_data_size))) {ret &#61; AVERROR(ENOMEM);goto fail;}if (s->iformat->priv_class) {*(const AVClass **) s->priv_data &#61; s->iformat->priv_class;av_opt_set_defaults(s->priv_data);if ((ret &#61; av_opt_set_dict(s->priv_data, &tmp)) <0)goto fail;}}/* e.g. AVFMT_NOFILE formats will not have a AVIOContext */if (s->pb)ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, 0);if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)if ((ret &#61; s->iformat->read_header(s)) <0)goto fail;if (id3v2_extra_meta) {if (!strcmp(s->iformat->name, "mp3") || !strcmp(s->iformat->name, "aac") ||!strcmp(s->iformat->name, "tta")) {if ((ret &#61; ff_id3v2_parse_apic(s, &id3v2_extra_meta)) <0)goto fail;} elseav_log(s, AV_LOG_DEBUG, "demuxer does not support additional id3 data, skipping\n");}ff_id3v2_free_extra_meta(&id3v2_extra_meta);if ((ret &#61; avformat_queue_attached_pictures(s)) <0)goto fail;if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->pb && !s->internal->data_offset)s->internal->data_offset &#61; avio_tell(s->pb);s->internal->raw_packet_buffer_remaining_size &#61; RAW_PACKET_BUFFER_SIZE;update_stream_avctx(s);for (i &#61; 0; i nb_streams; i&#43;&#43;)s->streams[i]->internal->orig_codec_id &#61; s->streams[i]->codecpar->codec_id;if (options) {av_dict_free(options);*options &#61; tmp;}*ps &#61; s;return 0;fail:ff_id3v2_free_extra_meta(&id3v2_extra_meta);av_dict_free(&tmp);if (s->pb && !(s->flags & AVFMT_FLAG_CUSTOM_IO))avio_closep(&s->pb);avformat_free_context(s);*ps &#61; NULL;return ret;
}