1 /*
2  * Copyright (C) 2017-2018 Julien Chavanton jchavanton@gmail.com
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20 
21 #include "../../core/mem/shm.h"
22 #include "../../core/sr_module.h"
23 #include "rtp_media_server.h"
24 
ptr_shm_malloc(size_t size)25 inline static void *ptr_shm_malloc(size_t size)
26 {
27 	return shm_malloc(size);
28 }
ptr_shm_realloc(void * ptr,size_t size)29 inline static void *ptr_shm_realloc(void *ptr, size_t size)
30 {
31 	return shm_realloc(ptr, size);
32 }
ptr_shm_free(void * ptr)33 inline static void ptr_shm_free(void *ptr)
34 {
35 	shm_free(ptr);
36 }
37 
38 typedef struct shared_global_vars
39 {
40 	MSFactory *ms_factory;
41 	gen_lock_t lock;
42 } shared_global_vars_t;
43 
44 
45 MSFilterDesc *rms_ms_filter_descs[] = {&ms_alaw_dec_desc, &ms_alaw_enc_desc,
46 		&ms_ulaw_dec_desc, &ms_ulaw_enc_desc, &ms_rtp_send_desc,
47 		&ms_rtp_recv_desc, &ms_dtmf_gen_desc, &ms_volume_desc,
48 		&ms_equalizer_desc, &ms_channel_adapter_desc, &ms_audio_mixer_desc,
49 		&ms_tone_detector_desc, &ms_speex_dec_desc, &ms_speex_enc_desc,
50 		&ms_speex_ec_desc, &ms_file_player_desc, &ms_file_rec_desc,
51 		&ms_resample_desc,
52 		&ms_opus_dec_desc,
53 		&ms_opus_enc_desc,
54 		NULL};
55 
rms_create_factory()56 static MSFactory *rms_create_factory()
57 {
58 	MSFactory *f = ms_factory_new();
59 	int i;
60 	for(i = 0; rms_ms_filter_descs[i] != NULL; i++) {
61 		ms_factory_register_filter(f, rms_ms_filter_descs[i]);
62 	}
63 	ms_factory_init_plugins(f);
64 	ms_factory_enable_statistics(f, TRUE);
65 	ms_factory_reset_statistics(f);
66 	return f;
67 }
68 
rms_media_init()69 int rms_media_init()
70 {
71 	//	OrtpMemoryFunctions ortp_memory_functions;
72 	//	ortp_memory_functions.malloc_fun = ptr_shm_malloc;
73 	//	ortp_memory_functions.realloc_fun = ptr_shm_realloc;
74 	//	ortp_memory_functions.free_fun = ptr_shm_free;
75 	//	ortp_set_memory_functions(&ortp_memory_functions);
76 	ortp_init();
77 	return 1;
78 }
79 
rms_create_ticker(char * name)80 static MSTicker *rms_create_ticker(char *name)
81 {
82 	MSTickerParams params;
83 	params.name = name;
84 	params.prio = MS_TICKER_PRIO_NORMAL;
85 	LM_DBG("\n");
86 	return ms_ticker_new_with_params(&params);
87 }
88 
rms_media_destroy(call_leg_media_t * m)89 void rms_media_destroy(call_leg_media_t *m)
90 {
91 	LM_DBG("rtp_session_destroy[%p]\n", m->rtps);
92 	rtp_session_destroy(m->rtps);
93 	m->rtps = NULL;
94 	ms_ticker_destroy(m->ms_ticker);
95 	m->ms_ticker = NULL;
96 	ms_factory_destroy(m->ms_factory);
97 	m->ms_factory = NULL;
98 }
99 
create_session_payload(call_leg_media_t * m)100 int create_session_payload(call_leg_media_t *m) {
101 	LM_INFO("RTP [%p][%d]\n", m->pt, m->pt->type);
102 	m->rtp_profile=rtp_profile_new("Call profile");
103 	if(!m->rtp_profile) return 0;
104 	rtp_profile_set_payload(m->rtp_profile, m->pt->type, m->pt);
105 	rtp_session_set_profile(m->rtps, m->rtp_profile);
106 	rtp_session_set_payload_type(m->rtps, m->pt->type);
107 	return 1;
108 }
109 
create_call_leg_media(call_leg_media_t * m)110 int create_call_leg_media(call_leg_media_t *m)
111 {
112 	if (m) rms_stop_media(m);
113 	m->ms_factory = rms_create_factory();
114 	// Create caller RTP session
115 	LM_INFO("RTP session [%s:%d]<>[%s:%d]\n", m->local_ip.s, m->local_port,
116 			m->remote_ip.s, m->remote_port);
117 	m->rtps = ms_create_duplex_rtp_session(m->local_ip.s, m->local_port,
118 			m->local_port + 1, ms_factory_get_mtu(m->ms_factory));
119 
120 	create_session_payload(m);
121 
122 	rtp_session_set_remote_addr_full(m->rtps, m->remote_ip.s, m->remote_port,
123 			m->remote_ip.s, m->remote_port + 1);
124 
125 	rtp_session_enable_rtcp(m->rtps, FALSE);
126 	// create caller filters : rtprecv1/rtpsend1/encoder1/decoder1
127 	m->ms_rtprecv = ms_factory_create_filter(m->ms_factory, MS_RTP_RECV_ID);
128 	m->ms_rtpsend = ms_factory_create_filter(m->ms_factory, MS_RTP_SEND_ID);
129 
130 	LM_INFO("codec[%s] rtprecv[%p] rtpsend[%p] rate[%dHz]\n", m->pt->mime_type,
131 			m->ms_rtprecv, m->ms_rtpsend, m->pt->clock_rate);
132 	m->ms_encoder = ms_factory_create_encoder(m->ms_factory, m->pt->mime_type);
133 	if(!m->ms_encoder) {
134 		LM_ERR("creating encoder failed.\n");
135 		return 0;
136 	}
137 	m->ms_decoder = ms_factory_create_decoder(m->ms_factory, m->pt->mime_type);
138 
139 	/* set filter params */
140 	ms_filter_call_method(m->ms_rtpsend, MS_RTP_SEND_SET_SESSION, m->rtps);
141 	ms_filter_call_method(m->ms_rtprecv, MS_RTP_RECV_SET_SESSION, m->rtps);
142 	return 1;
143 }
144 
145 
rms_player_eof(void * user_data,MSFilter * f,unsigned int event,void * event_data)146 static void rms_player_eof(
147 		void *user_data, MSFilter *f, unsigned int event, void *event_data)
148 {
149 	if(event == MS_FILE_PLAYER_EOF) {
150 		rms_action_t *a = (rms_action_t *)user_data;
151 		a->type = RMS_DONE;
152 	}
153 	MS_UNUSED(f), MS_UNUSED(event_data);
154 }
155 
156 
rms_get_dtmf(call_leg_media_t * m,char dtmf)157 int rms_get_dtmf(call_leg_media_t *m, char dtmf)
158 {
159 	//	static void tone_detected_cb(void *data, MSFilter *f, unsigned int event_id, MSToneDetectorEvent *ev) {
160 	//			MS_UNUSED(data), MS_UNUSED(f), MS_UNUSED(event_id), MS_UNUSED(ev);
161 	//				ms_tester_tone_detected = TRUE;
162 	//	}
163 	return 1;
164 }
165 
rms_playfile(call_leg_media_t * m,rms_action_t * a)166 int rms_playfile(call_leg_media_t *m, rms_action_t *a)
167 {
168 	int channels = 1;
169 	int file_sample_rate = 8000;
170 	if(!m->ms_player)
171 		return 0;
172 	ms_filter_add_notify_callback(m->ms_player, rms_player_eof, a, TRUE);
173 	ms_filter_call_method(
174 			m->ms_player, MS_FILE_PLAYER_OPEN, (void *)a->param.s);
175 	ms_filter_call_method(m->ms_player, MS_FILE_PLAYER_START, NULL);
176 	ms_filter_call_method(m->ms_player, MS_FILTER_GET_SAMPLE_RATE, &file_sample_rate);
177 	ms_filter_call_method(m->ms_player, MS_FILTER_GET_NCHANNELS, &channels);
178 
179 	if (m->ms_resampler) {
180 		ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_SAMPLE_RATE, &file_sample_rate);
181 		LM_INFO("clock[%d]file[%d]\n", m->pt->clock_rate, file_sample_rate);
182 		ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_OUTPUT_SAMPLE_RATE, &m->pt->clock_rate);
183 		ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_OUTPUT_NCHANNELS, &m->pt->channels);
184 	}
185 	LM_INFO("[%s]clock[%d][%d]\n", m->pt->mime_type, m->pt->clock_rate, file_sample_rate);
186 	return 1;
187 }
188 
rms_start_media(call_leg_media_t * m,char * file_name)189 int rms_start_media(call_leg_media_t *m, char *file_name)
190 {
191 	MSConnectionHelper h;
192 	int channels = 1;
193 	int file_sample_rate = 8000;
194 
195 	if (m) rms_stop_media(m);
196 
197 	m->ms_ticker = rms_create_ticker(NULL);
198 	if(!m->ms_ticker)
199 		goto error;
200 	m->ms_player = ms_factory_create_filter(m->ms_factory, MS_FILE_PLAYER_ID);
201 	if(!m->ms_player)
202 		goto error;
203 
204 
205 	// m->ms_recorder = ms_factory_create_filter(m->ms_factory, MS_FILE_PLAYER_ID);
206 	m->ms_voidsink = ms_factory_create_filter(m->ms_factory, MS_VOID_SINK_ID);
207 	if(!m->ms_voidsink)
208 		goto error;
209 	LM_INFO("m[%p]call-id[%p]pt[%s]\n", m, m->di->callid.s, m->pt->mime_type);
210 
211 	ms_filter_call_method(m->ms_player, MS_FILTER_SET_OUTPUT_NCHANNELS, &channels);
212 	ms_filter_call_method_noarg(m->ms_player, MS_FILE_PLAYER_START);
213 	ms_filter_call_method(m->ms_player, MS_FILTER_GET_SAMPLE_RATE, &file_sample_rate);
214 	if (strcasecmp(m->pt->mime_type,"opus") == 0) {
215 		ms_filter_call_method(m->ms_encoder, MS_FILTER_SET_SAMPLE_RATE, &file_sample_rate);
216 		ms_filter_call_method(m->ms_encoder, MS_FILTER_SET_NCHANNELS, &channels);
217 	} else {
218 		m->ms_resampler = ms_factory_create_filter(m->ms_factory, MS_RESAMPLE_ID);
219 		if (!m->ms_resampler) goto error;
220 	}
221 
222 	if (m->ms_resampler) {
223 		ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_SAMPLE_RATE, &file_sample_rate);
224 		ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_OUTPUT_SAMPLE_RATE, &m->pt->clock_rate);
225 	}
226 
227 	// sending graph
228 	ms_connection_helper_start(&h);
229 	ms_connection_helper_link(&h, m->ms_player, -1, 0);
230 	if (m->ms_resampler)
231 		ms_connection_helper_link(&h, m->ms_resampler, 0, 0);
232 	ms_connection_helper_link(&h, m->ms_encoder, 0, 0);
233 	ms_connection_helper_link(&h, m->ms_rtpsend, 0, -1);
234 
235 	// receiving graph
236 	ms_connection_helper_start(&h);
237 	ms_connection_helper_link(&h, m->ms_rtprecv, -1, 0);
238 	// ms_connection_helper_link(&h, m->ms_decoder, 0, 0);
239 	ms_connection_helper_link(&h, m->ms_voidsink, 0, -1);
240 
241 	ms_ticker_attach_multiple(m->ms_ticker, m->ms_player, m->ms_rtprecv, NULL);
242 	return 1;
243 error:
244 	LM_ERR(" can not start media!\n");
245 	return 0;
246 }
247 
rms_stop_media(call_leg_media_t * m)248 int rms_stop_media(call_leg_media_t *m)
249 {
250 	MSConnectionHelper h;
251 	if(!m->ms_ticker) {
252 		LM_ERR("RMS STOP MEDIA\n");
253 		return -1;
254 	}
255 	if(m->ms_player)
256 		ms_ticker_detach(m->ms_ticker, m->ms_player);
257 	if(m->ms_rtprecv)
258 		ms_ticker_detach(m->ms_ticker, m->ms_rtprecv);
259 
260 	rtp_stats_display(
261 			rtp_session_get_stats(m->rtps), " AUDIO SESSION'S RTP STATISTICS ");
262 	ms_factory_log_statistics(m->ms_factory);
263 
264 	/*dismantle the sending graph*/
265 	ms_connection_helper_start(&h);
266 	if(m->ms_player)
267 		ms_connection_helper_unlink(&h, m->ms_player, -1, 0);
268 	if(m->ms_resampler)
269 		ms_connection_helper_unlink(&h, m->ms_resampler, 0, 0);
270 	if(m->ms_encoder)
271 		ms_connection_helper_unlink(&h, m->ms_encoder, 0, 0);
272 	if(m->ms_rtpsend)
273 		ms_connection_helper_unlink(&h, m->ms_rtpsend, 0, -1);
274 	/*dismantle the receiving graph*/
275 	ms_connection_helper_start(&h);
276 	if(m->ms_rtprecv)
277 		ms_connection_helper_unlink(&h, m->ms_rtprecv, -1, 0);
278 	if(m->ms_voidsink)
279 		ms_connection_helper_unlink(&h, m->ms_voidsink, 0, -1);
280 
281 	if(m->ms_player)
282 		ms_filter_destroy(m->ms_player);
283 	if(m->ms_resampler)
284 		ms_filter_destroy(m->ms_resampler);
285 	if(m->ms_encoder)
286 		ms_filter_destroy(m->ms_encoder);
287 	if(m->ms_rtpsend) {
288 		LM_ERR("detroy rtpsend\n");
289 		ms_filter_destroy(m->ms_rtpsend);
290 	} else {
291 		LM_ERR("no rtpsend\n");
292 	}
293 	if(m->ms_rtprecv)
294 		ms_filter_destroy(m->ms_rtprecv);
295 	if(m->ms_voidsink)
296 		ms_filter_destroy(m->ms_voidsink);
297 
298 	rms_media_destroy(m);
299 	return 1;
300 }
301 
rms_bridge(call_leg_media_t * m1,call_leg_media_t * m2)302 int rms_bridge(call_leg_media_t *m1, call_leg_media_t *m2)
303 {
304 	MSConnectionHelper h;
305 	m1->ms_ticker = rms_create_ticker(NULL);
306 	LM_NOTICE("[%p][%p][%p][%p]\n", m1->ms_rtprecv, m1->ms_rtpsend,
307 			m2->ms_rtprecv, m2->ms_rtpsend);
308 	// direction 1
309 	ms_connection_helper_start(&h);
310 	ms_connection_helper_link(&h, m1->ms_rtprecv, -1, 0);
311 	ms_connection_helper_link(&h, m2->ms_rtpsend, 0, -1);
312 
313 	LM_NOTICE("[%p][%p][%p][%p]2\n", m1->ms_rtprecv, m1->ms_rtpsend,
314 			m2->ms_rtprecv, m2->ms_rtpsend);
315 	// direction 2
316 	ms_connection_helper_start(&h);
317 	ms_connection_helper_link(&h, m2->ms_rtprecv, -1, 0);
318 	ms_connection_helper_link(&h, m1->ms_rtpsend, 0, -1);
319 
320 	ms_ticker_attach_multiple(
321 			m1->ms_ticker, m1->ms_rtprecv, m2->ms_rtprecv, NULL);
322 
323 	return 1;
324 }
325 
rms_stop_bridge(call_leg_media_t * m1,call_leg_media_t * m2)326 int rms_stop_bridge(call_leg_media_t *m1, call_leg_media_t *m2)
327 {
328 	MSConnectionHelper h;
329 	MSTicker *ticker = NULL;
330 
331 	if(m1->ms_ticker) {
332 		ticker = m1->ms_ticker;
333 	}
334 	if(m2->ms_ticker) {
335 		ticker = m2->ms_ticker;
336 	}
337 	if(!ticker)
338 		return -1;
339 
340 	if(m1->ms_rtprecv)
341 		ms_ticker_detach(ticker, m1->ms_rtprecv);
342 	if(m1->ms_rtpsend)
343 		ms_ticker_detach(ticker, m1->ms_rtpsend);
344 	if(m2->ms_rtprecv)
345 		ms_ticker_detach(ticker, m2->ms_rtprecv);
346 	if(m2->ms_rtpsend)
347 		ms_ticker_detach(ticker, m2->ms_rtpsend);
348 
349 	ms_connection_helper_start(&h);
350 	if(m1->ms_rtprecv)
351 		ms_connection_helper_unlink(&h, m1->ms_rtprecv, -1, 0);
352 	if(m2->ms_rtpsend)
353 		ms_connection_helper_unlink(&h, m2->ms_rtpsend, 0, -1);
354 
355 	ms_connection_helper_start(&h);
356 	if(m2->ms_rtprecv)
357 		ms_connection_helper_unlink(&h, m2->ms_rtprecv, -1, 0);
358 	if(m1->ms_rtpsend)
359 		ms_connection_helper_unlink(&h, m1->ms_rtpsend, 0, -1);
360 
361 	rtp_stats_display(rtp_session_get_stats(m1->rtps),
362 			" AUDIO BRIDGE offer RTP STATISTICS ");
363 
364 	rtp_stats_display(rtp_session_get_stats(m2->rtps),
365 			" AUDIO BRIDGE answer RTP STATISTICS ");
366 
367 	if(m1->ms_rtpsend)
368 		ms_filter_destroy(m1->ms_rtpsend);
369 	if(m1->ms_rtprecv)
370 		ms_filter_destroy(m1->ms_rtprecv);
371 	if(m2->ms_rtpsend)
372 		ms_filter_destroy(m2->ms_rtpsend);
373 	if(m2->ms_rtprecv)
374 		ms_filter_destroy(m2->ms_rtprecv);
375 
376 	rtp_session_destroy(m1->rtps);
377 	rtp_session_destroy(m2->rtps);
378 	if(m1->ms_ticker)
379 		ms_ticker_destroy(m1->ms_ticker);
380 	if(m2->ms_ticker)
381 		ms_ticker_destroy(m2->ms_ticker);
382 	m1->ms_ticker = NULL;
383 	m2->ms_ticker = NULL;
384 	ms_factory_log_statistics(m1->ms_factory);
385 	return 1;
386 }
387