Libav 0.7.1
|
00001 /* 00002 * a very simple circular buffer FIFO implementation 00003 * Copyright (c) 2000, 2001, 2002 Fabrice Bellard 00004 * Copyright (c) 2006 Roman Shaposhnik 00005 * 00006 * This file is part of Libav. 00007 * 00008 * Libav is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * Libav is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with Libav; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 #include "common.h" 00023 #include "fifo.h" 00024 00025 AVFifoBuffer *av_fifo_alloc(unsigned int size) 00026 { 00027 AVFifoBuffer *f= av_mallocz(sizeof(AVFifoBuffer)); 00028 if(!f) 00029 return NULL; 00030 f->buffer = av_malloc(size); 00031 f->end = f->buffer + size; 00032 av_fifo_reset(f); 00033 if (!f->buffer) 00034 av_freep(&f); 00035 return f; 00036 } 00037 00038 void av_fifo_free(AVFifoBuffer *f) 00039 { 00040 if(f){ 00041 av_free(f->buffer); 00042 av_free(f); 00043 } 00044 } 00045 00046 void av_fifo_reset(AVFifoBuffer *f) 00047 { 00048 f->wptr = f->rptr = f->buffer; 00049 f->wndx = f->rndx = 0; 00050 } 00051 00052 int av_fifo_size(AVFifoBuffer *f) 00053 { 00054 return (uint32_t)(f->wndx - f->rndx); 00055 } 00056 00057 int av_fifo_space(AVFifoBuffer *f) 00058 { 00059 return f->end - f->buffer - av_fifo_size(f); 00060 } 00061 00062 int av_fifo_realloc2(AVFifoBuffer *f, unsigned int new_size) { 00063 unsigned int old_size= f->end - f->buffer; 00064 00065 if(old_size < new_size){ 00066 int len= av_fifo_size(f); 00067 AVFifoBuffer *f2= av_fifo_alloc(new_size); 00068 00069 if (!f2) 00070 return -1; 00071 av_fifo_generic_read(f, f2->buffer, len, NULL); 00072 f2->wptr += len; 00073 f2->wndx += len; 00074 av_free(f->buffer); 00075 *f= *f2; 00076 av_free(f2); 00077 } 00078 return 0; 00079 } 00080 00081 // src must NOT be const as it can be a context for func that may need updating (like a pointer or byte counter) 00082 int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int)) 00083 { 00084 int total = size; 00085 do { 00086 int len = FFMIN(f->end - f->wptr, size); 00087 if(func) { 00088 if(func(src, f->wptr, len) <= 0) 00089 break; 00090 } else { 00091 memcpy(f->wptr, src, len); 00092 src = (uint8_t*)src + len; 00093 } 00094 // Write memory barrier needed for SMP here in theory 00095 f->wptr += len; 00096 if (f->wptr >= f->end) 00097 f->wptr = f->buffer; 00098 f->wndx += len; 00099 size -= len; 00100 } while (size > 0); 00101 return total - size; 00102 } 00103 00104 00105 int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)) 00106 { 00107 // Read memory barrier needed for SMP here in theory 00108 do { 00109 int len = FFMIN(f->end - f->rptr, buf_size); 00110 if(func) func(dest, f->rptr, len); 00111 else{ 00112 memcpy(dest, f->rptr, len); 00113 dest = (uint8_t*)dest + len; 00114 } 00115 // memory barrier needed for SMP here in theory 00116 av_fifo_drain(f, len); 00117 buf_size -= len; 00118 } while (buf_size > 0); 00119 return 0; 00120 } 00121 00123 void av_fifo_drain(AVFifoBuffer *f, int size) 00124 { 00125 f->rptr += size; 00126 if (f->rptr >= f->end) 00127 f->rptr -= f->end - f->buffer; 00128 f->rndx += size; 00129 }