av_register_all()
几乎是所有使用 FFMPEG 编程调用的第一个函数。av_register_all()
的主要功能是注册所有的 formats 和 protocols。
av_register_all 框架
首先列一下该函数的大体框架:
av_register_all
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| void av_register_all(void)
{
static int initialized;
if(initialized)
return;
initialized = 1;
avcodec_register_all();
/*(de)muxers*/
......
REGISTER_MUXER (F4V, f4v);
......
REGISTER_MUXDEMUX(FLV, flv);
REGISTER_MUXDEMUX(H264, h264);
REGISTER_MUXDEMUX(HEVC, hevc);
REGISTER_MUXER (MP4, mp4);
/*protocols*/
REGISTER_PROTOCOL(RTMP, rtmp);
REGISTER_PROTOCOL(TCP, tcp);
REGISTER_PROTOCOL(UDP, udp);
......
}
|
调用关系
从调用关系图可以看出,通过调用avcodec_register_all注册了和编解码器有关的组件;硬件加速器、解码器、编码器、Parser、Bistream Filter等,以及复用器、解复用器、协议处理。
源码分析
注册一次
initialized_once
1
2
3
4
5
| static int initialized;
if (initialized)
return;
initialized = 1;
|
该段代码可以看出,当调用过该函数一次后,再次调用时,该函数直接返回。
注意,这种方法在 FFMEPG 源码中非常常见。
注册 codec
1
| avcodec_register_all();
|
该函数的作用为注册codecs
parsers
和filters
。
该函数的源码,还请访问avcodec_register_all函数。
注册复用器
REGISTER_MUXER
1
2
3
4
5
6
| #define REGISTER_MUXER(X, x) \
{ \
extern AVOutputFormat ff_##x##_muxer; \
if (CONFIG_##X##_MUXER) \
av_register_output_format(&ff_##x##_muxer); \
}
|
以MP4
为例,REGISTER_MUXER(MP4, mp4)
展开如下:
1
2
3
| extern AVOutpusFormat ff_mp4_muxer;
if(CONFIG_MP4_MUXER)
av_register_output_format(&ff_mp4_muxer);
|
av_register_output_format(&ff_mp4_muxer)
展开如下:
av_register_output_format
1
2
3
4
5
6
7
8
9
| void av_register_output_format(AVOutputFormat *format)
{
AVOutputFormat **p = last_oformat;
format->next = NULL;
while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
p = &(*p)->next;
last_oformat = &format->next;
}
|
注册解复用器
REGISTER_MUXER
1
2
3
4
5
6
| #define REGISTER_DEMUXER(X, x) \
{ \
extern AVInputFormat ff_##x##_demuxer; \
if (CONFIG_##X##_DEMUXER) \
av_register_input_format(&ff_##x##_demuxer); \
}
|
av_register_input_format(&ff_mp4_muxer)
展开如下:
av_register_output_format
1
2
3
4
5
6
7
8
9
| void av_register_input_format(AVInputFormat *format)
{
AVInputFormat **p = last_iformat;
format->next = NULL;
while(*p || avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format))
p = &(*p)->next;
last_iformat = &format->next;
}
|
avpriv_atomic_ptr_cas
1
2
3
4
5
6
7
8
9
10
| void *avpriv_atomic_ptr_cas(void * volatile *ptr, void *oldval, void *newval)
{
void *ret;
pthread_mutex_lock(&atomic_lock);
ret = *ptr;
if (ret == oldval)
*ptr = newval;
pthread_mutex_unlock(&atomic_lock);
return ret;
}
|
REGISTER_MUXDEMUX
1
| #define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x)
|
注册协议
REGISTER_PROTOCOL
1
2
3
4
5
6
| #define REGISTER_PROTOCOL(X, x) \
{ \
extern URLProtocol ff_##x##_protocol; \
if (CONFIG_##X##_PROTOCOL) \
ffurl_register_protocol(&ff_##x##_protocol); \
}
|
以TCP
为例,REGISTER_PROTOCOL(TCP,tcp)
展开如下:
1
2
3
| extern URLProtocol ff_tcp_protocol;
if(CONFIG_TCP_PROTOCOL)
ffurl_register_protocol(&ff_tcp_protocol);
|
ffurl_register_protocol(&ff_tcp_protocol)
展开如下:
ffurl_register_protocol
1
2
3
4
5
6
7
8
9
10
| int ffurl_register_protocol(URLProtocol *protocol)
{
URLProtocol **p;
p = &first_protocol;
while (*p)
p = &(*p)->next;
*p = protocol;
protocol->next = NULL;
return 0;
}
|