ffmpeg的内存的分配和释放av_malloc()、av_free()的函数

来源:互联网 发布:淘宝买东西店铺下架了 编辑:程序博客网 时间:2024/06/06 01:46

内存操作函数位于libavutil\mem.c中

函数有

  1. *av_malloc(size_t size)
  2. av_free(void *ptr)
  3. *av_realloc_f(void *ptr, size_t nelem, size_t elsize)
  4. *av_realloc_array(void *ptr, size_t nmemb, size_t size)
  5. av_freep(void *arg)
  6. *av_mallocz(size_t size)
  7. *av_calloc(size_t nmemb, size_t size)
  8. *av_memdup(const void *p, size_t size)
  9. av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem)
  10. *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,const uint8_t *elem_data)
  11. *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
  12. av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)

这里把源码附上

/* * default memory allocator for libavutil * Copyright (c) 2002 Fabrice Bellard * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *//** * @file * default memory allocator for libavutil */#define _XOPEN_SOURCE 600#include "config.h"#include <limits.h>#include <stdint.h>#include <stdlib.h>#include <string.h>#if HAVE_MALLOC_H#include <malloc.h>#endif#include "avassert.h"#include "avutil.h"#include "common.h"#include "dynarray.h"#include "intreadwrite.h"#include "mem.h"#ifdef MALLOC_PREFIX#define malloc         AV_JOIN(MALLOC_PREFIX, malloc)#define memalign       AV_JOIN(MALLOC_PREFIX, memalign)#define posix_memalign AV_JOIN(MALLOC_PREFIX, posix_memalign)#define realloc        AV_JOIN(MALLOC_PREFIX, realloc)#define free           AV_JOIN(MALLOC_PREFIX, free)void *malloc(size_t size);void *memalign(size_t align, size_t size);int   posix_memalign(void **ptr, size_t align, size_t size);void *realloc(void *ptr, size_t size);void  free(void *ptr);#endif /* MALLOC_PREFIX */#include "mem_internal.h"#define ALIGN (HAVE_AVX ? 32 : 16)/* NOTE: if you want to override these functions with your own * implementations (not recommended) you have to link libav* as * dynamic libraries and remove -Wl,-Bsymbolic from the linker flags. * Note that this will cost performance. */static size_t max_alloc_size= INT_MAX;void av_max_alloc(size_t max){    max_alloc_size = max;}void *av_malloc(size_t size){    void *ptr = NULL;    /* let's disallow possibly ambiguous cases */    if (size > (max_alloc_size - 32))        return NULL;#if HAVE_POSIX_MEMALIGN    if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation    if (posix_memalign(&ptr, ALIGN, size))        ptr = NULL;#elif HAVE_ALIGNED_MALLOC    ptr = _aligned_malloc(size, ALIGN);#elif HAVE_MEMALIGN#ifndef __DJGPP__    ptr = memalign(ALIGN, size);#else    ptr = memalign(size, ALIGN);#endif    /* Why 64?     * Indeed, we should align it:     *   on  4 for 386     *   on 16 for 486     *   on 32 for 586, PPro - K6-III     *   on 64 for K7 (maybe for P3 too).     * Because L1 and L2 caches are aligned on those values.     * But I don't want to code such logic here!     */    /* Why 32?     * For AVX ASM. SSE / NEON needs only 16.     * Why not larger? Because I did not see a difference in benchmarks ...     */    /* benchmarks with P3     * memalign(64) + 1          3071, 3051, 3032     * memalign(64) + 2          3051, 3032, 3041     * memalign(64) + 4          2911, 2896, 2915     * memalign(64) + 8          2545, 2554, 2550     * memalign(64) + 16         2543, 2572, 2563     * memalign(64) + 32         2546, 2545, 2571     * memalign(64) + 64         2570, 2533, 2558     *     * BTW, malloc seems to do 8-byte alignment by default here.     */#else    ptr = malloc(size);#endif    if(!ptr && !size) {        size = 1;        ptr= av_malloc(1);    }#if CONFIG_MEMORY_POISONING    if (ptr)        memset(ptr, FF_MEMORY_POISON, size);#endif    return ptr;}void *av_realloc(void *ptr, size_t size){    /* let's disallow possibly ambiguous cases */    if (size > (max_alloc_size - 32))        return NULL;#if HAVE_ALIGNED_MALLOC    return _aligned_realloc(ptr, size + !size, ALIGN);#else    return realloc(ptr, size + !size);#endif}void *av_realloc_f(void *ptr, size_t nelem, size_t elsize){    size_t size;    void *r;    if (av_size_mult(elsize, nelem, &size)) {        av_free(ptr);        return NULL;    }    r = av_realloc(ptr, size);    if (!r)        av_free(ptr);    return r;}int av_reallocp(void *ptr, size_t size){    void *val;    if (!size) {        av_freep(ptr);        return 0;    }    memcpy(&val, ptr, sizeof(val));    val = av_realloc(val, size);    if (!val) {        av_freep(ptr);        return AVERROR(ENOMEM);    }    memcpy(ptr, &val, sizeof(val));    return 0;}void *av_realloc_array(void *ptr, size_t nmemb, size_t size){    if (!size || nmemb >= INT_MAX / size)        return NULL;    return av_realloc(ptr, nmemb * size);}int av_reallocp_array(void *ptr, size_t nmemb, size_t size){    void *val;    memcpy(&val, ptr, sizeof(val));    val = av_realloc_f(val, nmemb, size);    memcpy(ptr, &val, sizeof(val));    if (!val && nmemb && size)        return AVERROR(ENOMEM);    return 0;}void av_free(void *ptr){#if HAVE_ALIGNED_MALLOC    _aligned_free(ptr);#else    free(ptr);#endif}void av_freep(void *arg){    void *val;    memcpy(&val, arg, sizeof(val));    memcpy(arg, &(void *){ NULL }, sizeof(val));    av_free(val);}void *av_mallocz(size_t size){    void *ptr = av_malloc(size);    if (ptr)        memset(ptr, 0, size);    return ptr;}void *av_calloc(size_t nmemb, size_t size){    if (size <= 0 || nmemb >= INT_MAX / size)        return NULL;    return av_mallocz(nmemb * size);}char *av_strdup(const char *s){    char *ptr = NULL;    if (s) {        size_t len = strlen(s) + 1;        ptr = av_realloc(NULL, len);        if (ptr)            memcpy(ptr, s, len);    }    return ptr;}char *av_strndup(const char *s, size_t len){    char *ret = NULL, *end;    if (!s)        return NULL;    end = memchr(s, 0, len);    if (end)        len = end - s;    ret = av_realloc(NULL, len + 1);    if (!ret)        return NULL;    memcpy(ret, s, len);    ret[len] = 0;    return ret;}void *av_memdup(const void *p, size_t size){    void *ptr = NULL;    if (p) {        ptr = av_malloc(size);        if (ptr)            memcpy(ptr, p, size);    }    return ptr;}int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem){    void **tab;    memcpy(&tab, tab_ptr, sizeof(tab));    FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {        tab[*nb_ptr] = elem;        memcpy(tab_ptr, &tab, sizeof(tab));    }, {        return AVERROR(ENOMEM);    });    return 0;}void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem){    void **tab;    memcpy(&tab, tab_ptr, sizeof(tab));    FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {        tab[*nb_ptr] = elem;        memcpy(tab_ptr, &tab, sizeof(tab));    }, {        *nb_ptr = 0;        av_freep(tab_ptr);    });}void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,                       const uint8_t *elem_data){    uint8_t *tab_elem_data = NULL;    FF_DYNARRAY_ADD(INT_MAX, elem_size, *tab_ptr, *nb_ptr, {        tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size;        if (elem_data)            memcpy(tab_elem_data, elem_data, elem_size);        else if (CONFIG_MEMORY_POISONING)            memset(tab_elem_data, FF_MEMORY_POISON, elem_size);    }, {        av_freep(tab_ptr);        *nb_ptr = 0;    });    return tab_elem_data;}static void fill16(uint8_t *dst, int len){    uint32_t v = AV_RN16(dst - 2);    v |= v << 16;    while (len >= 4) {        AV_WN32(dst, v);        dst += 4;        len -= 4;    }    while (len--) {        *dst = dst[-2];        dst++;    }}static void fill24(uint8_t *dst, int len){#if HAVE_BIGENDIAN    uint32_t v = AV_RB24(dst - 3);    uint32_t a = v << 8  | v >> 16;    uint32_t b = v << 16 | v >> 8;    uint32_t c = v << 24 | v;#else    uint32_t v = AV_RL24(dst - 3);    uint32_t a = v       | v << 24;    uint32_t b = v >> 8  | v << 16;    uint32_t c = v >> 16 | v << 8;#endif    while (len >= 12) {        AV_WN32(dst,     a);        AV_WN32(dst + 4, b);        AV_WN32(dst + 8, c);        dst += 12;        len -= 12;    }    if (len >= 4) {        AV_WN32(dst, a);        dst += 4;        len -= 4;    }    if (len >= 4) {        AV_WN32(dst, b);        dst += 4;        len -= 4;    }    while (len--) {        *dst = dst[-3];        dst++;    }}static void fill32(uint8_t *dst, int len){    uint32_t v = AV_RN32(dst - 4);    while (len >= 4) {        AV_WN32(dst, v);        dst += 4;        len -= 4;    }    while (len--) {        *dst = dst[-4];        dst++;    }}void av_memcpy_backptr(uint8_t *dst, int back, int cnt){    const uint8_t *src = &dst[-back];    if (!back)        return;    if (back == 1) {        memset(dst, *src, cnt);    } else if (back == 2) {        fill16(dst, cnt);    } else if (back == 3) {        fill24(dst, cnt);    } else if (back == 4) {        fill32(dst, cnt);    } else {        if (cnt >= 16) {            int blocklen = back;            while (cnt > blocklen) {                memcpy(dst, src, blocklen);                dst       += blocklen;                cnt       -= blocklen;                blocklen <<= 1;            }            memcpy(dst, src, cnt);            return;        }        if (cnt >= 8) {            AV_COPY32U(dst,     src);            AV_COPY32U(dst + 4, src + 4);            src += 8;            dst += 8;            cnt -= 8;        }        if (cnt >= 4) {            AV_COPY32U(dst, src);            src += 4;            dst += 4;            cnt -= 4;        }        if (cnt >= 2) {            AV_COPY16U(dst, src);            src += 2;            dst += 2;            cnt -= 2;        }        if (cnt)            *dst = *src;    }}void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size){    if (min_size < *size)        return ptr;    min_size = FFMAX(min_size + min_size / 16 + 32, min_size);    ptr = av_realloc(ptr, min_size);    /* we could set this to the unmodified min_size but this is safer     * if the user lost the ptr and uses NULL now     */    if (!ptr)        min_size = 0;    *size = min_size;    return ptr;}void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size){    ff_fast_malloc(ptr, size, min_size, 0);}void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size){    ff_fast_malloc(ptr, size, min_size, 1);}