FFmpeg
buffer.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <limits.h>
20 #include <stdio.h>
21 #include <string.h>
22 
23 #include "libavutil/buffer.h"
24 #include "libavutil/mem.h"
25 
26 static int custom_free_called;
27 static int pool_free_called;
28 static int pool_alloc2_called;
29 
30 static void custom_free(void *opaque, uint8_t *data)
31 {
33  av_free(data);
34 }
35 
36 static AVBufferRef *pool_alloc2(void *opaque, size_t size)
37 {
39  return av_buffer_alloc(size);
40 }
41 
42 static void pool_free_cb(void *opaque)
43 {
44  pool_free_called = 1;
45 }
46 
47 int main(void)
48 {
49  AVBufferRef *buf, *buf2;
50  AVBufferPool *pool;
51 
52  /* av_buffer_alloc */
53  printf("Testing av_buffer_alloc()\n");
54  buf = av_buffer_alloc(64);
55  if (buf) {
56  printf("alloc: size=%zu data=%s\n", buf->size, buf->data ? "set" : "null");
57  printf("writable: %d\n", av_buffer_is_writable(buf));
58  printf("refcount: %d\n", av_buffer_get_ref_count(buf));
59  av_buffer_unref(&buf);
60  printf("after unref: %s\n", buf == NULL ? "null" : "leaked");
61  }
62 
63  /* av_buffer_allocz */
64  printf("\nTesting av_buffer_allocz()\n");
65  buf = av_buffer_allocz(16);
66  if (buf) {
67  int zeroed = 1;
68  for (int i = 0; i < 16; i++)
69  if (buf->data[i] != 0) zeroed = 0;
70  printf("allocz: zeroed=%s\n", zeroed ? "yes" : "no");
71  av_buffer_unref(&buf);
72  }
73 
74  /* av_buffer_create with custom free */
75  printf("\nTesting av_buffer_create()\n");
76  {
77  uint8_t *data = av_malloc(32);
78  if (data) {
80  buf = av_buffer_create(data, 32, custom_free, NULL, 0);
81  if (buf) {
82  printf("create: size=%zu\n", buf->size);
83  printf("opaque: %s\n",
84  av_buffer_get_opaque(buf) == NULL ? "null" : "set");
85  av_buffer_unref(&buf);
86  printf("custom_free called: %s\n",
87  custom_free_called ? "yes" : "no");
88  } else {
89  av_free(data);
90  }
91  }
92  }
93 
94  /* av_buffer_create with READONLY flag */
95  printf("\nTesting AV_BUFFER_FLAG_READONLY\n");
96  {
97  uint8_t *data = av_malloc(16);
98  if (data) {
101  if (buf) {
102  printf("readonly writable: %d\n", av_buffer_is_writable(buf));
103  av_buffer_unref(&buf);
104  } else {
105  av_free(data);
106  }
107  }
108  }
109 
110  /* av_buffer_ref and refcounting */
111  printf("\nTesting av_buffer_ref()\n");
112  buf = av_buffer_alloc(32);
113  if (buf) {
114  buf->data[0] = 0xAB;
115  buf2 = av_buffer_ref(buf);
116  if (buf2) {
117  printf("ref: refcount=%d\n", av_buffer_get_ref_count(buf));
118  printf("shared data: %s\n",
119  buf2->data[0] == 0xAB ? "yes" : "no");
120  printf("writable after ref: %d\n", av_buffer_is_writable(buf));
121  av_buffer_unref(&buf2);
122  printf("refcount after unref: %d\n", av_buffer_get_ref_count(buf));
123  printf("writable after unref: %d\n", av_buffer_is_writable(buf));
124  }
125  av_buffer_unref(&buf);
126  }
127 
128  /* av_buffer_make_writable */
129  printf("\nTesting av_buffer_make_writable()\n");
130  buf = av_buffer_alloc(16);
131  if (buf) {
132  buf->data[0] = 0xCD;
133  buf2 = av_buffer_ref(buf);
134  if (buf2) {
135  int ret = av_buffer_make_writable(&buf2);
136  printf("make_writable ret: %d\n", ret >= 0);
137  printf("data preserved: %s\n",
138  buf2->data[0] == 0xCD ? "yes" : "no");
139  printf("now writable: %d\n", av_buffer_is_writable(buf2));
140  printf("original still valid: %s\n",
141  buf->data[0] == 0xCD ? "yes" : "no");
142  av_buffer_unref(&buf2);
143  }
144  av_buffer_unref(&buf);
145  }
146 
147  /* av_buffer_realloc */
148  printf("\nTesting av_buffer_realloc()\n");
149  buf = av_buffer_alloc(16);
150  if (buf) {
151  memset(buf->data, 0xEF, 16);
152  av_buffer_realloc(&buf, 32);
153  if (buf) {
154  printf("realloc: size=%zu\n", buf->size);
155  printf("data preserved: %s\n",
156  buf->data[0] == 0xEF ? "yes" : "no");
157  }
158  av_buffer_unref(&buf);
159  }
160  /* realloc from NULL */
161  buf = NULL;
162  av_buffer_realloc(&buf, 8);
163  printf("realloc from null: %s\n", buf ? "OK" : "FAIL");
164  av_buffer_unref(&buf);
165 
166  /* av_buffer_replace */
167  printf("\nTesting av_buffer_replace()\n");
168  buf = av_buffer_alloc(8);
169  buf2 = av_buffer_alloc(8);
170  if (buf && buf2) {
171  buf->data[0] = 0x11;
172  buf2->data[0] = 0x22;
173  av_buffer_replace(&buf, buf2);
174  printf("replace: data=0x%02x\n", buf->data[0]);
175  printf("refcount: %d\n", av_buffer_get_ref_count(buf2));
176  }
177  av_buffer_unref(&buf);
178  av_buffer_unref(&buf2);
179 
180  /* replace with NULL */
181  buf = av_buffer_alloc(8);
182  if (buf) {
183  av_buffer_replace(&buf, NULL);
184  printf("replace with null: %s\n", buf == NULL ? "OK" : "FAIL");
185  }
186 
187  /* av_buffer_pool */
188  printf("\nTesting av_buffer_pool()\n");
189  pool = av_buffer_pool_init(64, NULL);
190  if (pool) {
191  buf = av_buffer_pool_get(pool);
192  if (buf) {
193  printf("pool get: size=%zu\n", buf->size);
194  av_buffer_unref(&buf);
195  }
196  /* get again -- should reuse the released buffer */
197  buf = av_buffer_pool_get(pool);
198  if (buf) {
199  printf("pool reuse: size=%zu\n", buf->size);
200  av_buffer_unref(&buf);
201  }
202  av_buffer_pool_uninit(&pool);
203  printf("pool uninit: %s\n", pool == NULL ? "OK" : "FAIL");
204  }
205 
206  /* av_buffer_pool_init2 with custom alloc and pool_free callbacks */
207  printf("\nTesting av_buffer_pool_init2()\n");
208  pool_alloc2_called = 0;
209  pool_free_called = 0;
211  if (pool) {
212  buf = av_buffer_pool_get(pool);
213  if (buf) {
214  printf("pool2 get: size=%zu\n", buf->size);
215  printf("alloc2 called: %s\n", pool_alloc2_called ? "yes" : "no");
216  printf("pool_buffer_get_opaque: %s\n",
217  av_buffer_pool_buffer_get_opaque(buf) == NULL ? "null" : "set");
218  av_buffer_unref(&buf);
219  }
220  av_buffer_pool_uninit(&pool);
221  printf("pool_free called: %s\n", pool_free_called ? "yes" : "no");
222  }
223 
224  /* OOM paths via av_max_alloc */
225  printf("\nTesting OOM paths\n");
226  av_max_alloc(1);
227  buf = av_buffer_alloc(64);
228  printf("alloc OOM: %s\n", buf ? "FAIL" : "OK");
229  av_buffer_unref(&buf);
230  buf = av_buffer_allocz(64);
231  printf("allocz OOM: %s\n", buf ? "FAIL" : "OK");
232  av_buffer_unref(&buf);
233  pool = av_buffer_pool_init(64, NULL);
234  printf("pool init OOM: %s\n", pool ? "FAIL" : "OK");
235  av_buffer_pool_uninit(&pool);
236  av_max_alloc(INT_MAX);
237 
238  buf = av_buffer_alloc(16);
239  if (buf) {
240  av_max_alloc(1);
241  buf2 = av_buffer_ref(buf);
242  printf("ref OOM: %s\n", buf2 ? "FAIL" : "OK");
243  av_buffer_unref(&buf2);
244  printf("realloc OOM: %s\n",
245  av_buffer_realloc(&buf, 1024) < 0 ? "OK" : "FAIL");
246  av_max_alloc(INT_MAX);
247  av_buffer_unref(&buf);
248  }
249 
250  return 0;
251 }
av_buffer_pool_init
AVBufferPool * av_buffer_pool_init(size_t size, AVBufferRef *(*alloc)(size_t size))
Allocate and initialize a buffer pool.
Definition: buffer.c:283
pool_free_called
static int pool_free_called
Definition: buffer.c:27
printf
__device__ int printf(const char *,...)
AVBufferPool
The buffer pool.
Definition: buffer_internal.h:88
pool_free_cb
static void pool_free_cb(void *opaque)
Definition: buffer.c:42
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
data
const char data[16]
Definition: mxf.c:149
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
av_max_alloc
void av_max_alloc(size_t max)
Set the maximum size that may be allocated in one block.
Definition: mem.c:76
av_buffer_pool_init2
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:259
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:390
pool_alloc2_called
static int pool_alloc2_called
Definition: buffer.c:28
AV_BUFFER_FLAG_READONLY
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:114
limits.h
NULL
#define NULL
Definition: coverity.c:32
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
av_buffer_pool_uninit
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:328
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:55
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
size
int size
Definition: twinvq_data.h:10344
av_buffer_make_writable
int av_buffer_make_writable(AVBufferRef **pbuf)
Create a writable reference from a given buffer reference, avoiding data copy if possible.
Definition: buffer.c:165
buffer.h
main
int main(void)
Definition: buffer.c:47
av_buffer_get_ref_count
int av_buffer_get_ref_count(const AVBufferRef *buf)
Definition: buffer.c:160
av_buffer_pool_buffer_get_opaque
void * av_buffer_pool_buffer_get_opaque(const AVBufferRef *ref)
Query the original opaque parameter of an allocated buffer in the pool.
Definition: buffer.c:417
av_buffer_alloc
AVBufferRef * av_buffer_alloc(size_t size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:77
AVBufferRef::size
size_t size
Size of data in bytes.
Definition: buffer.h:94
av_malloc
#define av_malloc(s)
Definition: ops_asmgen.c:44
custom_free
static void custom_free(void *opaque, uint8_t *data)
Definition: buffer.c:30
av_buffer_replace
int av_buffer_replace(AVBufferRef **pdst, const AVBufferRef *src)
Ensure dst refers to the same data as src.
Definition: buffer.c:233
av_buffer_is_writable
int av_buffer_is_writable(const AVBufferRef *buf)
Definition: buffer.c:147
av_buffer_allocz
AVBufferRef * av_buffer_allocz(size_t size)
Same as av_buffer_alloc(), except the returned buffer will be initialized to zero.
Definition: buffer.c:93
ret
ret
Definition: filter_design.txt:187
av_buffer_realloc
int av_buffer_realloc(AVBufferRef **pbuf, size_t size)
Reallocate a given buffer.
Definition: buffer.c:183
av_buffer_get_opaque
void * av_buffer_get_opaque(const AVBufferRef *buf)
Definition: buffer.c:155
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
custom_free_called
static int custom_free_called
Definition: buffer.c:26
pool_alloc2
static AVBufferRef * pool_alloc2(void *opaque, size_t size)
Definition: buffer.c:36