LCOV - code coverage report
Current view: top level - libavutil - buffer.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 155 187 82.9 %
Date: 2017-10-20 23:03:07 Functions: 17 19 89.5 %

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

Generated by: LCOV version 1.13