本文简单记录一下FFmpeg中内存操作的函数。
内存操作的常见函数位于libavutil\mem.c中。本文记录FFmpeg开发中最常使用的几个函数:av_malloc(),av_realloc(),av_mallocz(),av_calloc(),av_free(),av_freep()。
av_malloc()
av_malloc()是FFmpeg中最常见的内存分配函数。它的定义如下。
void *av_malloc(size_t size)
{
void *ptr = NULL;
if (size > max_alloc_size)
return NULL;
#if HAVE_POSIX_MEMALIGN
if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
if (posix_memalign(&ptr, ALIGN, size))
ptr = NULL;
#elif HAVE_ALIGNED_MALLOC
ptr = _aligned_malloc(size, ALIGN);
#elif HAVE_MEMALIGN
#ifndef __DJGPP__
ptr = memalign(ALIGN, size);
#else
ptr = memalign(size, ALIGN);
#endif
/* Why 64?
* Indeed, we should align it:
* on 4 for 386
* on 16 for 486
* on 32 for 586, PPro - K6-III
* on 64 for K7 (maybe for P3 too).
* Because L1 and L2 caches are aligned on those values.
* But I don't want to code such logic here!
*/
/* Why 32?
* For AVX ASM. SSE / NEON needs only 16.
* Why not larger? Because I did not see a difference in benchmarks ...
*/
/* benchmarks with P3
* memalign(64) + 1 3071, 3051, 3032
* memalign(64) + 2 3051, 3032, 3041
* memalign(64) + 4 2911, 2896, 2915
* memalign(64) + 8 2545, 2554, 2550
* memalign(64) + 16 2543, 2572, 2563
* memalign(64) + 32 2546, 2545, 2571
* memalign(64) + 64 2570, 2533, 2558
*
* BTW, malloc seems to do 8-byte alignment by default here.
*/
#else
ptr = malloc(size);
#endif
if(!ptr && !size) {
size = 1;
ptr= av_malloc(1);
}
#if CONFIG_MEMORY_POISONING
if (ptr)
memset(ptr, FF_MEMORY_POISON, size);
#endif
return ptr;
}
如果不考虑上述代码中的一大堆宏定义(即类似CONFIG_MEMALIGN_HACK这类的宏都采用默认值0),av_malloc()的代码可以简化成如下形式。
void *av_malloc(size_t size)
{
void *ptr = NULL;
if (size > max_alloc_size)
return NULL;
ptr = malloc(size);
if(!ptr && !size) {
size = 1;
ptr= av_malloc(1);
}
return ptr;
}
可以看出,此时的av_malloc()就是简单的封装了系统函数malloc(),并做了一些错误检查工作。
av_realloc()
av_realloc()用于对申请的内存的大小进行调整。它的定义如下。
void *av_realloc(void *ptr, size_t size)
{
if (size > max_alloc_size)
return NULL;
#if HAVE_ALIGNED_MALLOC
return _aligned_realloc(ptr, size + !size, ALIGN);
#else
return realloc(ptr, size + !size);
#endif
}
默认情况下(CONFIG_MEMALIGN_HACK这些宏使用默认值0)的代码:
void *av_realloc(void *ptr, size_t size)
{
if (size > max_alloc_size)
return NULL;
return realloc(ptr, size + !size);
}
可以看出av_realloc()简单封装了系统的realloc()函数。
av_mallocz()
av_mallocz()可以理解为av_malloc()+zeromemory。代码如下。
void *av_mallocz(size_t size)
{
void *ptr = av_malloc(size);
if (ptr)
memset(ptr, 0, size);
return ptr;
}
从源代码可以看出av_mallocz()中调用了av_malloc()之后,又调用memset()将分配的内存设置为0。
av_calloc()
av_calloc()则是简单封装了av_mallocz(),定义如下所示。
void *av_calloc(size_t nmemb, size_t size)
{
size_t result;
if (av_size_mult(nmemb, size, &result) < 0)
return NULL;
return av_mallocz(result);
}
av_size_mult()定义如下:
static inline int av_size_mult(size_t a, size_t b, size_t *r)
{
size_t t = a * b;
/* Hack inspired from glibc: don't try the division if nelem and elsize
* are both less than sqrt(SIZE_MAX). */
if ((a | b) >= ((size_t)1 << (sizeof(size_t) * 4)) && a && t / a != b)
return AVERROR(EINVAL);
*r = t;
return 0;
}
从代码中可以看出,它调用av_mallocz()分配了nmemb*size个字节的内存。
av_free()
av_free()用于释放申请的内存。它的定义如下。
void av_free(void *ptr)
{
#if HAVE_ALIGNED_MALLOC
_aligned_free(ptr);
#else
free(ptr);
#endif
}
默认情况下:
void av_free(void *ptr)
{
free(ptr);
}
可以看出av_free()简单的封装了free()。
av_freep()
av_freep()简单封装了av_free()。并且在释放内存之后将目标指针设置为NULL。
void av_freep(void *arg)
{
void *val;
memcpy(&val, arg, sizeof(val));
memcpy(arg, &(void *){ NULL }, sizeof(val));
av_free(val);
}
参考文献
1、https://blog.csdn.net/leixiaohua1020/article/details/41176777