概述
AVBufferRef是对AVBuffer的一层封装,主要用来保护AVBuffer,以及管理AVBuffer的引用次数,从而达到自动释放的目的。
下面是两个结构体详细信息:
AVBufferRef 的内容:
typedef struct AVBufferRef {
AVBuffer *buffer;
/**
* The data buffer. It is considered writable if and only if
* this is the only reference to the buffer, in which case
* av_buffer_is_writable() returns 1.
*/
uint8_t *data;
/**
* Size of data in bytes.
*/
size_t size;
} AVBufferRef;
可以看到在AVBufferRef结构体中有一个AVBuffer,这个就是它管理的buf了,它在外部还有data和size,这两个变量跟buffer内部的data和size是一样的,是用来在AVBufferRef中修改buffer的内容。
AVBuffer 的内容:
struct AVBuffer {
uint8_t *data; /**< data described by this buffer */
size_t size; /**< size of data in bytes */
/**
* number of existing AVBufferRef instances referring to this buffer
*/
//这个是引用计数
atomic_uint refcount;
/**
* a callback for freeing the data
*/
void (*free)(void *opaque, uint8_t *data);
/**
* an opaque pointer, to be used by the freeing callback
*/
void *opaque;
/**
* A combination of AV_BUFFER_FLAG_*
*/
int flags;
/**
* A combination of BUFFER_FLAG_*
*/
int flags_internal;
};
核心函数有三个(正常情况下,视频数据在buf中是不改变的,仅仅传递):
//创建
AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
void (*free)(void *opaque, uint8_t *data),
void *opaque, int flags);
//引用,引用计数增加1
AVBufferRef *av_buffer_ref(const AVBufferRef *buf);
//解引用,应用技术计数减1,如果到1的时候就释放内容,跟智能指针一样
void av_buffer_unref(AVBufferRef **buf);
首先看av_buffer_create()里面有一个回调函数free,用来释放data用的
AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
void (*free)(void *opaque, uint8_t *data),
void *opaque, int flags)
{
AVBufferRef *ret;
//创建buf
AVBuffer *buf = av_mallocz(sizeof(*buf));
if (!buf)
return NULL;
ret = buffer_create(buf, data, size, free, opaque, flags);
if (!ret) {
av_free(buf);
return NULL;
}
return ret;
}
static AVBufferRef *buffer_create(AVBuffer *buf, uint8_t *data, size_t size,
void (*free)(void *opaque, uint8_t *data),
void *opaque, int flags)
{
AVBufferRef *ref = NULL;
//简单赋值
buf->data = data;
buf->size = size;
buf->free = free ? free : av_buffer_default_free;
buf->opaque = opaque;
//引用计数加1
atomic_init(&buf->refcount, 1);
buf->flags = flags;
//创建ref,返回
ref = av_mallocz(sizeof(*ref));
if (!ref)
return NULL;
//这里可以看出ref的data和size是和buf中的一样的
ref->buffer = buf;
ref->data = data;
ref->size = size;
return ref;
}
av_buffer_ref()获取引用
AVBufferRef *av_buffer_ref(const AVBufferRef *buf)
{
AVBufferRef *ret = av_mallocz(sizeof(*ret));
if (!ret)
return NULL;
//简单赋值
*ret = *buf;
//核心这里,引用计数加1
atomic_fetch_add_explicit(&buf->buffer->refcount, 1, memory_order_relaxed);
return ret;
}
av_buffer_unref()解引用
void av_buffer_unref(AVBufferRef **buf)
{
if (!buf || !*buf)
return;
buffer_replace(buf, NULL);
}
static void buffer_replace(AVBufferRef **dst, AVBufferRef **src)
{
AVBuffer *b;
b = (*dst)->buffer;
if (src) {
**dst = **src;
av_freep(src);
} else
av_freep(dst);//释放结构体
//引用减去1,并判断是否为1,如果为1就释放data中的数据
if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) {
/* b->free below might already free the structure containing *b,
* so we have to read the flag now to avoid use-after-free. */
int free_avbuffer = !(b->flags_internal & BUFFER_FLAG_NO_FREE);
b->free(b->opaque, b->data);
if (free_avbuffer)
av_free(b);
}
}
看完代码,发现很简单,也没什么可以讲的,就是malloc和free,最关键的是recount原子变量的增加和减少,从而达到控制释放data的能力。
最后
以上就是勤奋猫咪为你收集整理的ffmpeg的AVBuffer和AVBufferRef的全部内容,希望文章能够帮你解决ffmpeg的AVBuffer和AVBufferRef所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复