一、AvBuffer
AVBuffer是用于引用计数数据缓冲区的API。
这个API有两个核心对象 - AVBuffer和AVBufferRef。 AVBuffer表示数据缓冲区本身; 它是不透明的,并不意味着直接由调用者访问,而只能通过AVBufferRef。 然而,呼叫者可以例如 比较两个AVBuffer指针,以检查两个不同的引用是否描述相同的数据缓冲区。 AVBufferRef表示对AVBuffer的单一引用,它是可以由调用者直接操纵的对象。
提供了两个功能,用于创建一个具有单个引用的新AVBuffer - av_buffer_alloc()来分配新的缓冲区,并使用av_buffer_create()将现有的数组包装在AVBuffer中。 从现有参考中,可以使用av_buffer_ref()创建其他引用。 使用av_buffer_unref()来释放引用(一旦所有引用被释放,这将自动释放数据)。
整个API中的惯例和FFmpeg的其余部分使得如果只存在一个引用(并且没有被标记为只读),缓冲区被认为是可写的。 提供了av_buffer_is_writable()函数来检查是否为true,并且必要时,av_buffer_make_writable()将自动创建一个新的可写缓冲区。 当然没有什么可以阻止调用代码违反这个约定,但是只有当所有现有的引用都在其控制之下时才是安全的。
注意:引用和引用缓冲区是线程安全的,因此可以同时从多个线程完成,而不需要额外的锁定。
对相同缓冲区的两个不同引用可以指向缓冲区的不同部分(即它们的AVBufferRef.data将不相等)。
一)、数据结构
对数据缓冲区的引用。
此结构体的大小不是公共ABI的一部分,并不意味着直接分配。
struct | AVBufferRef{ AVBuffer * buffer; uint8_t * data; //数据缓冲区。当且仅当这是缓冲区的引用时才被认为是可写的,在这种情况下,av_buffer_is_writable()返回1。 int size; //数据大小(以字节计) } |
二)、宏
#define AV_BUFFER_FLAG_READONLY(1 << 0)
始终将缓冲区视为只读,即使只有一个引用。
三)、函数
AVBufferRef * | av_buffer_alloc (int size) |
返回:一个给定大小的AVBufferRef或当内存不足时为空
AVBufferRef * | av_buffer_allocz (int size) |
AVBufferRef * | av_buffer_create (uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags) |
如果此函数成功,则数据由AVBuffer拥有。 调用者只能通过返回的AVBufferRef和从其派生的引用来访问数据。 如果此功能失败,数据将保持不变。
参数:data:数据数组
size:数据大小(以字节为单位)
free:一个释放缓冲区数据的回调
opaque:要加工或传递给自由的参数
flags:组合AV_BUFFER_FLAG_ *
返回:AVBufferRef参考成功的数据,失败时为NULL。
void | av_buffer_default_free (void *opaque, uint8_t *data) |
这个函数是传递给av_buffer_create(),不直接调用。
AVBufferRef * | av_buffer_ref (AVBufferRef *buf) |
返回:一个新的AVBufferRef引用与buf相同的AVBuffer或失败时为NULL。
void | av_buffer_unref (AVBufferRef **buf) |
参数:buf:引用被释放。 指针在返回时设置为NULL。
int | av_buffer_is_writable (const AVBufferRef *buf) |
void * | av_buffer_get_opaque (const AVBufferRef *buf) |
int | av_buffer_get_ref_count (const AVBufferRef *buf) |
int | av_buffer_make_writable (AVBufferRef **buf) |
参数:buf:缓冲区引用使可写。 在成功时,buf或者保持不变,或者是未引用的,并且一个新的可写AVBufferRef写在它的位置。 失败时,buf保持不变。
返回:0成功,否定AVERROR失败。
int | av_buffer_realloc (AVBufferRef **buf, int size) |
参数:buf:一个缓冲区引用重新分配。 在成功的情况下,buf将被未引用,并且具有所需大小的新参考将被写入其中。 失败buf将保持不变。 * buf可能为NULL,则分配一个新的缓冲区。
size:需要新的缓冲区大小。
返回:0成功,否定AVERROR失败。
注意:如果最初通过av_buffer_realloc(NULL)分配缓冲区,并且只有一个引用(即传递给此函数的引用),则av_realloc()才会实际使用av_realloc()重新分配缓冲区。 在所有其他情况下,会分配一个新的缓冲区并复制数据。
二、AVBufferPool
AVBufferPool是AVBuffers无锁线程安全池的API。
经常分配和释放大型缓冲区可能很慢。 如果调用者需要一组相同大小的缓冲区(最明显的用例是原始视频或音频帧的缓冲区),则AVBufferPool旨在解决此问题。
开始时,用户必须调用av_buffer_pool_init()来创建缓冲池。 然后每当需要缓冲区时,调用av_buffer_pool_get()来获取对新缓冲区的引用,类似于av_buffer_alloc()。 这个新引用与所有方面的工作方式与由av_buffer_alloc()创建的引用相同。 但是,当对此缓冲区的最后一次引用未被引用时,它将返回到池而不是被释放,并将被重新用于后续的av_buffer_pool_get()调用。
当调用者完成池并且不再需要分配任何新的缓冲区时,必须调用av_buffer_pool_uninit()来将池标记为可以使用。 一旦释放所有缓冲区,它将自动释放。
只要使用默认的alloc回调,或用户提供的线程安全,就可以使用该API分配和释放缓冲区是线程安全的。
一)、函数
AVBufferPool * | av_buffer_pool_init (int size, AVBufferRef *(*alloc)(int size)) |
参数:size:该池中每个缓冲区的大小
alloc:当池为空时,将用于分配新缓冲区的函数。 可能为NULL,那么默认的分配器将被使用(av_buffer_alloc())。
返回:新创建的缓冲池成功,NULL出错。
AVBufferPool * | av_buffer_pool_init2 (int size, void *opaque, AVBufferRef *(*alloc)(void *opaque, int size), void(*pool_free)(void *opaque)) |
参数:size:该池中每个缓冲区的大小
opaque:分配器使用的任意用户数据
alloc: 当池为空时,将用于分配新缓冲区的函数。
pool_free:一个在池释放之前立即被调用的函数。即 之后,av_buffer_pool_uninit()由调用者调用,所有的帧都返回到池中并被释放。 用于取消初始化用户不透明数据。
返回:新创建的缓冲池成功,NULL出错。
void | av_buffer_pool_uninit (AVBufferPool **pool) |
只有释放与池相关联的所有分配的缓冲区,才能释放它。 因此,一些分配的缓冲区仍在使用中,可以安全地调用此函数。
参数:pool:指向要释放的池的指针。 它将被设置为NULL。
AVBufferRef * | av_buffer_pool_get (AVBufferPool *pool) |
该函数可以从多个线程同时调用。
返回:引用新的缓冲区成功,NULL出错。