annotate ffmpeg/libavutil/mem.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * default memory allocator for libavutil
yading@11 3 * Copyright (c) 2002 Fabrice Bellard
yading@11 4 *
yading@11 5 * This file is part of FFmpeg.
yading@11 6 *
yading@11 7 * FFmpeg is free software; you can redistribute it and/or
yading@11 8 * modify it under the terms of the GNU Lesser General Public
yading@11 9 * License as published by the Free Software Foundation; either
yading@11 10 * version 2.1 of the License, or (at your option) any later version.
yading@11 11 *
yading@11 12 * FFmpeg is distributed in the hope that it will be useful,
yading@11 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 15 * Lesser General Public License for more details.
yading@11 16 *
yading@11 17 * You should have received a copy of the GNU Lesser General Public
yading@11 18 * License along with FFmpeg; if not, write to the Free Software
yading@11 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 20 */
yading@11 21
yading@11 22 /**
yading@11 23 * @file
yading@11 24 * default memory allocator for libavutil
yading@11 25 */
yading@11 26
yading@11 27 #define _XOPEN_SOURCE 600
yading@11 28
yading@11 29 #include "config.h"
yading@11 30
yading@11 31 #include <limits.h>
yading@11 32 #include <stdint.h>
yading@11 33 #include <stdlib.h>
yading@11 34 #include <string.h>
yading@11 35 #if HAVE_MALLOC_H
yading@11 36 #include <malloc.h>
yading@11 37 #endif
yading@11 38
yading@11 39 #include "avassert.h"
yading@11 40 #include "avutil.h"
yading@11 41 #include "intreadwrite.h"
yading@11 42 #include "mem.h"
yading@11 43
yading@11 44 #ifdef MALLOC_PREFIX
yading@11 45
yading@11 46 #define malloc AV_JOIN(MALLOC_PREFIX, malloc)
yading@11 47 #define memalign AV_JOIN(MALLOC_PREFIX, memalign)
yading@11 48 #define posix_memalign AV_JOIN(MALLOC_PREFIX, posix_memalign)
yading@11 49 #define realloc AV_JOIN(MALLOC_PREFIX, realloc)
yading@11 50 #define free AV_JOIN(MALLOC_PREFIX, free)
yading@11 51
yading@11 52 void *malloc(size_t size);
yading@11 53 void *memalign(size_t align, size_t size);
yading@11 54 int posix_memalign(void **ptr, size_t align, size_t size);
yading@11 55 void *realloc(void *ptr, size_t size);
yading@11 56 void free(void *ptr);
yading@11 57
yading@11 58 #endif /* MALLOC_PREFIX */
yading@11 59
yading@11 60 #define ALIGN (HAVE_AVX ? 32 : 16)
yading@11 61
yading@11 62 /* NOTE: if you want to override these functions with your own
yading@11 63 * implementations (not recommended) you have to link libav* as
yading@11 64 * dynamic libraries and remove -Wl,-Bsymbolic from the linker flags.
yading@11 65 * Note that this will cost performance. */
yading@11 66
yading@11 67 static size_t max_alloc_size= INT_MAX;
yading@11 68
yading@11 69 void av_max_alloc(size_t max){
yading@11 70 max_alloc_size = max;
yading@11 71 }
yading@11 72
yading@11 73 void *av_malloc(size_t size)
yading@11 74 {
yading@11 75 void *ptr = NULL;
yading@11 76 #if CONFIG_MEMALIGN_HACK
yading@11 77 long diff;
yading@11 78 #endif
yading@11 79
yading@11 80 /* let's disallow possible ambiguous cases */
yading@11 81 if (size > (max_alloc_size - 32))
yading@11 82 return NULL;
yading@11 83
yading@11 84 #if CONFIG_MEMALIGN_HACK
yading@11 85 ptr = malloc(size + ALIGN);
yading@11 86 if (!ptr)
yading@11 87 return ptr;
yading@11 88 diff = ((~(long)ptr)&(ALIGN - 1)) + 1;
yading@11 89 ptr = (char *)ptr + diff;
yading@11 90 ((char *)ptr)[-1] = diff;
yading@11 91 #elif HAVE_POSIX_MEMALIGN
yading@11 92 if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
yading@11 93 if (posix_memalign(&ptr, ALIGN, size))
yading@11 94 ptr = NULL;
yading@11 95 #elif HAVE_ALIGNED_MALLOC
yading@11 96 ptr = _aligned_malloc(size, ALIGN);
yading@11 97 #elif HAVE_MEMALIGN
yading@11 98 #ifndef __DJGPP__
yading@11 99 ptr = memalign(ALIGN, size);
yading@11 100 #else
yading@11 101 ptr = memalign(size, ALIGN);
yading@11 102 #endif
yading@11 103 /* Why 64?
yading@11 104 * Indeed, we should align it:
yading@11 105 * on 4 for 386
yading@11 106 * on 16 for 486
yading@11 107 * on 32 for 586, PPro - K6-III
yading@11 108 * on 64 for K7 (maybe for P3 too).
yading@11 109 * Because L1 and L2 caches are aligned on those values.
yading@11 110 * But I don't want to code such logic here!
yading@11 111 */
yading@11 112 /* Why 32?
yading@11 113 * For AVX ASM. SSE / NEON needs only 16.
yading@11 114 * Why not larger? Because I did not see a difference in benchmarks ...
yading@11 115 */
yading@11 116 /* benchmarks with P3
yading@11 117 * memalign(64) + 1 3071, 3051, 3032
yading@11 118 * memalign(64) + 2 3051, 3032, 3041
yading@11 119 * memalign(64) + 4 2911, 2896, 2915
yading@11 120 * memalign(64) + 8 2545, 2554, 2550
yading@11 121 * memalign(64) + 16 2543, 2572, 2563
yading@11 122 * memalign(64) + 32 2546, 2545, 2571
yading@11 123 * memalign(64) + 64 2570, 2533, 2558
yading@11 124 *
yading@11 125 * BTW, malloc seems to do 8-byte alignment by default here.
yading@11 126 */
yading@11 127 #else
yading@11 128 ptr = malloc(size);
yading@11 129 #endif
yading@11 130 if(!ptr && !size) {
yading@11 131 size = 1;
yading@11 132 ptr= av_malloc(1);
yading@11 133 }
yading@11 134 #if CONFIG_MEMORY_POISONING
yading@11 135 if (ptr)
yading@11 136 memset(ptr, 0x2a, size);
yading@11 137 #endif
yading@11 138 return ptr;
yading@11 139 }
yading@11 140
yading@11 141 void *av_realloc(void *ptr, size_t size)
yading@11 142 {
yading@11 143 #if CONFIG_MEMALIGN_HACK
yading@11 144 int diff;
yading@11 145 #endif
yading@11 146
yading@11 147 /* let's disallow possible ambiguous cases */
yading@11 148 if (size > (max_alloc_size - 32))
yading@11 149 return NULL;
yading@11 150
yading@11 151 #if CONFIG_MEMALIGN_HACK
yading@11 152 //FIXME this isn't aligned correctly, though it probably isn't needed
yading@11 153 if (!ptr)
yading@11 154 return av_malloc(size);
yading@11 155 diff = ((char *)ptr)[-1];
yading@11 156 av_assert0(diff>0 && diff<=ALIGN);
yading@11 157 ptr = realloc((char *)ptr - diff, size + diff);
yading@11 158 if (ptr)
yading@11 159 ptr = (char *)ptr + diff;
yading@11 160 return ptr;
yading@11 161 #elif HAVE_ALIGNED_MALLOC
yading@11 162 return _aligned_realloc(ptr, size + !size, ALIGN);
yading@11 163 #else
yading@11 164 return realloc(ptr, size + !size);
yading@11 165 #endif
yading@11 166 }
yading@11 167
yading@11 168 void *av_realloc_f(void *ptr, size_t nelem, size_t elsize)
yading@11 169 {
yading@11 170 size_t size;
yading@11 171 void *r;
yading@11 172
yading@11 173 if (av_size_mult(elsize, nelem, &size)) {
yading@11 174 av_free(ptr);
yading@11 175 return NULL;
yading@11 176 }
yading@11 177 r = av_realloc(ptr, size);
yading@11 178 if (!r && size)
yading@11 179 av_free(ptr);
yading@11 180 return r;
yading@11 181 }
yading@11 182
yading@11 183 void av_free(void *ptr)
yading@11 184 {
yading@11 185 #if CONFIG_MEMALIGN_HACK
yading@11 186 if (ptr) {
yading@11 187 int v= ((char *)ptr)[-1];
yading@11 188 av_assert0(v>0 && v<=ALIGN);
yading@11 189 free((char *)ptr - v);
yading@11 190 }
yading@11 191 #elif HAVE_ALIGNED_MALLOC
yading@11 192 _aligned_free(ptr);
yading@11 193 #else
yading@11 194 free(ptr);
yading@11 195 #endif
yading@11 196 }
yading@11 197
yading@11 198 void av_freep(void *arg)
yading@11 199 {
yading@11 200 void **ptr = (void **)arg;
yading@11 201 av_free(*ptr);
yading@11 202 *ptr = NULL;
yading@11 203 }
yading@11 204
yading@11 205 void *av_mallocz(size_t size)
yading@11 206 {
yading@11 207 void *ptr = av_malloc(size);
yading@11 208 if (ptr)
yading@11 209 memset(ptr, 0, size);
yading@11 210 return ptr;
yading@11 211 }
yading@11 212
yading@11 213 void *av_calloc(size_t nmemb, size_t size)
yading@11 214 {
yading@11 215 if (size <= 0 || nmemb >= INT_MAX / size)
yading@11 216 return NULL;
yading@11 217 return av_mallocz(nmemb * size);
yading@11 218 }
yading@11 219
yading@11 220 char *av_strdup(const char *s)
yading@11 221 {
yading@11 222 char *ptr = NULL;
yading@11 223 if (s) {
yading@11 224 int len = strlen(s) + 1;
yading@11 225 ptr = av_malloc(len);
yading@11 226 if (ptr)
yading@11 227 memcpy(ptr, s, len);
yading@11 228 }
yading@11 229 return ptr;
yading@11 230 }
yading@11 231
yading@11 232 /* add one element to a dynamic array */
yading@11 233 void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem)
yading@11 234 {
yading@11 235 /* see similar ffmpeg.c:grow_array() */
yading@11 236 int nb, nb_alloc;
yading@11 237 intptr_t *tab;
yading@11 238
yading@11 239 nb = *nb_ptr;
yading@11 240 tab = *(intptr_t**)tab_ptr;
yading@11 241 if ((nb & (nb - 1)) == 0) {
yading@11 242 if (nb == 0)
yading@11 243 nb_alloc = 1;
yading@11 244 else
yading@11 245 nb_alloc = nb * 2;
yading@11 246 tab = av_realloc(tab, nb_alloc * sizeof(intptr_t));
yading@11 247 *(intptr_t**)tab_ptr = tab;
yading@11 248 }
yading@11 249 tab[nb++] = (intptr_t)elem;
yading@11 250 *nb_ptr = nb;
yading@11 251 }
yading@11 252
yading@11 253 static void fill16(uint8_t *dst, int len)
yading@11 254 {
yading@11 255 uint32_t v = AV_RN16(dst - 2);
yading@11 256
yading@11 257 v |= v << 16;
yading@11 258
yading@11 259 while (len >= 4) {
yading@11 260 AV_WN32(dst, v);
yading@11 261 dst += 4;
yading@11 262 len -= 4;
yading@11 263 }
yading@11 264
yading@11 265 while (len--) {
yading@11 266 *dst = dst[-2];
yading@11 267 dst++;
yading@11 268 }
yading@11 269 }
yading@11 270
yading@11 271 static void fill24(uint8_t *dst, int len)
yading@11 272 {
yading@11 273 #if HAVE_BIGENDIAN
yading@11 274 uint32_t v = AV_RB24(dst - 3);
yading@11 275 uint32_t a = v << 8 | v >> 16;
yading@11 276 uint32_t b = v << 16 | v >> 8;
yading@11 277 uint32_t c = v << 24 | v;
yading@11 278 #else
yading@11 279 uint32_t v = AV_RL24(dst - 3);
yading@11 280 uint32_t a = v | v << 24;
yading@11 281 uint32_t b = v >> 8 | v << 16;
yading@11 282 uint32_t c = v >> 16 | v << 8;
yading@11 283 #endif
yading@11 284
yading@11 285 while (len >= 12) {
yading@11 286 AV_WN32(dst, a);
yading@11 287 AV_WN32(dst + 4, b);
yading@11 288 AV_WN32(dst + 8, c);
yading@11 289 dst += 12;
yading@11 290 len -= 12;
yading@11 291 }
yading@11 292
yading@11 293 if (len >= 4) {
yading@11 294 AV_WN32(dst, a);
yading@11 295 dst += 4;
yading@11 296 len -= 4;
yading@11 297 }
yading@11 298
yading@11 299 if (len >= 4) {
yading@11 300 AV_WN32(dst, b);
yading@11 301 dst += 4;
yading@11 302 len -= 4;
yading@11 303 }
yading@11 304
yading@11 305 while (len--) {
yading@11 306 *dst = dst[-3];
yading@11 307 dst++;
yading@11 308 }
yading@11 309 }
yading@11 310
yading@11 311 static void fill32(uint8_t *dst, int len)
yading@11 312 {
yading@11 313 uint32_t v = AV_RN32(dst - 4);
yading@11 314
yading@11 315 while (len >= 4) {
yading@11 316 AV_WN32(dst, v);
yading@11 317 dst += 4;
yading@11 318 len -= 4;
yading@11 319 }
yading@11 320
yading@11 321 while (len--) {
yading@11 322 *dst = dst[-4];
yading@11 323 dst++;
yading@11 324 }
yading@11 325 }
yading@11 326
yading@11 327 void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
yading@11 328 {
yading@11 329 const uint8_t *src = &dst[-back];
yading@11 330 if (!back)
yading@11 331 return;
yading@11 332
yading@11 333 if (back == 1) {
yading@11 334 memset(dst, *src, cnt);
yading@11 335 } else if (back == 2) {
yading@11 336 fill16(dst, cnt);
yading@11 337 } else if (back == 3) {
yading@11 338 fill24(dst, cnt);
yading@11 339 } else if (back == 4) {
yading@11 340 fill32(dst, cnt);
yading@11 341 } else {
yading@11 342 if (cnt >= 16) {
yading@11 343 int blocklen = back;
yading@11 344 while (cnt > blocklen) {
yading@11 345 memcpy(dst, src, blocklen);
yading@11 346 dst += blocklen;
yading@11 347 cnt -= blocklen;
yading@11 348 blocklen <<= 1;
yading@11 349 }
yading@11 350 memcpy(dst, src, cnt);
yading@11 351 return;
yading@11 352 }
yading@11 353 if (cnt >= 8) {
yading@11 354 AV_COPY32U(dst, src);
yading@11 355 AV_COPY32U(dst + 4, src + 4);
yading@11 356 src += 8;
yading@11 357 dst += 8;
yading@11 358 cnt -= 8;
yading@11 359 }
yading@11 360 if (cnt >= 4) {
yading@11 361 AV_COPY32U(dst, src);
yading@11 362 src += 4;
yading@11 363 dst += 4;
yading@11 364 cnt -= 4;
yading@11 365 }
yading@11 366 if (cnt >= 2) {
yading@11 367 AV_COPY16U(dst, src);
yading@11 368 src += 2;
yading@11 369 dst += 2;
yading@11 370 cnt -= 2;
yading@11 371 }
yading@11 372 if (cnt)
yading@11 373 *dst = *src;
yading@11 374 }
yading@11 375 }
yading@11 376