马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
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),支持异构硬件资源管理。
三、代码逻辑简化示例
- [/code] [code]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。
- [/code] [code]uint8_t *data = av_malloc(100);
- av_freep(&data); // 释放内存,并将 data 置为 NULL
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |