> 文章列表 > FFMPEG源码分析一 av_register_all()

FFMPEG源码分析一 av_register_all()

FFMPEG源码分析一 av_register_all()

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

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

 解析和说明

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;//注册所有的codecavcodec_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()即可。