ffmpeg avformat_open_input详解

        
avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)
        首先声明几个变量,
        AVFormatContext* s=*ps  ;
        AVDictionary*        tmp=NULL;
        假设 调用参数f分别为   ps   filename  NULL NULL
  1.   首先调用 avformat_alloc_context(void)
         在函数里 声明一个AVFormatContext* ic 
        给ic开辟大小为sizeof(AVFormatContext)的内存空间 用av_malloc(size_t)
        然后给ic赋默认初始值:先将ic->av_class =&av_format_context_class  av_format_context_class为静态全局变量,存放在、libavformat里的Options.c中 值为:
 static const AVClass     av_format_context_class = { 
    .class_name = "AVFormatContext",
    .item_name = format_to_name,
    .option = options,                                                       options为静态全局变量 也存放在libavformat里的options_table.h中 是AVOption结构体数组的首地址 
    .version = LIBAVUTIL_VERSION_INT,
    .child_next = format_child_next,
    .child_class_next = format_child_class_next,
    .category = AV_CLASS_CATEGORY_MUXER,
    .get_category = get_category,
};
                    最后调用av_opt_set_defaults2(s, 0, 0);使得ic->av_class里的 指针option指向options数组的最后一个有效值,即倒数第二个值,options数组都是以NULL结尾的。
        就是说avformat_alloc_contexth 主要是编辑AVClass类型 av_class,而其他指针都还没赋值。
    2.    然后判断 fmt和options,
            if(fmt)
            s->iformat = fmt;
            if(options)
            av_dict_copy(&tmp,options);
            若不是自定义,但是一般都会是NULL
    3.    然后调用av_opt_set_dict(s,&tmp);
          作用是将AVDictionary(字典)tmp中的所有选项设置进传入的AVFormatContext(文件格式上下文),但是此处tmp=NULL,函数                          
                  会直接返回0
       4.        然后调用  if ((ret = init_input(s, filename, &tmp)) < 0)
                                        goto fail;
                  作用是建立并根据文件名 初始化AVFormatContext中的AVIOContext 和 AVInputFormat的变量指针。

        5.        然后若输入文件名是需要数字在里面的,测试文件名....待研究
                     if (s->iformat->flags & AVFMT_NEEDNUMBER) {
                    if (!av_filename_number_test(filename)) {
                    ret = AVERROR(EINVAL);
                    goto fail;
                    }
                   }
        6.        然后给AVFormatContext里的 filename赋值为输入文件名,duration 和 start_time赋值 AV_NOPTS_VALUE ,
                    s->duration = s->start_time = AV_NOPTS_VALUE; 
                    av_strlcpy(s->filename, filename ? filename : "", sizeof(s->filename));
        7.          s->iformat->priv_data_size已经在 init_input中的av_open2函数里被赋值,由大小等于URLProtocol里的priv_data_size,而它等                                                  于对应协议的协议头文件结构体的大小。由注册时得到。s->iformat->priv_class同理。  不过av_opt_set_defaults最后返回write_number()里    的 将priv_data指向了一个整数,意思不是很清楚。
     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)此处tmp还是为NULL,所以直接返回0;
                goto fail;
        }
    }
            8.           /* e.g. AVFMT_NOFILE formats will not have a AVIOContext */
                  if (s->pb) 
                       ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); 
            9.    每个iformat的read_header都是在注册时赋值好的,对应于相应的输入结构,注册时      对应相应的    demuxer(分离音视频的作用, 分离器是把流中的视频和音频数据分离开来,分别进行播放。不同协议的流有不同的分离器 )。               s->nb_stream就算不给它赋值,在开辟s的空间时,就已经被系统默认为0了,在read_header中会调用                                                      avformat_new_stream(s,NULL);
                        if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)
                        if ((ret = s->iformat->read_header(s)) < 0)
                       goto fail;
            10.        这个还不大了解 
  if (id3v2_extra_meta) {
        if (!strcmp(s->iformat->name, "mp3")) {
            if((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0)
                goto fail;
        } else
            av_log(s, AV_LOG_DEBUG, "demuxer does not support additional id3 data, skipping\n"); ff_id3v2_free_extra_meta(&id3v2_extra_meta);
            11.
                     avformat_queue_attached_pictures(s);
            12.    给AVFormatContext的data_offse和raw_packet_buffer_remaining_sizet赋值.  
                     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
            13.    最后options和tmp还是=NULL 将s赋值给*ps
 if (options) {
        av_dict_free(options);
        *options = tmp;
    }
    *ps = s;
    return 0;


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值