我是靠谱客的博主 勤奋猫咪,这篇文章主要介绍ffmpeg的AVBuffer和AVBufferRef,现在分享给大家,希望可以做个参考。

AVBufferRef是对AVBuffer的一层封装,主要用来保护AVBuffer,以及管理AVBuffer的引用次数,从而达到自动释放的目的。
下面是两个结构体详细信息:
AVBufferRef 的内容:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 的内容:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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中是不改变的,仅仅传递):

复制代码
1
2
3
4
5
6
7
8
9
//创建 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用的

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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()获取引用

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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()解引用

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(86)

评论列表共有 0 条评论

立即
投稿
返回
顶部