ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ffmpeg buffer管理

2022-05-23 18:36:13  阅读:177  来源: 互联网

标签:ffmpeg 管理 buffer opaque free BufferPoolEntry pool AVBuffer



除了内存管理之外,数据的前后级流转也涉及到buffer管理. 个人觉得ffmpeg里面的buffer管理实现极为巧妙,也很值得借鉴.

概述

image

重要数据结构

AVBufferPool

在libavutil/buffer_internal.h中定义,为内部数据结构,不能在应用程序中直接引用.

image

    • mutex 用于多线程资源保护
    • pool  指向BufferPoolEntry链表的头,AVBufferPool可以管理所有的BufferPoolEntry.
    •           在初始化AVBufferPool时pool是空,只有在av_buffer_pool_get()时才会判断
    •           和创建.如图av_buffer_pool_get函数流程:

image

    • refcount AVBufferPool的引用次数,初始化之后为1,av_buffer_pool_get()会+1,
    •                 pool_release_buffer()  av_buffer_pool_uninit()会-1. 为0时会buffer_pool_free
    •                释放pool
    • size  不是指缓存池的个数,而是指AVBuffer.size
    • opaque 用户自定义需要传递给回调函数参数,对应pool_free回调函数的opaque参数
    • allo alloc2 提供两种内存分配方式,1: 注册回调函数  2: av_buffer_alloc
    • pool_free  注册回调函数,av_buffer_pool_init2()注册,用于指定一种更负责的内存分配器。

BufferPoolEntry

在libavutil/buffer_internal.h中定义,为内部数据结构,不能在应用程序中直接引用.

从数据结构中开看到BufferPoolEntry就是一个链表,AVBufferPool中存储了BufferPoolEntry根节点.

image

    • data opaqu free 以上的BufferPoolEntry的opaque、data、free都是指向了AVBuffer最
    •                              开始的opaque、data、free,然后AVBuffer自己的opaque和free则指
    •                              向了BufferPoolEntry和pool_release_buffer
    • pool  当前BufferPoolEntry指向创建他的AVBufferPool. 这样每个BufferPoolEntry都可
    •                             以找到创建和管理他的AVBufferPool
    • next  
    • buffer 实际存储buffer相关信息,新版本才增加的

AVBufferRef

在libavutil/buffer.h中定义,是对外的,可以在应用程序中直接引用.

image

    • *buffer
    • *data size AVBufferRef.data和size与AVBuffer.data和size是一致的

       有两种方式创建AVBufferRef,一种是通过av_buffer_alloc,只要指定大小即可;另一种是

通过av_buffer_create,这种主要是用于已经有了数据的情况,同时它也支持自定义释放此

数据内存的方法

AVBuffer

在libavutil/buffer_internal.h中定义,为内部数据结构,不能在应用程序中直接引用.

AVBuffer对外不公开,必须要通过AVBufferRef来间接使用AVBuffer.

image

    • *data 实际存放数据的地址
    • size   实际存放数据的大小
    • refcount 记录当前buffer的引用计数
    • free  回调函数用于释放数据,当引用计数变为0时会被调用来释放内存。
    • opaque 用户自定义需要传递给回调函数参数,对应了回调函数的opaque参数
    • flags 标识一些属性 , AV_BUFFER_FLAG_READONLY
    •                         表示只读,引用计数为1时表示只有一个对象引用它,此时是可写的,否则就是只读的
    • flags_internal 标识一些buffer属性, 有BUFFER_FLAG_REALLOCATABLE, BUFFER_FLAG_NO_FREE两个。
    •                         BUFFER_FLAG_REALLOCATABLE标识是否可以重分配
    •                         BUFFER_FLAG_NO_FREE标识被其他结构体引用,不能释放.需要手动释放内存.
    •          新版本中
    •                          1.  BUFFER_FLAG_REALLOCATABLE移动到了flags_internal  
    •                          2. BUFFER_FLAG_READONLY改为了AV_BUFFER_FLAG_READONLY
    •                           3. 新增加了BUFFER_FLAG_NO_FREE

       AVBuffer在创建的时候引用计数为1,当调用av_buffer_ref()对其进行操作时,引用计数+1,当

av_buffer_unref对其操作时则引用计数-1(当-1后引用计数为0时,av_buffer_unref将自动释放分配的数据缓存

定义在libavutil/buffer.c中操作接口

Buffer管理

             以上的BufferPoolEntry的opaque、data、free都是指向了AVBuffer最开始的opaque、data、free,

然后AVBuffer自己的opaque和free则指向了BufferPoolEntry和pool_release_buffer为何这样设计呢,

因为AVBuffer最终要进行释放的话,那还是得调用它自己最本来的free函数,但是此时由于要放到

缓存池管理,因此在free时不能真正把AVBuffer释放了,因此用BufferPoolEntry来保存AVBuffer真正

的释放内存的函数,然后再用缓存池释放函数pool_release_buffer来代替free函数,这样,当用户

释放的时候,AVBuffer的free函数已经指向了pool_release_buffer函数,因此可以在pool_release_buffer

里把AVBuffer返回给缓存池,等到缓存池自己想要被释放的时候,这个时候缓存池就从BufferPoolEntry

把之前保存的真正释放AVBuffer的函数取出来,进行调用;不得不说,这个设计虽然非常绕,其实很巧妙.

image

如图:

  • 365行,调用pool.alloc分配一个新的AVBufferRef
  • 370行,  分配一个BufferPoolEntry
  • 376-379行,将AVBufferRef的data, opaque,  free赋值给BufferPoolEntry
  • 381-382行,重新赋值AVBuffer.opaque和AVBuffer.free, pool_release_buffer来代替free函数,
  •                         用户释放的时并不会真正释放内存而是通过pool_release_buffer将AVBuffer返回
  •                       给了缓存池.当用于真正需要释放内存时,再调用BufferPoolEntry.free实现真正意义释放.
  • 以上机制对用户不可见,巧妙将内存释放和缓存池回收buffer结合在一起了.


有一个写的很好的播客,不过对应的ffmpeg版本要旧一点, 在ffmpeg 5.0版本中有些结构体和实现方式有变化.

https://blog.csdn.net/huweijian5/article/details/105549692/

2022-05-16

标签:ffmpeg,管理,buffer,opaque,free,BufferPoolEntry,pool,AVBuffer
来源: https://www.cnblogs.com/545235abc/p/16285869.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有