2011-12-05 17:47
2500人阅读
收藏
举报
从打开文件开始.入口函数是avformat_open_input(),下面是对此函数的分析 -
-
-
-
-
-
-
-
- int avformat_open_input(AVFormatContext **ps,
- const char *filename,
- AVInputFormat *fmt,
- AVDictionary **options)
- {
- AVFormatContext *s = *ps;
- int ret = 0;
- AVFormatParameters ap = { { 0 } };
- AVDictionary *tmp = NULL;
-
-
- if (!s && !(s = avformat_alloc_context()))
- return AVERROR(ENOMEM);
-
- if (fmt)
- s->iformat = fmt;
-
-
- if (options)
- av_dict_copy(&tmp, *options, 0);
-
- if ((ret = av_opt_set_dict(s, &tmp)) < 0)
- goto fail;
-
-
-
- if ((ret = init_input(s, filename)) < 0)
- goto fail;
-
-
-
-
-
-
-
- if (s->iformat->flags & AVFMT_NEEDNUMBER) {
- if (!av_filename_number_test(filename)) {
- ret = AVERROR(EINVAL);
- goto fail;
- }
- }
-
- s->duration = s->start_time = AV_NOPTS_VALUE;
-
- av_strlcpy(s->filename, filename, sizeof(s->filename));
-
-
-
-
- if (s->iformat->priv_data_size > 0) {
- if (!(s->priv_data = av_mallocz(s->iformat->priv_data_size))) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- if (s->iformat->priv_class) {
- *(const AVClass**) s->priv_data = s->iformat->priv_class;
- av_opt_set_defaults(s->priv_data);
- if ((ret = av_opt_set_dict(s->priv_data, &tmp)) < 0)
- goto fail;
- }
- }
-
-
-
- if (s->pb)
- ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC);
-
-
-
- if (!(s->flags & AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)
- if ((ret = s->iformat->read_header(s, &ap)) < 0)
- goto fail;
-
-
- if (!(s->flags & AVFMT_FLAG_PRIV_OPT) && s->pb && !s->data_offset)
- s->data_offset = avio_tell(s->pb);
-
- s->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE;
-
- if (options) {
- av_dict_free(options);
- *options = tmp;
- }
- *ps = s;
-
- return 0;
-
-
- fail: av_dict_free(&tmp);
- if (s->pb && !(s->flags & AVFMT_FLAG_CUSTOM_IO))
- avio_close(s->pb);
- avformat_free_context(s);
- *ps = NULL;
- return ret;
- }
下面分析init_input():
-
- static int init_input(AVFormatContext *s, const char *filename)
- {
- int ret;
- AVProbeData pd = { filename, NULL, 0 };
-
-
- 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);
- else if (s->iformat->flags & AVFMT_NOFILE)
-
-
- av_log(s, AV_LOG_WARNING, "Custom AVIOContext makes no sense and "
- "will be ignored with AVFMT_NOFILE format.\n");
- return 0;
- }
-
-
- if ((s->iformat && s->iformat->flags & AVFMT_NOFILE)
- || (!s->iformat && (s->iformat = av_probe_input_format(&pd, 0))))
-
-
- return 0;
-
-
- if ((ret = avio_open(&s->pb, filename, AVIO_FLAG_READ)) < 0)
- return ret;
- if (s->iformat)
- return 0;
-
- return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, 0);
- }
再看一下文件打开过程:
-
- int avio_open(AVIOContext **s, const char *filename, int flags)
- {
-
-
-
-
-
- URLContext *h;
- int err;
-
-
- err = ffurl_open(&h, filename, flags);
- if (err < 0)
- return err;
-
-
- err = ffio_fdopen(s, h);
- if (err < 0) {
- ffurl_close(h);
- return err;
- }
- return 0;
- }
下面是探测函数
- int av_probe_input_buffer(AVIOContext *pb,
- AVInputFormat **fmt,
- const char *filename,
- void *logctx,
- unsigned int offset,
- unsigned int max_probe_size)
- {
- AVProbeData pd = { filename ? filename : "", NULL, -offset };
- unsigned char *buf = NULL;
- int ret = 0, probe_size;
-
-
- if (!max_probe_size) {
- max_probe_size = PROBE_BUF_MAX;
- } else if (max_probe_size > PROBE_BUF_MAX) {
- max_probe_size = PROBE_BUF_MAX;
- } else if (max_probe_size < PROBE_BUF_MIN) {
- return AVERROR(EINVAL);
- }
-
- if (offset >= max_probe_size) {
- return AVERROR(EINVAL);
- }
-
-
- for (probe_size = PROBE_BUF_MIN;
- probe_size <= max_probe_size && !*fmt;
- probe_size =
- FFMIN(probe_size<<1, FFMAX(max_probe_size, probe_size+1))) {
- int score = probe_size < max_probe_size ? AVPROBE_SCORE_MAX / 4 : 0;
- int buf_offset = (probe_size == PROBE_BUF_MIN) ? 0 : probe_size >> 1;
- void *buftmp;
-
- if (probe_size < offset) {
- continue;
- }
-
-
-
- buftmp = av_realloc(buf, probe_size + AVPROBE_PADDING_SIZE);
- if (!buftmp) {
- av_free(buf);
- return AVERROR(ENOMEM);
- }
- buf = buftmp;
-
- if ((ret = avio_read(pb, buf + buf_offset, probe_size - buf_offset))
- < 0) {
-
- if (ret != AVERROR_EOF) {
- av_free(buf);
- return ret;
- }
- score = 0;
- ret = 0;
- }
- pd.buf_size += ret;
- pd.buf = &buf[offset];
-
-
- memset(pd.buf + pd.buf_size, 0, AVPROBE_PADDING_SIZE);
-
-
-
- *fmt = av_probe_input_format2(&pd, 1, &score);
- if (*fmt) {
- if (score <= AVPROBE_SCORE_MAX / 4) {
- av_log(
- logctx,
- AV_LOG_WARNING,
- "Format %s detected only with low score of %d, misdetection possible!\n",
- (*fmt)->name, score);
- } else
- av_log(logctx, AV_LOG_DEBUG,
- "Format %s probed with size=%d and score=%d\n",
- (*fmt)->name, probe_size, score);
- }
-
- }
-
- if (!*fmt) {
- av_free(buf);
- return AVERROR_INVALIDDATA;
- }
-
-
-
- if ((ret = ffio_rewind_with_probe_data(pb, buf, pd.buf_size)) < 0)
- av_free(buf);
-
- return ret;
- }
|