blob: 9897e08b3ffd97583f0e10de965a01b8297d8456 [file] [log] [blame]
/*
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;
}