ffmpeg源码学习笔记二

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  就结束了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值