avcodec_register_all()的函数定义位于libavcodec/allcodecs.c。
它是用来注册编解码器的函数,只有调用了该函数,才能使用编解码器、解析器、硬件加速器等。
1. 函数主体如下:
-
void avcodec_register_all(void)
-
{
-
-
static int initialized;
-
-
-
if (initialized)
-
-
return;
-
-
initialized = 1;
-
/* hardware accelerators */
-
REGISTER_HWACCEL();
-
-
/* video codecs */
-
REGISTER_ENCODER();
-
REGISTER_DECODER();
-
-
/* audio codecs */
-
REGISTER_ENCODER();
-
REGISTER_DECODER();
-
-
/* PCM codecs */
-
REGISTER_ENCODER();
-
REGISTER_DECODER();
-
-
/* subtitles */
-
-
/* external libraries */
-
-
/* parsers */
-
REGISTER_PARSER();
-
-
-
}
2. 注册函数的宏定义如下:
-
#define REGISTER_HWACCEL(X, x) \
-
{ \
-
extern AVHWAccel ff_##x##_hwaccel; \
-
if (CONFIG_##X##_HWACCEL) \
-
av_register_hwaccel(&ff_##x##_hwaccel); \
-
}
-
-
#define REGISTER_ENCODER(X, x) \
-
{ \
-
extern AVCodec ff_##x##_encoder; \
-
if (CONFIG_##X##_ENCODER) \
-
avcodec_register(&ff_##x##_encoder); \
-
}
-
-
#define REGISTER_DECODER(X, x) \
-
{ \
-
extern AVCodec ff_##x##_decoder; \
-
if (CONFIG_##X##_DECODER) \
-
avcodec_register(&ff_##x##_decoder); \
-
}
-
-
#define REGISTER_ENCDEC(X, x) REGISTER_ENCODER(X, x); REGISTER_DECODER(X, x)
-
#define REGISTER_PARSER(X, x) \
-
{ \
-
extern AVCodecParser ff_##x##_parser; \
-
if (CONFIG_##X##_PARSER) \
-
av_register_codec_parser(&ff_##x##_parser); \
-
}
编码器和解码器调用的是同一个注册函数 avcodec_register();
3. 编解码器
-
REGISTER_DECODER(H264, h264);
-
-
#define REGISTER_DECODER(X, x) \
-
{ \
-
extern AVCodec ff_##x##_decoder; \
-
if (CONFIG_##X##_DECODER) \
-
avcodec_register(&ff_##x##_decoder); \
-
}
-
-
的宏展开后:
-
{
-
/* extern表明全局唯一 */
-
extern AVCodec ff_h264_decoder;
-
if (CONFIG_H264_DECODER)
-
avcodec_register(&ff_h264_decoder);
-
}
-
-
avcodec_register的函数定义: libavcodec/utils.c
-
/* encoder management */
-
static AVCodec *first_avcodec = NULL;
-
static AVCodec **last_avcodec = &first_avcodec;
-
av_cold void avcodec_register(AVCodec *codec)
-
{
-
AVCodec **p;
-
avcodec_init();
-
p = last_avcodec;
-
codec->next = NULL;
-
-
/* 将新的codec 添加到链接的尾部*/
-
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);
-
}
-
-
void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval)
-
{
-
if (*ptr == oldval) {
-
*ptr = newval;
-
return oldval;
-
}
-
return *ptr;
-
}
代码解析:
这段代码使用了链表结构,并为链表设置了两个全局指针,
指向链表头的 first_avcodec,
指向链表尾的 last_avcodec,
调用函数avpriv_atomic_ptr_cas((void * volatile *)p, NULL, codec),将新的codec添加到链表的尾部。
如果last_avcodec没有指向链表的尾,则要先遍历链表,将其指向链表的尾部。
这样做的好处是省去了每次添加一个新codec时,必须对链表的从头到尾遍历以找到链表的尾部。
如果使用遍历的方法,则代码要用如下写:
//注册所有的AVCodec
void avcodec_register(AVCodec *codec)
{
AVCodec **p;
/* 初始化 */
avcodec_init();
/* 从第一个开始, 遍历到链表的尾部 */
p = &first_avcodec;
while (*p != NULL)
p = &(*p)->next;
/* 将新的codec添加到链表的尾部 */
*p = codec;
codec->next = NULL;
if (codec->init_static_data)
codec->init_static_data(codec);
}
4. 硬件加速器
-
REGISTER_HWACCEL(H264_CUVID, h264_cuvid);
-
的宏展开后为:
-
{
-
extern AVHWAccel ff_h264_cuvid_hwacel;
-
if (CONFIG_H264_CUVID_HWACCEL)
-
av_register_hwaccel(&ff_h264_cuvid_hwacel);
-
}
-
-
av_register_hwaccel()的定义位于libavcodec/utils.c
-
static AVHWAccel *first_hwaccel = NULL;
-
-
static AVHWAccel **last_hwaccel = &first_hwaccel;
-
-
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;
-
}
这段代码和编解码器的用法一样。
5. 解析器
-
REGISTER_PARSER(AAC, aac);
-
#define REGISTER_PARSER(X, x) \
-
{ \
-
extern AVCodecParser ff_##x##_parser; \
-
if (CONFIG_##X##_PARSER) \
-
av_register_codec_parser(&ff_##x##_parser); \
-
}
-
-
宏展开后:
-
{
-
extern AVCodecParser ff_aac_parser;
-
if (CONFIG_AAC_PARSER)
-
av_register_codec_parser(&ff_aac_parser);
-
}
-
-
av_register_codec_parser的函数定义,libavcodec/parser.c
-
-
static AVCodecParser *av_first_parser = NULL;
-
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));
-
}
-
-
void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval)
-
{
-
if (*ptr == oldval) {
-
*ptr = newval;
-
return oldval;
-
}
-
return *ptr;
-
}
代码解析:
解析器的注册方法和编解码器的注册方法不一样,
它是用av_first_parser指向链表的头,
然后再将新的parser添加到原链表的头之前,再将av_first_parser指向这个新链表头。
参考文档:
http://blog.csdn.net/leixiaohua1020/article/details/12677265
阅读(1784) | 评论(0) | 转发(0) |