7. 接着看 avformat_open_input 后面的函数
int avformat_open_input(AVFormatContext **ps, const char *filename,
AVInputFormat *fmt, AVDictionary **options)
{
...
//这个函数前面已分析
if ((ret = init_input(s, filename, &tmp)) < 0)
goto fail;
s->probe_score = ret;
...
//skip_initial_bytes为0,seek到文件头
/*avio_skip其实就是seek,avio_read/write/seek都是优先对内部
buffer的操作(非ring buffer),
如果操作的范围超过buffer,就会直接call ioctx接口去操作*/
avio_skip(s->pb, s->skip_initial_bytes);
...
/* Allocate private data. */
/*和之前URLContext做着类似的勾当,以MKV为例,s->private保存着MatroskaDemuxContext,
MatroskaDemuxContext的class,为NULL, avi是有class的
AVInputFormat ff_matroska_demuxer = {
.name = "matroska,webm",
.long_name = NULL_IF_CONFIG_SMALL("Matroska / WebM"),
.extensions = "mkv,mk3d,mka,mks",
.priv_data_size = sizeof(MatroskaDemuxContext),
.read_probe = matroska_probe,
.read_header = matroska_read_header,
.read_packet = matroska_read_packet,
.read_close = matroska_read_close,
.read_seek = matroska_read_seek,
.mime_type = "audio/webm,audio/x-matroska,video/webm,video/x-matroska"
};
*/
if (s->iformat->priv_data_size > 0) {
if (!(s->priv_data = av_mallocz(s->iformat->priv_data_size))) {
ret = AVERROR(ENOMEM);
goto fail;
}
//如果是mkv,priv_class为NULL, avi 则不是NULL
/* avi 可以设置use_odml
AVInputFormat ff_avi_demuxer = {
.name = "avi",
.long_name = NULL_IF_CONFIG_SMALL("AVI (Audio Video Interleaved)"),
.priv_data_size = sizeof(AVIContext),
.extensions = "avi",
.read_probe = avi_probe,
.read_header = avi_read_header,
.read_packet = avi_read_packet,
.read_close = avi_read_close,
.read_seek = avi_read_seek,
.priv_class = &demuxer_class,
};
*/
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;
}
}
//read_header 重要函数
/*
调用到format内部的read_header,对于mkv:
.read_header = matroska_read_header,
读取mkv的一些头信息,包括track info和cue index(seek找key帧)
*/
if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)
if ((ret = s->iformat->read_header(s)) < 0)
goto fail;
...
}
8. read_header
以mkv为例
static int matroska_read_header(AVFormatContext *s)
{
...
//包罗万象的s,s和matroska构成指针环
matroska->ctx = s;
...
//read/seek操作,都是call 到avio里面去read/seek
...
/*
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
{
...
//AVStream以数组形式使用(s->streams[i]),每次parse一次track,就需要realloc一次
streams = av_realloc_array(s->streams, s->nb_streams + 1, sizeof(*streams));
if (!streams)
return NULL;
s->streams = streams;
...
************************************
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec)
{
AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));
if (!avctx)
return NULL;
if(avcodec_get_context_defaults3(avctx, codec) < 0){
av_free(avctx);
return NULL;
}
return avctx;
}
************************************
// c为NULL,alloc AVCodecContext,并将其挂在AVStream上
st->codec = avcodec_alloc_context3(c);
if (!st->codec) {
av_free(st->info);
av_free(st);
return NULL;
}
if (s->iformat) {
// no default bitrate if decoding
st->codec->bit_rate = 0;
// default pts setting is MPEG-like
//一个pts为1/90000 s
avpriv_set_pts_info(st, 33, 1, 90000);
}
...
}
static int matroska_parse_tracks(AVFormatContext *s)
{
...
st = track->stream = avformat_new_stream(s, NULL);
...
}
*/
//在parse track info去alloc AVStream. 并挂在AVFormatContext中
res = matroska_parse_tracks(s);
...
}
至此, avformat_open_input 就结束了