FFMPEG源码分析一 av_register_all()

我们在使用FFMPEG库时,第一个调用的就是av_register_all(),这个函数到底做了什么,有什么用,这里做个简单分析。

本文基于雷霄骅博客学习而来。详情请移步FFmpeg源代码结构图 - 编码_ffmpeg源码结构_雷霄骅的博客-CSDN博客

FFMPEG源码分析一 av_register_all()_第1张图片

 解析和说明

av_register_all()首先调用了 avcodec_register_all()注册了硬件加速器,编码器/解码器,parser,Bitstream Filter,而后注册所有的解复用器,还有支持的流媒体协议。

av_register_all()调用结构如下:


void av_register_all(void)
{
    static int initialized;
 
    //如果注册了,就直接返回,避免重复注册
    if (initialized)
        return;
    initialized = 1;
    //注册所有的codec
    avcodec_register_all();
    //注册所有的MUXER(复用器和解复用器)
    /* (de)muxers */
    REGISTER_MUXER    (A64, a64);
    REGISTER_DEMUXER  (AAC, aac);
    REGISTER_MUXDEMUX (AC3, ac3);
    ......
}

 avcodec_register_all()调用结构如下:


void avcodec_register_all(void)
{
    static int initialized;
 
    //如果注册了,就直接返回,避免重复注册
    if (initialized)
        return;
    initialized = 1;
 
    /* hardware accelerators */
    REGISTER_HWACCEL (H263_VAAPI, h263_vaapi);
    REGISTER_HWACCEL (H264_DXVA2, h264_dxva2);
    REGISTER_HWACCEL (H264_VAAPI, h264_vaapi);
    REGISTER_HWACCEL (H264_VDA, h264_vda);
    REGISTER_HWACCEL (MPEG1_VDPAU, mpeg1_vdpau);
    REGISTER_HWACCEL (MPEG2_DXVA2, mpeg2_dxva2);
    REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi);
    REGISTER_HWACCEL (MPEG2_VDPAU, mpeg2_vdpau);
    REGISTER_HWACCEL (MPEG4_VAAPI, mpeg4_vaapi);
    REGISTER_HWACCEL (VC1_DXVA2, vc1_dxva2);
    REGISTER_HWACCEL (VC1_VAAPI, vc1_vaapi);
    REGISTER_HWACCEL (WMV3_DXVA2, wmv3_dxva2);
    REGISTER_HWACCEL (WMV3_VAAPI, wmv3_vaapi);
 
    /* video codecs */
    REGISTER_ENCODER (A64MULTI, a64multi);
    REGISTER_ENCODER (A64MULTI5, a64multi5);
    REGISTER_DECODER (AASC, aasc);
    ......
}

我们再看REGISTER_XXXX这个宏的具体结构和作用。

解复用为例


#define REGISTER_DEMUXER(X,x) { \
    extern AVInputFormat ff_##x##_demuxer; \
    if(CONFIG_##X##_DEMUXER) av_register_input_format(&ff_##x##_demuxer); }

define里面的##可能不太常见,它的含义就是拼接两个字符串,比如

#define Conn(x,y) x##y

表示

int  n = Conn(123,456);  结果就是n=123456;

我们以REGISTER_DEMUXER  (AAC, aac)为例,则它等效于

extern AVInputFormat ff_aac_demuxer; 
if(CONFIG_AAC_DEMUXER) av_register_input_format(&ff_aac_demuxer);

使用REGISTER_DEMUXER  (AAC, aac)就是调用函数av_register_input_format函数

/** head of registered input format linked list */
static AVInputFormat *first_iformat = NULL;

void av_register_input_format(AVInputFormat *format)
{
    AVInputFormat **p;
    p = &first_iformat;
    while (*p != NULL) p = &(*p)->next;
    *p = format;
    format->next = NULL;
}

我们可以看到first_iformat是链表的头,这个函数就是遍历链表,然后把我们传入的结构添加链表尾,也就是完成了注册,这样后面我们就可以使用注册好了的结构,例如编码器等。所有的注册都是这样的操作。

这样我们就理解了为什么首先需要调用av_register_all(),以及内部的实现原理。

注意

av_register_all()和 avcodec_register_all()是公开的API函数都可以调用,其他函数仅供ffmpeg内部使用。如果你只需要做编码的操作可以直接调用 avcodec_register_all(),而不用调用av_register_all(),不过一般直接调用av_register_all()即可。

你可能感兴趣的:(ffmpeg,ffmpeg)