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

参考链接

  • FFmpeg源代码简单分析:内存的分配和释放(av_malloc()、av_free()等)_雷霄骅的博客-CSDN博客_av_malloc

内容介绍

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

代码

av_malloc()

void *av_malloc(size_t size)
{void *ptr = NULL;if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed))return NULL;#if HAVE_POSIX_MEMALIGNif (size) //OS X on SDK 10.6 has a broken posix_memalign implementationif (posix_memalign(&ptr, ALIGN, size))ptr = NULL;
#elif HAVE_ALIGNED_MALLOCptr = _aligned_malloc(size, ALIGN);
#elif HAVE_MEMALIGN
#ifndef __DJGPP__ptr = memalign(ALIGN, size);
#elseptr = 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.*/
#elseptr = malloc(size);
#endifif(!ptr && !size) {size = 1;ptr= av_malloc(1);}
#if CONFIG_MEMORY_POISONINGif (ptr)memset(ptr, FF_MEMORY_POISON, size);
#endifreturn ptr;
}
  • 如果不考虑上述代码中的一大堆宏定义
  • av_malloc()的代码可以简化成如下形式
  • 可以看出,此时的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()

void *av_realloc(void *ptr, size_t size)
{void *ret;if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed))return NULL;#if HAVE_ALIGNED_MALLOCret = _aligned_realloc(ptr, size + !size, ALIGN);
#elseret = realloc(ptr, size + !size);
#endif
#if CONFIG_MEMORY_POISONINGif (ret && !ptr)memset(ret, FF_MEMORY_POISON, size);
#endifreturn ret;
}
  • 默认情况下的代码:
  • 可以看出av_realloc()简单封装了系统的realloc()函数。
  • C 库函数 – 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()

void *av_mallocz(size_t size)
{void *ptr = av_malloc(size);if (ptr)memset(ptr, 0, size);return ptr;
}
  • av_mallocz()可以理解为av_malloc()+zeromemory
  • av_mallocz()中调用了av_malloc()之后,又调用memset()将分配的内存设置为0

av_calloc()

void *av_calloc(size_t nmemb, size_t size)
{size_t result;if (size_mult(nmemb, size, &result) < 0)return NULL;return av_mallocz(result);
}
static int size_mult(size_t a, size_t b, size_t *r)
{size_t t;#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_mul_overflow)if (__builtin_mul_overflow(a, b, &t))return AVERROR(EINVAL);
#elset = 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);
#endif*r = t;return 0;
}
  • av_calloc()则是简单封装了av_mallocz() 
  • 从代码中可以看出,它调用av_mallocz()分配了nmemb*size个字节的内存。

av_free()

void av_free(void *ptr)
{
#if HAVE_ALIGNED_MALLOC_aligned_free(ptr);
#elsefree(ptr);
#endif
}
  • 可以看出av_free()简单的封装了free() 

av_freep()

void av_freep(void *arg)
{void *val;memcpy(&val, arg, sizeof(val));memcpy(arg, &(void *){ NULL }, sizeof(val));av_free(val);
}
  • av_freep()简单封装了av_free()。并且在释放内存之后将目标指针设置为NULL。
  • C 库函数 – memcpy() | 菜鸟教程 

补充知识

内存对齐

  • 参考链接:计算机中的内存对齐与大小端 | MuYi's Blog
  • 程序员通常认为内存就是一个字节数组,每次可以一个一个字节存取内存。例如在C语言中使用char *指代“一块内存”,Java中使用byte[]指代一块内存。如下所示。

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

  • 上述的存取单位的大小称之为内存存取粒度。
  • 下面看一个实例,分别从地址0,和地址1读取4个字节到寄存器。
  • 从程序员的角度来看,读取方式如下图所示。

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

  • 可以看出2字节存取粒度的处理器从地址0读取4个字节一共读取2次;从地址1读取4个字节一共读取了3次。
  • 存储的时候也是将2个字节作为数据块的大小进行存储
  • 由于每次读取的开销是固定的,因此从地址1读取4字节的效率有所下降。
  • 4字节存取粒度的处理器的读取方式如下图所示。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/446001.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FFmpeg源代码简单分析-通用-结构体分析-AVFormatContext

