这个系列文章我们来介绍一位海外工程师如何探索安卓音视频基础技术,对于想要开始学习音视频技术的朋友,这些文章是份不错的入门资料,本篇介绍内存管理系统。
——来自公众号“关键帧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、性能优化要点
- SIMD 对齐:自动 32/64 B → 向量指令 3× 加速
- 指数增长:减少 85 % 重新分配
- 引用计数:4K60 场景 零拷贝 内存带宽 ↓ 40 %
- 平台后端:Windows
_aligned_mallocvs POSIXposix_memalign自动选择 - 原子操作:多线程并发 无锁 增加引用
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 举报,一经查实,本站将立刻删除。