运行avformat_open_input函数是ffmpeg初始化之后做的第一件事。从大面意思上来讲,函数作用是打开输入流,但是流具体是如何打开的,具体做了哪些事情,我们慢慢来分析研究下:
<pre name="code" class="cpp">int avformat_open_input(AVFormatContext **ps, const char *filename,
AVInputFormat *fmt, AVDictionary **options)
{
AVFormatContext *s = *ps;
int ret = 0;
AVDictionary *tmp = NULL;
ID3v2ExtraMeta *id3v2_extra_meta = NULL;//保存MP3的一些信息,比如作者,风格,年代什么的
//如果s没有初始化,则创建一个
if (!s && !(s = 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);
}
//如果指定了fmt,直接进行赋值
if (fmt)
s->iformat = fmt;
if (options)
av_dict_copy(&tmp, *options, 0);
if ((ret = av_opt_set_dict(s, &tmp)) < 0)//没有设置option参数,该步可以跳过
goto fail;
//探测输入流的格式是此步实现的。
if ((ret = init_input(s, filename, &tmp)) < 0)
goto fail;
.....
}
/* Open input file and probe the format if necessary. */
static int init_input(AVFormatContext *s, const char *filename,
AVDictionary **options)
{
int ret;
AVProbeData pd = { filename, NULL, 0 };//使用AVProbeData进行探测,里面的参数是文件名
int score = AVPROBE_SCORE_RETRY;
//调用者已经指定了Pb(一般不会这么做),除非自己去实现让ffmpeg去内存中获取数据
if (s->pb) { //AVFormatContext中的AVIOContext *pb是否已经初始化,里面保存着对底层数据的读写操作。
s->flags |= AVFMT_FLAG_CUSTOM_IO; //如果我们自己指定了pb,会执行到这,此处代表自己的IO
if (!s->iformat) //如果iformat没有指定,需要进行iformat探测和文件格式探测
//指定了pb但是没指定iformat,以pb读取媒体数据进行探测
return av_probe_input_buffer2(s->pb, &s->iformat, filename, s, 0, s->format_probesize);
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;
}
/*常规来讲会执行到这儿,首先如果指定了iformat,并且不需要文件,直接就返回
*如果没有指定iformat,就根据文件后缀猜测iformat
*/
if ((s->iformat && s->iformat->f