📄 audiostream.c
字号:
/*mediastreamer2 library - modular sound and video processing and streamingCopyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*/#ifdef HAVE_CONFIG_H#include "mediastreamer-config.h"#endif#include "mediastreamer2/mediastream.h"#include "mediastreamer2/dtmfgen.h"#include "mediastreamer2/mssndcard.h"#include "mediastreamer2/msrtp.h"#include "mediastreamer2/msfileplayer.h"#include "mediastreamer2/msfilerec.h"#ifdef INET6 #include <sys/types.h>#ifndef WIN32 #include <sys/socket.h> #include <netdb.h>#endif#endif#define MAX_RTP_SIZE 1500/* this code is not part of the library itself, it is part of the mediastream program */void audio_stream_free(AudioStream *stream){ if (stream->session!=NULL) rtp_session_destroy(stream->session); if (stream->rtpsend!=NULL) ms_filter_destroy(stream->rtpsend); if (stream->rtprecv!=NULL) ms_filter_destroy(stream->rtprecv); if (stream->soundread!=NULL) ms_filter_destroy(stream->soundread); if (stream->soundwrite!=NULL) ms_filter_destroy(stream->soundwrite); if (stream->encoder!=NULL) ms_filter_destroy(stream->encoder); if (stream->decoder!=NULL) ms_filter_destroy(stream->decoder); if (stream->dtmfgen!=NULL) ms_filter_destroy(stream->dtmfgen); if (stream->ec!=NULL) ms_filter_destroy(stream->ec); if (stream->ticker!=NULL) ms_ticker_destroy(stream->ticker); ms_free(stream);}static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'};static void on_dtmf_received(RtpSession *s, int dtmf, void * user_data){ MSFilter *dtmfgen=(MSFilter*)user_data; if (dtmf>15){ ms_warning("Unsupported telephone-event type."); return; } ms_message("Receiving dtmf %c.",dtmf_tab[dtmf]); if (dtmfgen!=NULL){ ms_filter_call_method(dtmfgen,MS_DTMF_GEN_PUT,&dtmf_tab[dtmf]); }}#if 0static void on_timestamp_jump(RtpSession *s,uint32_t* ts, void * user_data){ ms_warning("The remote sip-phone has send data with a future timestamp: %u," "resynchronising session.",*ts); rtp_session_reset(s);}#endifbool_t ms_is_ipv6(const char *remote){ bool_t ret=FALSE;#ifdef INET6 struct addrinfo hints, *res0; int err; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; err = getaddrinfo(remote,"8000", &hints, &res0); if (err!=0) { ms_warning ("get_local_addr_for: %s", gai_strerror(err)); return FALSE; } ret=(res0->ai_addr->sa_family==AF_INET6); freeaddrinfo(res0);#endif return ret;}RtpSession * create_duplex_rtpsession( int locport, bool_t ipv6){ RtpSession *rtpr; rtpr=rtp_session_new(RTP_SESSION_SENDRECV); rtp_session_set_recv_buf_size(rtpr,MAX_RTP_SIZE); rtp_session_set_scheduling_mode(rtpr,0); rtp_session_set_blocking_mode(rtpr,0); rtp_session_enable_adaptive_jitter_compensation(rtpr,TRUE); rtp_session_set_symmetric_rtp(rtpr,TRUE); rtp_session_set_local_addr(rtpr,ipv6 ? "::" : "0.0.0.0",locport); rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)rtp_session_resync,(long)NULL); rtp_session_signal_connect(rtpr,"ssrc_changed",(RtpCallback)rtp_session_resync,(long)NULL); return rtpr;}bool_t audio_stream_alive(AudioStream * stream, int timeout){ RtpSession *session=stream->session; const rtp_stats_t *stats=rtp_session_get_stats(session); if (stats->recv!=0){ if (stats->recv!=stream->last_packet_count){ stream->last_packet_count=stats->recv; stream->last_packet_time=time(NULL); }else{ if (time(NULL)-stream->last_packet_time>timeout){ /* more than timeout seconds of inactivity*/ return FALSE; } } } return TRUE;}/*this function must be called from the MSTicker thread:it replaces one filter by another one.This is a dirty hack that works anyway.It would be interesting to have something that does the jobsimplier within the MSTicker api*/void audio_stream_change_decoder(AudioStream *stream, int payload){ RtpSession *session=stream->session; RtpProfile *prof=rtp_session_get_profile(session); PayloadType *pt=rtp_profile_get_payload(prof,payload); if (pt!=NULL){ MSFilter *dec=ms_filter_create_decoder(pt->mime_type); if (dec!=NULL){ ms_filter_unlink(stream->rtprecv, 0, stream->decoder, 0); ms_filter_unlink(stream->decoder,0,stream->dtmfgen,0); ms_filter_postprocess(stream->decoder); ms_filter_destroy(stream->decoder); stream->decoder=dec; if (pt->recv_fmtp!=NULL) ms_filter_call_method(stream->decoder,MS_FILTER_ADD_FMTP,(void*)pt->recv_fmtp); ms_filter_link (stream->rtprecv, 0, stream->decoder, 0); ms_filter_link (stream->decoder,0 , stream->dtmfgen, 0); ms_filter_preprocess(stream->decoder,stream->ticker); }else{ ms_warning("No decoder found for %s",pt->mime_type); } }else{ ms_warning("No payload defined with number %i",payload); }}static void payload_type_changed(RtpSession *session, unsigned long data){ AudioStream *stream=(AudioStream*)data; int pt=rtp_session_get_recv_payload_type(stream->session); audio_stream_change_decoder(stream,pt);}int audio_stream_start_full(AudioStream *stream, RtpProfile *profile, const char *remip,int remport, int rem_rtcp_port, int payload,int jitt_comp, const char *infile, const char *outfile, MSSndCard *playcard, MSSndCard *captcard, bool_t use_ec){ RtpSession *rtps=stream->session; PayloadType *pt; int tmp; rtp_session_set_profile(rtps,profile); if (remport>0) rtp_session_set_remote_addr_full(rtps,remip,remport,rem_rtcp_port); rtp_session_set_payload_type(rtps,payload); rtp_session_set_jitter_compensation(rtps,jitt_comp); if (remport>0) ms_filter_call_method(stream->rtpsend,MS_RTP_SEND_SET_SESSION,rtps); stream->rtprecv=ms_filter_new(MS_RTP_RECV_ID); ms_filter_call_method(stream->rtprecv,MS_RTP_RECV_SET_SESSION,rtps); stream->session=rtps; stream->dtmfgen=ms_filter_new(MS_DTMF_GEN_ID); rtp_session_signal_connect(rtps,"telephone-event",(RtpCallback)on_dtmf_received,(unsigned long)stream->dtmfgen); rtp_session_signal_connect(rtps,"payload_type_changed",(RtpCallback)payload_type_changed,(unsigned long)stream); /* creates the local part */ if (captcard!=NULL) stream->soundread=ms_snd_card_create_reader(captcard); else { stream->soundread=ms_filter_new(MS_FILE_PLAYER_ID); if (infile!=NULL) audio_stream_play(stream,infile); } if (playcard!=NULL) stream->soundwrite=ms_snd_card_create_writer(playcard); else { stream->soundwrite=ms_filter_new(MS_FILE_REC_ID); if (outfile!=NULL) audio_stream_record(stream,outfile); } /* creates the couple of encoder/decoder */ pt=rtp_profile_get_payload(profile,payload);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -