| /* |
| The mediastreamer library aims at providing modular media processing and I/O |
| for linphone, but also for any telephony application. |
| Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org |
| |
| This library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 of the License, or (at your option) any later version. |
| |
| This library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with this library; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include <errno.h> |
| #include <string.h> |
| #include "msutils.h" |
| #include "msfifo.h" |
| |
| MSFifo * ms_fifo_new(MSBuffer *buf, gint r_gran, gint w_gran, gint r_offset, gint w_offset) |
| { |
| MSFifo *fifo; |
| gint saved_offset=MAX(r_gran+r_offset,w_offset); |
| |
| g_return_val_if_fail(saved_offset<=(buf->size),NULL); |
| fifo=g_malloc(sizeof(MSFifo)); |
| fifo->buffer=buf; |
| fifo->r_gran=r_gran; |
| fifo->w_gran=w_gran; |
| fifo->begin=fifo->wr_ptr=fifo->rd_ptr=buf->buffer+saved_offset; |
| fifo->readsize=0; |
| fifo->size=fifo->writesize=buf->size-saved_offset; |
| fifo->saved_offset= saved_offset; |
| fifo->r_end=fifo->w_end=buf->buffer+buf->size; |
| fifo->pre_end=fifo->w_end-saved_offset; |
| buf->ref_count++; |
| fifo->prev_data=NULL; |
| fifo->next_data=NULL; |
| ms_trace("fifo base=%x, begin=%x, end=%x, saved_offset=%i, size=%i" |
| ,fifo->buffer->buffer,fifo->begin,fifo->w_end,fifo->saved_offset,fifo->size); |
| return(fifo); |
| } |
| |
| MSFifo * ms_fifo_new_with_buffer(gint r_gran, gint w_gran, gint r_offset, gint w_offset, |
| gint min_fifo_size) |
| { |
| MSFifo *fifo; |
| MSBuffer *buf; |
| gint saved_offset=MAX(r_gran+r_offset,w_offset); |
| gint fifo_size; |
| gint tmp; |
| if (min_fifo_size==0) min_fifo_size=w_gran; |
| |
| /* we must allocate a fifo with a size multiple of min_fifo_size, |
| with a saved_offset */ |
| if (min_fifo_size>MS_BUFFER_LARGE) |
| fifo_size=(min_fifo_size) + saved_offset; |
| else fifo_size=(6*min_fifo_size) + saved_offset; |
| buf=ms_buffer_new(fifo_size); |
| fifo=ms_fifo_new(buf,r_gran,w_gran,r_offset,w_offset); |
| ms_trace("fifo_size=%i",fifo_size); |
| return(fifo); |
| } |
| |
| void ms_fifo_destroy( MSFifo *fifo) |
| { |
| g_free(fifo); |
| } |
| |
| void ms_fifo_destroy_with_buffer(MSFifo *fifo) |
| { |
| ms_buffer_destroy(fifo->buffer); |
| ms_fifo_destroy(fifo); |
| } |
| |
| gint ms_fifo_get_read_ptr(MSFifo *fifo, gint bsize, void **ret_ptr) |
| { |
| gchar *rnext; |
| |
| *ret_ptr=NULL; |
| //ms_trace("ms_fifo_get_read_ptr: entering."); |
| g_return_val_if_fail(bsize<=fifo->r_gran,-EINVAL); |
| |
| if (bsize>fifo->readsize) |
| { |
| ms_trace("Not enough data: bsize=%i, readsize=%i",bsize,fifo->readsize); |
| return (-ENODATA); |
| } |
| |
| rnext=fifo->rd_ptr+bsize; |
| if (rnext<=fifo->r_end){ |
| |
| *ret_ptr=fifo->rd_ptr; |
| fifo->rd_ptr=rnext; |
| }else{ |
| int unread=fifo->r_end-fifo->rd_ptr; |
| *ret_ptr=fifo->begin-unread; |
| memcpy(fifo->buffer->buffer,fifo->r_end-fifo->saved_offset,fifo->saved_offset); |
| fifo->rd_ptr=(char*)(*ret_ptr) + bsize; |
| fifo->r_end=fifo->w_end; /* this is important ! */ |
| ms_trace("moving read ptr to %x",fifo->rd_ptr); |
| |
| } |
| /* update write size*/ |
| fifo->writesize+=bsize; |
| fifo->readsize-=bsize; |
| return bsize; |
| } |
| |
| |
| void ms_fifo_update_write_ptr(MSFifo *fifo, gint written){ |
| gint reserved=fifo->wr_ptr-fifo->prev_wr_ptr; |
| gint unwritten; |
| g_return_if_fail(reserved>=0); |
| unwritten=reserved-written; |
| g_return_if_fail(unwritten>=0); |
| /* fix readsize and writesize */ |
| fifo->readsize-=unwritten; |
| fifo->writesize+=unwritten; |
| fifo->wr_ptr+=written; |
| } |
| |
| gint ms_fifo_get_write_ptr(MSFifo *fifo, gint bsize, void **ret_ptr) |
| { |
| gchar *wnext; |
| |
| *ret_ptr=NULL; |
| //ms_trace("ms_fifo_get_write_ptr: Entering."); |
| g_return_val_if_fail(bsize<=fifo->w_gran,-EINVAL); |
| if (bsize>fifo->writesize) |
| { |
| ms_trace("Not enough space: bsize=%i, writesize=%i",bsize,fifo->writesize); |
| *ret_ptr=NULL; |
| return(-ENODATA); |
| } |
| wnext=fifo->wr_ptr+bsize; |
| if (wnext<=fifo->w_end){ |
| *ret_ptr=fifo->wr_ptr; |
| fifo->wr_ptr=wnext; |
| }else{ |
| *ret_ptr=fifo->begin; |
| fifo->r_end=fifo->wr_ptr; |
| fifo->wr_ptr=fifo->begin+bsize; |
| ms_trace("moving write ptr to %x",fifo->wr_ptr); |
| } |
| fifo->prev_wr_ptr=*ret_ptr; |
| /* update readsize*/ |
| fifo->readsize+=bsize; |
| fifo->writesize-=bsize; |
| //ms_trace("ms_fifo_get_write_ptr: readsize=%i, writesize=%i",fifo->readsize,fifo->writesize); |
| return bsize; |
| } |
| |
| gint ms_fifo_get_rw_ptr(MSFifo *f1,void **p1,gint minsize1, |
| MSFifo *f2,void **p2,gint minsize2) |
| { |
| gint rbsize,wbsize; |
| |
| rbsize=MIN(f1->readsize,(f1->pre_end-f1->rd_ptr)); |
| wbsize=MIN(f2->writesize,(f2->w_end-f2->wr_ptr)); |
| return 0; |
| } |