src/mediastreamer/ms.c

branch
gaim
changeset 20470
77693555855f
parent 13071
b98e72d4089a
parent 20469
b2836a24d81e
child 20471
1966704b3e42
equal deleted inserted replaced
13071:b98e72d4089a 20470:77693555855f
1 /*
2 The mediastreamer library aims at providing modular media processing and I/O
3 for linphone, but also for any telephony application.
4 Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include "ms.h"
25 #include "sndcard.h"
26 #include "mscodec.h"
27
28 #include <sys/types.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #ifdef VIDEO_ENABLED
36 extern void ms_video_source_register_all();
37 #endif
38 #ifdef HAVE_ILBC
39 extern void ms_ilbc_codec_init();
40 #endif
41
42 /**
43 * ms_init:
44 *
45 *
46 * Initialize the mediastreamer. This must be the first function called in a program
47 * using the mediastreamer library.
48 *
49 *
50 */
51 void ms_init()
52 {
53 if (!g_thread_supported()) g_thread_init (NULL);
54 #ifdef HAVE_GLIB
55 if (!g_module_supported()){
56 g_error("GModule is not supported.");
57 }
58 #endif
59 /* initialize the oss subsystem */
60 snd_card_manager_init(snd_card_manager);
61 /* register the statically linked codecs */
62 ms_codec_register_all();
63 #ifdef VIDEO_ENABLED
64 ms_video_source_register_all();
65 #endif
66 #ifdef HAVE_ILBC
67 ms_ilbc_codec_init();
68 #endif
69 }
70
71
72 static gint compare(gconstpointer a, gconstpointer b)
73 {
74 MSFilter *f1=(MSFilter*)a,*f2=(MSFilter*)b;
75 if (f1->klass<f2->klass) return -1;
76 if (f1->klass==f2->klass) return 0;
77 /* if f1->klass>f2->klass ....*/
78 return 1;
79 }
80
81 static GList *g_list_append_if_new(GList *l,gpointer data)
82 {
83 GList *res=l;
84 if (g_list_find(res,data)==NULL)
85 res=g_list_append(res,data);
86 return(res);
87 }
88
89 static GList *get_nexts(MSFilter *f,GList *l)
90 {
91 int i;
92 MSFifo *fifo;
93 MSQueue *q;
94 GList *res=l;
95
96 /* check fifos*/
97 for (i=0;i <f->klass->max_foutputs;i++)
98 {
99 fifo=f->outfifos[i];
100 if (fifo!=NULL) res=g_list_append_if_new(res,(gpointer)fifo->next_data);
101 }
102 /* check queues*/
103 for (i=0;i <f->klass->max_qoutputs;i++)
104 {
105 q=f->outqueues[i];
106 if (q!=NULL) res=g_list_append_if_new(res,(gpointer)q->next_data);
107 }
108 return(res);
109 }
110
111 /* compile graphs attached to a sync source*/
112 int ms_compile(MSSync *sync)
113 {
114 int i;
115 GList *list1=NULL,*list2=NULL,*elem;
116 GList *proc_chain=NULL;
117 MSFilter *f;
118
119 /* first free the old list if we are just updating*/
120 if (sync->execution_list!=NULL) g_list_free(sync->execution_list);
121 /* get the list of filters attached to this sync*/
122 for (i=0;i<sync->filters;i++)
123 {
124 //printf("found filter !\n");
125 list1=g_list_append(list1,sync->attached_filters[i]);
126 }
127 /* find the processing chain */
128 while (list1!=NULL)
129 {
130 list2=NULL;
131 /* sort the list by types of filter*/
132 list1=g_list_sort(list1,compare);
133 /* save into the processing chain list*/
134 //printf("list1 :%i elements\n",g_list_length(list1));
135 proc_chain=g_list_concat(proc_chain,list1);
136 /* get all following filters. They are appended to list2*/
137 elem=list1;
138 while (elem!=NULL)
139 {
140 f=(MSFilter*)(elem->data);
141 /* check if filter 's status */
142 if (f->klass->attributes & FILTER_CAN_SYNC)
143 {
144 sync->samples_per_tick=0;
145 }
146 list2=get_nexts(f,list2);
147 elem=g_list_next(elem);
148 }
149 list1=list2;
150 }
151 sync->execution_list=proc_chain;
152 sync->flags&=~MS_SYNC_NEED_UPDATE;
153 ms_trace("%i filters successfully compiled in a processing chain.",g_list_length(sync->execution_list));
154 return 0;
155 }
156
157 /*execute the processing chain attached to a sync source. It is called as a thread by ms_main()*/
158 void *ms_thread_run(void *sync_ptr)
159 {
160 MSSync *sync=(MSSync*) sync_ptr;
161 GList *filter;
162 MSFilter *f;
163
164
165 ms_sync_lock(sync);
166 while(sync->run)
167 {
168 //g_message("sync->run=%i",sync->run);
169 if (sync->samples_per_tick==0) ms_sync_suspend(sync);
170 if (sync->flags & MS_SYNC_NEED_UPDATE){
171 ms_compile(sync);
172 ms_sync_setup(sync);
173 }
174 filter=sync->execution_list;
175 ms_sync_unlock(sync);
176 //ms_trace("Calling synchronisation");
177 ms_sync_synchronize(sync);
178 while(filter!=NULL)
179 {
180 f=(MSFilter*)filter->data;
181 if (MS_FILTER_GET_CLASS(f)->attributes & FILTER_IS_SOURCE)
182 {
183 /* execute it once */
184 ms_trace("Running source filter %s.",f->klass->name);
185 ms_filter_process(f);
186 }
187 else
188 {
189 /* make the filter process its input data until it has no more */
190 while ( ms_filter_fifos_have_data(f) || ms_filter_queues_have_data(f) )
191 {
192 ms_trace("Running filter %s.",f->klass->name);
193 ms_filter_process(f);
194 }
195 }
196 filter=g_list_next(filter);
197 }
198 ms_sync_lock(sync);
199 }
200 g_cond_signal(sync->stop_cond); /* signal that the sync thread has finished */
201 ms_sync_unlock(sync);
202 g_message("Mediastreamer processing thread is exiting.");
203 return NULL;
204 }
205
206 /* stop the processing chain attached to a sync source.*/
207 void ms_thread_stop(MSSync *sync)
208 {
209 if (sync->thread!=NULL)
210 {
211 if (sync->samples_per_tick==0)
212 {
213 /* to wakeup the thread */
214 //g_cond_signal(sync->thread_cond);
215 }
216 g_mutex_lock(sync->lock);
217 sync->run=0;
218 sync->thread=NULL;
219 g_cond_wait(sync->stop_cond,sync->lock);
220 g_mutex_unlock(sync->lock);
221 }
222 //g_message("ms_thread_stop() finished.");
223 }
224
225 /**
226 * ms_start:
227 * @sync: A synchronisation source to be started.
228 *
229 * Starts a thread that will shedule all processing chains attached to the synchronisation source @sync.
230 *
231 *
232 */
233 void ms_start(MSSync *sync)
234 {
235 if (sync->run==1) return; /*already running*/
236 ms_compile(sync);
237 ms_sync_setup(sync);
238 /* this is to avoid race conditions, for example:
239 ms_start(sync);
240 ms_oss_write_start(ossw);
241 here tge ossw filter need to be compiled to run ms_oss_write_start()
242 */
243 ms_trace("ms_start: creating new thread.");
244 sync->run=1;
245 sync->thread=g_thread_create((GThreadFunc)ms_thread_run,(gpointer)sync,TRUE,NULL);
246 if (sync->thread==NULL){
247 g_warning("Could not create thread !");
248 }
249 }
250
251 /**
252 * ms_stop:
253 * @sync: A synchronisation source to be stopped.
254 *
255 * Stop the thread that was sheduling the processing chains attached to the synchronisation source @sync.
256 * The processing chains are kept unchanged, no object is freed. The synchronisation source can be restarted using ms_start().
257 *
258 *
259 */
260 void ms_stop(MSSync *sync)
261 {
262 ms_thread_stop(sync);
263 ms_sync_unsetup(sync);
264 }
265
266
267 gint ms_load_plugin(gchar *path)
268 {
269 #ifdef HAVE_GLIB
270 g_module_open(path,0);
271 #endif
272 return 0;
273 }
274
275 gchar * ms_proc_get_param(gchar *parameter)
276 {
277 gchar *file;
278 int fd;
279 int err,len;
280 gchar *p,*begin,*end;
281 gchar *ret;
282 fd=open("/proc/cpuinfo",O_RDONLY);
283 if (fd<0){
284 g_warning("Could not open /proc/cpuinfo.");
285 return NULL;
286 }
287 file=g_malloc(1024);
288 err=read(fd,file,1024);
289 file[err-1]='\0';
290 /* find the parameter */
291 p=strstr(file,parameter);
292 if (p==NULL){
293 /* parameter not found */
294 g_free(file);
295 return NULL;
296 }
297 /* find the following ':' */
298 p=strchr(p,':');
299 if (p==NULL){
300 g_free(file);
301 return NULL;
302 }
303 /* find the value*/
304 begin=p+2;
305 end=strchr(begin,'\n');
306 if (end==NULL) end=strchr(begin,'\0');
307 len=end-begin+1;
308 ret=g_malloc(len+1);
309 snprintf(ret,len,"%s",begin);
310 //printf("%s=%s\n",parameter,ret);
311 g_free(file);
312 return ret;
313 }
314
315 gint ms_proc_get_type()
316 {
317 static int proc_type=0;
318 gchar *value;
319 if (proc_type==0){
320 value=ms_proc_get_param("cpu family");
321 if (value!=NULL) {
322 proc_type=atoi(value);
323 g_free(value);
324 }else return -1;
325 }
326 return proc_type;
327 }
328
329 gint ms_proc_get_speed()
330 {
331 char *value;
332 static int proc_speed=0;
333 if (proc_speed==0){
334 value=ms_proc_get_param("cpu MHz");
335 if (value!=NULL){
336 proc_speed=atoi(value);
337 g_free(value);
338 }else return -1;
339 }
340 //printf("proc_speed=%i\n",proc_speed);
341 return proc_speed;
342 }

mercurial