1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * This file is part of FFmpeg.
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
8cabdff1aSopenharmony_ci *
9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12cabdff1aSopenharmony_ci * Lesser General Public License for more details.
13cabdff1aSopenharmony_ci *
14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17cabdff1aSopenharmony_ci */
18cabdff1aSopenharmony_ci
19cabdff1aSopenharmony_ci#include <stdatomic.h>
20cabdff1aSopenharmony_ci#include <stdint.h>
21cabdff1aSopenharmony_ci#include <string.h>
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci#include "avassert.h"
24cabdff1aSopenharmony_ci#include "buffer_internal.h"
25cabdff1aSopenharmony_ci#include "common.h"
26cabdff1aSopenharmony_ci#include "mem.h"
27cabdff1aSopenharmony_ci#include "thread.h"
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_cistatic AVBufferRef *buffer_create(AVBuffer *buf, uint8_t *data, size_t size,
30cabdff1aSopenharmony_ci                                  void (*free)(void *opaque, uint8_t *data),
31cabdff1aSopenharmony_ci                                  void *opaque, int flags)
32cabdff1aSopenharmony_ci{
33cabdff1aSopenharmony_ci    AVBufferRef *ref = NULL;
34cabdff1aSopenharmony_ci
35cabdff1aSopenharmony_ci    buf->data     = data;
36cabdff1aSopenharmony_ci    buf->size     = size;
37cabdff1aSopenharmony_ci    buf->free     = free ? free : av_buffer_default_free;
38cabdff1aSopenharmony_ci    buf->opaque   = opaque;
39cabdff1aSopenharmony_ci
40cabdff1aSopenharmony_ci    atomic_init(&buf->refcount, 1);
41cabdff1aSopenharmony_ci
42cabdff1aSopenharmony_ci    buf->flags = flags;
43cabdff1aSopenharmony_ci
44cabdff1aSopenharmony_ci    ref = av_mallocz(sizeof(*ref));
45cabdff1aSopenharmony_ci    if (!ref)
46cabdff1aSopenharmony_ci        return NULL;
47cabdff1aSopenharmony_ci
48cabdff1aSopenharmony_ci    ref->buffer = buf;
49cabdff1aSopenharmony_ci    ref->data   = data;
50cabdff1aSopenharmony_ci    ref->size   = size;
51cabdff1aSopenharmony_ci
52cabdff1aSopenharmony_ci    return ref;
53cabdff1aSopenharmony_ci}
54cabdff1aSopenharmony_ci
55cabdff1aSopenharmony_ciAVBufferRef *av_buffer_create(uint8_t *data, size_t size,
56cabdff1aSopenharmony_ci                              void (*free)(void *opaque, uint8_t *data),
57cabdff1aSopenharmony_ci                              void *opaque, int flags)
58cabdff1aSopenharmony_ci{
59cabdff1aSopenharmony_ci    AVBufferRef *ret;
60cabdff1aSopenharmony_ci    AVBuffer *buf = av_mallocz(sizeof(*buf));
61cabdff1aSopenharmony_ci    if (!buf)
62cabdff1aSopenharmony_ci        return NULL;
63cabdff1aSopenharmony_ci
64cabdff1aSopenharmony_ci    ret = buffer_create(buf, data, size, free, opaque, flags);
65cabdff1aSopenharmony_ci    if (!ret) {
66cabdff1aSopenharmony_ci        av_free(buf);
67cabdff1aSopenharmony_ci        return NULL;
68cabdff1aSopenharmony_ci    }
69cabdff1aSopenharmony_ci    return ret;
70cabdff1aSopenharmony_ci}
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_civoid av_buffer_default_free(void *opaque, uint8_t *data)
73cabdff1aSopenharmony_ci{
74cabdff1aSopenharmony_ci    av_free(data);
75cabdff1aSopenharmony_ci}
76cabdff1aSopenharmony_ci
77cabdff1aSopenharmony_ciAVBufferRef *av_buffer_alloc(size_t size)
78cabdff1aSopenharmony_ci{
79cabdff1aSopenharmony_ci    AVBufferRef *ret = NULL;
80cabdff1aSopenharmony_ci    uint8_t    *data = NULL;
81cabdff1aSopenharmony_ci
82cabdff1aSopenharmony_ci    data = av_malloc(size);
83cabdff1aSopenharmony_ci    if (!data)
84cabdff1aSopenharmony_ci        return NULL;
85cabdff1aSopenharmony_ci
86cabdff1aSopenharmony_ci    ret = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);
87cabdff1aSopenharmony_ci    if (!ret)
88cabdff1aSopenharmony_ci        av_freep(&data);
89cabdff1aSopenharmony_ci
90cabdff1aSopenharmony_ci    return ret;
91cabdff1aSopenharmony_ci}
92cabdff1aSopenharmony_ci
93cabdff1aSopenharmony_ciAVBufferRef *av_buffer_allocz(size_t size)
94cabdff1aSopenharmony_ci{
95cabdff1aSopenharmony_ci    AVBufferRef *ret = av_buffer_alloc(size);
96cabdff1aSopenharmony_ci    if (!ret)
97cabdff1aSopenharmony_ci        return NULL;
98cabdff1aSopenharmony_ci
99cabdff1aSopenharmony_ci    memset(ret->data, 0, size);
100cabdff1aSopenharmony_ci    return ret;
101cabdff1aSopenharmony_ci}
102cabdff1aSopenharmony_ci
103cabdff1aSopenharmony_ciAVBufferRef *av_buffer_ref(const AVBufferRef *buf)
104cabdff1aSopenharmony_ci{
105cabdff1aSopenharmony_ci    AVBufferRef *ret = av_mallocz(sizeof(*ret));
106cabdff1aSopenharmony_ci
107cabdff1aSopenharmony_ci    if (!ret)
108cabdff1aSopenharmony_ci        return NULL;
109cabdff1aSopenharmony_ci
110cabdff1aSopenharmony_ci    *ret = *buf;
111cabdff1aSopenharmony_ci
112cabdff1aSopenharmony_ci    atomic_fetch_add_explicit(&buf->buffer->refcount, 1, memory_order_relaxed);
113cabdff1aSopenharmony_ci
114cabdff1aSopenharmony_ci    return ret;
115cabdff1aSopenharmony_ci}
116cabdff1aSopenharmony_ci
117cabdff1aSopenharmony_cistatic void buffer_replace(AVBufferRef **dst, AVBufferRef **src)
118cabdff1aSopenharmony_ci{
119cabdff1aSopenharmony_ci    AVBuffer *b;
120cabdff1aSopenharmony_ci
121cabdff1aSopenharmony_ci    b = (*dst)->buffer;
122cabdff1aSopenharmony_ci
123cabdff1aSopenharmony_ci    if (src) {
124cabdff1aSopenharmony_ci        **dst = **src;
125cabdff1aSopenharmony_ci        av_freep(src);
126cabdff1aSopenharmony_ci    } else
127cabdff1aSopenharmony_ci        av_freep(dst);
128cabdff1aSopenharmony_ci
129cabdff1aSopenharmony_ci    if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) {
130cabdff1aSopenharmony_ci        /* b->free below might already free the structure containing *b,
131cabdff1aSopenharmony_ci         * so we have to read the flag now to avoid use-after-free. */
132cabdff1aSopenharmony_ci        int free_avbuffer = !(b->flags_internal & BUFFER_FLAG_NO_FREE);
133cabdff1aSopenharmony_ci        b->free(b->opaque, b->data);
134cabdff1aSopenharmony_ci        if (free_avbuffer)
135cabdff1aSopenharmony_ci            av_free(b);
136cabdff1aSopenharmony_ci    }
137cabdff1aSopenharmony_ci}
138cabdff1aSopenharmony_ci
139cabdff1aSopenharmony_civoid av_buffer_unref(AVBufferRef **buf)
140cabdff1aSopenharmony_ci{
141cabdff1aSopenharmony_ci    if (!buf || !*buf)
142cabdff1aSopenharmony_ci        return;
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_ci    buffer_replace(buf, NULL);
145cabdff1aSopenharmony_ci}
146cabdff1aSopenharmony_ci
147cabdff1aSopenharmony_ciint av_buffer_is_writable(const AVBufferRef *buf)
148cabdff1aSopenharmony_ci{
149cabdff1aSopenharmony_ci    if (buf->buffer->flags & AV_BUFFER_FLAG_READONLY)
150cabdff1aSopenharmony_ci        return 0;
151cabdff1aSopenharmony_ci
152cabdff1aSopenharmony_ci    return atomic_load(&buf->buffer->refcount) == 1;
153cabdff1aSopenharmony_ci}
154cabdff1aSopenharmony_ci
155cabdff1aSopenharmony_civoid *av_buffer_get_opaque(const AVBufferRef *buf)
156cabdff1aSopenharmony_ci{
157cabdff1aSopenharmony_ci    return buf->buffer->opaque;
158cabdff1aSopenharmony_ci}
159cabdff1aSopenharmony_ci
160cabdff1aSopenharmony_ciint av_buffer_get_ref_count(const AVBufferRef *buf)
161cabdff1aSopenharmony_ci{
162cabdff1aSopenharmony_ci    return atomic_load(&buf->buffer->refcount);
163cabdff1aSopenharmony_ci}
164cabdff1aSopenharmony_ci
165cabdff1aSopenharmony_ciint av_buffer_make_writable(AVBufferRef **pbuf)
166cabdff1aSopenharmony_ci{
167cabdff1aSopenharmony_ci    AVBufferRef *newbuf, *buf = *pbuf;
168cabdff1aSopenharmony_ci
169cabdff1aSopenharmony_ci    if (av_buffer_is_writable(buf))
170cabdff1aSopenharmony_ci        return 0;
171cabdff1aSopenharmony_ci
172cabdff1aSopenharmony_ci    newbuf = av_buffer_alloc(buf->size);
173cabdff1aSopenharmony_ci    if (!newbuf)
174cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
175cabdff1aSopenharmony_ci
176cabdff1aSopenharmony_ci    memcpy(newbuf->data, buf->data, buf->size);
177cabdff1aSopenharmony_ci
178cabdff1aSopenharmony_ci    buffer_replace(pbuf, &newbuf);
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci    return 0;
181cabdff1aSopenharmony_ci}
182cabdff1aSopenharmony_ci
183cabdff1aSopenharmony_ciint av_buffer_realloc(AVBufferRef **pbuf, size_t size)
184cabdff1aSopenharmony_ci{
185cabdff1aSopenharmony_ci    AVBufferRef *buf = *pbuf;
186cabdff1aSopenharmony_ci    uint8_t *tmp;
187cabdff1aSopenharmony_ci    int ret;
188cabdff1aSopenharmony_ci
189cabdff1aSopenharmony_ci    if (!buf) {
190cabdff1aSopenharmony_ci        /* allocate a new buffer with av_realloc(), so it will be reallocatable
191cabdff1aSopenharmony_ci         * later */
192cabdff1aSopenharmony_ci        uint8_t *data = av_realloc(NULL, size);
193cabdff1aSopenharmony_ci        if (!data)
194cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
195cabdff1aSopenharmony_ci
196cabdff1aSopenharmony_ci        buf = av_buffer_create(data, size, av_buffer_default_free, NULL, 0);
197cabdff1aSopenharmony_ci        if (!buf) {
198cabdff1aSopenharmony_ci            av_freep(&data);
199cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
200cabdff1aSopenharmony_ci        }
201cabdff1aSopenharmony_ci
202cabdff1aSopenharmony_ci        buf->buffer->flags_internal |= BUFFER_FLAG_REALLOCATABLE;
203cabdff1aSopenharmony_ci        *pbuf = buf;
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci        return 0;
206cabdff1aSopenharmony_ci    } else if (buf->size == size)
207cabdff1aSopenharmony_ci        return 0;
208cabdff1aSopenharmony_ci
209cabdff1aSopenharmony_ci    if (!(buf->buffer->flags_internal & BUFFER_FLAG_REALLOCATABLE) ||
210cabdff1aSopenharmony_ci        !av_buffer_is_writable(buf) || buf->data != buf->buffer->data) {
211cabdff1aSopenharmony_ci        /* cannot realloc, allocate a new reallocable buffer and copy data */
212cabdff1aSopenharmony_ci        AVBufferRef *new = NULL;
213cabdff1aSopenharmony_ci
214cabdff1aSopenharmony_ci        ret = av_buffer_realloc(&new, size);
215cabdff1aSopenharmony_ci        if (ret < 0)
216cabdff1aSopenharmony_ci            return ret;
217cabdff1aSopenharmony_ci
218cabdff1aSopenharmony_ci        memcpy(new->data, buf->data, FFMIN(size, buf->size));
219cabdff1aSopenharmony_ci
220cabdff1aSopenharmony_ci        buffer_replace(pbuf, &new);
221cabdff1aSopenharmony_ci        return 0;
222cabdff1aSopenharmony_ci    }
223cabdff1aSopenharmony_ci
224cabdff1aSopenharmony_ci    tmp = av_realloc(buf->buffer->data, size);
225cabdff1aSopenharmony_ci    if (!tmp)
226cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
227cabdff1aSopenharmony_ci
228cabdff1aSopenharmony_ci    buf->buffer->data = buf->data = tmp;
229cabdff1aSopenharmony_ci    buf->buffer->size = buf->size = size;
230cabdff1aSopenharmony_ci    return 0;
231cabdff1aSopenharmony_ci}
232cabdff1aSopenharmony_ci
233cabdff1aSopenharmony_ciint av_buffer_replace(AVBufferRef **pdst, const AVBufferRef *src)
234cabdff1aSopenharmony_ci{
235cabdff1aSopenharmony_ci    AVBufferRef *dst = *pdst;
236cabdff1aSopenharmony_ci    AVBufferRef *tmp;
237cabdff1aSopenharmony_ci
238cabdff1aSopenharmony_ci    if (!src) {
239cabdff1aSopenharmony_ci        av_buffer_unref(pdst);
240cabdff1aSopenharmony_ci        return 0;
241cabdff1aSopenharmony_ci    }
242cabdff1aSopenharmony_ci
243cabdff1aSopenharmony_ci    if (dst && dst->buffer == src->buffer) {
244cabdff1aSopenharmony_ci        /* make sure the data pointers match */
245cabdff1aSopenharmony_ci        dst->data = src->data;
246cabdff1aSopenharmony_ci        dst->size = src->size;
247cabdff1aSopenharmony_ci        return 0;
248cabdff1aSopenharmony_ci    }
249cabdff1aSopenharmony_ci
250cabdff1aSopenharmony_ci    tmp = av_buffer_ref(src);
251cabdff1aSopenharmony_ci    if (!tmp)
252cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
253cabdff1aSopenharmony_ci
254cabdff1aSopenharmony_ci    av_buffer_unref(pdst);
255cabdff1aSopenharmony_ci    *pdst = tmp;
256cabdff1aSopenharmony_ci    return 0;
257cabdff1aSopenharmony_ci}
258cabdff1aSopenharmony_ci
259cabdff1aSopenharmony_ciAVBufferPool *av_buffer_pool_init2(size_t size, void *opaque,
260cabdff1aSopenharmony_ci                                   AVBufferRef* (*alloc)(void *opaque, size_t size),
261cabdff1aSopenharmony_ci                                   void (*pool_free)(void *opaque))
262cabdff1aSopenharmony_ci{
263cabdff1aSopenharmony_ci    AVBufferPool *pool = av_mallocz(sizeof(*pool));
264cabdff1aSopenharmony_ci    if (!pool)
265cabdff1aSopenharmony_ci        return NULL;
266cabdff1aSopenharmony_ci
267cabdff1aSopenharmony_ci    ff_mutex_init(&pool->mutex, NULL);
268cabdff1aSopenharmony_ci
269cabdff1aSopenharmony_ci    pool->size      = size;
270cabdff1aSopenharmony_ci    pool->opaque    = opaque;
271cabdff1aSopenharmony_ci    pool->alloc2    = alloc;
272cabdff1aSopenharmony_ci    pool->alloc     = av_buffer_alloc; // fallback
273cabdff1aSopenharmony_ci    pool->pool_free = pool_free;
274cabdff1aSopenharmony_ci
275cabdff1aSopenharmony_ci    atomic_init(&pool->refcount, 1);
276cabdff1aSopenharmony_ci
277cabdff1aSopenharmony_ci    return pool;
278cabdff1aSopenharmony_ci}
279cabdff1aSopenharmony_ci
280cabdff1aSopenharmony_ciAVBufferPool *av_buffer_pool_init(size_t size, AVBufferRef* (*alloc)(size_t size))
281cabdff1aSopenharmony_ci{
282cabdff1aSopenharmony_ci    AVBufferPool *pool = av_mallocz(sizeof(*pool));
283cabdff1aSopenharmony_ci    if (!pool)
284cabdff1aSopenharmony_ci        return NULL;
285cabdff1aSopenharmony_ci
286cabdff1aSopenharmony_ci    ff_mutex_init(&pool->mutex, NULL);
287cabdff1aSopenharmony_ci
288cabdff1aSopenharmony_ci    pool->size     = size;
289cabdff1aSopenharmony_ci    pool->alloc    = alloc ? alloc : av_buffer_alloc;
290cabdff1aSopenharmony_ci
291cabdff1aSopenharmony_ci    atomic_init(&pool->refcount, 1);
292cabdff1aSopenharmony_ci
293cabdff1aSopenharmony_ci    return pool;
294cabdff1aSopenharmony_ci}
295cabdff1aSopenharmony_ci
296cabdff1aSopenharmony_cistatic void buffer_pool_flush(AVBufferPool *pool)
297cabdff1aSopenharmony_ci{
298cabdff1aSopenharmony_ci    while (pool->pool) {
299cabdff1aSopenharmony_ci        BufferPoolEntry *buf = pool->pool;
300cabdff1aSopenharmony_ci        pool->pool = buf->next;
301cabdff1aSopenharmony_ci
302cabdff1aSopenharmony_ci        buf->free(buf->opaque, buf->data);
303cabdff1aSopenharmony_ci        av_freep(&buf);
304cabdff1aSopenharmony_ci    }
305cabdff1aSopenharmony_ci}
306cabdff1aSopenharmony_ci
307cabdff1aSopenharmony_ci/*
308cabdff1aSopenharmony_ci * This function gets called when the pool has been uninited and
309cabdff1aSopenharmony_ci * all the buffers returned to it.
310cabdff1aSopenharmony_ci */
311cabdff1aSopenharmony_cistatic void buffer_pool_free(AVBufferPool *pool)
312cabdff1aSopenharmony_ci{
313cabdff1aSopenharmony_ci    buffer_pool_flush(pool);
314cabdff1aSopenharmony_ci    ff_mutex_destroy(&pool->mutex);
315cabdff1aSopenharmony_ci
316cabdff1aSopenharmony_ci    if (pool->pool_free)
317cabdff1aSopenharmony_ci        pool->pool_free(pool->opaque);
318cabdff1aSopenharmony_ci
319cabdff1aSopenharmony_ci    av_freep(&pool);
320cabdff1aSopenharmony_ci}
321cabdff1aSopenharmony_ci
322cabdff1aSopenharmony_civoid av_buffer_pool_uninit(AVBufferPool **ppool)
323cabdff1aSopenharmony_ci{
324cabdff1aSopenharmony_ci    AVBufferPool *pool;
325cabdff1aSopenharmony_ci
326cabdff1aSopenharmony_ci    if (!ppool || !*ppool)
327cabdff1aSopenharmony_ci        return;
328cabdff1aSopenharmony_ci    pool   = *ppool;
329cabdff1aSopenharmony_ci    *ppool = NULL;
330cabdff1aSopenharmony_ci
331cabdff1aSopenharmony_ci    ff_mutex_lock(&pool->mutex);
332cabdff1aSopenharmony_ci    buffer_pool_flush(pool);
333cabdff1aSopenharmony_ci    ff_mutex_unlock(&pool->mutex);
334cabdff1aSopenharmony_ci
335cabdff1aSopenharmony_ci    if (atomic_fetch_sub_explicit(&pool->refcount, 1, memory_order_acq_rel) == 1)
336cabdff1aSopenharmony_ci        buffer_pool_free(pool);
337cabdff1aSopenharmony_ci}
338cabdff1aSopenharmony_ci
339cabdff1aSopenharmony_cistatic void pool_release_buffer(void *opaque, uint8_t *data)
340cabdff1aSopenharmony_ci{
341cabdff1aSopenharmony_ci    BufferPoolEntry *buf = opaque;
342cabdff1aSopenharmony_ci    AVBufferPool *pool = buf->pool;
343cabdff1aSopenharmony_ci
344cabdff1aSopenharmony_ci    if(CONFIG_MEMORY_POISONING)
345cabdff1aSopenharmony_ci        memset(buf->data, FF_MEMORY_POISON, pool->size);
346cabdff1aSopenharmony_ci
347cabdff1aSopenharmony_ci    ff_mutex_lock(&pool->mutex);
348cabdff1aSopenharmony_ci    buf->next = pool->pool;
349cabdff1aSopenharmony_ci    pool->pool = buf;
350cabdff1aSopenharmony_ci    ff_mutex_unlock(&pool->mutex);
351cabdff1aSopenharmony_ci
352cabdff1aSopenharmony_ci    if (atomic_fetch_sub_explicit(&pool->refcount, 1, memory_order_acq_rel) == 1)
353cabdff1aSopenharmony_ci        buffer_pool_free(pool);
354cabdff1aSopenharmony_ci}
355cabdff1aSopenharmony_ci
356cabdff1aSopenharmony_ci/* allocate a new buffer and override its free() callback so that
357cabdff1aSopenharmony_ci * it is returned to the pool on free */
358cabdff1aSopenharmony_cistatic AVBufferRef *pool_alloc_buffer(AVBufferPool *pool)
359cabdff1aSopenharmony_ci{
360cabdff1aSopenharmony_ci    BufferPoolEntry *buf;
361cabdff1aSopenharmony_ci    AVBufferRef     *ret;
362cabdff1aSopenharmony_ci
363cabdff1aSopenharmony_ci    av_assert0(pool->alloc || pool->alloc2);
364cabdff1aSopenharmony_ci
365cabdff1aSopenharmony_ci    ret = pool->alloc2 ? pool->alloc2(pool->opaque, pool->size) :
366cabdff1aSopenharmony_ci                         pool->alloc(pool->size);
367cabdff1aSopenharmony_ci    if (!ret)
368cabdff1aSopenharmony_ci        return NULL;
369cabdff1aSopenharmony_ci
370cabdff1aSopenharmony_ci    buf = av_mallocz(sizeof(*buf));
371cabdff1aSopenharmony_ci    if (!buf) {
372cabdff1aSopenharmony_ci        av_buffer_unref(&ret);
373cabdff1aSopenharmony_ci        return NULL;
374cabdff1aSopenharmony_ci    }
375cabdff1aSopenharmony_ci
376cabdff1aSopenharmony_ci    buf->data   = ret->buffer->data;
377cabdff1aSopenharmony_ci    buf->opaque = ret->buffer->opaque;
378cabdff1aSopenharmony_ci    buf->free   = ret->buffer->free;
379cabdff1aSopenharmony_ci    buf->pool   = pool;
380cabdff1aSopenharmony_ci
381cabdff1aSopenharmony_ci    ret->buffer->opaque = buf;
382cabdff1aSopenharmony_ci    ret->buffer->free   = pool_release_buffer;
383cabdff1aSopenharmony_ci
384cabdff1aSopenharmony_ci    return ret;
385cabdff1aSopenharmony_ci}
386cabdff1aSopenharmony_ci
387cabdff1aSopenharmony_ciAVBufferRef *av_buffer_pool_get(AVBufferPool *pool)
388cabdff1aSopenharmony_ci{
389cabdff1aSopenharmony_ci    AVBufferRef *ret;
390cabdff1aSopenharmony_ci    BufferPoolEntry *buf;
391cabdff1aSopenharmony_ci
392cabdff1aSopenharmony_ci    ff_mutex_lock(&pool->mutex);
393cabdff1aSopenharmony_ci    buf = pool->pool;
394cabdff1aSopenharmony_ci    if (buf) {
395cabdff1aSopenharmony_ci        memset(&buf->buffer, 0, sizeof(buf->buffer));
396cabdff1aSopenharmony_ci        ret = buffer_create(&buf->buffer, buf->data, pool->size,
397cabdff1aSopenharmony_ci                            pool_release_buffer, buf, 0);
398cabdff1aSopenharmony_ci        if (ret) {
399cabdff1aSopenharmony_ci            pool->pool = buf->next;
400cabdff1aSopenharmony_ci            buf->next = NULL;
401cabdff1aSopenharmony_ci            buf->buffer.flags_internal |= BUFFER_FLAG_NO_FREE;
402cabdff1aSopenharmony_ci        }
403cabdff1aSopenharmony_ci    } else {
404cabdff1aSopenharmony_ci        ret = pool_alloc_buffer(pool);
405cabdff1aSopenharmony_ci    }
406cabdff1aSopenharmony_ci    ff_mutex_unlock(&pool->mutex);
407cabdff1aSopenharmony_ci
408cabdff1aSopenharmony_ci    if (ret)
409cabdff1aSopenharmony_ci        atomic_fetch_add_explicit(&pool->refcount, 1, memory_order_relaxed);
410cabdff1aSopenharmony_ci
411cabdff1aSopenharmony_ci    return ret;
412cabdff1aSopenharmony_ci}
413cabdff1aSopenharmony_ci
414cabdff1aSopenharmony_civoid *av_buffer_pool_buffer_get_opaque(const AVBufferRef *ref)
415cabdff1aSopenharmony_ci{
416cabdff1aSopenharmony_ci    BufferPoolEntry *buf = ref->buffer->opaque;
417cabdff1aSopenharmony_ci    av_assert0(buf);
418cabdff1aSopenharmony_ci    return buf->opaque;
419cabdff1aSopenharmony_ci}
420