LCOV - code coverage report
Current view: top level - libavutil - fifo.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 110 122 90.2 %
Date: 2017-10-20 23:03:07 Functions: 15 15 100.0 %

          Line data    Source code
       1             : /*
       2             :  * a very simple circular buffer FIFO implementation
       3             :  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
       4             :  * Copyright (c) 2006 Roman Shaposhnik
       5             :  *
       6             :  * This file is part of FFmpeg.
       7             :  *
       8             :  * FFmpeg is free software; you can redistribute it and/or
       9             :  * modify it under the terms of the GNU Lesser General Public
      10             :  * License as published by the Free Software Foundation; either
      11             :  * version 2.1 of the License, or (at your option) any later version.
      12             :  *
      13             :  * FFmpeg is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public
      19             :  * License along with FFmpeg; if not, write to the Free Software
      20             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      21             :  */
      22             : 
      23             : #include "avassert.h"
      24             : #include "common.h"
      25             : #include "fifo.h"
      26             : 
      27       16766 : static AVFifoBuffer *fifo_alloc_common(void *buffer, size_t size)
      28             : {
      29             :     AVFifoBuffer *f;
      30       16766 :     if (!buffer)
      31           0 :         return NULL;
      32       16766 :     f = av_mallocz(sizeof(AVFifoBuffer));
      33       16766 :     if (!f) {
      34           0 :         av_free(buffer);
      35           0 :         return NULL;
      36             :     }
      37       16766 :     f->buffer = buffer;
      38       16766 :     f->end    = f->buffer + size;
      39       16766 :     av_fifo_reset(f);
      40       16766 :     return f;
      41             : }
      42             : 
      43       16538 : AVFifoBuffer *av_fifo_alloc(unsigned int size)
      44             : {
      45       16538 :     void *buffer = av_malloc(size);
      46       16538 :     return fifo_alloc_common(buffer, size);
      47             : }
      48             : 
      49         228 : AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size)
      50             : {
      51         228 :     void *buffer = av_malloc_array(nmemb, size);
      52         228 :     return fifo_alloc_common(buffer, nmemb * size);
      53             : }
      54             : 
      55       16618 : void av_fifo_free(AVFifoBuffer *f)
      56             : {
      57       16618 :     if (f) {
      58       16618 :         av_freep(&f->buffer);
      59       16618 :         av_free(f);
      60             :     }
      61       16618 : }
      62             : 
      63       16617 : void av_fifo_freep(AVFifoBuffer **f)
      64             : {
      65       16617 :     if (f) {
      66       16617 :         av_fifo_free(*f);
      67       16617 :         *f = NULL;
      68             :     }
      69       16617 : }
      70             : 
      71       16767 : void av_fifo_reset(AVFifoBuffer *f)
      72             : {
      73       16767 :     f->wptr = f->rptr = f->buffer;
      74       16767 :     f->wndx = f->rndx = 0;
      75       16767 : }
      76             : 
      77     2377569 : int av_fifo_size(const AVFifoBuffer *f)
      78             : {
      79     2377569 :     return (uint32_t)(f->wndx - f->rndx);
      80             : }
      81             : 
      82      451890 : int av_fifo_space(const AVFifoBuffer *f)
      83             : {
      84      451890 :     return f->end - f->buffer - av_fifo_size(f);
      85             : }
      86             : 
      87         250 : int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size)
      88             : {
      89         250 :     unsigned int old_size = f->end - f->buffer;
      90             : 
      91         250 :     if (old_size < new_size) {
      92         148 :         int len          = av_fifo_size(f);
      93         148 :         AVFifoBuffer *f2 = av_fifo_alloc(new_size);
      94             : 
      95         148 :         if (!f2)
      96           0 :             return AVERROR(ENOMEM);
      97         148 :         av_fifo_generic_read(f, f2->buffer, len, NULL);
      98         148 :         f2->wptr += len;
      99         148 :         f2->wndx += len;
     100         148 :         av_free(f->buffer);
     101         148 :         *f = *f2;
     102         148 :         av_free(f2);
     103             :     }
     104         250 :     return 0;
     105             : }
     106             : 
     107           1 : int av_fifo_grow(AVFifoBuffer *f, unsigned int size)
     108             : {
     109           1 :     unsigned int old_size = f->end - f->buffer;
     110           1 :     if(size + (unsigned)av_fifo_size(f) < size)
     111           0 :         return AVERROR(EINVAL);
     112             : 
     113           1 :     size += av_fifo_size(f);
     114             : 
     115           1 :     if (old_size < size)
     116           1 :         return av_fifo_realloc2(f, FFMAX(size, 2*old_size));
     117           0 :     return 0;
     118             : }
     119             : 
     120             : /* src must NOT be const as it can be a context for func that may need
     121             :  * updating (like a pointer or byte counter) */
     122      430308 : int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size,
     123             :                           int (*func)(void *, void *, int))
     124             : {
     125      430308 :     int total = size;
     126      430308 :     uint32_t wndx= f->wndx;
     127      430308 :     uint8_t *wptr= f->wptr;
     128             : 
     129             :     do {
     130      430447 :         int len = FFMIN(f->end - wptr, size);
     131      430447 :         if (func) {
     132           0 :             len = func(src, wptr, len);
     133           0 :             if (len <= 0)
     134           0 :                 break;
     135             :         } else {
     136      430447 :             memcpy(wptr, src, len);
     137      430447 :             src = (uint8_t *)src + len;
     138             :         }
     139             : // Write memory barrier needed for SMP here in theory
     140      430447 :         wptr += len;
     141      430447 :         if (wptr >= f->end)
     142      382867 :             wptr = f->buffer;
     143      430447 :         wndx    += len;
     144      430447 :         size    -= len;
     145      430447 :     } while (size > 0);
     146      430308 :     f->wndx= wndx;
     147      430308 :     f->wptr= wptr;
     148      430308 :     return total - size;
     149             : }
     150             : 
     151         202 : int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int))
     152             : {
     153         202 :     uint8_t *rptr = f->rptr;
     154             : 
     155             :     av_assert2(offset >= 0);
     156             : 
     157             :     /*
     158             :      * *ndx are indexes modulo 2^32, they are intended to overflow,
     159             :      * to handle *ndx greater than 4gb.
     160             :      */
     161             :     av_assert2(buf_size + (unsigned)offset <= f->wndx - f->rndx);
     162             : 
     163         202 :     if (offset >= f->end - rptr)
     164           0 :         rptr += offset - (f->end - f->buffer);
     165             :     else
     166         202 :         rptr += offset;
     167             : 
     168         606 :     while (buf_size > 0) {
     169             :         int len;
     170             : 
     171         202 :         if (rptr >= f->end)
     172           0 :             rptr -= f->end - f->buffer;
     173             : 
     174         202 :         len = FFMIN(f->end - rptr, buf_size);
     175         202 :         if (func)
     176          76 :             func(dest, rptr, len);
     177             :         else {
     178         126 :             memcpy(dest, rptr, len);
     179         126 :             dest = (uint8_t *)dest + len;
     180             :         }
     181             : 
     182         202 :         buf_size -= len;
     183         202 :         rptr     += len;
     184             :     }
     185             : 
     186         202 :     return 0;
     187             : }
     188             : 
     189          10 : int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size,
     190             :                          void (*func)(void *, void *, int))
     191             : {
     192             : // Read memory barrier needed for SMP here in theory
     193          10 :     uint8_t *rptr = f->rptr;
     194             : 
     195             :     do {
     196          10 :         int len = FFMIN(f->end - rptr, buf_size);
     197          10 :         if (func)
     198           0 :             func(dest, rptr, len);
     199             :         else {
     200          10 :             memcpy(dest, rptr, len);
     201          10 :             dest = (uint8_t *)dest + len;
     202             :         }
     203             : // memory barrier needed for SMP here in theory
     204          10 :         rptr += len;
     205          10 :         if (rptr >= f->end)
     206           1 :             rptr -= f->end - f->buffer;
     207          10 :         buf_size -= len;
     208          10 :     } while (buf_size > 0);
     209             : 
     210          10 :     return 0;
     211             : }
     212             : 
     213      391289 : int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size,
     214             :                          void (*func)(void *, void *, int))
     215             : {
     216             : // Read memory barrier needed for SMP here in theory
     217             :     do {
     218      391289 :         int len = FFMIN(f->end - f->rptr, buf_size);
     219      391289 :         if (func)
     220         560 :             func(dest, f->rptr, len);
     221             :         else {
     222      390729 :             memcpy(dest, f->rptr, len);
     223      390729 :             dest = (uint8_t *)dest + len;
     224             :         }
     225             : // memory barrier needed for SMP here in theory
     226      391289 :         av_fifo_drain(f, len);
     227      391289 :         buf_size -= len;
     228      391289 :     } while (buf_size > 0);
     229      391260 :     return 0;
     230             : }
     231             : 
     232             : /** Discard data from the FIFO. */
     233      394004 : void av_fifo_drain(AVFifoBuffer *f, int size)
     234             : {
     235             :     av_assert2(av_fifo_size(f) >= size);
     236      394004 :     f->rptr += size;
     237      394004 :     if (f->rptr >= f->end)
     238      382865 :         f->rptr -= f->end - f->buffer;
     239      394004 :     f->rndx += size;
     240      394004 : }

Generated by: LCOV version 1.13