source: mediastreamer2/tests/mediastream.c @ 1375:cc4c4148e0cb

Last change on this file since 1375:cc4c4148e0cb was 1375:cc4c4148e0cb, checked in by Simon Morlat <simon.morlat@…>, 2 years ago

Merge branch 'dev_videomac' of git://git.linphone.org/mediastreamer2 into dev_videomac

Conflicts:

tests/mediastream.c

File size: 14.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
24#include <math.h>
25
26#include "mediastreamer2/mediastream.h"
27#include "mediastreamer2/msequalizer.h"
28#include "mediastreamer2/msvolume.h"
29#ifdef VIDEO_ENABLED
30#include "mediastreamer2/msv4l.h"
31#endif
32
33#include <signal.h>
34#include <sys/types.h>
35#ifndef WIN32
36#include <unistd.h>
37#else
38#include <malloc.h>
39#endif
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43
44#ifdef __APPLE__
45#include <CoreFoundation/CFRunLoop.h>
46#endif
47
48static int cond=1;
49
50static const char * capture_card=NULL;
51static const char * playback_card=NULL;
52static const char * camera=NULL;
53static const char *infile=NULL,*outfile=NULL;
54static float ng_threshold=-1;
55static bool_t use_ng=FALSE;
56static bool_t two_windows=FALSE;
57static bool_t el=FALSE;
58static float el_speed=-1;
59static float el_thres=-1;
60static float el_force=-1;
61static int el_sustain=-1;
62static float el_transmit_thres=-1;
63static float ng_floorgain=-1;
64
65/* starting values echo canceller */
66static int ec_len_ms=0, ec_delay_ms=0, ec_framesize=0;
67
68static void run_media_streams(int localport, const char *remote_ip, int remoteport, int payload, const char *fmtp,
69          int jitter, int bitrate, MSVideoSize vs, bool_t ec, bool_t agc, bool_t eq);
70
71static void stop_handler(int signum)
72{
73        cond--;
74        if (cond<0) exit(-1);
75}
76
77static bool_t parse_addr(const char *addr, char *ip, int len, int *port)
78{
79        const char *semicolon=NULL;
80        int iplen;
81        int slen;
82        const char *p;
83
84        *port=0;
85        semicolon=strchr(addr,':');
86        for (p=addr+strlen(addr)-1;p>addr;p--){
87                if (*p==':') {
88                        semicolon=p;
89                        break;
90                }
91        }
92        if (semicolon==NULL) return FALSE;
93        iplen=semicolon-addr;
94        slen=MIN(iplen,len-1);
95        strncpy(ip,addr,slen);
96        ip[slen]='\0';
97        *port=atoi(semicolon+1);
98        return TRUE;
99}
100
101static void display_items(void *user_data, uint32_t csrc, rtcp_sdes_type_t t, const char *content, uint8_t content_len){
102        char str[256];
103        int len=MIN(sizeof(str)-1,content_len);
104        strncpy(str,content,len);
105        str[len]='\0';
106        switch(t){
107                case RTCP_SDES_CNAME:
108                        ms_message("Found CNAME=%s",str);
109                break;
110                case RTCP_SDES_TOOL:
111                        ms_message("Found TOOL=%s",str);
112                break;
113                case RTCP_SDES_NOTE:
114                        ms_message("Found NOTE=%s",str);
115                break;
116                default:
117                        ms_message("Unhandled SDES item (%s)",str);
118        }
119}
120
121static void parse_rtcp(mblk_t *m){
122        do{
123                if (rtcp_is_RR(m)){
124                        ms_message("Receiving RTCP RR");
125                }else if (rtcp_is_SR(m)){
126                        ms_message("Receiving RTCP SR");
127                }else if (rtcp_is_SDES(m)){
128                        ms_message("Receiving RTCP SDES");
129                        rtcp_sdes_parse(m,display_items,NULL);
130                }else {
131                        ms_message("Receiving unhandled RTCP message");
132                }
133        }while(rtcp_next_packet(m));
134}
135
136static void parse_events(OrtpEvQueue *q){
137        OrtpEvent *ev;
138        while((ev=ortp_ev_queue_get(q))!=NULL){
139                OrtpEventData *d=ortp_event_get_data(ev);
140                switch(ortp_event_get_type(ev)){
141                        case ORTP_EVENT_RTCP_PACKET_RECEIVED:
142                                parse_rtcp(d->packet);
143                        break;
144                        default:
145                                ms_warning("Unhandled ortp event.");
146                }
147                ortp_event_destroy(ev);
148        }
149}
150
151const char *usage="mediastream --local <port> --remote <ip:port> --payload <payload type number>\n"
152                                                                "[ --fmtp <fmtpline>]\n"
153                                                                "[ --jitter <miliseconds>]\n"
154                                                                "[ --width <pixels>]\n"
155                                                                "[ --height <pixels> ]\n"
156                                                                "[ --bitrate <bits per seconds>]\n"
157                                                                "[ --ec (enable echo canceller)]\n"
158                                                                "[ --ec-tail <echo canceller tail length in ms> ]\n"
159                                                                "[ --ec-delay <echo canceller delay in ms> ]\n"
160                                                                "[ --ec-framesize <echo canceller framesize in samples> ]\n"
161                                                                "[ --agc (enable automatic gain control)]\n"
162                                                                "[ --ng (enable noise gate)]\n"
163                                                                "[ --ng-threshold <(float) [0-1]> (noise gate threshold)]\n"
164                                                                "[ --ng-floorgain <(float) [0-1]> (gain applied to the signal when its energy is below the threshold.)]\n"
165                                                                "[ --capture-card <name>] \n"
166                                                                "[ --playback-card <name>] \n"
167                                                                "[ --infile     <input wav file>] specify a wav file to be used for input, instead of soundcard\n"
168                                                                "[ --outfile <output wav file>] specify a wav file to write audio into, instead of soundcard\n"
169                                                                "[ --camera <camera id as listed at startup> ]\n"
170                                                                "[ --el (enable echo limiter) ]\n"
171                                                                "[ --el-speed <(float) [0-1]> (gain changes are smoothed with a coefficent) ]\n"
172                                                                "[ --el-thres <(float) [0-1]> (Threshold above which the system becomes active) ]\n"
173                                                                "[ --el-force <(float) [0-1]> (The proportional coefficient controlling the mic attenuation) ]\n"
174                                                                "[ --el-sustain <(int)> (Time in milliseconds for which the attenuation is kept unchanged after) ]\n"
175                                                                "[ --el-transmit-thres <(float) [0-1]> (TO BE DOCUMENTED) ]\n";
176
177
178int main(int argc, char * argv[])
179{
180        int i;
181        int localport=0,remoteport=0,payload=0;
182        char ip[50];
183        const char *fmtp=NULL;
184        int jitter=50;
185        int bitrate=0;
186        MSVideoSize vs;
187        bool_t ec=FALSE;
188        bool_t agc=FALSE;
189        bool_t eq=FALSE;
190
191
192        /*create the rtp session */
193        ortp_init();
194        ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
195        rtp_profile_set_payload(&av_profile,115,&payload_type_lpc1015);
196        rtp_profile_set_payload(&av_profile,110,&payload_type_speex_nb);
197        rtp_profile_set_payload(&av_profile,111,&payload_type_speex_wb);
198        rtp_profile_set_payload(&av_profile,112,&payload_type_ilbc);
199        rtp_profile_set_payload(&av_profile,113,&payload_type_amr);
200#ifdef VIDEO_ENABLED
201        rtp_profile_set_payload(&av_profile,26,&payload_type_jpeg);
202        rtp_profile_set_payload(&av_profile,98,&payload_type_h263_1998);
203        rtp_profile_set_payload(&av_profile,97,&payload_type_theora);
204        rtp_profile_set_payload(&av_profile,99,&payload_type_mp4v);
205        rtp_profile_set_payload(&av_profile,100,&payload_type_x_snow);
206        rtp_profile_set_payload(&av_profile,102,&payload_type_h264);
207#endif
208
209        vs.width=MS_VIDEO_SIZE_CIF_W;
210        vs.height=MS_VIDEO_SIZE_CIF_H;
211        if (argc<4) {
212                printf("%s",usage);
213                return -1;
214        }
215        for (i=1;i<argc;i++){
216                if (strcmp(argv[i],"--local")==0){
217                        i++;
218                        localport=atoi(argv[i]);
219                }else if (strcmp(argv[i],"--remote")==0){
220                        i++;
221                        if (!parse_addr(argv[i],ip,sizeof(ip),&remoteport)) {
222                                printf("%s",usage);
223                                return -1;
224                        }
225                        printf("Remote addr: ip=%s port=%i\n",ip,remoteport);
226                }else if (strcmp(argv[i],"--payload")==0){
227                        i++;
228                        payload=atoi(argv[i]);
229                }else if (strcmp(argv[i],"--fmtp")==0){
230                        i++;
231                        fmtp=argv[i];
232                }else if (strcmp(argv[i],"--jitter")==0){
233                        i++;
234                        jitter=atoi(argv[i]);
235                }else if (strcmp(argv[i],"--bitrate")==0){
236                        i++;
237                        bitrate=atoi(argv[i]);
238                }else if (strcmp(argv[i],"--width")==0){
239                        i++;
240                        vs.width=atoi(argv[i]);
241                }else if (strcmp(argv[i],"--height")==0){
242                        i++;
243                        vs.height=atoi(argv[i]);
244                }else if (strcmp(argv[i],"--capture-card")==0){
245                        i++;
246                        capture_card=argv[i];
247                }else if (strcmp(argv[i],"--playback-card")==0){
248                        i++;
249                        playback_card=argv[i];
250                }else if (strcmp(argv[i],"--ec")==0){
251                        ec=TRUE;
252                }else if (strcmp(argv[i],"--ec-tail")==0){
253                        i++;
254                        ec_len_ms=atoi(argv[i]);
255                }else if (strcmp(argv[i],"--ec-delay")==0){
256                        i++;
257                        ec_delay_ms=atoi(argv[i]);
258                }else if (strcmp(argv[i],"--ec-framesize")==0){
259                        i++;
260                        ec_framesize=atoi(argv[i]);
261                }else if (strcmp(argv[i],"--agc")==0){
262                        agc=TRUE;
263                }else if (strcmp(argv[i],"--eq")==0){
264                        eq=TRUE;
265                }else if (strcmp(argv[i],"--ng")==0){
266                        use_ng=1;
267                }else if (strcmp(argv[i],"--ng-threshold")==0){
268                        i++;
269                        ng_threshold=atof(argv[i]);
270                }else if (strcmp(argv[i],"--ng-floorgain")==0){
271                        i++;
272                        ng_floorgain=atof(argv[i]);
273                }else if (strcmp(argv[i],"--two-windows")==0){
274                        two_windows=TRUE;
275                }else if (strcmp(argv[i],"--infile")==0){
276                        i++;
277                        infile=argv[i];
278                }else if (strcmp(argv[i],"--outfile")==0){
279                        i++;
280                        outfile=argv[i];
281                }else if (strcmp(argv[i],"--camera")==0){
282                        i++;
283                        camera=argv[i];
284                }else if (strcmp(argv[i],"--el")==0){
285                        el=TRUE;
286                }else if (strcmp(argv[i],"--el-speed")==0){
287                        i++;
288                        el_speed=atof(argv[i]);
289                }else if (strcmp(argv[i],"--el-thres")==0){
290                        i++;
291                        el_thres=atof(argv[i]);
292                }else if (strcmp(argv[i],"--el-force")==0){
293                        i++;
294                        el_force=atof(argv[i]);
295                }else if (strcmp(argv[i],"--el-sustain")==0){
296                        i++;
297                        el_sustain=atoi(argv[i]);
298                }else if (strcmp(argv[i],"--el-transmit-thres")==0){
299                        i++;
300                        el_transmit_thres=atof(argv[i]);
301                }else if (strcmp(argv[i],"--help")==0){
302                        printf("%s",usage);
303                        return -1;
304                }
305
306        }
307
308        run_media_streams(localport,ip,remoteport,payload,fmtp,jitter,bitrate,vs,ec,agc,eq);
309        return 0;
310}
311
312static void run_media_streams(int localport, const char *remote_ip, int remoteport, int payload, const char *fmtp,
313          int jitter, int bitrate, MSVideoSize vs, bool_t ec, bool_t agc, bool_t eq)
314{
315        AudioStream *audio=NULL;
316#ifdef VIDEO_ENABLED
317        VideoStream *video=NULL;
318        MSWebCam *cam=NULL;
319#endif
320        RtpSession *session=NULL;
321        PayloadType *pt;
322        RtpProfile *profile=rtp_profile_clone_full(&av_profile);
323        OrtpEvQueue *q=ortp_ev_queue_new();     
324
325        ms_init();
326        signal(SIGINT,stop_handler);
327        pt=rtp_profile_get_payload(profile,payload);
328        if (pt==NULL){
329                printf("Error: no payload defined with number %i.",payload);
330                exit(-1);
331        }
332        if (fmtp!=NULL) payload_type_set_send_fmtp(pt,fmtp);
333        if (bitrate>0) pt->normal_bitrate=bitrate;
334
335        if (pt->type!=PAYLOAD_VIDEO){
336                MSSndCardManager *manager=ms_snd_card_manager_get();
337                MSSndCard *capt= capture_card==NULL ? ms_snd_card_manager_get_default_capture_card(manager) :
338                                ms_snd_card_manager_get_card(manager,capture_card);
339                MSSndCard *play= playback_card==NULL ? ms_snd_card_manager_get_default_playback_card(manager) :
340                                ms_snd_card_manager_get_card(manager,playback_card);
341                audio=audio_stream_new(localport,ms_is_ipv6(remote_ip));
342                audio_stream_enable_automatic_gain_control(audio,agc);
343                audio_stream_enable_noise_gate(audio,use_ng);
344                audio_stream_set_echo_canceller_params(audio,ec_len_ms,ec_delay_ms,ec_framesize);
345                audio_stream_enable_echo_limiter(audio,el);
346                printf("Starting audio stream.\n");
347       
348                audio_stream_start_full(audio,profile,remote_ip,remoteport,remoteport+1, payload, jitter,infile,outfile,
349                                        outfile==NULL ? play : NULL ,infile==NULL ? capt : NULL,infile!=NULL ? FALSE: ec);
350               
351                if (audio) {
352                        if (el) {
353                                if (el_speed!=-1)
354                                        ms_filter_call_method(audio->volsend,MS_VOLUME_SET_EA_SPEED,&el_speed);
355                                if (el_force!=-1)
356                                        ms_filter_call_method(audio->volsend,MS_VOLUME_SET_EA_FORCE,&el_force);
357                                if (el_thres!=-1)
358                                        ms_filter_call_method(audio->volsend,MS_VOLUME_SET_EA_THRESHOLD,&el_thres);
359                                if (el_sustain!=-1)
360                                        ms_filter_call_method(audio->volsend,MS_VOLUME_SET_EA_SUSTAIN,&el_sustain);
361                                if (el_transmit_thres!=-1)
362                                        ms_filter_call_method(audio->volsend,MS_VOLUME_SET_EA_TRANSMIT_THRESHOLD,&el_transmit_thres);
363
364                        }
365                        if (use_ng){
366                                if (ng_threshold!=-1) {
367                                        ms_filter_call_method(audio->volsend,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_threshold);
368                                        ms_filter_call_method(audio->volrecv,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_threshold);
369                                }
370                                if (ng_floorgain != -1) {
371                                        ms_filter_call_method(audio->volsend,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&ng_floorgain);
372                                        ms_filter_call_method(audio->volrecv,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&ng_floorgain);
373                                }
374                        }
375                        session=audio->session;
376                }
377        }else{
378#ifdef VIDEO_ENABLED
379                if (eq){
380                        ms_fatal("Cannot put an audio equalizer in a video stream !");
381                        exit(-1);
382                }
383                printf("Starting video stream.\n");
384                video=video_stream_new(localport, ms_is_ipv6(remote_ip));
385                video_stream_set_sent_video_size(video,vs);
386                video_stream_use_preview_video_window(video,two_windows);
387               
388                if (camera)
389                        cam=ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),camera);
390                if (cam==NULL)
391                        cam=ms_web_cam_manager_get_default_cam(ms_web_cam_manager_get());
392                video_stream_start(video,profile,
393                                        remote_ip,
394                                        remoteport,remoteport+1,
395                                        payload,
396                                        jitter,cam
397                                        );
398                session=video->session;
399#else
400                printf("Error: video support not compiled.\n");
401#endif
402        }
403        if (eq){ /*read from stdin interactive commands */
404                char commands[128];
405                commands[127]='\0';
406                ms_sleep(1);  /* ensure following text be printed after ortp messages */
407                if (eq)
408                printf("\nPlease enter equalizer requests, such as 'eq active 1', 'eq active 0', 'eq 1200 0.1 200'\n");
409
410                while(fgets(commands,sizeof(commands)-1,stdin)!=NULL){
411                        int active,freq,freq_width;
412
413                        float gain;
414                        if (sscanf(commands,"eq active %i",&active)==1){
415                                audio_stream_enable_equalizer(audio,active);
416                                printf("OK\n");
417                        }else if (sscanf(commands,"eq %i %f %i",&freq,&gain,&freq_width)==3){
418                                audio_stream_equalizer_set_gain(audio,freq,gain,freq_width);
419                                printf("OK\n");
420                        }else if (sscanf(commands,"eq %i %f",&freq,&gain)==2){
421                                audio_stream_equalizer_set_gain(audio,freq,gain,0);
422                                printf("OK\n");
423                        }else if (strstr(commands,"dump")){
424                                int n=0,i;
425                                float *t;
426                                ms_filter_call_method(audio->equalizer,MS_EQUALIZER_GET_NUM_FREQUENCIES,&n);
427                                t=(float*)alloca(sizeof(float)*n);
428                                ms_filter_call_method(audio->equalizer,MS_EQUALIZER_DUMP_STATE,t);
429                                for(i=0;i<n;++i){
430                                        if (fabs(t[i]-1)>0.01){
431                                        printf("%i:%f:0 ",(i*pt->clock_rate)/(2*n),t[i]);
432                                        }
433                                }
434                                printf("\nOK\n");
435                        } else if (strstr(commands,"quit")){
436                                break;
437                        }else printf("Cannot understand this.\n");
438                }
439        }else{  /* no interactive stuff - continuous debug output */
440                rtp_session_register_event_queue(session,q);
441
442                #ifdef __APPLE__
443                CFRunLoopRun();
444                #else
445                while(cond)
446                {
447                        int n;
448                        for(n=0;n<100;++n){
449        #ifdef WIN32
450                                MSG msg;
451                                Sleep(10);
452                                while (PeekMessage(&msg, NULL, 0, 0,1)){
453                                        TranslateMessage(&msg);
454                                        DispatchMessage(&msg);
455                                }
456        #else
457                                struct timespec ts;
458                                ts.tv_sec=0;
459                                ts.tv_nsec=10000000;
460                                nanosleep(&ts,NULL);
461        #endif
462        #if defined(VIDEO_ENABLED)
463                                if (video) video_stream_iterate(video);
464        #endif
465                        }
466                        ortp_global_stats_display();
467                        if (session){
468                                printf("Bandwidth usage: download=%f kbits/sec, upload=%f kbits/sec\n",
469                                        rtp_session_compute_recv_bandwidth(session)*1e-3,
470                                        rtp_session_compute_send_bandwidth(session)*1e-3);
471                                parse_events(q);
472                        }
473                }
474        #endif // target MAC
475        }
476       
477        printf("stopping all...\n");
478       
479        if (audio) audio_stream_stop(audio);
480#ifdef VIDEO_ENABLED
481        if (video) video_stream_stop(video);
482#endif
483        ortp_ev_queue_destroy(q);
484        rtp_profile_destroy(profile);
485}
486
Note: See TracBrowser for help on using the repository browser.