1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * a very simple circular buffer FIFO implementation 3cabdff1aSopenharmony_ci * Copyright (c) 2000, 2001, 2002 Fabrice Bellard 4cabdff1aSopenharmony_ci * Copyright (c) 2006 Roman Shaposhnik 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include <stdint.h> 24cabdff1aSopenharmony_ci#include <string.h> 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include "avassert.h" 27cabdff1aSopenharmony_ci#include "error.h" 28cabdff1aSopenharmony_ci#include "fifo.h" 29cabdff1aSopenharmony_ci#include "macros.h" 30cabdff1aSopenharmony_ci#include "mem.h" 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_ci// by default the FIFO can be auto-grown to 1MB 33cabdff1aSopenharmony_ci#define AUTO_GROW_DEFAULT_BYTES (1024 * 1024) 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_cistruct AVFifo { 36cabdff1aSopenharmony_ci uint8_t *buffer; 37cabdff1aSopenharmony_ci 38cabdff1aSopenharmony_ci size_t elem_size, nb_elems; 39cabdff1aSopenharmony_ci size_t offset_r, offset_w; 40cabdff1aSopenharmony_ci // distinguishes the ambiguous situation offset_r == offset_w 41cabdff1aSopenharmony_ci int is_empty; 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_ci unsigned int flags; 44cabdff1aSopenharmony_ci size_t auto_grow_limit; 45cabdff1aSopenharmony_ci}; 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ciAVFifo *av_fifo_alloc2(size_t nb_elems, size_t elem_size, 48cabdff1aSopenharmony_ci unsigned int flags) 49cabdff1aSopenharmony_ci{ 50cabdff1aSopenharmony_ci AVFifo *f; 51cabdff1aSopenharmony_ci void *buffer = NULL; 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_ci if (!elem_size) 54cabdff1aSopenharmony_ci return NULL; 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_ci if (nb_elems) { 57cabdff1aSopenharmony_ci buffer = av_realloc_array(NULL, nb_elems, elem_size); 58cabdff1aSopenharmony_ci if (!buffer) 59cabdff1aSopenharmony_ci return NULL; 60cabdff1aSopenharmony_ci } 61cabdff1aSopenharmony_ci f = av_mallocz(sizeof(*f)); 62cabdff1aSopenharmony_ci if (!f) { 63cabdff1aSopenharmony_ci av_free(buffer); 64cabdff1aSopenharmony_ci return NULL; 65cabdff1aSopenharmony_ci } 66cabdff1aSopenharmony_ci f->buffer = buffer; 67cabdff1aSopenharmony_ci f->nb_elems = nb_elems; 68cabdff1aSopenharmony_ci f->elem_size = elem_size; 69cabdff1aSopenharmony_ci f->is_empty = 1; 70cabdff1aSopenharmony_ci 71cabdff1aSopenharmony_ci f->flags = flags; 72cabdff1aSopenharmony_ci f->auto_grow_limit = FFMAX(AUTO_GROW_DEFAULT_BYTES / elem_size, 1); 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci return f; 75cabdff1aSopenharmony_ci} 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_civoid av_fifo_auto_grow_limit(AVFifo *f, size_t max_elems) 78cabdff1aSopenharmony_ci{ 79cabdff1aSopenharmony_ci f->auto_grow_limit = max_elems; 80cabdff1aSopenharmony_ci} 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_cisize_t av_fifo_elem_size(const AVFifo *f) 83cabdff1aSopenharmony_ci{ 84cabdff1aSopenharmony_ci return f->elem_size; 85cabdff1aSopenharmony_ci} 86cabdff1aSopenharmony_ci 87cabdff1aSopenharmony_cisize_t av_fifo_can_read(const AVFifo *f) 88cabdff1aSopenharmony_ci{ 89cabdff1aSopenharmony_ci if (f->offset_w <= f->offset_r && !f->is_empty) 90cabdff1aSopenharmony_ci return f->nb_elems - f->offset_r + f->offset_w; 91cabdff1aSopenharmony_ci return f->offset_w - f->offset_r; 92cabdff1aSopenharmony_ci} 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_cisize_t av_fifo_can_write(const AVFifo *f) 95cabdff1aSopenharmony_ci{ 96cabdff1aSopenharmony_ci return f->nb_elems - av_fifo_can_read(f); 97cabdff1aSopenharmony_ci} 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ciint av_fifo_grow2(AVFifo *f, size_t inc) 100cabdff1aSopenharmony_ci{ 101cabdff1aSopenharmony_ci uint8_t *tmp; 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_ci if (inc > SIZE_MAX - f->nb_elems) 104cabdff1aSopenharmony_ci return AVERROR(EINVAL); 105cabdff1aSopenharmony_ci 106cabdff1aSopenharmony_ci tmp = av_realloc_array(f->buffer, f->nb_elems + inc, f->elem_size); 107cabdff1aSopenharmony_ci if (!tmp) 108cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 109cabdff1aSopenharmony_ci f->buffer = tmp; 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci // move the data from the beginning of the ring buffer 112cabdff1aSopenharmony_ci // to the newly allocated space 113cabdff1aSopenharmony_ci if (f->offset_w <= f->offset_r && !f->is_empty) { 114cabdff1aSopenharmony_ci const size_t copy = FFMIN(inc, f->offset_w); 115cabdff1aSopenharmony_ci memcpy(tmp + f->nb_elems * f->elem_size, tmp, copy * f->elem_size); 116cabdff1aSopenharmony_ci if (copy < f->offset_w) { 117cabdff1aSopenharmony_ci memmove(tmp, tmp + copy * f->elem_size, 118cabdff1aSopenharmony_ci (f->offset_w - copy) * f->elem_size); 119cabdff1aSopenharmony_ci f->offset_w -= copy; 120cabdff1aSopenharmony_ci } else 121cabdff1aSopenharmony_ci f->offset_w = copy == inc ? 0 : f->nb_elems + copy; 122cabdff1aSopenharmony_ci } 123cabdff1aSopenharmony_ci 124cabdff1aSopenharmony_ci f->nb_elems += inc; 125cabdff1aSopenharmony_ci 126cabdff1aSopenharmony_ci return 0; 127cabdff1aSopenharmony_ci} 128cabdff1aSopenharmony_ci 129cabdff1aSopenharmony_cistatic int fifo_check_space(AVFifo *f, size_t to_write) 130cabdff1aSopenharmony_ci{ 131cabdff1aSopenharmony_ci const size_t can_write = av_fifo_can_write(f); 132cabdff1aSopenharmony_ci const size_t need_grow = to_write > can_write ? to_write - can_write : 0; 133cabdff1aSopenharmony_ci size_t can_grow; 134cabdff1aSopenharmony_ci 135cabdff1aSopenharmony_ci if (!need_grow) 136cabdff1aSopenharmony_ci return 0; 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci can_grow = f->auto_grow_limit > f->nb_elems ? 139cabdff1aSopenharmony_ci f->auto_grow_limit - f->nb_elems : 0; 140cabdff1aSopenharmony_ci if ((f->flags & AV_FIFO_FLAG_AUTO_GROW) && need_grow <= can_grow) { 141cabdff1aSopenharmony_ci // allocate a bit more than necessary, if we can 142cabdff1aSopenharmony_ci const size_t inc = (need_grow < can_grow / 2 ) ? need_grow * 2 : can_grow; 143cabdff1aSopenharmony_ci return av_fifo_grow2(f, inc); 144cabdff1aSopenharmony_ci } 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci return AVERROR(ENOSPC); 147cabdff1aSopenharmony_ci} 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_cistatic int fifo_write_common(AVFifo *f, const uint8_t *buf, size_t *nb_elems, 150cabdff1aSopenharmony_ci AVFifoCB read_cb, void *opaque) 151cabdff1aSopenharmony_ci{ 152cabdff1aSopenharmony_ci size_t to_write = *nb_elems; 153cabdff1aSopenharmony_ci size_t offset_w; 154cabdff1aSopenharmony_ci int ret = 0; 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci ret = fifo_check_space(f, to_write); 157cabdff1aSopenharmony_ci if (ret < 0) 158cabdff1aSopenharmony_ci return ret; 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_ci offset_w = f->offset_w; 161cabdff1aSopenharmony_ci 162cabdff1aSopenharmony_ci while (to_write > 0) { 163cabdff1aSopenharmony_ci size_t len = FFMIN(f->nb_elems - offset_w, to_write); 164cabdff1aSopenharmony_ci uint8_t *wptr = f->buffer + offset_w * f->elem_size; 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_ci if (read_cb) { 167cabdff1aSopenharmony_ci ret = read_cb(opaque, wptr, &len); 168cabdff1aSopenharmony_ci if (ret < 0 || len == 0) 169cabdff1aSopenharmony_ci break; 170cabdff1aSopenharmony_ci } else { 171cabdff1aSopenharmony_ci memcpy(wptr, buf, len * f->elem_size); 172cabdff1aSopenharmony_ci buf += len * f->elem_size; 173cabdff1aSopenharmony_ci } 174cabdff1aSopenharmony_ci offset_w += len; 175cabdff1aSopenharmony_ci if (offset_w >= f->nb_elems) 176cabdff1aSopenharmony_ci offset_w = 0; 177cabdff1aSopenharmony_ci to_write -= len; 178cabdff1aSopenharmony_ci } 179cabdff1aSopenharmony_ci f->offset_w = offset_w; 180cabdff1aSopenharmony_ci 181cabdff1aSopenharmony_ci if (*nb_elems != to_write) 182cabdff1aSopenharmony_ci f->is_empty = 0; 183cabdff1aSopenharmony_ci *nb_elems -= to_write; 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_ci return ret; 186cabdff1aSopenharmony_ci} 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_ciint av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems) 189cabdff1aSopenharmony_ci{ 190cabdff1aSopenharmony_ci return fifo_write_common(f, buf, &nb_elems, NULL, NULL); 191cabdff1aSopenharmony_ci} 192cabdff1aSopenharmony_ci 193cabdff1aSopenharmony_ciint av_fifo_write_from_cb(AVFifo *f, AVFifoCB read_cb, 194cabdff1aSopenharmony_ci void *opaque, size_t *nb_elems) 195cabdff1aSopenharmony_ci{ 196cabdff1aSopenharmony_ci return fifo_write_common(f, NULL, nb_elems, read_cb, opaque); 197cabdff1aSopenharmony_ci} 198cabdff1aSopenharmony_ci 199cabdff1aSopenharmony_cistatic int fifo_peek_common(const AVFifo *f, uint8_t *buf, size_t *nb_elems, 200cabdff1aSopenharmony_ci size_t offset, AVFifoCB write_cb, void *opaque) 201cabdff1aSopenharmony_ci{ 202cabdff1aSopenharmony_ci size_t to_read = *nb_elems; 203cabdff1aSopenharmony_ci size_t offset_r = f->offset_r; 204cabdff1aSopenharmony_ci size_t can_read = av_fifo_can_read(f); 205cabdff1aSopenharmony_ci int ret = 0; 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ci if (offset > can_read || to_read > can_read - offset) { 208cabdff1aSopenharmony_ci *nb_elems = 0; 209cabdff1aSopenharmony_ci return AVERROR(EINVAL); 210cabdff1aSopenharmony_ci } 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci if (offset_r >= f->nb_elems - offset) 213cabdff1aSopenharmony_ci offset_r -= f->nb_elems - offset; 214cabdff1aSopenharmony_ci else 215cabdff1aSopenharmony_ci offset_r += offset; 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_ci while (to_read > 0) { 218cabdff1aSopenharmony_ci size_t len = FFMIN(f->nb_elems - offset_r, to_read); 219cabdff1aSopenharmony_ci uint8_t *rptr = f->buffer + offset_r * f->elem_size; 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_ci if (write_cb) { 222cabdff1aSopenharmony_ci ret = write_cb(opaque, rptr, &len); 223cabdff1aSopenharmony_ci if (ret < 0 || len == 0) 224cabdff1aSopenharmony_ci break; 225cabdff1aSopenharmony_ci } else { 226cabdff1aSopenharmony_ci memcpy(buf, rptr, len * f->elem_size); 227cabdff1aSopenharmony_ci buf += len * f->elem_size; 228cabdff1aSopenharmony_ci } 229cabdff1aSopenharmony_ci offset_r += len; 230cabdff1aSopenharmony_ci if (offset_r >= f->nb_elems) 231cabdff1aSopenharmony_ci offset_r = 0; 232cabdff1aSopenharmony_ci to_read -= len; 233cabdff1aSopenharmony_ci } 234cabdff1aSopenharmony_ci 235cabdff1aSopenharmony_ci *nb_elems -= to_read; 236cabdff1aSopenharmony_ci 237cabdff1aSopenharmony_ci return ret; 238cabdff1aSopenharmony_ci} 239cabdff1aSopenharmony_ci 240cabdff1aSopenharmony_ciint av_fifo_read(AVFifo *f, void *buf, size_t nb_elems) 241cabdff1aSopenharmony_ci{ 242cabdff1aSopenharmony_ci int ret = fifo_peek_common(f, buf, &nb_elems, 0, NULL, NULL); 243cabdff1aSopenharmony_ci av_fifo_drain2(f, nb_elems); 244cabdff1aSopenharmony_ci return ret; 245cabdff1aSopenharmony_ci} 246cabdff1aSopenharmony_ci 247cabdff1aSopenharmony_ciint av_fifo_read_to_cb(AVFifo *f, AVFifoCB write_cb, 248cabdff1aSopenharmony_ci void *opaque, size_t *nb_elems) 249cabdff1aSopenharmony_ci{ 250cabdff1aSopenharmony_ci int ret = fifo_peek_common(f, NULL, nb_elems, 0, write_cb, opaque); 251cabdff1aSopenharmony_ci av_fifo_drain2(f, *nb_elems); 252cabdff1aSopenharmony_ci return ret; 253cabdff1aSopenharmony_ci} 254cabdff1aSopenharmony_ci 255cabdff1aSopenharmony_ciint av_fifo_peek(AVFifo *f, void *buf, size_t nb_elems, size_t offset) 256cabdff1aSopenharmony_ci{ 257cabdff1aSopenharmony_ci return fifo_peek_common(f, buf, &nb_elems, offset, NULL, NULL); 258cabdff1aSopenharmony_ci} 259cabdff1aSopenharmony_ci 260cabdff1aSopenharmony_ciint av_fifo_peek_to_cb(AVFifo *f, AVFifoCB write_cb, void *opaque, 261cabdff1aSopenharmony_ci size_t *nb_elems, size_t offset) 262cabdff1aSopenharmony_ci{ 263cabdff1aSopenharmony_ci return fifo_peek_common(f, NULL, nb_elems, offset, write_cb, opaque); 264cabdff1aSopenharmony_ci} 265cabdff1aSopenharmony_ci 266cabdff1aSopenharmony_civoid av_fifo_drain2(AVFifo *f, size_t size) 267cabdff1aSopenharmony_ci{ 268cabdff1aSopenharmony_ci const size_t cur_size = av_fifo_can_read(f); 269cabdff1aSopenharmony_ci 270cabdff1aSopenharmony_ci av_assert0(cur_size >= size); 271cabdff1aSopenharmony_ci if (cur_size == size) 272cabdff1aSopenharmony_ci f->is_empty = 1; 273cabdff1aSopenharmony_ci 274cabdff1aSopenharmony_ci if (f->offset_r >= f->nb_elems - size) 275cabdff1aSopenharmony_ci f->offset_r -= f->nb_elems - size; 276cabdff1aSopenharmony_ci else 277cabdff1aSopenharmony_ci f->offset_r += size; 278cabdff1aSopenharmony_ci} 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_civoid av_fifo_reset2(AVFifo *f) 281cabdff1aSopenharmony_ci{ 282cabdff1aSopenharmony_ci f->offset_r = f->offset_w = 0; 283cabdff1aSopenharmony_ci f->is_empty = 1; 284cabdff1aSopenharmony_ci} 285cabdff1aSopenharmony_ci 286cabdff1aSopenharmony_civoid av_fifo_freep2(AVFifo **f) 287cabdff1aSopenharmony_ci{ 288cabdff1aSopenharmony_ci if (*f) { 289cabdff1aSopenharmony_ci av_freep(&(*f)->buffer); 290cabdff1aSopenharmony_ci av_freep(f); 291cabdff1aSopenharmony_ci } 292cabdff1aSopenharmony_ci} 293cabdff1aSopenharmony_ci 294cabdff1aSopenharmony_ci 295cabdff1aSopenharmony_ci#if FF_API_FIFO_OLD_API 296cabdff1aSopenharmony_ciFF_DISABLE_DEPRECATION_WARNINGS 297cabdff1aSopenharmony_ci#define OLD_FIFO_SIZE_MAX (size_t)FFMIN3(INT_MAX, UINT32_MAX, SIZE_MAX) 298cabdff1aSopenharmony_ci 299cabdff1aSopenharmony_ciAVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size) 300cabdff1aSopenharmony_ci{ 301cabdff1aSopenharmony_ci AVFifoBuffer *f; 302cabdff1aSopenharmony_ci void *buffer; 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci if (nmemb > OLD_FIFO_SIZE_MAX / size) 305cabdff1aSopenharmony_ci return NULL; 306cabdff1aSopenharmony_ci 307cabdff1aSopenharmony_ci buffer = av_realloc_array(NULL, nmemb, size); 308cabdff1aSopenharmony_ci if (!buffer) 309cabdff1aSopenharmony_ci return NULL; 310cabdff1aSopenharmony_ci f = av_mallocz(sizeof(AVFifoBuffer)); 311cabdff1aSopenharmony_ci if (!f) { 312cabdff1aSopenharmony_ci av_free(buffer); 313cabdff1aSopenharmony_ci return NULL; 314cabdff1aSopenharmony_ci } 315cabdff1aSopenharmony_ci f->buffer = buffer; 316cabdff1aSopenharmony_ci f->end = f->buffer + nmemb * size; 317cabdff1aSopenharmony_ci av_fifo_reset(f); 318cabdff1aSopenharmony_ci return f; 319cabdff1aSopenharmony_ci} 320cabdff1aSopenharmony_ci 321cabdff1aSopenharmony_ciAVFifoBuffer *av_fifo_alloc(unsigned int size) 322cabdff1aSopenharmony_ci{ 323cabdff1aSopenharmony_ci return av_fifo_alloc_array(size, 1); 324cabdff1aSopenharmony_ci} 325cabdff1aSopenharmony_ci 326cabdff1aSopenharmony_civoid av_fifo_free(AVFifoBuffer *f) 327cabdff1aSopenharmony_ci{ 328cabdff1aSopenharmony_ci if (f) { 329cabdff1aSopenharmony_ci av_freep(&f->buffer); 330cabdff1aSopenharmony_ci av_free(f); 331cabdff1aSopenharmony_ci } 332cabdff1aSopenharmony_ci} 333cabdff1aSopenharmony_ci 334cabdff1aSopenharmony_civoid av_fifo_freep(AVFifoBuffer **f) 335cabdff1aSopenharmony_ci{ 336cabdff1aSopenharmony_ci if (f) { 337cabdff1aSopenharmony_ci av_fifo_free(*f); 338cabdff1aSopenharmony_ci *f = NULL; 339cabdff1aSopenharmony_ci } 340cabdff1aSopenharmony_ci} 341cabdff1aSopenharmony_ci 342cabdff1aSopenharmony_civoid av_fifo_reset(AVFifoBuffer *f) 343cabdff1aSopenharmony_ci{ 344cabdff1aSopenharmony_ci f->wptr = f->rptr = f->buffer; 345cabdff1aSopenharmony_ci f->wndx = f->rndx = 0; 346cabdff1aSopenharmony_ci} 347cabdff1aSopenharmony_ci 348cabdff1aSopenharmony_ciint av_fifo_size(const AVFifoBuffer *f) 349cabdff1aSopenharmony_ci{ 350cabdff1aSopenharmony_ci return (uint32_t)(f->wndx - f->rndx); 351cabdff1aSopenharmony_ci} 352cabdff1aSopenharmony_ci 353cabdff1aSopenharmony_ciint av_fifo_space(const AVFifoBuffer *f) 354cabdff1aSopenharmony_ci{ 355cabdff1aSopenharmony_ci return f->end - f->buffer - av_fifo_size(f); 356cabdff1aSopenharmony_ci} 357cabdff1aSopenharmony_ci 358cabdff1aSopenharmony_ciint av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size) 359cabdff1aSopenharmony_ci{ 360cabdff1aSopenharmony_ci unsigned int old_size = f->end - f->buffer; 361cabdff1aSopenharmony_ci 362cabdff1aSopenharmony_ci if (new_size > OLD_FIFO_SIZE_MAX) 363cabdff1aSopenharmony_ci return AVERROR(EINVAL); 364cabdff1aSopenharmony_ci 365cabdff1aSopenharmony_ci if (old_size < new_size) { 366cabdff1aSopenharmony_ci size_t offset_r = f->rptr - f->buffer; 367cabdff1aSopenharmony_ci size_t offset_w = f->wptr - f->buffer; 368cabdff1aSopenharmony_ci uint8_t *tmp; 369cabdff1aSopenharmony_ci 370cabdff1aSopenharmony_ci tmp = av_realloc(f->buffer, new_size); 371cabdff1aSopenharmony_ci if (!tmp) 372cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 373cabdff1aSopenharmony_ci 374cabdff1aSopenharmony_ci // move the data from the beginning of the ring buffer 375cabdff1aSopenharmony_ci // to the newly allocated space 376cabdff1aSopenharmony_ci // the second condition distinguishes full vs empty fifo 377cabdff1aSopenharmony_ci if (offset_w <= offset_r && av_fifo_size(f)) { 378cabdff1aSopenharmony_ci const size_t copy = FFMIN(new_size - old_size, offset_w); 379cabdff1aSopenharmony_ci memcpy(tmp + old_size, tmp, copy); 380cabdff1aSopenharmony_ci if (copy < offset_w) { 381cabdff1aSopenharmony_ci memmove(tmp, tmp + copy , offset_w - copy); 382cabdff1aSopenharmony_ci offset_w -= copy; 383cabdff1aSopenharmony_ci } else 384cabdff1aSopenharmony_ci offset_w = old_size + copy; 385cabdff1aSopenharmony_ci } 386cabdff1aSopenharmony_ci 387cabdff1aSopenharmony_ci f->buffer = tmp; 388cabdff1aSopenharmony_ci f->end = f->buffer + new_size; 389cabdff1aSopenharmony_ci f->rptr = f->buffer + offset_r; 390cabdff1aSopenharmony_ci f->wptr = f->buffer + offset_w; 391cabdff1aSopenharmony_ci } 392cabdff1aSopenharmony_ci return 0; 393cabdff1aSopenharmony_ci} 394cabdff1aSopenharmony_ci 395cabdff1aSopenharmony_ciint av_fifo_grow(AVFifoBuffer *f, unsigned int size) 396cabdff1aSopenharmony_ci{ 397cabdff1aSopenharmony_ci unsigned int old_size = f->end - f->buffer; 398cabdff1aSopenharmony_ci if(size + (unsigned)av_fifo_size(f) < size) 399cabdff1aSopenharmony_ci return AVERROR(EINVAL); 400cabdff1aSopenharmony_ci 401cabdff1aSopenharmony_ci size += av_fifo_size(f); 402cabdff1aSopenharmony_ci 403cabdff1aSopenharmony_ci if (old_size < size) 404cabdff1aSopenharmony_ci return av_fifo_realloc2(f, FFMAX(size, 2*old_size)); 405cabdff1aSopenharmony_ci return 0; 406cabdff1aSopenharmony_ci} 407cabdff1aSopenharmony_ci 408cabdff1aSopenharmony_ci/* src must NOT be const as it can be a context for func that may need 409cabdff1aSopenharmony_ci * updating (like a pointer or byte counter) */ 410cabdff1aSopenharmony_ciint av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, 411cabdff1aSopenharmony_ci int (*func)(void *, void *, int)) 412cabdff1aSopenharmony_ci{ 413cabdff1aSopenharmony_ci int total = size; 414cabdff1aSopenharmony_ci uint32_t wndx= f->wndx; 415cabdff1aSopenharmony_ci uint8_t *wptr= f->wptr; 416cabdff1aSopenharmony_ci 417cabdff1aSopenharmony_ci if (size > av_fifo_space(f)) 418cabdff1aSopenharmony_ci return AVERROR(ENOSPC); 419cabdff1aSopenharmony_ci 420cabdff1aSopenharmony_ci do { 421cabdff1aSopenharmony_ci int len = FFMIN(f->end - wptr, size); 422cabdff1aSopenharmony_ci if (func) { 423cabdff1aSopenharmony_ci len = func(src, wptr, len); 424cabdff1aSopenharmony_ci if (len <= 0) 425cabdff1aSopenharmony_ci break; 426cabdff1aSopenharmony_ci } else { 427cabdff1aSopenharmony_ci memcpy(wptr, src, len); 428cabdff1aSopenharmony_ci src = (uint8_t *)src + len; 429cabdff1aSopenharmony_ci } 430cabdff1aSopenharmony_ci wptr += len; 431cabdff1aSopenharmony_ci if (wptr >= f->end) 432cabdff1aSopenharmony_ci wptr = f->buffer; 433cabdff1aSopenharmony_ci wndx += len; 434cabdff1aSopenharmony_ci size -= len; 435cabdff1aSopenharmony_ci } while (size > 0); 436cabdff1aSopenharmony_ci f->wndx= wndx; 437cabdff1aSopenharmony_ci f->wptr= wptr; 438cabdff1aSopenharmony_ci return total - size; 439cabdff1aSopenharmony_ci} 440cabdff1aSopenharmony_ci 441cabdff1aSopenharmony_ciint av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int)) 442cabdff1aSopenharmony_ci{ 443cabdff1aSopenharmony_ci uint8_t *rptr = f->rptr; 444cabdff1aSopenharmony_ci 445cabdff1aSopenharmony_ci if (offset < 0 || buf_size > av_fifo_size(f) - offset) 446cabdff1aSopenharmony_ci return AVERROR(EINVAL); 447cabdff1aSopenharmony_ci 448cabdff1aSopenharmony_ci if (offset >= f->end - rptr) 449cabdff1aSopenharmony_ci rptr += offset - (f->end - f->buffer); 450cabdff1aSopenharmony_ci else 451cabdff1aSopenharmony_ci rptr += offset; 452cabdff1aSopenharmony_ci 453cabdff1aSopenharmony_ci while (buf_size > 0) { 454cabdff1aSopenharmony_ci int len; 455cabdff1aSopenharmony_ci 456cabdff1aSopenharmony_ci if (rptr >= f->end) 457cabdff1aSopenharmony_ci rptr -= f->end - f->buffer; 458cabdff1aSopenharmony_ci 459cabdff1aSopenharmony_ci len = FFMIN(f->end - rptr, buf_size); 460cabdff1aSopenharmony_ci if (func) 461cabdff1aSopenharmony_ci func(dest, rptr, len); 462cabdff1aSopenharmony_ci else { 463cabdff1aSopenharmony_ci memcpy(dest, rptr, len); 464cabdff1aSopenharmony_ci dest = (uint8_t *)dest + len; 465cabdff1aSopenharmony_ci } 466cabdff1aSopenharmony_ci 467cabdff1aSopenharmony_ci buf_size -= len; 468cabdff1aSopenharmony_ci rptr += len; 469cabdff1aSopenharmony_ci } 470cabdff1aSopenharmony_ci 471cabdff1aSopenharmony_ci return 0; 472cabdff1aSopenharmony_ci} 473cabdff1aSopenharmony_ci 474cabdff1aSopenharmony_ciint av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, 475cabdff1aSopenharmony_ci void (*func)(void *, void *, int)) 476cabdff1aSopenharmony_ci{ 477cabdff1aSopenharmony_ci return av_fifo_generic_peek_at(f, dest, 0, buf_size, func); 478cabdff1aSopenharmony_ci} 479cabdff1aSopenharmony_ci 480cabdff1aSopenharmony_ciint av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, 481cabdff1aSopenharmony_ci void (*func)(void *, void *, int)) 482cabdff1aSopenharmony_ci{ 483cabdff1aSopenharmony_ci if (buf_size > av_fifo_size(f)) 484cabdff1aSopenharmony_ci return AVERROR(EINVAL); 485cabdff1aSopenharmony_ci 486cabdff1aSopenharmony_ci do { 487cabdff1aSopenharmony_ci int len = FFMIN(f->end - f->rptr, buf_size); 488cabdff1aSopenharmony_ci if (func) 489cabdff1aSopenharmony_ci func(dest, f->rptr, len); 490cabdff1aSopenharmony_ci else { 491cabdff1aSopenharmony_ci memcpy(dest, f->rptr, len); 492cabdff1aSopenharmony_ci dest = (uint8_t *)dest + len; 493cabdff1aSopenharmony_ci } 494cabdff1aSopenharmony_ci av_fifo_drain(f, len); 495cabdff1aSopenharmony_ci buf_size -= len; 496cabdff1aSopenharmony_ci } while (buf_size > 0); 497cabdff1aSopenharmony_ci return 0; 498cabdff1aSopenharmony_ci} 499cabdff1aSopenharmony_ci 500cabdff1aSopenharmony_ci/** Discard data from the FIFO. */ 501cabdff1aSopenharmony_civoid av_fifo_drain(AVFifoBuffer *f, int size) 502cabdff1aSopenharmony_ci{ 503cabdff1aSopenharmony_ci av_assert2(av_fifo_size(f) >= size); 504cabdff1aSopenharmony_ci f->rptr += size; 505cabdff1aSopenharmony_ci if (f->rptr >= f->end) 506cabdff1aSopenharmony_ci f->rptr -= f->end - f->buffer; 507cabdff1aSopenharmony_ci f->rndx += size; 508cabdff1aSopenharmony_ci} 509cabdff1aSopenharmony_ciFF_ENABLE_DEPRECATION_WARNINGS 510cabdff1aSopenharmony_ci#endif 511