source: mediastreamer2/linphone/mediastreamer2/src/mscommon.c @ 365:7ccc07194905

Last change on this file since 365:7ccc07194905 was 365:7ccc07194905, checked in by smorlat <smorlat@…>, 4 years ago

check that ffmpeg encoder are present before registering them.

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@368 3f6dc0c8-ddfe-455d-9043-3cd528dc4637

File size: 13.6 KB
Line 
1/*
2mediastreamer2 library - modular sound and video processing and streaming
3Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18*/
19
20#ifdef HAVE_CONFIG_H
21#include "mediastreamer-config.h"
22#endif
23
24extern void __register_ffmpeg_encoders_if_possible(void);
25
26#include "mediastreamer2/mscommon.h"
27#include "mediastreamer2/msfilter.h"
28
29#include "alldescs.h"
30#include "mediastreamer2/mssndcard.h"
31#include "mediastreamer2/mswebcam.h"
32
33#if !defined(_WIN32_WCE)
34#include <sys/types.h>
35#endif
36#ifndef WIN32
37#include <dirent.h>
38#else
39#ifndef PACKAGE_PLUGINS_DIR
40#if defined(WIN32) || defined(_WIN32_WCE)
41#define PACKAGE_PLUGINS_DIR "plugins\\"
42#else
43#define PACKAGE_PLUGINS_DIR "."
44#endif
45#endif
46#endif
47#ifdef HAVE_DLOPEN
48#include <dlfcn.h>
49#endif
50
51#ifdef __APPLE__
52#import <Cocoa/Cocoa.h>
53#include <Foundation/Foundation.h>
54#endif
55
56MSList *ms_list_new(void *data){
57        MSList *new_elem=(MSList *)ms_new(MSList,1);
58        new_elem->prev=new_elem->next=NULL;
59        new_elem->data=data;
60        return new_elem;
61}
62
63MSList * ms_list_append(MSList *elem, void * data){
64        MSList *new_elem=ms_list_new(data);
65        MSList *it=elem;
66        if (elem==NULL) return new_elem;
67        while (it->next!=NULL) it=ms_list_next(it);
68        it->next=new_elem;
69        new_elem->prev=it;
70        return elem;
71}
72
73MSList * ms_list_prepend(MSList *elem, void *data){
74        MSList *new_elem=ms_list_new(data);
75        if (elem!=NULL) {
76                new_elem->next=elem;
77                elem->prev=new_elem;
78        }
79        return new_elem;
80}
81
82
83MSList * ms_list_concat(MSList *first, MSList *second){
84        MSList *it=first;
85        if (it==NULL) return second;
86        while(it->next!=NULL) it=ms_list_next(it);
87        it->next=second;
88        second->prev=it;
89        return first;
90}
91
92MSList * ms_list_free(MSList *list){
93        MSList *elem = list;
94        MSList *tmp;
95        if (list==NULL) return NULL;
96        while(elem->next!=NULL) {
97                tmp = elem;
98                elem = elem->next;
99                ms_free(tmp);
100        }
101        ms_free(elem);
102        return NULL;
103}
104
105MSList * ms_list_remove(MSList *first, void *data){
106        MSList *it;
107        it=ms_list_find(first,data);
108        if (it) return ms_list_remove_link(first,it);
109        else {
110                ms_warning("ms_list_remove: no element with %p data was in the list", data);
111                return first;
112        }
113}
114
115int ms_list_size(const MSList *first){
116        int n=0;
117        while(first!=NULL){
118                ++n;
119                first=first->next;
120        }
121        return n;
122}
123
124void ms_list_for_each(const MSList *list, void (*func)(void *)){
125        for(;list!=NULL;list=list->next){
126                func(list->data);
127        }
128}
129
130void ms_list_for_each2(const MSList *list, void (*func)(void *, void *), void *user_data){
131        for(;list!=NULL;list=list->next){
132                func(list->data,user_data);
133        }
134}
135
136MSList *ms_list_remove_link(MSList *list, MSList *elem){
137        MSList *ret;
138        if (elem==list){
139                ret=elem->next;
140                elem->prev=NULL;
141                elem->next=NULL;
142                if (ret!=NULL) ret->prev=NULL;
143                ms_free(elem);
144                return ret;
145        }
146        elem->prev->next=elem->next;
147        if (elem->next!=NULL) elem->next->prev=elem->prev;
148        elem->next=NULL;
149        elem->prev=NULL;
150        ms_free(elem);
151        return list;
152}
153
154MSList *ms_list_find(MSList *list, void *data){
155        for(;list!=NULL;list=list->next){
156                if (list->data==data) return list;
157        }
158        return NULL;
159}
160
161MSList *ms_list_find_custom(MSList *list, int (*compare_func)(const void *, const void*), void *user_data){
162        for(;list!=NULL;list=list->next){
163                if (compare_func(list->data,user_data)==0) return list;
164        }
165        return NULL;
166}
167
168void * ms_list_nth_data(const MSList *list, int index){
169        int i;
170        for(i=0;list!=NULL;list=list->next,++i){
171                if (i==index) return list->data;
172        }
173        ms_error("ms_list_nth_data: no such index in list.");
174        return NULL;
175}
176
177int ms_list_position(const MSList *list, MSList *elem){
178        int i;
179        for(i=0;list!=NULL;list=list->next,++i){
180                if (elem==list) return i;
181        }
182        ms_error("ms_list_position: no such element in list.");
183        return -1;
184}
185
186int ms_list_index(const MSList *list, void *data){
187        int i;
188        for(i=0;list!=NULL;list=list->next,++i){
189                if (data==list->data) return i;
190        }
191        ms_error("ms_list_index: no such element in list.");
192        return -1;
193}
194
195MSList *ms_list_insert_sorted(MSList *list, void *data, int (*compare_func)(const void *, const void*)){
196        MSList *it,*previt=NULL;
197        MSList *nelem;
198        MSList *ret=list;
199        if (list==NULL) return ms_list_append(list,data);
200        else{
201                nelem=ms_list_new(data);
202                for(it=list;it!=NULL;it=it->next){
203                        previt=it;
204                        if (compare_func(data,it->data)<=0){
205                                nelem->prev=it->prev;
206                                nelem->next=it;
207                                if (it->prev!=NULL)
208                                        it->prev->next=nelem;
209                                else{
210                                        ret=nelem;
211                                }
212                                it->prev=nelem;
213                                return ret;
214                        }
215                }
216                previt->next=nelem;
217                nelem->prev=previt;
218        }
219        return ret;
220}
221
222MSList *ms_list_insert(MSList *list, MSList *before, void *data){
223        MSList *elem;
224        if (list==NULL || before==NULL) return ms_list_append(list,data);
225        for(elem=list;elem!=NULL;elem=ms_list_next(elem)){
226                if (elem==before){
227                        if (elem->prev==NULL)
228                                return ms_list_prepend(list,data);
229                        else{
230                                MSList *nelem=ms_list_new(data);
231                                nelem->prev=elem->prev;
232                                nelem->next=elem;
233                                elem->prev->next=nelem;
234                                elem->prev=nelem;
235                        }
236                }
237        }
238        return list;
239}
240
241MSList *ms_list_copy(const MSList *list){
242        MSList *copy=NULL;
243        const MSList *iter;
244        for(iter=list;iter!=NULL;iter=ms_list_next(iter)){
245                copy=ms_list_append(copy,iter->data);
246        }
247        return copy;
248}
249
250
251#ifdef __APPLE__
252#define PLUGINS_EXT ".dylib"
253#else
254#define PLUGINS_EXT ".so"
255#endif
256
257typedef void (*init_func_t)(void);
258
259int ms_load_plugins(const char *dir){
260    int num=0;
261#if defined(WIN32) && !defined(_WIN32_WCE)
262    WIN32_FIND_DATA FileData; 
263    HANDLE hSearch; 
264    char szDirPath[1024]; 
265    char szPluginFile[1024]; 
266    BOOL fFinished = FALSE;
267   
268        snprintf(szDirPath, sizeof(szDirPath), "%s", dir);
269    // Create a new directory.   
270#if 0
271    if (!CreateDirectory(szDirPath, NULL))
272    {
273        ms_message("plugins directory already exist (%s).", szDirPath);
274    }
275#endif
276   
277    // Start searching for .TXT files in the current directory.
278   
279        snprintf(szDirPath, sizeof(szDirPath), "%s\\*.dll", dir);
280    hSearch = FindFirstFile(szDirPath, &FileData);
281    if (hSearch == INVALID_HANDLE_VALUE)
282    {
283        ms_message("no plugin (*.dll) found in %s.", szDirPath);
284                return 0;
285    }
286        snprintf(szDirPath, sizeof(szDirPath), "%s", dir);
287
288    while (!fFinished) 
289    {
290        /* load library */
291        HINSTANCE os_handle;
292        UINT em;
293        em = SetErrorMode (SEM_FAILCRITICALERRORS);
294
295        snprintf(szPluginFile, sizeof(szPluginFile), "%s\\%s", szDirPath, FileData.cFileName);
296        os_handle = LoadLibraryEx (szPluginFile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
297        if (os_handle==NULL)
298        {
299                        ms_warning("Fail to load plugin %s: error %i",szPluginFile,GetLastError());
300            os_handle = LoadLibraryEx (szPluginFile, NULL, 0);
301        }
302        SetErrorMode (em);
303        if (os_handle==NULL)
304            ms_warning("Fail to load plugin %s", szPluginFile); 
305        else
306        {
307            init_func_t initroutine;
308            char szPluginName[256]; 
309            char szMethodName[256]; 
310            snprintf(szPluginName, 256, "%s", FileData.cFileName);
311            szPluginName[strlen(szPluginName)-4]='\0';
312            snprintf(szMethodName, 256, "%s_init", szPluginName);
313            initroutine = (init_func_t) GetProcAddress (os_handle, szMethodName);
314                        if (initroutine!=NULL){
315                                initroutine();
316                                ms_message("Plugin loaded (%s)", szPluginFile);
317                                num++;
318                        }else{
319                                ms_warning("Could not locate init routine of plugin %s", szPluginFile);
320                        }
321        }
322
323
324        if (!FindNextFile(hSearch, &FileData)) 
325        {
326            if (GetLastError() == ERROR_NO_MORE_FILES) 
327            { 
328                fFinished = TRUE; 
329            } 
330            else 
331            { 
332                ms_error("couldn't find next plugin dll."); 
333                fFinished = TRUE; 
334            } 
335        }
336    } 
337     
338    // Close the search handle.
339     
340    FindClose(hSearch);
341
342#elif HAVE_DLOPEN
343        DIR *ds;
344        struct dirent *de;
345        char *fullpath;
346        ds=opendir(dir);       
347        if (ds==NULL){
348                ms_message("Cannot open directory %s: %s",dir,strerror(errno));
349                return -1;
350        }
351        while( (de=readdir(ds))!=NULL){
352                if ((de->d_type==DT_REG && strstr(de->d_name,PLUGINS_EXT)!=NULL)
353                    || (de->d_type==DT_UNKNOWN && strstr(de->d_name,PLUGINS_EXT)==de->d_name+strlen(de->d_name)-strlen(PLUGINS_EXT))) {
354                        void *handle;
355                        fullpath=ms_strdup_printf("%s/%s",dir,de->d_name);
356                        ms_message("Loading plugin %s...",fullpath);
357                       
358                        if ( (handle=dlopen(fullpath,RTLD_NOW))==NULL){
359                                ms_warning("Fail to load plugin %s : %s",fullpath,dlerror());
360                        }else {
361                                char *initroutine_name=ms_malloc0(strlen(de->d_name)+10);
362                                char *p;
363                                void *initroutine=NULL;
364                                strcpy(initroutine_name,de->d_name);
365                                p=strstr(initroutine_name,PLUGINS_EXT);
366                                if (p!=NULL)
367                                  {
368                                    strcpy(p,"_init");
369                                    initroutine=dlsym(handle,initroutine_name);
370                                  }
371
372#ifdef __APPLE__
373                                if (initroutine==NULL){
374                                  /* on macosx: library name are libxxxx.1.2.3.dylib */
375                                  /* -> MUST remove the .1.2.3 */
376                                  p=strstr(initroutine_name,".");
377                                  if (p!=NULL)
378                                    {
379                                      strcpy(p,"_init");
380                                      initroutine=dlsym(handle,initroutine_name);
381                                    }
382                                }
383#endif
384
385                                if (initroutine!=NULL){
386                                        init_func_t func=(init_func_t)initroutine;
387                                        func();
388                                        ms_message("Plugin loaded (%s)", fullpath);
389                                        num++;
390                                }else{
391                                        ms_warning("Could not locate init routine of plugin %s",de->d_name);
392                                }
393                                ms_free(initroutine_name);
394                        }
395                        ms_free(fullpath);
396                }
397        }
398        closedir(ds);
399#else
400        ms_warning("no loadable plugin support: plugins cannot be loaded.");
401        num=-1;
402#endif
403        return num;
404}
405
406
407#ifdef __ALSA_ENABLED__
408extern MSSndCardDesc alsa_card_desc;
409#endif
410
411#ifdef HAVE_SYS_SOUNDCARD_H
412extern MSSndCardDesc oss_card_desc;
413#endif
414
415#ifdef __ARTS_ENABLED__
416extern MSSndCardDesc arts_card_desc;
417#endif
418
419#ifdef WIN32
420extern MSSndCardDesc winsnd_card_desc;
421#endif
422
423#ifdef __DIRECTSOUND_ENABLED__
424extern MSSndCardDesc winsndds_card_desc;
425#endif
426
427#ifdef __MACSND_ENABLED__
428extern MSSndCardDesc ca_card_desc;
429#endif
430
431#ifdef __PORTAUDIO_ENABLED__
432extern MSSndCardDesc pasnd_card_desc;
433#endif
434
435#ifdef __MAC_AQ_ENABLED__
436extern MSSndCardDesc aq_card_desc;
437#endif
438
439static MSSndCardDesc * ms_snd_card_descs[]={
440#ifdef __ALSA_ENABLED__
441        &alsa_card_desc,
442#endif
443#ifdef HAVE_SYS_SOUNDCARD_H
444        &oss_card_desc,
445#endif
446#ifdef __ARTS_ENABLED__
447        &arts_card_desc,
448#endif
449#ifdef WIN32
450        &winsnd_card_desc,
451#endif
452#ifdef __DIRECTSOUND_ENABLED__
453        &winsndds_card_desc,
454#endif
455#ifdef __PORTAUDIO_ENABLED__
456        &pasnd_card_desc,
457#endif
458#ifdef __MACSND_ENABLED__
459        &ca_card_desc,
460#endif
461#ifdef __MAC_AQ_ENABLED__
462        &aq_card_desc,
463#endif
464        NULL
465};
466
467#ifdef VIDEO_ENABLED
468
469#ifdef __linux
470extern MSWebCamDesc v4l_desc;
471#endif
472
473#ifdef HAVE_LINUX_VIDEODEV2_H
474extern MSWebCamDesc v4l2_desc;
475#endif
476
477#ifdef WIN32
478extern MSWebCamDesc ms_vfw_cam_desc;
479#endif
480#if defined(WIN32) && defined(HAVE_DIRECTSHOW)
481extern MSWebCamDesc ms_directx_cam_desc;
482#endif
483
484extern MSWebCamDesc static_image_desc;
485extern MSWebCamDesc mire_desc;
486
487static MSWebCamDesc * ms_web_cam_descs[]={
488#ifdef HAVE_LINUX_VIDEODEV2_H
489        &v4l2_desc,
490#endif
491#ifdef __linux
492        &v4l_desc,
493#endif
494#if defined(WIN32) && defined(HAVE_DIRECTSHOW)
495        &ms_directx_cam_desc,
496#endif
497#if defined(WIN32) && !defined(HAVE_DIRECTSHOW)
498        &ms_vfw_cam_desc,
499#endif
500        &mire_desc,
501        &static_image_desc,
502        NULL
503};
504
505#endif
506
507void ms_init(){
508        int i;
509        MSSndCardManager *cm;
510#ifdef __APPLE__
511        NSApplicationLoad();
512#endif
513
514#if !defined(_WIN32_WCE)
515        if (getenv("MEDIASTREAMER_DEBUG")!=NULL){
516                ortp_set_log_level_mask(ORTP_DEBUG|ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
517        }
518#endif
519        ms_message("Registering all filters...");
520        /* register builtin MSFilter's */
521        for (i=0;ms_filter_descs[i]!=NULL;i++){
522                ms_filter_register(ms_filter_descs[i]);
523        }
524        ms_message("Registering all soundcard handlers");
525        cm=ms_snd_card_manager_get();
526        for (i=0;ms_snd_card_descs[i]!=NULL;i++){
527                ms_snd_card_manager_register_desc(cm,ms_snd_card_descs[i]);
528        }
529
530#ifdef VIDEO_ENABLED
531        ms_message("Registering all webcam handlers");
532        {
533                MSWebCamManager *wm;
534                wm=ms_web_cam_manager_get();
535                for (i=0;ms_web_cam_descs[i]!=NULL;i++){
536                        ms_web_cam_manager_register_desc(wm,ms_web_cam_descs[i]);
537                }
538        }
539        __register_ffmpeg_encoders_if_possible();
540#endif
541        ms_message("Loading plugins");
542        ms_load_plugins(PACKAGE_PLUGINS_DIR);
543        ms_message("ms_init() done");
544}
545
546void ms_exit(){
547        ms_filter_unregister_all();
548        ms_snd_card_manager_destroy();
549#ifdef VIDEO_ENABLED
550        ms_web_cam_manager_destroy();
551#endif
552}
553
554void ms_reload_snd_card(MSSndCardDesc *snd_desc){
555        MSSndCardManager *cm;
556        int i;
557
558        ms_snd_card_manager_destroy();
559
560        ms_message("Registering all soundcard handlers");
561        if (snd_desc!=NULL)
562        {
563                cm=ms_snd_card_manager_get();
564                if (cm!=NULL)
565                        ms_snd_card_manager_register_desc(cm,snd_desc);
566                return;
567        }
568
569        /*register SndCardDesc */
570        cm=ms_snd_card_manager_get();
571        for (i=0;ms_snd_card_descs[i]!=NULL;i++){
572                ms_snd_card_manager_register_desc(cm,ms_snd_card_descs[i]);
573        }
574
575        return;
576}
577
578void ms_sleep(int seconds){
579#ifdef WIN32
580        Sleep(seconds*1000);
581#else
582        struct timespec ts,rem;
583        int err;
584        ts.tv_sec=seconds;
585        ts.tv_nsec=0;
586        do {
587                err=nanosleep(&ts,&rem);
588                ts=rem;
589        }while(err==-1 && errno==EINTR);
590#endif
591}
592
593#define DEFAULT_MAX_PAYLOAD_SIZE 1440
594
595static int max_payload_size=DEFAULT_MAX_PAYLOAD_SIZE;
596
597int ms_get_payload_max_size(){
598        return max_payload_size;
599}
600
601void ms_set_payload_max_size(int size){
602        if (size<=0) size=DEFAULT_MAX_PAYLOAD_SIZE;
603        max_payload_size=size;
604}
Note: See TracBrowser for help on using the repository browser.