[9]【ffmpeg源码分析 1】av_register_all()和avcodec_register_all()

来源:互联网 发布:kk是什么软件 编辑:程序博客网 时间:2024/06/06 05:04

日期:2016.10.18
作者:isshe
github:github.com/isshe
邮箱:i.sshe@outlook.com

前言

接下来打算学习一下编解码,不过好像很难的样子, 希望能看懂。

1. av_register_all()

  • 所在文件:allformats.c
  • 主要代码:(每个宏只列举一个)
void av_register_all(void){    static int initialized;    if (initialized)        return;    //注册编解码器    avcodec_register_all();    /* (de)muxers */    //注册复用器    REGISTER_MUXER   (A64,              a64);    //注册解复用器    REGISTER_DEMUXER (AA,               aa);    //两个同时注册    REGISTER_MUXDEMUX(AC3,              ac3);

1.1 REGISTER_MUXER宏

  • 代码:
#define REGISTER_MUXER(X, x)                                            \    {                                                                   \        extern AVOutputFormat ff_##x##_muxer;                           \        if (CONFIG_##X##_MUXER)                                         \            av_register_output_format(&ff_##x##_muxer);                 \    }
  • “##”号起连接作用,例如:a##b = ab.
  • ff_##x##_muxer, 一个与x对应的AVOutputFormat.
  • 其实这些外部变量,一般定义的时候就赋了初值。(限于篇幅,具体的示例在下面编解码相关的地方)

1.1.1 av_register_output_format()

  • 注册一个与该格式相应的AVFormat结构
  • 相关代码:
//head of registered output format linked list static AVOutputFormat *first_oformat = NULL;static AVOutputFormat **last_oformat = &first_oformat;void av_register_output_format(AVOutputFormat *format){    AVOutputFormat **p = last_oformat;    // Note, format could be added after the first 2 checks but that implies that *p is no longer NULL    //检查链表中有无指定的format,没有就加入。    //在前面两个条件成立后才把format连接到p链表中。    while(p != &format->next && !format->next && avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))        p = &(*p)->next;    if (!format->next)        last_oformat = &format->next;}
  • last_oformat是一个二次指针。
  • avpriv_atomic_ptr_cas把format放到p链表中。
  • 遍历链表,把指定format加到链表后面。

1.2 REGISTER_DEMUXER 宏

  • 和REGISTER_MUXER()类似。

1.3 REGISTER_MUXDEMUX 宏

  • #define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x)

2. avcodec_register_all()

  • 所在文件:allcodecs.c
  • 主要代码:(每种情况列举一个)
void avcodec_register_all(void){    static int initialized;    if (initialized)        return;    initialized = 1;    //硬件加速器    /* hardware accelerators */    REGISTER_HWACCEL(H263_CUVID,        h263_cuvid);    //注意以下函数适用于视频和音频    //注册编码器    REGISTER_ENCODER(A64MULTI,          a64multi);    //注册解码器    REGISTER_DECODER(AASC,              aasc);    //两个同时注册    REGISTER_ENCDEC (ALIAS_PIX,         alias_pix);    //注册分析器???不懂    REGISTER_PARSER(AAC,                aac);

2.1 REGISTER_HWACCEL 宏

  • 注册硬件加速器宏
  • 代码:
#define REGISTER_HWACCEL(X, x)                                          \    {                                                                   \        extern AVHWAccel ff_##x##_hwaccel;                              \        if (CONFIG_##X##_HWACCEL)                                       \            av_register_hwaccel(&ff_##x##_hwaccel);                     \    }
  • extern的那个变量在源码中没找着…

2.1.1 av_register_hwaccel()

  • 注册硬件加速器的函数
  • 代码:和前面的muter类似。
void av_register_hwaccel(AVHWAccel *hwaccel){    AVHWAccel **p = last_hwaccel;    hwaccel->next = NULL;    while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, hwaccel))        p = &(*p)->next;    last_hwaccel = &hwaccel->next;}

2.2 REGISTER_ENCODER宏

  • 注册编码器的宏
  • 代码:
#define REGISTER_ENCODER(X, x)                                          \    {                                                                   \        extern AVCodec ff_##x##_encoder;                                \        if (CONFIG_##X##_ENCODER)                                       \            avcodec_register(&ff_##x##_encoder);                        \    }

2.2.1 ff_##x##_encoder变量

  • 用aac示例:ff_aac_encoder变量
AVCodec ff_aac_encoder = {    .name           = "aac",    .long_name      = NULL_IF_CONFIG_SMALL("AAC (Advanced Audio Coding)"),    .type           = AVMEDIA_TYPE_AUDIO,    .id             = AV_CODEC_ID_AAC,    .priv_data_size = sizeof(AACEncContext),    .init           = aac_encode_init,   //初始化    .encode2        = aac_encode_frame,  //编码函数    .close          = aac_encode_end,    //    .defaults       = aac_encode_defaults,    .supported_samplerates = mpeg4audio_sample_rates,    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,    .capabilities   = AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_DELAY,    .sample_fmts    = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,                                                     AV_SAMPLE_FMT_NONE },    .priv_class     = &aacenc_class,};
  • 可见,这些外部变量都是已经赋值好的,解码的【或其他】也类似。
  • 下面调用的注册函数就是把这么一个结构放到链表中。

2.2.2 avcodec_register

  • 注册编码器的函数
  • 代码:
av_cold void avcodec_register(AVCodec *codec){    AVCodec **p;    avcodec_init();      //!!!    p = last_avcodec;      codec->next = NULL;    while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, codec))        p = &(*p)->next;    last_avcodec = &codec->next;    if (codec->init_static_data)        codec->init_static_data(codec);}

2.3 REGISTER_DECODER 宏

  • 和编码类似

2.4 REGISTER_ENCDEC 宏

  • 同时注册解码和编码器

2.5 REGISTER_PARSER 宏

  • 代码:
#define REGISTER_PARSER(X, x)                                           \    {                                                                   \        extern AVCodecParser ff_##x##_parser;                           \        if (CONFIG_##X##_PARSER)                                        \            av_register_codec_parser(&ff_##x##_parser);                 \    }

av_register_codec_parser()

  • 代码:
void av_register_codec_parser(AVCodecParser *parser){    do {        parser->next = av_first_parser;    } while (parser->next != avpriv_atomic_ptr_cas((void * volatile *)&av_first_parser, parser->next, parser));}

参考资料

  • 雷神博文:av_register_all()
  • 雷神博文:avcodec_register_all()
  • ffmpeg-3.1.3源码

代码下载

  • ffmpeg-3.1.3源码:http://download.csdn.net/detail/i_scream_/9657369
0 0
原创粉丝点击