参考链接 FFMPEG结构体分析&#xff1a;AVFormatContext_雷霄骅的博客-CSDN博客_avformatcontext AVFormatContext AVFormatContext是包含码流参数较多的结构体结构体的定义位于libavformat/avformat.h/*** Format I/O context.//格式化 I/O 上下文* New fields can be added…

plsql如何显示表结构图_【论文攻略】排版技巧——如何用 Word 编辑参考文献

每个需要写毕业论文的朋友都会发现&#xff0c;修改文献是一件非常痛苦的事情&#xff0c;虽然现在也有很多软件可以编排参考文献&#xff0c;其实 word 本身就可以。采用合适的编辑方法会方便地做到整齐,规范, 自动排序和交叉引用。 1. 以尾注的方式插入第一个参考文献将光标定…

FFmpeg源代码简单分析-通用-结构体分析-AVCodecContext

参考链接 FFMPEG结构体分析&#xff1a;AVCodecContext_雷霄骅的博客-CSDN博客_avcodeccontext AVCodecContext AVCodecContext是包含变量较多的结构体&#xff08;感觉差不多是变量最多的结构体&#xff09;结构体的定义位于avcodec.h关键的变量如下所示&#xff08;仅仅考虑…

Hello OpenGL——OpenGL在Visual c++6.0安装和配置

1、下载并安装glut库opengl的glut库 GLUT不是OpenGL所必须的&#xff0c;但它会给我们的学习带来一定的方便&#xff0c;推荐安装。 Windows环境下的GLUT下载地址&#xff1a;&#xff08;大小约为150k&#xff09; http://www.opengl.org/resources/libraries/glut/glutdlls37…

FFmpeg源代码简单分析-通用-结构体分析-AVIOContext

参考链接 FFMPEG结构体分析&#xff1a;AVIOContext_雷霄骅的博客-CSDN博客_aviocontext AVIOContext AVIOContext是FFMPEG管理输入输出数据的结构体结构体的定义位于位于avio.h关键的变量如下所示 unsigned char *buffer&#xff1a;缓存开始位置int buffer_size&#xff1…

初闻动态规划

前言 本文以一道常见的算法面试题开篇&#xff0c;引入动态规划的基础概念&#xff0c; 介绍其思考过程。 正文 一、常见的一道算法面试题——上台阶 有一个楼梯总共n个台阶&#xff0c;只能往上走&#xff0c;每次只能上1个、2个台阶&#xff0c;总共有多少种走法。 解决…

FFmpeg源代码简单分析-通用-结构体分析-AVCodec

参考链接 FFMPEG结构体分析&#xff1a;AVCodec_雷霄骅的博客-CSDN博客_avcodec AVCodec AVCodec是存储编解码器信息的结构体结构体的定义位于avcodec.h文件中最主要的几个变量 const char *name&#xff1a;编解码器的名字&#xff0c;比较短const char *long_name&#xff…

SLF4J简介与使用(整合log4j)

SLF4J简介与使用(整合log4j) 一、概念 SLF4J的全称是Simple Logging Facade for Java&#xff0c;即简单日志门面。SLF4J并不是具体的日志框架&#xff0c;而是作为一个简单门面服务于各类日志框架&#xff0c;如java.util.logging, logback和log4j。 SLF4J提供了统一的记录…

multism中ui和uo应该怎么表示_王者荣耀:梦泪直播时谈到体验服大改动,表示装备的改动很关键...

王者荣耀的主播梦泪&#xff0c;大家都很熟了&#xff0c;也是一个很强的主播&#xff0c;他对于王者荣耀的理解&#xff0c;还是非常深刻的&#xff0c;而最近王者荣耀的体验服&#xff0c;进行了大改动&#xff0c;也是改变了很多的东西。对此&#xff0c;网友们也是非常的在…

怎么关闭或者卸载ivanti_电脑软件卸载不了怎么办,教您解决电脑软件无法卸载方法技巧...

我们在使用电脑的过程中&#xff0c;肯定会安装各种软件&#xff0c;但是一些软件在使用完之后就不会再使用了&#xff0c;但又无法卸载。下面由小编分享一下电脑安装的软件无法卸载解决方法&#xff0c;如果你在某卸载软件的时候出现无法卸载的情况&#xff0c;不妨通过以下方…

