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 Libav. 7 * 8 * Libav 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 * Libav 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 Libav; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22#include "common.h" 23#include "fifo.h" 24 25AVFifoBuffer *av_fifo_alloc(unsigned int size) 26{ 27 AVFifoBuffer *f= av_mallocz(sizeof(AVFifoBuffer)); 28 if(!f) 29 return NULL; 30 f->buffer = av_malloc(size); 31 f->end = f->buffer + size; 32 av_fifo_reset(f); 33 if (!f->buffer) 34 av_freep(&f); 35 return f; 36} 37 38void av_fifo_free(AVFifoBuffer *f) 39{ 40 if(f){ 41 av_free(f->buffer); 42 av_free(f); 43 } 44} 45 46void av_fifo_reset(AVFifoBuffer *f) 47{ 48 f->wptr = f->rptr = f->buffer; 49 f->wndx = f->rndx = 0; 50} 51 52int av_fifo_size(AVFifoBuffer *f) 53{ 54 return (uint32_t)(f->wndx - f->rndx); 55} 56 57int av_fifo_space(AVFifoBuffer *f) 58{ 59 return f->end - f->buffer - av_fifo_size(f); 60} 61 62int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size) { 63 unsigned int old_size= f->end - f->buffer; 64 65 if(old_size < new_size){ 66 int len= av_fifo_size(f); 67 AVFifoBuffer *f2= av_fifo_alloc(new_size); 68 69 if (!f2) 70 return -1; 71 av_fifo_generic_read(f, f2->buffer, len, NULL); 72 f2->wptr += len; 73 f2->wndx += len; 74 av_free(f->buffer); 75 *f= *f2; 76 av_free(f2); 77 } 78 return 0; 79} 80 81// src must NOT be const as it can be a context for func that may need updating (like a pointer or byte counter) 82int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int)) 83{ 84 int total = size; 85 do { 86 int len = FFMIN(f->end - f->wptr, size); 87 if(func) { 88 if(func(src, f->wptr, len) <= 0) 89 break; 90 } else { 91 memcpy(f->wptr, src, len); 92 src = (uint8_t*)src + len; 93 } 94// Write memory barrier needed for SMP here in theory 95 f->wptr += len; 96 if (f->wptr >= f->end) 97 f->wptr = f->buffer; 98 f->wndx += len; 99 size -= len; 100 } while (size > 0); 101 return total - size; 102} 103 104 105int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)) 106{ 107// Read memory barrier needed for SMP here in theory 108 do { 109 int len = FFMIN(f->end - f->rptr, buf_size); 110 if(func) func(dest, f->rptr, len); 111 else{ 112 memcpy(dest, f->rptr, len); 113 dest = (uint8_t*)dest + len; 114 } 115// memory barrier needed for SMP here in theory 116 av_fifo_drain(f, len); 117 buf_size -= len; 118 } while (buf_size > 0); 119 return 0; 120} 121 122/** Discard data from the FIFO. */ 123void av_fifo_drain(AVFifoBuffer *f, int size) 124{ 125 f->rptr += size; 126 if (f->rptr >= f->end) 127 f->rptr -= f->end - f->buffer; 128 f->rndx += size; 129} 130 131#ifdef TEST 132 133#undef printf 134 135int main(void) 136{ 137 /* create a FIFO buffer */ 138 AVFifoBuffer *fifo = av_fifo_alloc(13 * sizeof(int)); 139 int i, j, n; 140 141 /* fill data */ 142 for (i = 0; av_fifo_space(fifo) >= sizeof(int); i++) 143 av_fifo_generic_write(fifo, &i, sizeof(int), NULL); 144 145 /* peek at FIFO */ 146 n = av_fifo_size(fifo)/sizeof(int); 147 for (i = -n+1; i < n; i++) { 148 int *v = (int *)av_fifo_peek2(fifo, i*sizeof(int)); 149 printf("%d: %d\n", i, *v); 150 } 151 printf("\n"); 152 153 /* read data */ 154 for (i = 0; av_fifo_size(fifo) >= sizeof(int); i++) { 155 av_fifo_generic_read(fifo, &j, sizeof(int), NULL); 156 printf("%d ", j); 157 } 158 printf("\n"); 159 160 av_fifo_free(fifo); 161 162 return 0; 163} 164 165#endif 166