1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * default memory allocator for libavutil 3cabdff1aSopenharmony_ci * Copyright (c) 2002 Fabrice Bellard 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * default memory allocator for libavutil 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#define _XOPEN_SOURCE 600 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "config.h" 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ci#include <limits.h> 32cabdff1aSopenharmony_ci#include <stdint.h> 33cabdff1aSopenharmony_ci#include <stdlib.h> 34cabdff1aSopenharmony_ci#include <stdatomic.h> 35cabdff1aSopenharmony_ci#include <string.h> 36cabdff1aSopenharmony_ci#if HAVE_MALLOC_H 37cabdff1aSopenharmony_ci#include <malloc.h> 38cabdff1aSopenharmony_ci#endif 39cabdff1aSopenharmony_ci 40cabdff1aSopenharmony_ci#include "attributes.h" 41cabdff1aSopenharmony_ci#include "avassert.h" 42cabdff1aSopenharmony_ci#include "dynarray.h" 43cabdff1aSopenharmony_ci#include "error.h" 44cabdff1aSopenharmony_ci#include "internal.h" 45cabdff1aSopenharmony_ci#include "intreadwrite.h" 46cabdff1aSopenharmony_ci#include "macros.h" 47cabdff1aSopenharmony_ci#include "mem.h" 48cabdff1aSopenharmony_ci 49cabdff1aSopenharmony_ci#ifdef MALLOC_PREFIX 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_ci#define malloc AV_JOIN(MALLOC_PREFIX, malloc) 52cabdff1aSopenharmony_ci#define memalign AV_JOIN(MALLOC_PREFIX, memalign) 53cabdff1aSopenharmony_ci#define posix_memalign AV_JOIN(MALLOC_PREFIX, posix_memalign) 54cabdff1aSopenharmony_ci#define realloc AV_JOIN(MALLOC_PREFIX, realloc) 55cabdff1aSopenharmony_ci#define free AV_JOIN(MALLOC_PREFIX, free) 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_civoid *malloc(size_t size); 58cabdff1aSopenharmony_civoid *memalign(size_t align, size_t size); 59cabdff1aSopenharmony_ciint posix_memalign(void **ptr, size_t align, size_t size); 60cabdff1aSopenharmony_civoid *realloc(void *ptr, size_t size); 61cabdff1aSopenharmony_civoid free(void *ptr); 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_ci#endif /* MALLOC_PREFIX */ 64cabdff1aSopenharmony_ci 65cabdff1aSopenharmony_ci#define ALIGN (HAVE_AVX512 ? 64 : (HAVE_AVX ? 32 : 16)) 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci/* NOTE: if you want to override these functions with your own 68cabdff1aSopenharmony_ci * implementations (not recommended) you have to link libav* as 69cabdff1aSopenharmony_ci * dynamic libraries and remove -Wl,-Bsymbolic from the linker flags. 70cabdff1aSopenharmony_ci * Note that this will cost performance. */ 71cabdff1aSopenharmony_ci 72cabdff1aSopenharmony_cistatic atomic_size_t max_alloc_size = ATOMIC_VAR_INIT(INT_MAX); 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_civoid av_max_alloc(size_t max){ 75cabdff1aSopenharmony_ci atomic_store_explicit(&max_alloc_size, max, memory_order_relaxed); 76cabdff1aSopenharmony_ci} 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_cistatic int size_mult(size_t a, size_t b, size_t *r) 79cabdff1aSopenharmony_ci{ 80cabdff1aSopenharmony_ci size_t t; 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_ci#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_mul_overflow) 83cabdff1aSopenharmony_ci if (__builtin_mul_overflow(a, b, &t)) 84cabdff1aSopenharmony_ci return AVERROR(EINVAL); 85cabdff1aSopenharmony_ci#else 86cabdff1aSopenharmony_ci t = a * b; 87cabdff1aSopenharmony_ci /* Hack inspired from glibc: don't try the division if nelem and elsize 88cabdff1aSopenharmony_ci * are both less than sqrt(SIZE_MAX). */ 89cabdff1aSopenharmony_ci if ((a | b) >= ((size_t)1 << (sizeof(size_t) * 4)) && a && t / a != b) 90cabdff1aSopenharmony_ci return AVERROR(EINVAL); 91cabdff1aSopenharmony_ci#endif 92cabdff1aSopenharmony_ci *r = t; 93cabdff1aSopenharmony_ci return 0; 94cabdff1aSopenharmony_ci} 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_civoid *av_malloc(size_t size) 97cabdff1aSopenharmony_ci{ 98cabdff1aSopenharmony_ci void *ptr = NULL; 99cabdff1aSopenharmony_ci 100cabdff1aSopenharmony_ci if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed)) 101cabdff1aSopenharmony_ci return NULL; 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_ci#if HAVE_POSIX_MEMALIGN 104cabdff1aSopenharmony_ci if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation 105cabdff1aSopenharmony_ci if (posix_memalign(&ptr, ALIGN, size)) 106cabdff1aSopenharmony_ci ptr = NULL; 107cabdff1aSopenharmony_ci#elif HAVE_ALIGNED_MALLOC 108cabdff1aSopenharmony_ci ptr = _aligned_malloc(size, ALIGN); 109cabdff1aSopenharmony_ci#elif HAVE_MEMALIGN 110cabdff1aSopenharmony_ci#ifndef __DJGPP__ 111cabdff1aSopenharmony_ci ptr = memalign(ALIGN, size); 112cabdff1aSopenharmony_ci#else 113cabdff1aSopenharmony_ci ptr = memalign(size, ALIGN); 114cabdff1aSopenharmony_ci#endif 115cabdff1aSopenharmony_ci /* Why 64? 116cabdff1aSopenharmony_ci * Indeed, we should align it: 117cabdff1aSopenharmony_ci * on 4 for 386 118cabdff1aSopenharmony_ci * on 16 for 486 119cabdff1aSopenharmony_ci * on 32 for 586, PPro - K6-III 120cabdff1aSopenharmony_ci * on 64 for K7 (maybe for P3 too). 121cabdff1aSopenharmony_ci * Because L1 and L2 caches are aligned on those values. 122cabdff1aSopenharmony_ci * But I don't want to code such logic here! 123cabdff1aSopenharmony_ci */ 124cabdff1aSopenharmony_ci /* Why 32? 125cabdff1aSopenharmony_ci * For AVX ASM. SSE / NEON needs only 16. 126cabdff1aSopenharmony_ci * Why not larger? Because I did not see a difference in benchmarks ... 127cabdff1aSopenharmony_ci */ 128cabdff1aSopenharmony_ci /* benchmarks with P3 129cabdff1aSopenharmony_ci * memalign(64) + 1 3071, 3051, 3032 130cabdff1aSopenharmony_ci * memalign(64) + 2 3051, 3032, 3041 131cabdff1aSopenharmony_ci * memalign(64) + 4 2911, 2896, 2915 132cabdff1aSopenharmony_ci * memalign(64) + 8 2545, 2554, 2550 133cabdff1aSopenharmony_ci * memalign(64) + 16 2543, 2572, 2563 134cabdff1aSopenharmony_ci * memalign(64) + 32 2546, 2545, 2571 135cabdff1aSopenharmony_ci * memalign(64) + 64 2570, 2533, 2558 136cabdff1aSopenharmony_ci * 137cabdff1aSopenharmony_ci * BTW, malloc seems to do 8-byte alignment by default here. 138cabdff1aSopenharmony_ci */ 139cabdff1aSopenharmony_ci#else 140cabdff1aSopenharmony_ci ptr = malloc(size); 141cabdff1aSopenharmony_ci#endif 142cabdff1aSopenharmony_ci if(!ptr && !size) { 143cabdff1aSopenharmony_ci size = 1; 144cabdff1aSopenharmony_ci ptr= av_malloc(1); 145cabdff1aSopenharmony_ci } 146cabdff1aSopenharmony_ci#if CONFIG_MEMORY_POISONING 147cabdff1aSopenharmony_ci if (ptr) 148cabdff1aSopenharmony_ci memset(ptr, FF_MEMORY_POISON, size); 149cabdff1aSopenharmony_ci#endif 150cabdff1aSopenharmony_ci return ptr; 151cabdff1aSopenharmony_ci} 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_civoid *av_realloc(void *ptr, size_t size) 154cabdff1aSopenharmony_ci{ 155cabdff1aSopenharmony_ci void *ret; 156cabdff1aSopenharmony_ci if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed)) 157cabdff1aSopenharmony_ci return NULL; 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_ci#if HAVE_ALIGNED_MALLOC 160cabdff1aSopenharmony_ci ret = _aligned_realloc(ptr, size + !size, ALIGN); 161cabdff1aSopenharmony_ci#else 162cabdff1aSopenharmony_ci ret = realloc(ptr, size + !size); 163cabdff1aSopenharmony_ci#endif 164cabdff1aSopenharmony_ci#if CONFIG_MEMORY_POISONING 165cabdff1aSopenharmony_ci if (ret && !ptr) 166cabdff1aSopenharmony_ci memset(ret, FF_MEMORY_POISON, size); 167cabdff1aSopenharmony_ci#endif 168cabdff1aSopenharmony_ci return ret; 169cabdff1aSopenharmony_ci} 170cabdff1aSopenharmony_ci 171cabdff1aSopenharmony_civoid *av_realloc_f(void *ptr, size_t nelem, size_t elsize) 172cabdff1aSopenharmony_ci{ 173cabdff1aSopenharmony_ci size_t size; 174cabdff1aSopenharmony_ci void *r; 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci if (size_mult(elsize, nelem, &size)) { 177cabdff1aSopenharmony_ci av_free(ptr); 178cabdff1aSopenharmony_ci return NULL; 179cabdff1aSopenharmony_ci } 180cabdff1aSopenharmony_ci r = av_realloc(ptr, size); 181cabdff1aSopenharmony_ci if (!r) 182cabdff1aSopenharmony_ci av_free(ptr); 183cabdff1aSopenharmony_ci return r; 184cabdff1aSopenharmony_ci} 185cabdff1aSopenharmony_ci 186cabdff1aSopenharmony_ciint av_reallocp(void *ptr, size_t size) 187cabdff1aSopenharmony_ci{ 188cabdff1aSopenharmony_ci void *val; 189cabdff1aSopenharmony_ci 190cabdff1aSopenharmony_ci if (!size) { 191cabdff1aSopenharmony_ci av_freep(ptr); 192cabdff1aSopenharmony_ci return 0; 193cabdff1aSopenharmony_ci } 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ci memcpy(&val, ptr, sizeof(val)); 196cabdff1aSopenharmony_ci val = av_realloc(val, size); 197cabdff1aSopenharmony_ci 198cabdff1aSopenharmony_ci if (!val) { 199cabdff1aSopenharmony_ci av_freep(ptr); 200cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 201cabdff1aSopenharmony_ci } 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_ci memcpy(ptr, &val, sizeof(val)); 204cabdff1aSopenharmony_ci return 0; 205cabdff1aSopenharmony_ci} 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_civoid *av_malloc_array(size_t nmemb, size_t size) 208cabdff1aSopenharmony_ci{ 209cabdff1aSopenharmony_ci size_t result; 210cabdff1aSopenharmony_ci if (size_mult(nmemb, size, &result) < 0) 211cabdff1aSopenharmony_ci return NULL; 212cabdff1aSopenharmony_ci return av_malloc(result); 213cabdff1aSopenharmony_ci} 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_ci#if FF_API_AV_MALLOCZ_ARRAY 216cabdff1aSopenharmony_civoid *av_mallocz_array(size_t nmemb, size_t size) 217cabdff1aSopenharmony_ci{ 218cabdff1aSopenharmony_ci size_t result; 219cabdff1aSopenharmony_ci if (size_mult(nmemb, size, &result) < 0) 220cabdff1aSopenharmony_ci return NULL; 221cabdff1aSopenharmony_ci return av_mallocz(result); 222cabdff1aSopenharmony_ci} 223cabdff1aSopenharmony_ci#endif 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_civoid *av_realloc_array(void *ptr, size_t nmemb, size_t size) 226cabdff1aSopenharmony_ci{ 227cabdff1aSopenharmony_ci size_t result; 228cabdff1aSopenharmony_ci if (size_mult(nmemb, size, &result) < 0) 229cabdff1aSopenharmony_ci return NULL; 230cabdff1aSopenharmony_ci return av_realloc(ptr, result); 231cabdff1aSopenharmony_ci} 232cabdff1aSopenharmony_ci 233cabdff1aSopenharmony_ciint av_reallocp_array(void *ptr, size_t nmemb, size_t size) 234cabdff1aSopenharmony_ci{ 235cabdff1aSopenharmony_ci void *val; 236cabdff1aSopenharmony_ci 237cabdff1aSopenharmony_ci memcpy(&val, ptr, sizeof(val)); 238cabdff1aSopenharmony_ci val = av_realloc_f(val, nmemb, size); 239cabdff1aSopenharmony_ci memcpy(ptr, &val, sizeof(val)); 240cabdff1aSopenharmony_ci if (!val && nmemb && size) 241cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 242cabdff1aSopenharmony_ci 243cabdff1aSopenharmony_ci return 0; 244cabdff1aSopenharmony_ci} 245cabdff1aSopenharmony_ci 246cabdff1aSopenharmony_civoid av_free(void *ptr) 247cabdff1aSopenharmony_ci{ 248cabdff1aSopenharmony_ci#if HAVE_ALIGNED_MALLOC 249cabdff1aSopenharmony_ci _aligned_free(ptr); 250cabdff1aSopenharmony_ci#else 251cabdff1aSopenharmony_ci free(ptr); 252cabdff1aSopenharmony_ci#endif 253cabdff1aSopenharmony_ci} 254cabdff1aSopenharmony_ci 255cabdff1aSopenharmony_civoid av_freep(void *arg) 256cabdff1aSopenharmony_ci{ 257cabdff1aSopenharmony_ci void *val; 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_ci memcpy(&val, arg, sizeof(val)); 260cabdff1aSopenharmony_ci memcpy(arg, &(void *){ NULL }, sizeof(val)); 261cabdff1aSopenharmony_ci av_free(val); 262cabdff1aSopenharmony_ci} 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_civoid *av_mallocz(size_t size) 265cabdff1aSopenharmony_ci{ 266cabdff1aSopenharmony_ci void *ptr = av_malloc(size); 267cabdff1aSopenharmony_ci if (ptr) 268cabdff1aSopenharmony_ci memset(ptr, 0, size); 269cabdff1aSopenharmony_ci return ptr; 270cabdff1aSopenharmony_ci} 271cabdff1aSopenharmony_ci 272cabdff1aSopenharmony_civoid *av_calloc(size_t nmemb, size_t size) 273cabdff1aSopenharmony_ci{ 274cabdff1aSopenharmony_ci size_t result; 275cabdff1aSopenharmony_ci if (size_mult(nmemb, size, &result) < 0) 276cabdff1aSopenharmony_ci return NULL; 277cabdff1aSopenharmony_ci return av_mallocz(result); 278cabdff1aSopenharmony_ci} 279cabdff1aSopenharmony_ci 280cabdff1aSopenharmony_cichar *av_strdup(const char *s) 281cabdff1aSopenharmony_ci{ 282cabdff1aSopenharmony_ci char *ptr = NULL; 283cabdff1aSopenharmony_ci if (s) { 284cabdff1aSopenharmony_ci size_t len = strlen(s) + 1; 285cabdff1aSopenharmony_ci ptr = av_realloc(NULL, len); 286cabdff1aSopenharmony_ci if (ptr) 287cabdff1aSopenharmony_ci memcpy(ptr, s, len); 288cabdff1aSopenharmony_ci } 289cabdff1aSopenharmony_ci return ptr; 290cabdff1aSopenharmony_ci} 291cabdff1aSopenharmony_ci 292cabdff1aSopenharmony_cichar *av_strndup(const char *s, size_t len) 293cabdff1aSopenharmony_ci{ 294cabdff1aSopenharmony_ci char *ret = NULL, *end; 295cabdff1aSopenharmony_ci 296cabdff1aSopenharmony_ci if (!s) 297cabdff1aSopenharmony_ci return NULL; 298cabdff1aSopenharmony_ci 299cabdff1aSopenharmony_ci end = memchr(s, 0, len); 300cabdff1aSopenharmony_ci if (end) 301cabdff1aSopenharmony_ci len = end - s; 302cabdff1aSopenharmony_ci 303cabdff1aSopenharmony_ci ret = av_realloc(NULL, len + 1); 304cabdff1aSopenharmony_ci if (!ret) 305cabdff1aSopenharmony_ci return NULL; 306cabdff1aSopenharmony_ci 307cabdff1aSopenharmony_ci memcpy(ret, s, len); 308cabdff1aSopenharmony_ci ret[len] = 0; 309cabdff1aSopenharmony_ci return ret; 310cabdff1aSopenharmony_ci} 311cabdff1aSopenharmony_ci 312cabdff1aSopenharmony_civoid *av_memdup(const void *p, size_t size) 313cabdff1aSopenharmony_ci{ 314cabdff1aSopenharmony_ci void *ptr = NULL; 315cabdff1aSopenharmony_ci if (p) { 316cabdff1aSopenharmony_ci ptr = av_malloc(size); 317cabdff1aSopenharmony_ci if (ptr) 318cabdff1aSopenharmony_ci memcpy(ptr, p, size); 319cabdff1aSopenharmony_ci } 320cabdff1aSopenharmony_ci return ptr; 321cabdff1aSopenharmony_ci} 322cabdff1aSopenharmony_ci 323cabdff1aSopenharmony_ciint av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem) 324cabdff1aSopenharmony_ci{ 325cabdff1aSopenharmony_ci void **tab; 326cabdff1aSopenharmony_ci memcpy(&tab, tab_ptr, sizeof(tab)); 327cabdff1aSopenharmony_ci 328cabdff1aSopenharmony_ci FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, { 329cabdff1aSopenharmony_ci tab[*nb_ptr] = elem; 330cabdff1aSopenharmony_ci memcpy(tab_ptr, &tab, sizeof(tab)); 331cabdff1aSopenharmony_ci }, { 332cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 333cabdff1aSopenharmony_ci }); 334cabdff1aSopenharmony_ci return 0; 335cabdff1aSopenharmony_ci} 336cabdff1aSopenharmony_ci 337cabdff1aSopenharmony_civoid av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem) 338cabdff1aSopenharmony_ci{ 339cabdff1aSopenharmony_ci void **tab; 340cabdff1aSopenharmony_ci memcpy(&tab, tab_ptr, sizeof(tab)); 341cabdff1aSopenharmony_ci 342cabdff1aSopenharmony_ci FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, { 343cabdff1aSopenharmony_ci tab[*nb_ptr] = elem; 344cabdff1aSopenharmony_ci memcpy(tab_ptr, &tab, sizeof(tab)); 345cabdff1aSopenharmony_ci }, { 346cabdff1aSopenharmony_ci *nb_ptr = 0; 347cabdff1aSopenharmony_ci av_freep(tab_ptr); 348cabdff1aSopenharmony_ci }); 349cabdff1aSopenharmony_ci} 350cabdff1aSopenharmony_ci 351cabdff1aSopenharmony_civoid *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, 352cabdff1aSopenharmony_ci const uint8_t *elem_data) 353cabdff1aSopenharmony_ci{ 354cabdff1aSopenharmony_ci uint8_t *tab_elem_data = NULL; 355cabdff1aSopenharmony_ci 356cabdff1aSopenharmony_ci FF_DYNARRAY_ADD(INT_MAX, elem_size, *tab_ptr, *nb_ptr, { 357cabdff1aSopenharmony_ci tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size; 358cabdff1aSopenharmony_ci if (elem_data) 359cabdff1aSopenharmony_ci memcpy(tab_elem_data, elem_data, elem_size); 360cabdff1aSopenharmony_ci else if (CONFIG_MEMORY_POISONING) 361cabdff1aSopenharmony_ci memset(tab_elem_data, FF_MEMORY_POISON, elem_size); 362cabdff1aSopenharmony_ci }, { 363cabdff1aSopenharmony_ci av_freep(tab_ptr); 364cabdff1aSopenharmony_ci *nb_ptr = 0; 365cabdff1aSopenharmony_ci }); 366cabdff1aSopenharmony_ci return tab_elem_data; 367cabdff1aSopenharmony_ci} 368cabdff1aSopenharmony_ci 369cabdff1aSopenharmony_cistatic void fill16(uint8_t *dst, int len) 370cabdff1aSopenharmony_ci{ 371cabdff1aSopenharmony_ci uint32_t v = AV_RN16(dst - 2); 372cabdff1aSopenharmony_ci 373cabdff1aSopenharmony_ci v |= v << 16; 374cabdff1aSopenharmony_ci 375cabdff1aSopenharmony_ci while (len >= 4) { 376cabdff1aSopenharmony_ci AV_WN32(dst, v); 377cabdff1aSopenharmony_ci dst += 4; 378cabdff1aSopenharmony_ci len -= 4; 379cabdff1aSopenharmony_ci } 380cabdff1aSopenharmony_ci 381cabdff1aSopenharmony_ci while (len--) { 382cabdff1aSopenharmony_ci *dst = dst[-2]; 383cabdff1aSopenharmony_ci dst++; 384cabdff1aSopenharmony_ci } 385cabdff1aSopenharmony_ci} 386cabdff1aSopenharmony_ci 387cabdff1aSopenharmony_cistatic void fill24(uint8_t *dst, int len) 388cabdff1aSopenharmony_ci{ 389cabdff1aSopenharmony_ci#if HAVE_BIGENDIAN 390cabdff1aSopenharmony_ci uint32_t v = AV_RB24(dst - 3); 391cabdff1aSopenharmony_ci uint32_t a = v << 8 | v >> 16; 392cabdff1aSopenharmony_ci uint32_t b = v << 16 | v >> 8; 393cabdff1aSopenharmony_ci uint32_t c = v << 24 | v; 394cabdff1aSopenharmony_ci#else 395cabdff1aSopenharmony_ci uint32_t v = AV_RL24(dst - 3); 396cabdff1aSopenharmony_ci uint32_t a = v | v << 24; 397cabdff1aSopenharmony_ci uint32_t b = v >> 8 | v << 16; 398cabdff1aSopenharmony_ci uint32_t c = v >> 16 | v << 8; 399cabdff1aSopenharmony_ci#endif 400cabdff1aSopenharmony_ci 401cabdff1aSopenharmony_ci while (len >= 12) { 402cabdff1aSopenharmony_ci AV_WN32(dst, a); 403cabdff1aSopenharmony_ci AV_WN32(dst + 4, b); 404cabdff1aSopenharmony_ci AV_WN32(dst + 8, c); 405cabdff1aSopenharmony_ci dst += 12; 406cabdff1aSopenharmony_ci len -= 12; 407cabdff1aSopenharmony_ci } 408cabdff1aSopenharmony_ci 409cabdff1aSopenharmony_ci if (len >= 4) { 410cabdff1aSopenharmony_ci AV_WN32(dst, a); 411cabdff1aSopenharmony_ci dst += 4; 412cabdff1aSopenharmony_ci len -= 4; 413cabdff1aSopenharmony_ci } 414cabdff1aSopenharmony_ci 415cabdff1aSopenharmony_ci if (len >= 4) { 416cabdff1aSopenharmony_ci AV_WN32(dst, b); 417cabdff1aSopenharmony_ci dst += 4; 418cabdff1aSopenharmony_ci len -= 4; 419cabdff1aSopenharmony_ci } 420cabdff1aSopenharmony_ci 421cabdff1aSopenharmony_ci while (len--) { 422cabdff1aSopenharmony_ci *dst = dst[-3]; 423cabdff1aSopenharmony_ci dst++; 424cabdff1aSopenharmony_ci } 425cabdff1aSopenharmony_ci} 426cabdff1aSopenharmony_ci 427cabdff1aSopenharmony_cistatic void fill32(uint8_t *dst, int len) 428cabdff1aSopenharmony_ci{ 429cabdff1aSopenharmony_ci uint32_t v = AV_RN32(dst - 4); 430cabdff1aSopenharmony_ci 431cabdff1aSopenharmony_ci#if HAVE_FAST_64BIT 432cabdff1aSopenharmony_ci uint64_t v2= v + ((uint64_t)v<<32); 433cabdff1aSopenharmony_ci while (len >= 32) { 434cabdff1aSopenharmony_ci AV_WN64(dst , v2); 435cabdff1aSopenharmony_ci AV_WN64(dst+ 8, v2); 436cabdff1aSopenharmony_ci AV_WN64(dst+16, v2); 437cabdff1aSopenharmony_ci AV_WN64(dst+24, v2); 438cabdff1aSopenharmony_ci dst += 32; 439cabdff1aSopenharmony_ci len -= 32; 440cabdff1aSopenharmony_ci } 441cabdff1aSopenharmony_ci#endif 442cabdff1aSopenharmony_ci 443cabdff1aSopenharmony_ci while (len >= 4) { 444cabdff1aSopenharmony_ci AV_WN32(dst, v); 445cabdff1aSopenharmony_ci dst += 4; 446cabdff1aSopenharmony_ci len -= 4; 447cabdff1aSopenharmony_ci } 448cabdff1aSopenharmony_ci 449cabdff1aSopenharmony_ci while (len--) { 450cabdff1aSopenharmony_ci *dst = dst[-4]; 451cabdff1aSopenharmony_ci dst++; 452cabdff1aSopenharmony_ci } 453cabdff1aSopenharmony_ci} 454cabdff1aSopenharmony_ci 455cabdff1aSopenharmony_civoid av_memcpy_backptr(uint8_t *dst, int back, int cnt) 456cabdff1aSopenharmony_ci{ 457cabdff1aSopenharmony_ci const uint8_t *src = &dst[-back]; 458cabdff1aSopenharmony_ci if (!back) 459cabdff1aSopenharmony_ci return; 460cabdff1aSopenharmony_ci 461cabdff1aSopenharmony_ci if (back == 1) { 462cabdff1aSopenharmony_ci memset(dst, *src, cnt); 463cabdff1aSopenharmony_ci } else if (back == 2) { 464cabdff1aSopenharmony_ci fill16(dst, cnt); 465cabdff1aSopenharmony_ci } else if (back == 3) { 466cabdff1aSopenharmony_ci fill24(dst, cnt); 467cabdff1aSopenharmony_ci } else if (back == 4) { 468cabdff1aSopenharmony_ci fill32(dst, cnt); 469cabdff1aSopenharmony_ci } else { 470cabdff1aSopenharmony_ci if (cnt >= 16) { 471cabdff1aSopenharmony_ci int blocklen = back; 472cabdff1aSopenharmony_ci while (cnt > blocklen) { 473cabdff1aSopenharmony_ci memcpy(dst, src, blocklen); 474cabdff1aSopenharmony_ci dst += blocklen; 475cabdff1aSopenharmony_ci cnt -= blocklen; 476cabdff1aSopenharmony_ci blocklen <<= 1; 477cabdff1aSopenharmony_ci } 478cabdff1aSopenharmony_ci memcpy(dst, src, cnt); 479cabdff1aSopenharmony_ci return; 480cabdff1aSopenharmony_ci } 481cabdff1aSopenharmony_ci if (cnt >= 8) { 482cabdff1aSopenharmony_ci AV_COPY32U(dst, src); 483cabdff1aSopenharmony_ci AV_COPY32U(dst + 4, src + 4); 484cabdff1aSopenharmony_ci src += 8; 485cabdff1aSopenharmony_ci dst += 8; 486cabdff1aSopenharmony_ci cnt -= 8; 487cabdff1aSopenharmony_ci } 488cabdff1aSopenharmony_ci if (cnt >= 4) { 489cabdff1aSopenharmony_ci AV_COPY32U(dst, src); 490cabdff1aSopenharmony_ci src += 4; 491cabdff1aSopenharmony_ci dst += 4; 492cabdff1aSopenharmony_ci cnt -= 4; 493cabdff1aSopenharmony_ci } 494cabdff1aSopenharmony_ci if (cnt >= 2) { 495cabdff1aSopenharmony_ci AV_COPY16U(dst, src); 496cabdff1aSopenharmony_ci src += 2; 497cabdff1aSopenharmony_ci dst += 2; 498cabdff1aSopenharmony_ci cnt -= 2; 499cabdff1aSopenharmony_ci } 500cabdff1aSopenharmony_ci if (cnt) 501cabdff1aSopenharmony_ci *dst = *src; 502cabdff1aSopenharmony_ci } 503cabdff1aSopenharmony_ci} 504cabdff1aSopenharmony_ci 505cabdff1aSopenharmony_civoid *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size) 506cabdff1aSopenharmony_ci{ 507cabdff1aSopenharmony_ci size_t max_size; 508cabdff1aSopenharmony_ci 509cabdff1aSopenharmony_ci if (min_size <= *size) 510cabdff1aSopenharmony_ci return ptr; 511cabdff1aSopenharmony_ci 512cabdff1aSopenharmony_ci max_size = atomic_load_explicit(&max_alloc_size, memory_order_relaxed); 513cabdff1aSopenharmony_ci /* *size is an unsigned, so the real maximum is <= UINT_MAX. */ 514cabdff1aSopenharmony_ci max_size = FFMIN(max_size, UINT_MAX); 515cabdff1aSopenharmony_ci 516cabdff1aSopenharmony_ci if (min_size > max_size) { 517cabdff1aSopenharmony_ci *size = 0; 518cabdff1aSopenharmony_ci return NULL; 519cabdff1aSopenharmony_ci } 520cabdff1aSopenharmony_ci 521cabdff1aSopenharmony_ci min_size = FFMIN(max_size, FFMAX(min_size + min_size / 16 + 32, min_size)); 522cabdff1aSopenharmony_ci 523cabdff1aSopenharmony_ci ptr = av_realloc(ptr, min_size); 524cabdff1aSopenharmony_ci /* we could set this to the unmodified min_size but this is safer 525cabdff1aSopenharmony_ci * if the user lost the ptr and uses NULL now 526cabdff1aSopenharmony_ci */ 527cabdff1aSopenharmony_ci if (!ptr) 528cabdff1aSopenharmony_ci min_size = 0; 529cabdff1aSopenharmony_ci 530cabdff1aSopenharmony_ci *size = min_size; 531cabdff1aSopenharmony_ci 532cabdff1aSopenharmony_ci return ptr; 533cabdff1aSopenharmony_ci} 534cabdff1aSopenharmony_ci 535cabdff1aSopenharmony_cistatic inline void fast_malloc(void *ptr, unsigned int *size, size_t min_size, int zero_realloc) 536cabdff1aSopenharmony_ci{ 537cabdff1aSopenharmony_ci size_t max_size; 538cabdff1aSopenharmony_ci void *val; 539cabdff1aSopenharmony_ci 540cabdff1aSopenharmony_ci memcpy(&val, ptr, sizeof(val)); 541cabdff1aSopenharmony_ci if (min_size <= *size) { 542cabdff1aSopenharmony_ci av_assert0(val || !min_size); 543cabdff1aSopenharmony_ci return; 544cabdff1aSopenharmony_ci } 545cabdff1aSopenharmony_ci 546cabdff1aSopenharmony_ci max_size = atomic_load_explicit(&max_alloc_size, memory_order_relaxed); 547cabdff1aSopenharmony_ci /* *size is an unsigned, so the real maximum is <= UINT_MAX. */ 548cabdff1aSopenharmony_ci max_size = FFMIN(max_size, UINT_MAX); 549cabdff1aSopenharmony_ci 550cabdff1aSopenharmony_ci if (min_size > max_size) { 551cabdff1aSopenharmony_ci av_freep(ptr); 552cabdff1aSopenharmony_ci *size = 0; 553cabdff1aSopenharmony_ci return; 554cabdff1aSopenharmony_ci } 555cabdff1aSopenharmony_ci min_size = FFMIN(max_size, FFMAX(min_size + min_size / 16 + 32, min_size)); 556cabdff1aSopenharmony_ci av_freep(ptr); 557cabdff1aSopenharmony_ci val = zero_realloc ? av_mallocz(min_size) : av_malloc(min_size); 558cabdff1aSopenharmony_ci memcpy(ptr, &val, sizeof(val)); 559cabdff1aSopenharmony_ci if (!val) 560cabdff1aSopenharmony_ci min_size = 0; 561cabdff1aSopenharmony_ci *size = min_size; 562cabdff1aSopenharmony_ci return; 563cabdff1aSopenharmony_ci} 564cabdff1aSopenharmony_ci 565cabdff1aSopenharmony_civoid av_fast_malloc(void *ptr, unsigned int *size, size_t min_size) 566cabdff1aSopenharmony_ci{ 567cabdff1aSopenharmony_ci fast_malloc(ptr, size, min_size, 0); 568cabdff1aSopenharmony_ci} 569cabdff1aSopenharmony_ci 570cabdff1aSopenharmony_civoid av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size) 571cabdff1aSopenharmony_ci{ 572cabdff1aSopenharmony_ci fast_malloc(ptr, size, min_size, 1); 573cabdff1aSopenharmony_ci} 574cabdff1aSopenharmony_ci 575cabdff1aSopenharmony_ciint av_size_mult(size_t a, size_t b, size_t *r) 576cabdff1aSopenharmony_ci{ 577cabdff1aSopenharmony_ci return size_mult(a, b, r); 578cabdff1aSopenharmony_ci} 579