内存操作的常见函数位于libavutil\mem.c中。本文记录FFmpeg开发中最常使用的几个函数:av_malloc(),av_realloc(),av_mallocz(),av_calloc(),av_free(),av_freep()。

av_malloc()

av_malloc()是FFmpeg中最常见的内存分配函数。它的定义如下。

#define FF_MEMORY_POISON 0x2a

#define ALIGN (HAVE_AVX ? 32 : 16)

static size_t max_alloc_size= INT_MAX;

void *av_malloc(size_t size)

{

void *ptr = NULL;

#if CONFIG_MEMALIGN_HACK

long diff;

#endif

/* let‘s disallow possibly ambiguous cases */

if (size > (max_alloc_size - 32))

return NULL;

#if CONFIG_MEMALIGN_HACK

ptr = malloc(size + ALIGN);

if (!ptr)

return ptr;

diff = ((~(long)ptr)&(ALIGN - 1)) + 1;

ptr = (char *)ptr + diff;

((char *)ptr)[-1] = diff;

#elif 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;

/* 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_malloc()就是简单的封装了系统函数malloc(),并做了一些错误检查工作。

关于size_tsize _t 这个类型在FFmpeg中多次出现,简单解释一下其作用。size _t是为了增强程序的可移植性而定义的。不同系统上,定义size_t可能不一样。它实际上就是unsigned int。

为什么要内存对齐?FFmpeg内存分配方面多次涉及到“内存对齐”(memory alignment)的概念。

这方面内容在IBM的网站上有一篇文章,讲的挺通俗易懂的,在此简单转述一下。

程序员通常认为内存就是一个字节数组,每次可以一个一个字节存取内存。例如在C语言中使用char *指代“一块内存”,Java中使用byte[]指代一块内存。如下所示。

但那实际上计算机处理器却不是这样认为的。处理器相对比较“懒惰”,它会以2字节,4字节,8字节,16字节甚至32字节来存取内存。例如下图显示了以4字节为单位读写内存的处理器“看待”上述内存的方式。

上述的存取单位的大小称之为内存存取粒度。

下面看一个实例,分别从地址0,和地址1读取4个字节到寄存器。

从程序员的角度来看,读取方式如下图所示。

而2字节存取粒度的处理器的读取方式如下图所示。

可以看出2字节存取粒度的处理器从地址0读取4个字节一共读取2次;从地址1读取4个字节一共读取了3次。由于每次读取的开销是固定的,因此从地址1读取4字节的效率有所下降。

4字节存取粒度的处理器的读取方式如下图所示。

可以看出4字节存取粒度的处理器从地址0读取4个字节一共读取1次;从地址1读取4个字节一共读取了2次。从地址1读取的开销比从地址0读取多了一倍。由此可见内存不对齐对CPU的性能是有影响的。

av_realloc()

av_realloc()用于对申请的内存的大小进行调整。它的定义如下。

void *av_realloc(void *ptr, size_t size)

{

#if CONFIG_MEMALIGN_HACK

int diff;

#endif

/* let‘s disallow possibly ambiguous cases */

if (size > (max_alloc_size - 32))

return NULL;

#if CONFIG_MEMALIGN_HACK

//FIXME this isn‘t aligned correctly, though it probably isn‘t needed

if (!ptr)

return av_malloc(size);

diff = ((char *)ptr)[-1];

av_assert0(diff>0 && diff<=ALIGN);

ptr = realloc((char *)ptr - diff, size + diff);

if (ptr)

ptr = (char *)ptr + diff;

return ptr;

#elif 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)

{

/* let‘s disallow possibly ambiguous cases */

if (size > (max_alloc_size - 32))

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)

{

if (size <= 0 || nmemb >= INT_MAX / size)

return NULL;

return av_mallocz(nmemb * size);

}

从代码中可以看出,它调用av_mallocz()分配了nmemb*size个字节的内存。

av_free()

av_free()用于释放申请的内存。它的定义如下。

void av_free(void *ptr)

{

#if CONFIG_MEMALIGN_HACK

if (ptr) {

int v= ((char *)ptr)[-1];

av_assert0(v>0 && v<=ALIGN);

free((char *)ptr - v);

}

#elif HAVE_ALIGNED_MALLOC

_aligned_free(ptr);

#else

free(ptr);

#endif

}

默认情况下(CONFIG_MEMALIGN_HACK这些宏使用默认值0)的代码:

void av_free(void *ptr)

{

free(ptr);

}可以看出av_free()简单的封装了free()。

av_freep()

av_freep()简单封装了av_free()。并且在释放内存之后将目标指针设置为NULL。void av_freep(void *arg)

{

void **ptr = (void **)arg;

av_free(*ptr);

*ptr = NULL;

}

原文:http://blog.csdn.net/leixiaohua1020/article/details/41176777

ffmpeg源代码处理流程分析_FFmpeg源代码简单分析:内存的分配和释放相关推荐

  1. FFmpeg源代码简单分析:内存的分配和释放(av_malloc()、av_free()等)

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  2. FFmpeg源代码简单分析-通用- 内存的分配和释放(av_malloc()、av_free()等)

    参考链接 FFmpeg源代码简单分析:内存的分配和释放(av_malloc().av_free()等)_雷霄骅的博客-CSDN博客_av_malloc 内容介绍 内存操作的常见函数位于libavuti ...

  3. modem (1)---手机主叫的信道流程与Modem Log简单分析

    手机主叫的信道流程与Modem Log简单分析 层三信令里看到建立RRCCMM层什么的到底是什么意思?建立这些层有什么用? 从协议栈的角度来说,RR属于接入层,而MM和CC都属于非接入层即NAS. R ...

  4. R语言splines包构建基于logistic回归的自然样条分析:南非心脏病数据集、非线性:基函数展开和样条分析、你简单分析的不重要特征,可能只是线性不显著、而非线性是显著的

    R语言splines包构建基于logistic回归的自然样条分析:南非心脏病数据集.非线性:基函数展开和样条分析.你简单分析的不重要特征,可能只是线性不显著.而非线性是显著的 目录

  5. 智能情绪分析技术_简单分析人工智能的表现在计算机网络应用技术中的优势

    简单分析人工智能的表现在计算机网络应用技术中的优势 大数据时代背景下, 计算机网络技术迅猛发展, 而人工智能技术的发展也进一步推动了计算机网络技术的发展, 两者相互融合, 相互促进, 实现了双赢发展. ...

  6. FFmpeg音频解码流程详解及简单demo参考

    本文主要讲解FFmpeg的音频解码具体流程,API使用.最后再以一个非常简单的demo演示将一个mp3格式的音频文件解码为原始数据pcm文件. 本文主要基于FFmpeg音频解码新接口. 一.FFmpe ...

  7. FFmpeg内存的分配和释放---av_malloc()、av_free()等

    本文简单记录一下FFmpeg中内存操作的函数. 内存操作的常见函数位于libavutil\mem.c中.本文记录FFmpeg开发中最常使用的几个函数:av_malloc(),av_realloc(), ...

  8. FFmpeg源代码简单分析:libavdevice的gdigrab

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  9. FFmpeg源代码简单分析:configure

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

最新文章

  1. [力扣] 501. 二叉搜索树中的众数
  2. 第十一章 机器学习系统设计-机器学习老师板书-斯坦福吴恩达教授
  3. 粉丝提问:有没有人会做彩虹表
  4. java final内存机制_Java中的内存处理机制和final、static、final static总结
  5. Java-基础---继承,方法重写,super关键字
  6. 火狐浏览器中一个插件-httpfox
  7. Win7/Win8/IIS7/IIS8配置ASP/ACCESS
  8. CATIA V6二次开发——复杂装配体的结构树遍历
  9. autojs开发的ip地址查询工具开源代码免费分享
  10. 哲学的终极解释:48张图了解48种主义
  11. 如何在命令行状态清除SEP隔离区(Quarantine)
  12. CC2640R2F学习笔记二:昇润科技开发资料阅读
  13. 从代码和底层探究Synchronized锁实现
  14. 【CAD算法】【计算机图形学】Coons Patch曲面生成程序(python/numpy实现)[2]
  15. Android O 版本(Android 8.0) 存储空间不足时提醒
  16. display:flex 意思是弹性布局
  17. 秒杀分部积分,提高计算幸福感——表格积分法
  18. APP自动化简单理解(在python中实现简单的app自动化框架)
  19. mysql经典问题四表查询(教师,学生,成绩,课程表)
  20. CVPR 2018摘要:第一部分

热门文章

  1. 如何截取视频片段 批量截取片段的方法
  2. mysql upgrade 报错_mysql_upgrade
  3. jupyter notebook多行注释方法
  4. 计算机基础实验教程第二版苏州大学出版社,计算机基础与实验
  5. 第5篇 熊猫烧香逆向分析(下)
  6. (二)树莓派系列教程:树莓派4B手动连接wifi,远程控制。命令行界面、桌面界面
  7. C# 实现刻录光盘功能
  8. multisim变压器反馈式_Multisim在负反馈放大器性能测试中的应用
  9. linux 存储映射lun 给_LINUX系统下添加映射存储LUN(无需重启)
  10. 循环赛日程表(递归实现)