av_buffer_unref 是 FFmpeg 中用于管理引用计数和内存释放的核心函数,其内部实现机制如下:
一、核心流程
-
引用计数递减
函数首先对AVBufferRef
的buffer->refcount
进行原子递减操作(通过atomic_fetch_add_explicit
等机制保证线程安全)。 -
引用计数检查
- 若递减后
refcount > 0
:仅释放当前AVBufferRef
结构体,保留底层AVBuffer
和数据内存。 - 若递减后
refcount == 0
:触发内存释放流程(包括AVBuffer
自身及其数据)。
- 若递减后
-
内存释放逻辑
- 调用
buffer->free
回调函数(如默认的av_buffer_default_free
或用户自定义的释放函数),释放buffer->data
指向的数据内存。 - 若
AVBuffer
属于内存池(AVBufferPool
),则通过buffer_pool_release_buffer
将内存块返回池中以供复用。
- 调用
-
资源清理
- 置空
AVBufferRef->buffer
指针,避免悬垂引用。 - 释放
AVBufferRef
结构体本身的内存。
- 置空
二、关键设计细节
-
线程安全
引用计数的增减操作通过原子指令实现,确保多线程环境下数据一致性26。 -
内存池优化
若AVBuffer
来自内存池,释放时不会立即归还给系统,而是通过链表管理复用,减少频繁内存分配开销。 -
回调扩展性
buffer->free
允许注册自定义释放逻辑(如 GPU 内存释放需调用特定驱动 API),支持异构硬件资源管理。
三、代码逻辑简化示例
void av_buffer_unref(AVBufferRef **ref) {if (!*ref)return;AVBuffer *buf = (*ref)->buffer;// 原子操作减少引用计数int refcount = atomic_fetch_sub_explicit(&buf->refcount, 1, memory_order_acq_rel);if (refcount == 1) { // 引用归零if (buf->free) // 调用释放回调buf->free(buf->opaque, buf->data);if (buf->pool) // 内存池回收逻辑buffer_pool_release_buffer(buf->pool, buf);av_free(buf); // 释放AVBuffer结构体}av_freep(ref); // 释放AVBufferRef并置空指针
}
四、关联机制
-
与
av_buffer_ref
的关系
av_buffer_ref
增加引用计数并复制AVBufferRef
,而av_buffer_unref
负责递减计数和释放,两者共同维护引用生命周期。 -
与
AVPacket/AVFrame
的交互
当AVPacket
或AVFrame
调用av_packet_unref
或av_frame_unref
时,内部最终通过av_buffer_unref
释放底层数据内存。
通过上述机制,av_buffer_unref
实现了高效且安全的内存管理,成为 FFmpeg 多模块资源共享和生命周期控制的基础。
av_freep 和 av_freep函数的区别
-
av_free(void * p)
- 参数类型:接受
void *
类型的指针13。 - 作用:仅释放指针指向的内存块,不修改指针本身的值,释放后指针仍指向原地址(即悬垂指针)
- 参数类型:接受
uint8_t *data = av_malloc(100);
av_free(data); // 释放内存,但 data 仍指向已释放的地址
-
av_freep(
void ** p
)- 参数类型:接受
void **
类型的指针地址12。 - 作用:
- 释放指针指向的内存块;
- 将原指针置为
NULL
,避免悬垂指针问题12。
uint8_t *data = av_malloc(100); av_freep(&data); // 释放内存,并将 data 置为 NULL
- 参数类型:接受