内存分配与释放
内存管理在libavutil下mem.h。
av_malloc()就是简单的封装了系统函数malloc(),并做了一些错误检查工作。
void *av_malloc(size_t size)
{
void *ptr = NULL;
/* let's disallow possibly ambiguous cases */
if (size > (max_alloc_size - 32))
return NULL;
ptr = malloc(size);
if(!ptr && !size) {
size = 1;
ptr= av_malloc(1);
}
return ptr;
}
av_realloc()简单封装了系统的realloc()函数。
void *av_realloc(void *ptr, size_t size)
{
/* let's disallow possibly ambiguous cases */
if (size > (max_alloc_size - 32))
return NULL;
return realloc(ptr, size + !size);
}
av_mallocz()可以理解为av_malloc()+zeromemory。从源代码可以看出av_mallocz()中调用了av_malloc()之后,又调用memset()将分配的内存设置为0。
void *av_mallocz(size_t size)
{
void *ptr = av_malloc(size);
if (ptr)
memset(ptr, 0, size);
return ptr;
}
av_calloc()则是简单封装了av_mallocz(),
从代码中可以看出,它调用av_mallocz()分配了nmemb*size个字节的内存。
void *av_calloc(size_t nmemb, size_t size)
{
if (size <= 0 || nmemb >= INT_MAX / size)
return NULL;
return av_mallocz(nmemb * size);
}
释放内存
av_free()简单的封装了free()。
void av_free(void *ptr)
{
free(ptr);
}
av_freep()简单封装了av_free()。并且在释放内存之后将目标指针设置为NULL。
void av_freep(void *arg)
{
void **ptr = (void **)arg;
av_free(*ptr);
*ptr = NULL;
}
av_register_all
av_register_all的源代码(libavformat下allformats.c)如下:
……
#define REGISTER_DEMUXER(X, x) \
{ \
extern AVInputFormat ff_##x##_demuxer; \
if (CONFIG_##X##_DEMUXER) \
av_register_input_format(&ff_##x##_demuxer); \
}
void av_register_all(void)
{
static int initialized;
if (initialized)
return;
initialized = 1;
avcodec_register_all();
/* (de)muxers */
REGISTER_MUXER (A64, a64);
REGISTER_DEMUXER (AAC, aac);
……
}
我们以REGISTER_DEMUXER (AAC, aac)为例,则它等效于
extern AVInputFormat ff_aac_demuxer;
if(CONFIG_AAC_DEMUXER) av_register_input_format(&ff_aac_demuxer);
从上面这段代码我们可以看出,真正注册的函数是av_register_input_format(&ff_aac_demuxer),那我就看看这个和函数的作用,查看一下av_register_input_format()的代码:
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是个什么东东呢?其实它是Input Format链表的头部地址,是一个全局静态变量,定义如下:
/** head of registered input format linked list */
static AVInputFormat *first_iformat = NULL;
由此我们可以分析出av_register_input_format()的含义,一句话概括就是:遍历链表并把当前的Input Format加到链表的尾部。
至此REGISTER_DEMUXER (X, x)分析完毕。
avcodec_register_all
avcodec_register_all的源代码(libavcodec下的allcodecs.c)如下:
#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); \
}
……
void avcodec_register_all (void)
{
static int initialized;
if (initialized)
return;
initialized = 1;
……
REGISTER_DECODER(H264, h264);
……
}
在这里,我发现其实编码器和解码器用的注册函数都是一样的:avcodec_register()
以REGISTER_DECODER (H264, h264)为例,就是等效于
extern AVCodec ff_h264_decoder;
if(CONFIG_H264_DECODER) avcodec_register(&ff_h264_decoder);
下面看一下avcodec_register()的源代码:
//注册所有的AVCodec
void avcodec_register(AVCodec *codec)
{
AVCodec **p;
//初始化
avcodec_init();
//从第一个开始
p = &first_avcodec;
while (*p != NULL) p = &(*p)->next;
*p = codec;
codec->next = NULL;
if (codec->init_static_data)
codec->init_static_data(codec);
}
这段代码是比较容易理解的。首先先提一点,first_avcdec是就是AVCodec链表的头部地址,是一个全局静态变量,定义如下:
/* encoder management */
static AVCodec *first_avcodec = NULL;
由此我们可以分析出avcodec_register()的含义,一句话概括就是:遍历链表并把当前的AVCodec加到链表的尾部。
同理,Parser,BSF(bitstream filters,比特流滤镜),HWACCEL(hardware accelerators,硬件加速器)的注册方式都是类似的。不再详述。
AVFormatContext-AVIOContext-AVStream-AVFrame-AVPacket
AVFormatContext:统领全局的基本结构体。主要用于处理封装格式(FLV/MKV/RMVB等)。
AVIOContext:输入输出对应的结构体,用于输入输出(读写文件,RTMP协议等)。
AVStream,AVCodecContext:视音频流对应的结构体,用于视音频编解码。
AVFrame:存储非压缩的数据(视频对应RGB/YUV像素数据,音频对应PCM采样数据)
AVPacket:存储压缩数据(视频对应H.264等码流数据,音频对应AAC/MP3等码流数据)
他们之间的关系如下图所示:
结构体 | 初始化 | 销毁 |
AVFormatContext | avformat_alloc_context() (声明libavformat\avformat.hh, 定义libavformat\options.c) | avformat_free_context() |
AVIOContext | avio_alloc_context() (声明libavformat\avio.h, 定义libavformat\aviobuf.c) |
|
AVStream | avformat_new_stream() (声明libavformat\avformat.h, 定义libavformat\utils.c) |
|
AVCodecContext | avcodec_alloc_context3() (声明libavcodec\avcodec.h, 定义libavcodec\options.c) |
|
AVFrame | av_frame_alloc(); (声明libavutil\frame.h, 定义libavutil\frame.c) | av_frame_free() |
AVPacket | av_init_packet(); (声明libavcodec\avcodec.h, 定义libavcodec\avpacket.c) av_new_packet() (声明libavcodec\avcodec.h, 定义libavcodec\avpacket.c) | av_free_packet() |