eventqueue.c 3.51 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2010  Simon MORLAT (simon.morlat@linphone.org)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

Simon Morlat's avatar
Simon Morlat committed
20

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
#include "mediastreamer2/mseventqueue.h"
#include "mediastreamer2/msfilter.h"

#ifndef MS_EVENT_BUF_SIZE
#define MS_EVENT_BUF_SIZE 8192
#endif

struct _MSEventQueue{
	ms_mutex_t mutex; /*could be replaced by an atomic counter for freeroom*/
	uint8_t *rptr;
	uint8_t *wptr;
	uint8_t *endptr;
	uint8_t *lim;
	int freeroom;
	int size;
	uint8_t buffer[MS_EVENT_BUF_SIZE];
};

static void write_event(MSEventQueue *q, MSFilter *f, unsigned int ev_id, void *arg){
Simon Morlat's avatar
Simon Morlat committed
40
	int argsize=ev_id & 0xff;
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
	int size=argsize+16;
	uint8_t *nextpos=q->wptr+size;

	if (q->freeroom<size){
		ms_error("Dropped event, no more free space in event buffer !");
		return;
	}
	
	if (nextpos>q->lim){
		/* need to wrap around */
		q->endptr=q->wptr;
		q->wptr=q->buffer;
		nextpos=q->wptr+size;
	}
	*(long*)q->wptr=(long)f;
	*(long*)(q->wptr+8)=(long)ev_id;
	if (argsize>0) memcpy(q->wptr+16,arg,argsize);
	q->wptr=nextpos;
	ms_mutex_lock(&q->mutex);
	q->freeroom-=size;
	ms_mutex_unlock(&q->mutex);
}

static bool_t read_event(MSEventQueue *q){
	int available=q->size-q->freeroom;
	if (available>0){
		MSFilter *f;
		unsigned int id;
		void *data;
70 71 72
		int argsize;
		int evsize;
		
73 74
		f=(MSFilter *)*(long*)(q->rptr);
		id=(unsigned int)*(long*)(q->rptr+8);
75 76
		argsize=id & 0xffff;
		evsize=argsize+16;
77 78
		data=q->rptr+16;
		if (f->notify!=NULL)
79
			f->notify(f->notify_ud,f,id,argsize>0 ? data : NULL);
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
		q->rptr+=evsize;
		if (q->rptr>=q->endptr){
			q->rptr=q->buffer;
		}
		ms_mutex_lock(&q->mutex);
		q->freeroom+=evsize;
		ms_mutex_unlock(&q->mutex);
		return TRUE;
	}
	return FALSE;
}

MSEventQueue *ms_event_queue_new(){
	MSEventQueue *q=ms_new0(MSEventQueue,1);
	int bufsize=MS_EVENT_BUF_SIZE;
	ms_mutex_init(&q->mutex,NULL);
	q->lim=q->buffer+bufsize;
	q->freeroom=bufsize;
	q->wptr=q->rptr=q->buffer;
	q->endptr=q->lim;
	q->size=bufsize;
	return q;
}

void ms_event_queue_destroy(MSEventQueue *q){
	ms_mutex_destroy(&q->mutex);
	ms_free(q);
}

static MSEventQueue *ms_global_event_queue=NULL;

void ms_set_global_event_queue(MSEventQueue *q){
	ms_global_event_queue=q;
}

115 116 117 118 119 120 121 122 123
void ms_event_queue_skip(MSEventQueue *q){
	int bufsize=q->size;
	q->lim=q->buffer+bufsize;
	q->freeroom=bufsize;
	q->wptr=q->rptr=q->buffer;
	q->endptr=q->lim;
}


124 125 126 127 128 129 130 131 132 133
void ms_event_queue_pump(MSEventQueue *q){
	while(read_event(q)){
	}
}


void ms_filter_notify(MSFilter *f, unsigned int id, void *arg){
	if (f->notify!=NULL){
		if (ms_global_event_queue==NULL){
			/* synchronous notification */
134
			f->notify(f->notify_ud,f,id,arg);
135 136 137 138 139 140
		}else{
			write_event(ms_global_event_queue,f,id,arg);
		}
	}
}

141 142 143 144 145 146
void ms_filter_notify_synchronous(MSFilter *f, unsigned int id, void *arg){
	if (f->notify){
		f->notify(f->notify_ud,f,id,arg);
	}
}

147 148 149
void ms_filter_notify_no_arg(MSFilter *f, unsigned int id){
	ms_filter_notify(f,id,NULL);
}