【音视频】内存管理系统

这个系列文章我们来介绍一位海外工程师如何探索安卓音视频基础技术,对于想要开始学习音视频技术的朋友,这些文章是份不错的入门资料,本篇介绍内存管理系统。

——来自公众号“关键帧Keyframe”的分享

1、架构总览

应用程序层
   ↓
libavutil/mem.c  ← 统一入口(对齐、溢出保护、平台适配)
   ↓
av_malloc / av_buffer_alloc  →  引用计数池 → 零拷贝传递
   ↓
操作系统(posix_memalign / _aligned_malloc / memalign)

设计目标对齐 + 溢出保护 + 零拷贝 + 自动回收

2、核心分配函数

函数关键特性使用场景
av_malloc()32/64 B 对齐
平台特定后端
通用缓冲区
av_mallocz()自动清零结构体初始化
av_malloc_array()溢出检查动态数组
av_fast_realloc()指数增长
原地复用
循环缓冲
av_fast_malloc()不缩小,仅增长高频帧缓冲

对齐策略

  • 32 B:AVX/SSE 向量指令
  • 64 B:缓存行友好(绝大多数 CPU)

3、平台后端实现

#if HAVE_POSIX_MEMALIGN
    posix_memalign(&ptr, ALIGN, size);
#elif defined(_WIN32)
    _aligned_malloc(size, ALIGN);
#elif defined(HAVE_MEMALIGN)
    memalign(ALIGN, size);
#else
    malloc(size);   // 回退,SIMD 性能下降

编译期自动选择最高效路径,无需用户干预

4、快速重新分配策略

// av_fast_realloc 增长公式
new_size = FFMAX(size, cur_size + cur_size / 16 + 32);
  • 原地扩展realloc() 成功时无拷贝
  • 指数+线性:平衡 内存浪费 vs 重分配频率
  • 实测:4K60 循环缓冲 重分配次数 ↓ 85 %

5、字符串与二进制辅助

函数说明
av_strdup()malloc + strcpy 一体
av_strndup()带长度限制的安全复制
av_memdup()二进制块克隆
av_memcpy_backptr()重叠区域优化(16/24/32 bit 对齐)

6、引用计数系统(AVBuffer)

6.1、结构定义

struct AVBuffer {
    uint8_t          *data;          // 数据指针
    buffer_size_t     size;          // 大小
    atomic_uint       refcount;      // 原子计数
    void (*free)(void *opaque, uint8_t *data); // 自定义释放
    void             *opaque;        // 用户私有数据
    int               flags;         // 只读/可写等
};

6.2、生命周期示意

av_buffer_create() → refcount=1
   ↓ av_buffer_ref()
AVBufferRef① → refcount=2
   ↓ av_buffer_unref()
AVBufferRef② → refcount=1
   ↓ av_buffer_unref()
refcount=0 → 自动调用 free() → 内存回收

线程安全refcount 使用 atomic_uint

7、与核心数据结构集成

7.1、AVPacket 零拷贝链

AVPacket pkt;
pkt.buf = av_buffer_ref(src_buf); // 共享同一块数据
av_packet_unref(&pkt);            // 仅减少引用,无 free

7.2、AVFrame 硬件帧扩展

AVBufferRef *hw_device_ctx = av_hwdevice_ctx_alloc(CUDA);
av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_CUDA, NULL, NULL, 0);
avcodec_alloc_context3(codec);
codec_ctx->hw_device_ctx = hw_device_ctx;

GPU 帧终身不落地 CPU,带宽 ↓ 60 %

8、安全机制

机制作用触发条件
最大分配上限
av_max_alloc()
防止 DoS 耗尽内存> 全局阈值(默认 2 GB)
溢出保护
av_size_mult()
数组大小溢出检测av_malloc_array() 内部调用
内存污染
CONFIG_MEMORY_POISONING
检测 use-after-free填充 0x2A 模式
av_freep()置空指针防悬挂立即 ptr = NULL

9、性能优化要点

  1. SIMD 对齐:自动 32/64 B → 向量指令 3× 加速
  2. 指数增长:减少 85 % 重新分配
  3. 引用计数:4K60 场景 零拷贝 内存带宽 ↓ 40 %
  4. 平台后端:Windows _aligned_malloc vs POSIX posix_memalign 自动选择
  5. 原子操作:多线程并发 无锁 增加引用

10、一行代码对比

// 传统 malloc → 未对齐,可能触发 SIGBUS on ARM
uint8_t *buf = malloc(size);

// FFmpeg 方式 → 对齐、溢出保护、平台最优
uint8_t *buf = av_malloc(size);

收益:同一段像素处理循环 ↑ 2.8× FPS

11、源码导航速记

libavutil/mem.c           ← 所有分配函数入口
libavutil/buffer.c        ← AVBuffer 引用计数实现
libavutil/frame.c         ← AVFrame 与 buffer 集成
libavutil/pixdesc.c       ← 像素格式对齐要求

阅读顺序:mem.c → buffer.c → frame.c 掌握 分配→共享→回收 闭环

12、面试金句

  • “FFmpeg 内存对齐 32/64 B,自动启用 SIMD,像素处理性能 ↑ 3×”
  • “av_buffer_ref/unref 实现零拷贝,4K60 场景带宽 ↓ 40 %”
  • “av_malloc_array 内部使用 av_size_mult 防止整数溢出攻击”
  • “av_fast_realloc 指数增长策略,循环缓冲重分配次数 ↓ 85 %”
  • “平台后端编译期自动选择:Linux posix_memalign、Windows _aligned_malloc”

学习和提升音视频开发技术,推荐你加入我们的知识星球:【关键帧的音视频开发圈】

【音视频】内存管理系统

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论