解决Github图片加载失败

问题描述 浏览自己Github某仓库的README.md内时&#xff0c;发现文档的图片始终加载不出&#xff0c;打开浏览器后台&#xff0c;冒出一片红&#xff0c;Failed to load resource: net::ERR_CONNECTION_RESET&#xff0c;如下图所示&#xff1a; 问题分析 可能造成这问题的原…

FFmpeg源代码简单分析-通用-结构体分析-关键结构体之间的关系

参考链接 FFMPEG中最关键的结构体之间的关系_雷霄骅的博客-CSDN博客_ffmpeg 结构体关系 最关键的结构体可以分成以下几类&#xff1a; 解协议&#xff08;http,rtsp,rtmp,mms&#xff09; AVIOContext&#xff0c;URLProtocol&#xff0c;URLContext主要存储视音频使用的协…

用Python下载文件

前提条件 需要事先安装requests模块&#xff1a; pip install requests 放码过来 import requestsurl XXX #文件下载来源URL filename #下载到本地后新文件名 r requests.get(url) with open(filename, "wb") as code:code.write(r.content)实战演习 从目标…

FFmpeg源代码简单分析-通用-常见结构体的初始化和销毁(AVFormatContext,AVFrame等)

参考链接 FFmpeg源代码简单分析&#xff1a;常见结构体的初始化和销毁&#xff08;AVFormatContext&#xff0c;AVFrame等&#xff09;_雷霄骅的博客-CSDN博客 结构体 AVFormatContext&#xff1a;统领全局的基本结构体。主要用于处理封装格式&#xff08;FLV/MKV/RMVB等&…

FFmpeg源代码简单分析-通用-avio_open2()

参考链接 FFmpeg源代码简单分析&#xff1a;avio_open2()_雷霄骅的博客-CSDN博客_avio_open avio_open2() 该函数用于打开FFmpeg的输入输出文件avio_open2()的声明位于libavformat\avio.h文件中&#xff0c;如下所示。 /*** Create and initialize a AVIOContext for accessi…

用Tomcat构建一个简单图片服务器

前提条件 Tomcat 7.0.90 方法一&#xff1a;修改配置文件 在TOMCAT_HOME/conf/server.xml配置文件内的<Host>内添加一子标签&#xff1a; <Context docBase"C:\exambase\" path"/img"/>方法二&#xff1a;添加Servlet 新建一应用&#xf…

FFmpeg源代码简单分析-通用-av_find_decoder()和av_find_encoder()

参考链接 FFmpeg源代码简单分析&#xff1a;av_find_decoder()和av_find_encoder()_雷霄骅的博客-CSDN博客_avcodec_find_encoder avcodec_find_encoder avcodec_find_encoder()用于查找FFmpeg的编码器avcodec_find_encoder()的声明位于libavcodec\codec.h 版本差异avcode…

post方法就反回了一个string字符串前台怎么接_Golang Web入门(2):如何实现一个RESTful风格的路由...

摘要在上一篇文章中&#xff0c;我们聊了聊在Golang中怎么实现一个Http服务器。但是在最后我们可以发现&#xff0c;固然DefaultServeMux可以做路由分发的功能&#xff0c;但是他的功能同样是不完善的。由DefaultServeMux做路由分发&#xff0c;是不能实现RESTful风格的API的&a…

FFmpeg源代码简单分析-通用-avcodec_open2()

参考链接 FFmpeg源代码简单分析&#xff1a;avcodec_open2()_雷霄骅的博客-CSDN博客 avcodec_open2() 该函数用于初始化一个音视频编解码器的AVCodecContextavcodec_open2()的声明位于libavcodec\avcodec.h&#xff0c;如下所示。 /*** Initialize the AVCodecContext to use…

统计MySQL中某数据库硬盘占用量大小

放码过来 select TABLE_NAME, concat(truncate(data_length/1024/1024,2), MB) as data_size, concat(truncate(index_length/1024/1024,2), MB) as index_size from information_schema.tables where TABLE_SCHEMA your_db_name order by data_length desc;运行结果 参考…