ffmpeg学习记录avformat_open_input个人整理

本文只是整理了该函数的大概轮廓。

avformat_open_input 初始化AVFormatContext结构体对象,主要有三个功能:

AVIOContext 结构体对象初始化(pb);  AVInputFormat 结构体对象初始化(iformat);  

AVStream 结构体对象初始化(streams)

摘录主要功能点

avformat_open_input (AVFormatContext **ps, const char *filename,
                        AVInputFormat *fmt, AVDictionary **options){

 AVFormatContext *s = *ps;

s = avformat_alloc_context();  //实现avformatcontext对象的初始化,变量的默认值赋值

init_input(s, filename, &tmp); //实现 s中pb(AVIOContext)和 iformat(AVInputFormat)的构建

s->iformat->read_header(s); //实现s中sreams(AVStream)的构建

}

1. AVIOContext 结构体对象初始化

avformat_alloc_context(){ //对代码进行了整理,主要是整理逻辑    (libavformat/option.c)

   AVFormatContext *ic;
   ic = av_malloc(sizeof(AVFormatContext));

    ic->av_class = &av_format_context_class; //av_format_context_class为静态变量(AVClass),

                                                                       //option指向 option_tables.h中的静态变量avformat_options

    ic->io_open  = io_open_default;
    ic->io_close = io_close_default;

    av_opt_set_defaults(ic);  

}

av_opt_set_defaults()调用avformat_options中的默认值给ic中的变量赋值

io_open_default为打开文件或者url的函数,在该函数中会构造ic的pb;该函数会被init_input调用,流程如下:

init_input(AVFormatContext *s, const char *filename, AVDictionary **options){  //摘录主要流程(libavformat/utils.c)

    s->io_open(s, &s->pb, filename, AVIO_FLAG_READ | s->avio_flags, options);//构造s的pb(AVIOContext)

    av_probe_input_buffer2(s->pb, &s->iformat, filename, s, 0, s->format_probesize);//构造s的iformat(AVInputFormat)

}

s->io_open就是io_open_default函数  //libavformat/options.c

io_open_default(AVFormatContext *s, AVIOContext **pb,  const char *url, int flags, AVDictionary **options) {

     ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist, s->protocol_blacklist);

}

 ffio_open_whitelist(AVIOContext **s, const char *filename, int flags, ...){ //libavformat/aviobuf.c)

     URLContext *h;

     ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist, blacklist, NULL);//构造h对象 (libavformat/avio.c)

     ffio_fdopen(s, h);//根据h构造s对象,至此完成AVIOContext的构造    libavformat/aviobuf.c)

}

2. AVInputFormat 结构体对象初始化(iformat);

 init_input(AVFormatContext *s, const char *filename, AVDictionary **options){  //摘录主要流程(libavformat/utils.c)

    s->io_open(s, &s->pb, filename, AVIO_FLAG_READ | s->avio_flags, options);//构造s的pb(AVIOContext)

    av_probe_input_buffer2(s->pb, &s->iformat, filename, s, 0, s->format_probesize);//构造s的iformat(AVInputFormat)

}

av_probe_input_buffer2(AVIOContext *pb, ff_const59 AVInputFormat **fmt, const char *filename,  ...){ //(libavformat/format.c)

      AVProbeData pd = { filename ? filename : "" };

      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))) {

                //修改pd缓存大小

               *fmt = av_probe_input_format2(&pd, 1, &score);

      }

}

AVInputFormat *av_probe_input_format3(ff_const59 AVProbeData *pd, int is_opened,  int *score_ret){ //(libavformat/format.c)

//便利所有的AVInputFormat,根据读取的文件头,比较extensions, mini_type获取一个最高分,就是选用的AVInputFormat

      while ((fmt1 = av_demuxer_iterate(&i))) {

            if (fmt1->read_probe) {
                score = fmt1->read_probe(&lpd);
                if (fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions)) { //这个一项基本不用
                 //.....
                }
            } else if (fmt1->extensions) {  //这个一项基本不用
                if (av_match_ext(lpd.filename, fmt1->extensions))
                   score = AVPROBE_SCORE_EXTENSION;
            }
           if (av_match_name(lpd.mime_type, fmt1->mime_type)) {
                  score = AVPROBE_SCORE_MIME;
            }
        if (score > score_max) {
            score_max = score;
            fmt       = (AVInputFormat*)fmt1;  //根据分数大小确定  至此确定AVInputFormat
        } else if (score == score_max)
            fmt = NULL;

  } // end while

}

3. AVStream 结构体对象初始化(streams)

s->iformat->read_header(s); // 比如ts流文件,调用(libavformat/mpegts.c)中的mpegts_read_header

mpegts_read_header(){

  //该函数会获取streams信息

if (s->iformat == &ff_mpegts_demuxer) {
        seek_back(s, pb, pos);

        mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1);

        mpegts_open_section_filter(ts, PAT_PID, pat_cb, ts, 1);

        handle_packets(ts, probesize / ts->raw_packet_size);  //该函数会对streams赋值,完成streams的检索
        /* if could not find service, enable auto_guess */

        ts->auto_guess = 1;

        av_log(ts->stream, AV_LOG_TRACE, "tuning done\n");

        s->ctx_flags |= AVFMTCTX_NOHEADER;
    }

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值