source: mediastreamer2/src/audiostream.c @ 1015:a977425ae3c7

Last change on this file since 1015:a977425ae3c7 was 1015:a977425ae3c7, checked in by Simon Morlat <simon.morlat@…>, 3 years ago

merge msvolume improvements by rob

File size: 21.7 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
21#ifdef HAVE_CONFIG_H
22#include "mediastreamer-config.h"
23#endif
24
25#include "mediastreamer2/mediastream.h"
26
27#include "mediastreamer2/dtmfgen.h"
28#include "mediastreamer2/mssndcard.h"
29#include "mediastreamer2/msrtp.h"
30#include "mediastreamer2/msfileplayer.h"
31#include "mediastreamer2/msfilerec.h"
32#include "mediastreamer2/msvolume.h"
33#include "mediastreamer2/msequalizer.h"
34
35#ifdef INET6
36        #include <sys/types.h>
37#ifndef WIN32
38        #include <sys/socket.h>
39        #include <netdb.h>
40#endif
41#endif
42
43
44#define MAX_RTP_SIZE    1500
45
46
47/* this code is not part of the library itself, it is part of the mediastream program */
48void audio_stream_free(AudioStream *stream)
49{
50        if (stream->session!=NULL) rtp_session_destroy(stream->session);
51        if (stream->rtpsend!=NULL) ms_filter_destroy(stream->rtpsend);
52        if (stream->rtprecv!=NULL) ms_filter_destroy(stream->rtprecv);
53        if (stream->soundread!=NULL) ms_filter_destroy(stream->soundread);
54        if (stream->soundwrite!=NULL) ms_filter_destroy(stream->soundwrite);
55        if (stream->encoder!=NULL) ms_filter_destroy(stream->encoder);
56        if (stream->decoder!=NULL) ms_filter_destroy(stream->decoder);
57        if (stream->dtmfgen!=NULL) ms_filter_destroy(stream->dtmfgen);
58        if (stream->ec!=NULL)   ms_filter_destroy(stream->ec);
59        if (stream->volrecv!=NULL) ms_filter_destroy(stream->volrecv);
60        if (stream->volsend!=NULL) ms_filter_destroy(stream->volsend);
61        if (stream->equalizer!=NULL) ms_filter_destroy(stream->equalizer);
62        if (stream->ticker!=NULL) ms_ticker_destroy(stream->ticker);
63        if (stream->read_resampler!=NULL) ms_filter_destroy(stream->read_resampler);
64        if (stream->write_resampler!=NULL) ms_filter_destroy(stream->write_resampler);
65        ms_free(stream);
66}
67
68static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'};
69
70static void on_dtmf_received(RtpSession *s, int dtmf, void * user_data)
71{
72        AudioStream *stream=(AudioStream*)user_data;
73        if (dtmf>15){
74                ms_warning("Unsupported telephone-event type.");
75                return;
76        }
77        ms_message("Receiving dtmf %c.",dtmf_tab[dtmf]);
78        if (stream->dtmfgen!=NULL && stream->play_dtmfs){
79                ms_filter_call_method(stream->dtmfgen,MS_DTMF_GEN_PUT,&dtmf_tab[dtmf]);
80        }
81}
82
83bool_t ms_is_ipv6(const char *remote){
84        bool_t ret=FALSE;
85#ifdef INET6
86        struct addrinfo hints, *res0;
87
88        int err;
89        memset(&hints, 0, sizeof(hints));
90        hints.ai_family = PF_UNSPEC;
91        hints.ai_socktype = SOCK_DGRAM;
92        err = getaddrinfo(remote,"8000", &hints, &res0);
93        if (err!=0) {
94                ms_warning ("get_local_addr_for: %s", gai_strerror(err));
95                return FALSE;
96        }
97        ret=(res0->ai_addr->sa_family==AF_INET6);
98        freeaddrinfo(res0);
99#endif
100        return ret;
101}
102
103static void audio_stream_configure_resampler(MSFilter *resampler,MSFilter *from,MSFilter *to) {
104        int from_rate=0, to_rate=0;
105        ms_filter_call_method(from,MS_FILTER_GET_SAMPLE_RATE,&from_rate);
106        ms_filter_call_method(to,MS_FILTER_GET_SAMPLE_RATE,&to_rate);
107        ms_filter_call_method(resampler,MS_FILTER_SET_SAMPLE_RATE,&from_rate);
108        ms_filter_call_method(resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&to_rate);
109        ms_debug("configuring from rate[%i] to rate [%i]",from_rate,to_rate);
110}
111
112RtpSession * create_duplex_rtpsession( int locport, bool_t ipv6){
113        RtpSession *rtpr;
114        rtpr=rtp_session_new(RTP_SESSION_SENDRECV);
115        rtp_session_set_recv_buf_size(rtpr,MAX_RTP_SIZE);
116        rtp_session_set_scheduling_mode(rtpr,0);
117        rtp_session_set_blocking_mode(rtpr,0);
118        rtp_session_enable_adaptive_jitter_compensation(rtpr,TRUE);
119        rtp_session_set_symmetric_rtp(rtpr,TRUE);
120        rtp_session_set_local_addr(rtpr,ipv6 ? "::" : "0.0.0.0",locport);
121        rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)rtp_session_resync,(long)NULL);
122        rtp_session_signal_connect(rtpr,"ssrc_changed",(RtpCallback)rtp_session_resync,(long)NULL);
123        rtp_session_set_ssrc_changed_threshold(rtpr,0);
124        return rtpr;
125}
126
127#if defined(_WIN32_WCE)
128time_t
129ms_time (time_t *t)
130{
131    DWORD timemillis = GetTickCount();
132        if (timemillis>0)
133        {
134                if (t!=NULL)
135                        *t = timemillis/1000;
136        }
137        return timemillis/1000;
138}
139#endif
140
141bool_t audio_stream_alive(AudioStream * stream, int timeout){
142        RtpSession *session=stream->session;
143        const rtp_stats_t *stats=rtp_session_get_stats(session);
144        if (stats->recv!=0){
145                if (stats->recv!=stream->last_packet_count){
146                        stream->last_packet_count=stats->recv;
147                        stream->last_packet_time=ms_time(NULL);
148                }else{
149                        if (ms_time(NULL)-stream->last_packet_time>timeout){
150                                /* more than timeout seconds of inactivity*/
151                                return FALSE;
152                        }
153                }
154        }
155        return TRUE;
156}
157
158/*this function must be called from the MSTicker thread:
159it replaces one filter by another one.
160This is a dirty hack that works anyway.
161It would be interesting to have something that does the job
162simplier within the MSTicker api
163*/
164void audio_stream_change_decoder(AudioStream *stream, int payload){
165        RtpSession *session=stream->session;
166        RtpProfile *prof=rtp_session_get_profile(session);
167        PayloadType *pt=rtp_profile_get_payload(prof,payload);
168        if (pt!=NULL){
169                MSFilter *dec=ms_filter_create_decoder(pt->mime_type);
170                if (dec!=NULL){
171                        ms_filter_unlink(stream->rtprecv, 0, stream->decoder, 0);
172                        ms_filter_unlink(stream->decoder,0,stream->dtmfgen,0);
173                        ms_filter_postprocess(stream->decoder);
174                        ms_filter_destroy(stream->decoder);
175                        stream->decoder=dec;
176                        if (pt->recv_fmtp!=NULL)
177                                ms_filter_call_method(stream->decoder,MS_FILTER_ADD_FMTP,(void*)pt->recv_fmtp);
178                        ms_filter_link (stream->rtprecv, 0, stream->decoder, 0);
179                        ms_filter_link (stream->decoder,0 , stream->dtmfgen, 0);
180                        ms_filter_preprocess(stream->decoder,stream->ticker);
181
182                }else{
183                        ms_warning("No decoder found for %s",pt->mime_type);
184                }
185        }else{
186                ms_warning("No payload defined with number %i",payload);
187        }
188}
189
190static void payload_type_changed(RtpSession *session, unsigned long data){
191        AudioStream *stream=(AudioStream*)data;
192        int pt=rtp_session_get_recv_payload_type(stream->session);
193        audio_stream_change_decoder(stream,pt);
194}
195
196
197int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char *remip,int remport,
198        int rem_rtcp_port, int payload,int jitt_comp, const char *infile, const char *outfile,
199        MSSndCard *playcard, MSSndCard *captcard, bool_t use_ec)
200{
201        RtpSession *rtps=stream->session;
202        PayloadType *pt;
203        int tmp;
204        MSConnectionHelper h;
205
206        rtp_session_set_profile(rtps,profile);
207        if (remport>0) rtp_session_set_remote_addr_full(rtps,remip,remport,rem_rtcp_port);
208        rtp_session_set_payload_type(rtps,payload);
209        rtp_session_set_jitter_compensation(rtps,jitt_comp);
210
211        if (remport>0)
212                ms_filter_call_method(stream->rtpsend,MS_RTP_SEND_SET_SESSION,rtps);
213        stream->rtprecv=ms_filter_new(MS_RTP_RECV_ID);
214        ms_filter_call_method(stream->rtprecv,MS_RTP_RECV_SET_SESSION,rtps);
215        stream->session=rtps;
216
217        stream->dtmfgen=ms_filter_new(MS_DTMF_GEN_ID);
218        rtp_session_signal_connect(rtps,"telephone-event",(RtpCallback)on_dtmf_received,(unsigned long)stream);
219        rtp_session_signal_connect(rtps,"payload_type_changed",(RtpCallback)payload_type_changed,(unsigned long)stream);
220
221        /* creates the local part */
222        if (captcard!=NULL) stream->soundread=ms_snd_card_create_reader(captcard);
223        else {
224                stream->soundread=ms_filter_new(MS_FILE_PLAYER_ID);
225                stream->read_resampler=ms_filter_new(MS_RESAMPLE_ID);
226                if (infile!=NULL) audio_stream_play(stream,infile);
227        }
228        if (playcard!=NULL) stream->soundwrite=ms_snd_card_create_writer(playcard);
229        else {
230                stream->soundwrite=ms_filter_new(MS_FILE_REC_ID);
231                if (outfile!=NULL) audio_stream_record(stream,outfile);
232        }
233
234        /* creates the couple of encoder/decoder */
235        pt=rtp_profile_get_payload(profile,payload);
236        if (pt==NULL){
237                ms_error("audiostream.c: undefined payload type.");
238                return -1;
239        }
240        stream->encoder=ms_filter_create_encoder(pt->mime_type);
241        stream->decoder=ms_filter_create_decoder(pt->mime_type);
242        if ((stream->encoder==NULL) || (stream->decoder==NULL)){
243                /* big problem: we have not a registered codec for this payload...*/
244                ms_error("mediastream.c: No decoder available for payload %i.",payload);
245                return -1;
246        }
247
248        if (use_ec) {
249                stream->ec=ms_filter_new(MS_SPEEX_EC_ID);
250                ms_filter_call_method(stream->ec,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate);
251                if (stream->ec_tail_len!=0)
252                        ms_filter_call_method(stream->ec,MS_ECHO_CANCELLER_SET_TAIL_LENGTH,&stream->ec_tail_len);
253                if (stream->ec_delay!=0)
254                        ms_filter_call_method(stream->ec,MS_ECHO_CANCELLER_SET_DELAY,&stream->ec_delay);
255                if (stream->ec_framesize!=0)
256                        ms_filter_call_method(stream->ec,MS_ECHO_CANCELLER_SET_FRAMESIZE,&stream->ec_framesize);
257        }
258
259        if (stream->el_type!=ELInactive || stream->use_gc || stream->use_ng){
260                stream->volsend=ms_filter_new(MS_VOLUME_ID);
261                stream->volrecv=ms_filter_new(MS_VOLUME_ID);
262                if (stream->el_type!=ELInactive){
263                        if (stream->el_type==ELControlFull) {
264                                /* also reduce speaker gain when no signal - same parameters as std. noise gate */
265                                int tmp=1;
266                                ms_filter_call_method(stream->volrecv,MS_VOLUME_ENABLE_NOISE_GATE,&tmp);
267                        }
268                        ms_filter_call_method(stream->volsend,MS_VOLUME_SET_PEER,stream->volrecv);
269                }
270                if (stream->use_ng){
271                        int tmp=1;
272                        ms_filter_call_method(stream->volsend,MS_VOLUME_ENABLE_NOISE_GATE,&tmp);
273                }
274        }
275
276        if (stream->use_agc){
277                int tmp=1;
278                if (stream->volsend==NULL)
279                        stream->volsend=ms_filter_new(MS_VOLUME_ID);
280                ms_filter_call_method(stream->volsend,MS_VOLUME_ENABLE_AGC,&tmp);
281        }
282
283        /* give the sound filters some properties */
284        if (ms_filter_call_method(stream->soundread,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate) != 0) {
285                /* need to add resampler*/
286                if (stream->read_resampler == NULL) stream->read_resampler=ms_filter_new(MS_RESAMPLE_ID);
287        }
288
289        if (ms_filter_call_method(stream->soundwrite,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate) != 0) {
290                /* need to add resampler*/
291                if (stream->write_resampler == NULL) stream->write_resampler=ms_filter_new(MS_RESAMPLE_ID);
292        }
293
294
295        tmp=1;
296        ms_filter_call_method(stream->soundwrite,MS_FILTER_SET_NCHANNELS, &tmp);
297
298        /* give the encoder/decoder some parameters*/
299        ms_filter_call_method(stream->encoder,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate);
300        ms_message("Payload's bitrate is %i",pt->normal_bitrate);
301        if (pt->normal_bitrate>0){
302                ms_message("Setting audio encoder network bitrate to %i",pt->normal_bitrate);
303                ms_filter_call_method(stream->encoder,MS_FILTER_SET_BITRATE,&pt->normal_bitrate);
304        }
305        ms_filter_call_method(stream->decoder,MS_FILTER_SET_SAMPLE_RATE,&pt->clock_rate);
306
307        if (pt->send_fmtp!=NULL) ms_filter_call_method(stream->encoder,MS_FILTER_ADD_FMTP, (void*)pt->send_fmtp);
308        if (pt->recv_fmtp!=NULL) ms_filter_call_method(stream->decoder,MS_FILTER_ADD_FMTP,(void*)pt->recv_fmtp);
309
310        /*create the equalizer*/
311        stream->equalizer=ms_filter_new(MS_EQUALIZER_ID);
312        tmp=stream->eq_active;
313        ms_filter_call_method(stream->equalizer,MS_EQUALIZER_SET_ACTIVE,&tmp);
314        /*configure resampler if needed*/
315        if (stream->read_resampler){
316                audio_stream_configure_resampler(stream->read_resampler,stream->soundread,stream->rtpsend);
317        }
318
319        if (stream->write_resampler){
320                audio_stream_configure_resampler(stream->write_resampler,stream->rtprecv,stream->soundwrite);
321        }
322        /* and then connect all */
323        /* tip: draw yourself the picture if you don't understand */
324
325        /*sending graph*/
326        ms_connection_helper_start(&h);
327        ms_connection_helper_link(&h,stream->soundread,-1,0);
328        if (stream->read_resampler)
329                ms_connection_helper_link(&h,stream->read_resampler,0,0);
330        if (stream->ec)
331                ms_connection_helper_link(&h,stream->ec,1,1);
332        if (stream->volsend)
333                ms_connection_helper_link(&h,stream->volsend,0,0);
334        ms_connection_helper_link(&h,stream->encoder,0,0);
335        ms_connection_helper_link(&h,stream->rtpsend,0,-1);
336
337        /*receiving graph*/
338        ms_connection_helper_start(&h);
339        ms_connection_helper_link(&h,stream->rtprecv,-1,0);
340        ms_connection_helper_link(&h,stream->decoder,0,0);
341        ms_connection_helper_link(&h,stream->dtmfgen,0,0);
342        if (stream->equalizer)
343                ms_connection_helper_link(&h,stream->equalizer,0,0);
344        if (stream->volrecv)
345                ms_connection_helper_link(&h,stream->volrecv,0,0);
346        if (stream->ec)
347                ms_connection_helper_link(&h,stream->ec,0,0);
348        if (stream->write_resampler)
349                ms_connection_helper_link(&h,stream->write_resampler,0,0);
350        ms_connection_helper_link(&h,stream->soundwrite,0,-1);
351
352        /* create ticker */
353        stream->ticker=ms_ticker_new();
354        ms_ticker_set_name(stream->ticker,"Audio MSTicker");
355        ms_ticker_attach(stream->ticker,stream->soundread);
356        ms_ticker_attach(stream->ticker,stream->rtprecv);
357
358        return 0;
359}
360
361
362int audio_stream_start_with_files(AudioStream *stream, RtpProfile *prof,const char *remip, int remport,
363        int rem_rtcp_port, int pt,int jitt_comp, const char *infile, const char * outfile)
364{
365        return audio_stream_start_full(stream,prof,remip,remport,rem_rtcp_port,pt,jitt_comp,infile,outfile,NULL,NULL,FALSE);
366}
367
368AudioStream * audio_stream_start(RtpProfile *prof,int locport,const char *remip,int remport,int profile,int jitt_comp,bool_t use_ec)
369{
370        MSSndCard *sndcard_playback;
371        MSSndCard *sndcard_capture;
372        AudioStream *stream;
373        sndcard_capture=ms_snd_card_manager_get_default_capture_card(ms_snd_card_manager_get());
374        sndcard_playback=ms_snd_card_manager_get_default_playback_card(ms_snd_card_manager_get());
375        if (sndcard_capture==NULL || sndcard_playback==NULL)
376                return NULL;
377        stream=audio_stream_new(locport, ms_is_ipv6(remip));
378        if (audio_stream_start_full(stream,prof,remip,remport,remport+1,profile,jitt_comp,NULL,NULL,sndcard_playback,sndcard_capture,use_ec)==0) return stream;
379        audio_stream_free(stream);
380        return NULL;
381}
382
383AudioStream *audio_stream_start_with_sndcards(RtpProfile *prof,int locport,const char *remip,int remport,int profile,int jitt_comp,MSSndCard *playcard, MSSndCard *captcard, bool_t use_ec)
384{
385        AudioStream *stream;
386        if (playcard==NULL) {
387                ms_error("No playback card.");
388                return NULL;
389        }
390        if (captcard==NULL) {
391                ms_error("No capture card.");
392                return NULL;
393        }
394        stream=audio_stream_new(locport, ms_is_ipv6(remip));
395        if (audio_stream_start_full(stream,prof,remip,remport,remport+1,profile,jitt_comp,NULL,NULL,playcard,captcard,use_ec)==0) return stream;
396        audio_stream_free(stream);
397        return NULL;
398}
399
400void audio_stream_set_rtcp_information(AudioStream *st, const char *cname, const char *tool){
401        if (st->session!=NULL){
402                rtp_session_set_source_description(st->session,cname,NULL,NULL,NULL,NULL,tool , "This is free software (GPL) !");
403        }
404}
405
406void audio_stream_play(AudioStream *st, const char *name){
407        if (ms_filter_get_id(st->soundread)==MS_FILE_PLAYER_ID){
408                ms_filter_call_method_noarg(st->soundread,MS_FILE_PLAYER_CLOSE);
409                ms_filter_call_method(st->soundread,MS_FILE_PLAYER_OPEN,(void*)name);
410                if (st->read_resampler){
411                        audio_stream_configure_resampler(st->read_resampler,st->soundread,st->rtpsend);
412                }
413                ms_filter_call_method_noarg(st->soundread,MS_FILE_PLAYER_START);
414        }else{
415                ms_error("Cannot play file: the stream hasn't been started with"
416                " audio_stream_start_with_files");
417        }
418}
419
420void audio_stream_record(AudioStream *st, const char *name){
421        if (ms_filter_get_id(st->soundwrite)==MS_FILE_REC_ID){
422                ms_filter_call_method_noarg(st->soundwrite,MS_FILE_REC_CLOSE);
423                ms_filter_call_method(st->soundwrite,MS_FILE_REC_OPEN,(void*)name);
424                ms_filter_call_method_noarg(st->soundwrite,MS_FILE_REC_START);
425        }else{
426                ms_error("Cannot record file: the stream hasn't been started with"
427                " audio_stream_start_with_files");
428        }
429}
430
431
432AudioStream *audio_stream_new(int locport, bool_t ipv6){
433        AudioStream *stream=(AudioStream *)ms_new0(AudioStream,1);
434        stream->session=create_duplex_rtpsession(locport,ipv6);
435        stream->rtpsend=ms_filter_new(MS_RTP_SEND_ID);
436        stream->play_dtmfs=TRUE;
437        stream->use_gc=FALSE;
438        stream->use_agc=FALSE;
439        stream->use_ng=FALSE;
440        return stream;
441}
442
443void audio_stream_play_received_dtmfs(AudioStream *st, bool_t yesno){
444        st->play_dtmfs=yesno;
445}
446
447int audio_stream_start_now(AudioStream *stream, RtpProfile * prof,  const char *remip, int remport, int rem_rtcp_port, int payload_type, int jitt_comp, MSSndCard *playcard, MSSndCard *captcard, bool_t use_ec){
448        return audio_stream_start_full(stream,prof,remip,remport,rem_rtcp_port,
449                payload_type,jitt_comp,NULL,NULL,playcard,captcard,use_ec);
450}
451
452void audio_stream_set_relay_session_id(AudioStream *stream, const char *id){
453        ms_filter_call_method(stream->rtpsend, MS_RTP_SEND_SET_RELAY_SESSION_ID,(void*)id);
454}
455
456void audio_stream_set_echo_canceller_params(AudioStream *st, int tail_len_ms, int delay_ms, int framesize){
457        st->ec_tail_len=tail_len_ms;
458        st->ec_delay=delay_ms;
459        st->ec_framesize=framesize;
460}
461
462void audio_stream_enable_echo_limiter(AudioStream *stream, EchoLimiterType type){
463        stream->el_type=type;
464}
465
466void audio_stream_enable_gain_control(AudioStream *stream, bool_t val){
467        stream->use_gc=val;
468}
469
470void audio_stream_enable_automatic_gain_control(AudioStream *stream, bool_t val){
471        stream->use_agc=val;
472}
473
474void audio_stream_enable_noise_gate(AudioStream *stream, bool_t val){
475        stream->use_ng=val;
476}
477
478void audio_stream_set_mic_gain(AudioStream *stream, float gain){
479        if (stream->volsend){
480                ms_filter_call_method(stream->volsend,MS_VOLUME_SET_GAIN,&gain);
481        }else ms_warning("Could not apply gain: gain control wasn't activated. "
482                        "Use audio_stream_enable_gain_control() before starting the stream.");
483}
484
485void audio_stream_enable_equalizer(AudioStream *stream, bool_t enabled){
486        stream->eq_active=enabled;
487        if (stream->equalizer){
488                int tmp=enabled;
489                ms_filter_call_method(stream->equalizer,MS_EQUALIZER_SET_ACTIVE,&tmp);
490        }
491}
492
493void audio_stream_equalizer_set_gain(AudioStream *stream, int frequency, float gain, int freq_width){
494        if (stream->equalizer){
495                MSEqualizerGain d;
496                d.frequency=frequency;
497                d.gain=gain;
498                d.width=freq_width;
499                ms_filter_call_method(stream->equalizer,MS_EQUALIZER_SET_GAIN,&d);
500        }
501}
502
503void audio_stream_stop(AudioStream * stream)
504{
505        if (stream->ticker){
506                MSConnectionHelper h;
507                ms_ticker_detach(stream->ticker,stream->soundread);
508                ms_ticker_detach(stream->ticker,stream->rtprecv);
509
510                rtp_stats_display(rtp_session_get_stats(stream->session),"Audio session's RTP statistics");
511
512                /*dismantle the outgoing graph*/
513                ms_connection_helper_start(&h);
514                ms_connection_helper_unlink(&h,stream->soundread,-1,0);
515                if (stream->read_resampler!=NULL)
516                        ms_connection_helper_unlink(&h,stream->read_resampler,0,0);
517                if (stream->ec!=NULL)
518                        ms_connection_helper_unlink(&h,stream->ec,1,1);
519                if (stream->volsend!=NULL)
520                        ms_connection_helper_unlink(&h,stream->volsend,0,0);
521                ms_connection_helper_unlink(&h,stream->encoder,0,0);
522                ms_connection_helper_unlink(&h,stream->rtpsend,0,-1);
523
524                /*dismantle the receiving graph*/
525                ms_connection_helper_start(&h);
526                ms_connection_helper_unlink(&h,stream->rtprecv,-1,0);
527                ms_connection_helper_unlink(&h,stream->decoder,0,0);
528                ms_connection_helper_unlink(&h,stream->dtmfgen,0,0);
529                if (stream->equalizer)
530                        ms_connection_helper_unlink(&h,stream->equalizer,0,0);
531                if (stream->volrecv!=NULL)
532                        ms_connection_helper_unlink(&h,stream->volrecv,0,0);
533                if (stream->ec!=NULL)
534                        ms_connection_helper_unlink(&h,stream->ec,0,0);
535                if (stream->write_resampler!=NULL)
536                        ms_connection_helper_unlink(&h,stream->write_resampler,0,0);
537                ms_connection_helper_unlink(&h,stream->soundwrite,0,-1);
538
539        }
540        audio_stream_free(stream);
541}
542
543RingStream * ring_start(const char *file, int interval, MSSndCard *sndcard){
544   return ring_start_with_cb(file,interval,sndcard,NULL,NULL);
545}
546
547RingStream * ring_start_with_cb(const char *file,int interval,MSSndCard *sndcard, MSFilterNotifyFunc func,void * user_data)
548{
549        RingStream *stream;
550        int tmp;
551        stream=(RingStream *)ms_new0(RingStream,1);
552        stream->source=ms_filter_new(MS_FILE_PLAYER_ID);
553        if (ms_filter_call_method(stream->source,MS_FILE_PLAYER_OPEN,(void*)file)<0){
554                ms_filter_destroy(stream->source);
555                ms_free(stream);
556                return NULL;
557        }
558        ms_filter_call_method(stream->source,MS_FILE_PLAYER_LOOP,&interval);
559        ms_filter_call_method_noarg(stream->source,MS_FILE_PLAYER_START);
560        if (func!=NULL)
561                ms_filter_set_notify_callback(stream->source,func,user_data);
562        stream->sndwrite=ms_snd_card_create_writer(sndcard);
563        ms_filter_call_method(stream->source,MS_FILTER_GET_SAMPLE_RATE,&tmp);
564        ms_filter_call_method(stream->sndwrite,MS_FILTER_SET_SAMPLE_RATE,&tmp);
565        ms_filter_call_method(stream->source,MS_FILTER_GET_NCHANNELS,&tmp);
566        ms_filter_call_method(stream->sndwrite,MS_FILTER_SET_NCHANNELS,&tmp);
567        stream->ticker=ms_ticker_new();
568        ms_ticker_set_name(stream->ticker,"Audio (ring) MSTicker");
569        ms_filter_link(stream->source,0,stream->sndwrite,0);
570        ms_ticker_attach(stream->ticker,stream->source);
571        return stream;
572}
573
574void ring_stop(RingStream *stream){
575        ms_ticker_detach(stream->ticker,stream->source);
576        ms_filter_unlink(stream->source,0,stream->sndwrite,0);
577        ms_ticker_destroy(stream->ticker);
578        ms_filter_destroy(stream->source);
579        ms_filter_destroy(stream->sndwrite);
580        ms_free(stream);
581#ifdef _WIN32_WCE
582        ms_warning("Sleeping a bit after closing the audio device...");
583        ms_sleep(1);
584#endif
585}
586
587
588int audio_stream_send_dtmf(AudioStream *stream, char dtmf)
589{
590        if (stream->rtpsend)
591                ms_filter_call_method(stream->rtpsend,MS_RTP_SEND_SEND_DTMF,&dtmf);
592        if (stream->dtmfgen)
593                ms_filter_call_method(stream->dtmfgen,MS_DTMF_GEN_PUT,&dtmf);
594        return 0;
595}
596
597void audio_stream_get_local_rtp_stats(AudioStream *stream, rtp_stats_t *lstats){
598        if (stream->session){
599                const rtp_stats_t *stats=rtp_session_get_stats(stream->session);
600                memcpy(lstats,stats,sizeof(*stats));
601        }else memset(lstats,0,sizeof(rtp_stats_t));
602}
603
604
605void audio_stream_mute_rtp(AudioStream *stream, bool_t val) 
606{
607  if (stream->rtpsend){
608    if (val)
609      ms_filter_call_method(stream->rtpsend,MS_RTP_SEND_MUTE_MIC,&val);
610    else
611      ms_filter_call_method(stream->rtpsend,MS_RTP_SEND_UNMUTE_MIC,&val);
612  }
613}
Note: See TracBrowser for help on using the repository browser.