ffmpeg av_buffer_unref的逻辑实现; av_freep 和 av_freep函数的区别 ...

打印 上一主题 下一主题

主题 1682|帖子 1682|积分 5046

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

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),支持异构硬件资源管理。

三、代码逻辑简化示例

  1. [/code] [code]void av_buffer_unref(AVBufferRef **ref) {
  2.     if (!*ref)
  3.         return;
  4.     AVBuffer *buf = (*ref)->buffer;
  5.     // 原子操作减少引用计数
  6.     int refcount = atomic_fetch_sub_explicit(&buf->refcount, 1, memory_order_acq_rel);
  7.     if (refcount == 1) { // 引用归零
  8.         if (buf->free)   // 调用释放回调
  9.             buf->free(buf->opaque, buf->data);
  10.         if (buf->pool)   // 内存池回收逻辑
  11.             buffer_pool_release_buffer(buf->pool, buf);
  12.         av_free(buf);    // 释放AVBuffer结构体
  13.     }
  14.     av_freep(ref);       // 释放AVBufferRef并置空指针
  15. }
复制代码

四、关联机制


  • 与 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。
    • 作用‌:仅开释指针指向的内存块,‌不修改指针本身的值‌,开释后指针仍指向原地址(即悬垂指针)

                
  1. uint8_t *data = av_malloc(100);
  2. av_free(data); // 释放内存,但 data 仍指向已释放的地址
复制代码


  • av_freep(void ** p)

    • 参数范例‌:担当 void ** 范例的指针地址12。
    • 作用‌:

      • 开释指针指向的内存块;
      • 将原指针置为 NULL‌,避免悬垂指针问题12。
      1. [/code] [code]uint8_t *data = av_malloc(100);
      2. av_freep(&data); // 释放内存,并将 data 置为 NULL
      复制代码




免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

美丽的神话

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表