LCOV - code coverage report
Current view: top level - src/libavutil - fifo.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 110 122 90.2 %
Date: 2017-01-21 09:32:20 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       10931 : static AVFifoBuffer *fifo_alloc_common(void *buffer, size_t size)
      28             : {
      29             :     AVFifoBuffer *f;
      30       10931 :     if (!buffer)
      31           0 :         return NULL;
      32       10931 :     f = av_mallocz(sizeof(AVFifoBuffer));
      33       10931 :     if (!f) {
      34           0 :         av_free(buffer);
      35           0 :         return NULL;
      36             :     }
      37       10931 :     f->buffer = buffer;
      38       10931 :     f->end    = f->buffer + size;
      39       10931 :     av_fifo_reset(f);
      40       10931 :     return f;
      41             : }
      42             : 
      43       10708 : AVFifoBuffer *av_fifo_alloc(unsigned int size)
      44             : {
      45       10708 :     void *buffer = av_malloc(size);
      46       10708 :     return fifo_alloc_common(buffer, size);
      47             : }
      48             : 
      49         223 : AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size)
      50             : {
      51         223 :     void *buffer = av_malloc_array(nmemb, size);
      52         223 :     return fifo_alloc_common(buffer, nmemb * size);
      53             : }
      54             : 
      55       10800 : void av_fifo_free(AVFifoBuffer *f)
      56             : {
      57       10800 :     if (f) {
      58       10800 :         av_freep(&f->buffer);
      59       10800 :         av_free(f);
      60             :     }
      61       10800 : }
      62             : 
      63       10799 : void av_fifo_freep(AVFifoBuffer **f)
      64             : {
      65       10799 :     if (f) {
      66       10799 :         av_fifo_free(*f);
      67       10799 :         *f = NULL;
      68             :     }
      69       10799 : }
      70             : 
      71       10932 : void av_fifo_reset(AVFifoBuffer *f)
      72             : {
      73       10932 :     f->wptr = f->rptr = f->buffer;
      74       10932 :     f->wndx = f->rndx = 0;
      75       10932 : }
      76             : 
      77     1274233 : int av_fifo_size(const AVFifoBuffer *f)
      78             : {
      79     1274233 :     return (uint32_t)(f->wndx - f->rndx);
      80             : }
      81             : 
      82      447058 : int av_fifo_space(const AVFifoBuffer *f)
      83             : {
      84      447058 :     return f->end - f->buffer - av_fifo_size(f);
      85             : }
      86             : 
      87         233 : int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size)
      88             : {
      89         233 :     unsigned int old_size = f->end - f->buffer;
      90             : 
      91         233 :     if (old_size < new_size) {
      92         131 :         int len          = av_fifo_size(f);
      93         131 :         AVFifoBuffer *f2 = av_fifo_alloc(new_size);
      94             : 
      95         131 :         if (!f2)
      96           0 :             return AVERROR(ENOMEM);
      97         131 :         av_fifo_generic_read(f, f2->buffer, len, NULL);
      98         131 :         f2->wptr += len;
      99         131 :         f2->wndx += len;
     100         131 :         av_free(f->buffer);
     101         131 :         *f = *f2;
     102         131 :         av_free(f2);
     103             :     }
     104         233 :     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      426980 : int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size,
     123             :                           int (*func)(void *, void *, int))
     124             : {
     125      426980 :     int total = size;
     126      426980 :     uint32_t wndx= f->wndx;
     127      426980 :     uint8_t *wptr= f->wptr;
     128             : 
     129             :     do {
     130      427119 :         int len = FFMIN(f->end - wptr, size);
     131      427119 :         if (func) {
     132           0 :             len = func(src, wptr, len);
     133           0 :             if (len <= 0)
     134           0 :                 break;
     135             :         } else {
     136      427119 :             memcpy(wptr, src, len);
     137      427119 :             src = (uint8_t *)src + len;
     138             :         }
     139             : // Write memory barrier needed for SMP here in theory
     140      427119 :         wptr += len;
     141      427119 :         if (wptr >= f->end)
     142      379376 :             wptr = f->buffer;
     143      427119 :         wndx    += len;
     144      427119 :         size    -= len;
     145      427119 :     } while (size > 0);
     146      426980 :     f->wndx= wndx;
     147      426980 :     f->wptr= wptr;
     148      426980 :     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      387731 : 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      387731 :         int len = FFMIN(f->end - f->rptr, buf_size);
     219      387731 :         if (func)
     220         560 :             func(dest, f->rptr, len);
     221             :         else {
     222      387171 :             memcpy(dest, f->rptr, len);
     223      387171 :             dest = (uint8_t *)dest + len;
     224             :         }
     225             : // memory barrier needed for SMP here in theory
     226      387731 :         av_fifo_drain(f, len);
     227      387731 :         buf_size -= len;
     228      387731 :     } while (buf_size > 0);
     229      387702 :     return 0;
     230             : }
     231             : 
     232             : /** Discard data from the FIFO. */
     233      390439 : void av_fifo_drain(AVFifoBuffer *f, int size)
     234             : {
     235             :     av_assert2(av_fifo_size(f) >= size);
     236      390439 :     f->rptr += size;
     237      390439 :     if (f->rptr >= f->end)
     238      379374 :         f->rptr -= f->end - f->buffer;
     239      390439 :     f->rndx += size;
     240      390439 : }

Generated by: LCOV version 1.12