mediastreamer2_audio_stream_tester.c 25.7 KB
Newer Older
jehan's avatar
jehan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
mediastreamer2 library - modular sound and video processing and streaming
Copyright (C) 2006-2013 Belledonne Communications, Grenoble

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of 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 of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
jehan's avatar
jehan committed
18 19 20 21 22 23 24 25 26 27 28 29
*/

#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/dtmfgen.h"
#include "mediastreamer2/msfileplayer.h"
#include "mediastreamer2/msfilerec.h"
#include "mediastreamer2/msrtp.h"
#include "mediastreamer2/mstonedetector.h"
#include "mediastreamer2_tester.h"
#include "mediastreamer2_tester_private.h"

static RtpProfile rtp_profile;
30
static MSFactory *_factory= NULL;
jehan's avatar
jehan committed
31

32
#define OPUS_PAYLOAD_TYPE    121
jehan's avatar
jehan committed
33
#define SPEEX16_PAYLOAD_TYPE 122
34
#define SILK16_PAYLOAD_TYPE  123
35
#define PCMA8_PAYLOAD_TYPE 8
jehan's avatar
jehan committed
36

37
static int tester_before_all(void) {
38
	//ms_init();
39 40 41
	_factory = ms_factory_new();
	ms_factory_init_voip(_factory);
	ms_factory_init_plugins(_factory);
42

43
	//ms_filter_enable_statistics(TRUE);
44
	ms_factory_enable_statistics(_factory, TRUE);
jehan's avatar
jehan committed
45 46 47 48 49
	ortp_init();
	rtp_profile_set_payload (&rtp_profile,0,&payload_type_pcmu8000);
	rtp_profile_set_payload (&rtp_profile,OPUS_PAYLOAD_TYPE,&payload_type_opus);
	rtp_profile_set_payload (&rtp_profile,SPEEX16_PAYLOAD_TYPE,&payload_type_speex_wb);
	rtp_profile_set_payload (&rtp_profile,SILK16_PAYLOAD_TYPE,&payload_type_silk_wb);
50
	rtp_profile_set_payload (&rtp_profile,PCMA8_PAYLOAD_TYPE,&payload_type_pcma8000);
jehan's avatar
jehan committed
51 52 53
	return 0;
}

54
static int tester_after_all(void) {
55 56
	//ms_exit();

57
	ms_factory_destroy(_factory);
jehan's avatar
jehan committed
58 59 60 61 62 63 64 65 66 67 68 69
	rtp_profile_clear_all(&rtp_profile);
	return 0;
}

#define MARIELLE_RTP_PORT 2564
#define MARIELLE_RTCP_PORT 2565
#define MARIELLE_IP "127.0.0.1"

#define MARGAUX_RTP_PORT 9864
#define MARGAUX_RTCP_PORT 9865
#define MARGAUX_IP "127.0.0.1"

70 71
#define HELLO_8K_1S_FILE  "sounds/hello8000-1s.wav"
#define HELLO_16K_1S_FILE  "sounds/hello16000-1s.wav"
72 73
#define RECORDED_8K_1S_FILE  "recorded_hello8000-1s.wav"
#define RECORDED_16K_1S_FILE  "recorded_hello16000-1s.wav"
jehan's avatar
jehan committed
74

jehan's avatar
jehan committed
75
#define MULTICAST_IP  "224.1.2.3"
76

jehan's avatar
jehan committed
77
typedef struct _stats_t {
78
	OrtpEvQueue *q;
jehan's avatar
jehan committed
79 80
	rtp_stats_t rtp;
	int number_of_EndOfFile;
81
	int number_of_TMMBR;
jehan's avatar
jehan committed
82
} stats_t;
83

jehan's avatar
jehan committed
84 85 86 87 88 89 90 91
static void reset_stats(stats_t* s) {
	memset(s,0,sizeof(stats_t));
}


static void notify_cb(void *user_data, MSFilter *f, unsigned int event, void *eventdata) {
	stats_t* stats = (stats_t*)user_data;
	switch (event) {
92 93 94 95 96
		case MS_FILE_PLAYER_EOF: {
			ms_message("EndOfFile received");
			stats->number_of_EndOfFile++;
			break;
		}
jehan's avatar
jehan committed
97 98 99 100
		break;
	}
}

101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
static void event_queue_cb(MediaStream *ms, void *user_pointer) {
	stats_t *st = (stats_t *)user_pointer;
	OrtpEvent *ev = NULL;

	if (st->q != NULL) {
		while ((ev = ortp_ev_queue_get(st->q)) != NULL) {
			OrtpEventType evt = ortp_event_get_type(ev);
			OrtpEventData *d = ortp_event_get_data(ev);
			if (evt == ORTP_EVENT_TMMBR_RECEIVED) {
				do {
					if (rtcp_is_RTPFB(d->packet)) {
						switch (rtcp_RTPFB_get_type(d->packet)) {
							case RTCP_RTPFB_TMMBR:
								st->number_of_TMMBR++;
								break;
							default:
								break;
						}
					}
				} while (rtcp_next_packet(d->packet));
			}
			ortp_event_destroy(ev);
		}
	}
}

127 128 129 130 131 132 133 134 135 136 137 138 139
static void basic_audio_stream_base_2(	const char* marielle_local_ip
									  ,	const char* marielle_remote_ip
									  , int marielle_local_rtp_port
									  , int marielle_remote_rtp_port
									  ,	int marielle_local_rtcp_port
									  , int marielle_remote_rtcp_port
									  ,	const char*  margaux_local_ip
									  , const char*  margaux_remote_ip
									  ,	int margaux_local_rtp_port
									  , int margaux_remote_rtp_port
									  ,	int margaux_local_rtcp_port
									  , int margaux_remote_rtcp_port
									  , int lost_percentage) {
140
	AudioStream * 	marielle = audio_stream_new2 (_factory, marielle_local_ip, marielle_local_rtp_port, marielle_local_rtcp_port);
jehan's avatar
jehan committed
141
	stats_t marielle_stats;
142
	AudioStream * 	margaux = audio_stream_new2 (_factory, margaux_local_ip, margaux_local_rtp_port,margaux_local_rtcp_port);
jehan's avatar
jehan committed
143 144
	stats_t margaux_stats;
	RtpProfile* profile = rtp_profile_new("default profile");
145 146
	char* hello_file = bc_tester_res(HELLO_8K_1S_FILE);
	char* recorded_file = bc_tester_file(RECORDED_8K_1S_FILE);
147
	uint64_t marielle_rtp_sent=0;
148

jehan's avatar
jehan committed
149
	rtp_session_set_multicast_loopback(marielle->ms.sessions.rtp_session,TRUE);
150
	rtp_session_set_multicast_loopback(margaux->ms.sessions.rtp_session,TRUE);
151 152
	rtp_session_set_rtcp_report_interval(marielle->ms.sessions.rtp_session, 1000);
	rtp_session_set_rtcp_report_interval(margaux->ms.sessions.rtp_session, 1000);
153

154
	reset_stats(&marielle_stats);
jehan's avatar
jehan committed
155 156
	reset_stats(&margaux_stats);

157
	rtp_profile_set_payload (profile,0,&payload_type_pcmu8000);
158

159
	BC_ASSERT_EQUAL(audio_stream_start_full(margaux
160
											, profile
161 162 163 164
											, ms_is_multicast(margaux_local_ip)?margaux_local_ip:margaux_remote_ip
											, ms_is_multicast(margaux_local_ip)?margaux_local_rtp_port:margaux_remote_rtp_port
											, margaux_remote_ip
											, margaux_remote_rtcp_port
165
											, 0
166 167 168 169 170
											, 50
											, NULL
											, recorded_file
											, NULL
											, NULL
171 172
											, 0)
					,0, int, "%d");
173

174
	BC_ASSERT_EQUAL(audio_stream_start_full(marielle
175
											, profile
176 177 178 179
											, marielle_remote_ip
											, marielle_remote_rtp_port
											, marielle_remote_ip
											, marielle_remote_rtcp_port
180
											, 0
181 182 183 184 185
											, 50
											, hello_file
											, NULL
											, NULL
											, NULL
186 187
											, 0)
					,0, int, "%d");
188 189 190

	ms_filter_add_notify_callback(marielle->soundread, notify_cb, &marielle_stats,TRUE);

191
	wait_for_until(&marielle->ms,&margaux->ms,&marielle_stats.number_of_EndOfFile,1,12000);
192

193 194
	audio_stream_get_local_rtp_stats(marielle,&marielle_stats.rtp);
	audio_stream_get_local_rtp_stats(margaux,&margaux_stats.rtp);
195
	marielle_rtp_sent = marielle_stats.rtp.sent;
196 197


198
	if (rtp_session_rtcp_enabled(marielle->ms.sessions.rtp_session) && rtp_session_rtcp_enabled(margaux->ms.sessions.rtp_session)) {
199
		BC_ASSERT_GREATER_STRICT(rtp_session_get_round_trip_propagation(marielle->ms.sessions.rtp_session),0,float,"%f");
200
		BC_ASSERT_GREATER_STRICT(rtp_session_get_stats(marielle->ms.sessions.rtp_session)->recv_rtcp_packets,0,unsigned long long,"%llu");
201
	}
202

203
	audio_stream_stop(marielle);
204

205
	BC_ASSERT_TRUE(wait_for_until(&margaux->ms,NULL,(int*)&margaux_stats.rtp.hw_recv,(int)((marielle_rtp_sent*(100-lost_percentage))/100),2500));
206 207 208 209

	audio_stream_stop(margaux);

	unlink(recorded_file);
210 211
	free(recorded_file);
	free(hello_file);
212
	rtp_profile_destroy(profile);
213
}
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
static void basic_audio_stream_base(	const char* marielle_local_ip
									, 	int marielle_local_rtp_port
									, 	int marielle_local_rtcp_port
									, 	const char*  margaux_local_ip
									, 	int margaux_local_rtp_port
									, 	int margaux_local_rtcp_port) {
	basic_audio_stream_base_2( marielle_local_ip
							  , margaux_local_ip
							  , marielle_local_rtp_port
							  , margaux_local_rtp_port
							  , marielle_local_rtcp_port
							  , margaux_local_rtcp_port
							  , margaux_local_ip
							  , marielle_local_ip
							  , margaux_local_rtp_port
							  , marielle_local_rtp_port
							  , margaux_local_rtcp_port
							  , marielle_local_rtcp_port
							  , 0);
233

234
}
235
static void basic_audio_stream(void)  {
jehan's avatar
jehan committed
236 237 238 239
	basic_audio_stream_base(MARIELLE_IP,MARIELLE_RTP_PORT,MARIELLE_RTCP_PORT
							,MARGAUX_IP, MARGAUX_RTP_PORT, MARGAUX_RTCP_PORT);
}

240
static void multicast_audio_stream(void)  {
jehan's avatar
jehan committed
241 242 243
	basic_audio_stream_base("0.0.0.0",MARIELLE_RTP_PORT, 0
							,MULTICAST_IP, MARGAUX_RTP_PORT, 0);
}
244

245 246 247
static void encrypted_audio_stream_base( bool_t change_ssrc,
										 bool_t change_send_key_in_the_middle
										,bool_t set_both_send_recv_key
248
										,bool_t send_key_first
249 250
										,bool_t encryption_mandatory,
										MSCryptoSuite suite) {
251 252
	AudioStream * 	marielle = audio_stream_new (_factory, MARIELLE_RTP_PORT, MARIELLE_RTCP_PORT,FALSE);
	AudioStream * 	margaux = audio_stream_new (_factory, MARGAUX_RTP_PORT,MARGAUX_RTCP_PORT, FALSE);
253
	RtpProfile* profile = rtp_profile_new("default profile");
254 255
	char* hello_file = bc_tester_res(HELLO_8K_1S_FILE);
	char* recorded_file = bc_tester_file(RECORDED_8K_1S_FILE);
256 257
	stats_t marielle_stats;
	stats_t margaux_stats;
258
	int dummy=0;
259
	uint64_t number_of_dropped_packets=0;
260

261 262 263
	const char *aes_128_bits_send_key = "d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj";
	const char *aes_128_bits_send_key_2 = "eCYF4nYyCvmCpFWjUeDaxI2GWp2BzCRlIPfg52Te";
	const char *aes_128_bits_recv_key = "6jCLmtRkVW9E/BUuJtYj/R2z6+4iEe06/DWohQ9F";
264

265 266 267
	const char *aes_256_bits_send_key = "nJNTwiMkyAu8zs0MWUiSQbnBL4M+xkWTYgrVLR2eFwZyO+ca2UqBy2Uh9pVRbA==";
	const char *aes_256_bits_send_key_2 = "N3vq6TMfvtyYpqGaEi9vAHMCzgWJvaD1PIfwEYtdEgI2ACezZo2vpOdV2YWEcQ==";
	const char *aes_256_bits_recv_key = "UKg69sFLbrA7d0hEVKMtT83R3GR3sjhE0XMqNBbQ+axoDWMP5dQNfjNuSQQHbw==";
268

François Grisez's avatar
François Grisez committed
269 270 271 272 273
	const char *send_key = NULL;
	const char *send_key_2 = NULL;
	const char *recv_key = NULL;

	ms_media_stream_sessions_set_encryption_mandatory(&marielle->ms.sessions,encryption_mandatory);
274 275 276 277 278 279 280 281 282 283

	switch (suite) {
		case MS_AES_128_SHA1_32:
		case MS_AES_128_SHA1_80:
			send_key = aes_128_bits_send_key;
			send_key_2 = aes_128_bits_send_key_2;
			recv_key = aes_128_bits_recv_key;
			break;
		case MS_AES_256_SHA1_32:
		case MS_AES_256_SHA1_80:
284
		case MS_AES_CM_256_SHA1_80:
285 286 287 288
			send_key = aes_256_bits_send_key;
			send_key_2 = aes_256_bits_send_key_2;
			recv_key = aes_256_bits_recv_key;
			break;
289
		default:
François Grisez's avatar
François Grisez committed
290
			BC_FAIL("Unsupported suite");
291
			return;
292 293
	}

294

295
 	if (ms_srtp_supported()) {
296 297 298 299 300
		reset_stats(&marielle_stats);
		reset_stats(&margaux_stats);

		rtp_profile_set_payload (profile,0,&payload_type_pcmu8000);

301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
		BC_ASSERT_EQUAL(audio_stream_start_full(margaux
												, profile
												, MARIELLE_IP
												, MARIELLE_RTP_PORT
												, MARIELLE_IP
												, MARIELLE_RTCP_PORT
												, 0
												, 50
												, NULL
												, recorded_file
												, NULL
												, NULL
												, 0)
		,0, int, "%d");

		BC_ASSERT_EQUAL(audio_stream_start_full(marielle
												, profile
												, MARGAUX_IP
												, MARGAUX_RTP_PORT
												, MARGAUX_IP
												, MARGAUX_RTCP_PORT
												, 0
												, 50
												, hello_file
												, NULL
												, NULL
												, NULL
												, 0)
		,0, int, "%d");
330

331 332 333 334 335
		if (encryption_mandatory) {
			/*wait a bit to make sure packets are discarded*/
			wait_for_until(&marielle->ms,&margaux->ms,&dummy,1,1000);
			audio_stream_get_local_rtp_stats(margaux,&margaux_stats.rtp);
			audio_stream_get_local_rtp_stats(marielle,&marielle_stats.rtp);
336
			BC_ASSERT_EQUAL(margaux_stats.rtp.recv,0, unsigned long long, "%llu");
337 338 339
			number_of_dropped_packets=marielle_stats.rtp.packet_sent;
		}

340
		if (send_key_first) {
341
			BC_ASSERT_TRUE(ms_media_stream_sessions_set_srtp_send_key_b64(&(marielle->ms.sessions), suite, send_key) == 0);
342
			if (set_both_send_recv_key)
343
				BC_ASSERT_TRUE(ms_media_stream_sessions_set_srtp_send_key_b64(&(margaux->ms.sessions), suite, recv_key) == 0);
344

345
			BC_ASSERT_TRUE(ms_media_stream_sessions_set_srtp_recv_key_b64(&(margaux->ms.sessions), suite, send_key) ==0);
346
			if (set_both_send_recv_key)
347
				BC_ASSERT_TRUE(ms_media_stream_sessions_set_srtp_recv_key_b64(&(marielle->ms.sessions), suite, recv_key) ==0);
348 349

		} else {
350
			BC_ASSERT_TRUE(ms_media_stream_sessions_set_srtp_recv_key_b64(&(margaux->ms.sessions), suite, send_key) ==0);
351
			if (set_both_send_recv_key)
352
				BC_ASSERT_TRUE(ms_media_stream_sessions_set_srtp_recv_key_b64(&(marielle->ms.sessions), suite, recv_key) ==0);
353

354
			BC_ASSERT_TRUE(ms_media_stream_sessions_set_srtp_send_key_b64(&(marielle->ms.sessions), suite, send_key) == 0);
355
			if (set_both_send_recv_key)
356
				BC_ASSERT_TRUE(ms_media_stream_sessions_set_srtp_send_key_b64(&(margaux->ms.sessions), suite, recv_key) == 0);
357 358

		}
359

360 361
		if (set_both_send_recv_key) {
			wait_for_until(&marielle->ms,&margaux->ms,&dummy,1,1000);
362 363
			BC_ASSERT_TRUE(media_stream_secured((MediaStream*)marielle));
			BC_ASSERT_TRUE(media_stream_secured((MediaStream*)margaux));
364 365
		} else {
			/*so far, not possible to know audio stream direction*/
366 367
			BC_ASSERT_FALSE(media_stream_secured((MediaStream*)marielle));
			BC_ASSERT_FALSE(media_stream_secured((MediaStream*)margaux));
368 369
		}

370
		ms_filter_add_notify_callback(marielle->soundread, notify_cb, &marielle_stats,TRUE);
371 372
		if (change_send_key_in_the_middle) {
			wait_for_until(&marielle->ms,&margaux->ms,&dummy,1,2000);
373 374
			BC_ASSERT_TRUE(ms_media_stream_sessions_set_srtp_send_key_b64(&(marielle->ms.sessions), suite, send_key_2) == 0);
			BC_ASSERT_TRUE(ms_media_stream_sessions_set_srtp_recv_key_b64(&(margaux->ms.sessions), suite, send_key_2) ==0);
375
		}
376
		BC_ASSERT_TRUE(wait_for_until(&marielle->ms,&margaux->ms,&marielle_stats.number_of_EndOfFile,1,12000));
377

378 379 380
		/*make sure packets can cross from sender to receiver*/
		wait_for_until(&marielle->ms,&margaux->ms,&dummy,1,500);

381 382 383 384
		audio_stream_get_local_rtp_stats(marielle,&marielle_stats.rtp);
		audio_stream_get_local_rtp_stats(margaux,&margaux_stats.rtp);

		/* No packet loss is assumed */
385 386
		if (change_send_key_in_the_middle) {
			/*we can accept one or 2 error in such case*/
387
			BC_ASSERT_TRUE((marielle_stats.rtp.packet_sent-margaux_stats.rtp.packet_recv-number_of_dropped_packets)<3);
388
		} else
389
			BC_ASSERT_EQUAL(marielle_stats.rtp.packet_sent,margaux_stats.rtp.packet_recv+number_of_dropped_packets, unsigned long long, "%llu");
390

391 392
		if (change_ssrc) {
			audio_stream_stop(marielle);
393
			marielle = audio_stream_new (_factory, MARIELLE_RTP_PORT, MARIELLE_RTCP_PORT,FALSE);
394 395 396 397 398 399 400 401 402 403 404 405 406 407
			BC_ASSERT_EQUAL(audio_stream_start_full(marielle
													, profile
													, MARGAUX_IP
													, MARGAUX_RTP_PORT
													, MARGAUX_IP
													, MARGAUX_RTCP_PORT
													, 0
													, 50
													, hello_file
													, NULL
													, NULL
													, NULL
													, 0)
			,0, int, "%d");
408
			BC_ASSERT(ms_media_stream_sessions_set_srtp_send_key_b64(&(marielle->ms.sessions), suite, send_key) == 0);
409 410 411

			ms_filter_add_notify_callback(marielle->soundread, notify_cb, &marielle_stats,TRUE);

412
			BC_ASSERT_TRUE(wait_for_until(&marielle->ms,&margaux->ms,&marielle_stats.number_of_EndOfFile,2,12000));
413

414 415 416
			/*make sure packets can cross from sender to receiver*/
			wait_for_until(&marielle->ms,&margaux->ms,&dummy,1,500);

417 418 419 420
			audio_stream_get_local_rtp_stats(marielle,&marielle_stats.rtp);
			audio_stream_get_local_rtp_stats(margaux,&margaux_stats.rtp);

			/* No packet loss is assumed */
421
			BC_ASSERT_EQUAL(marielle_stats.rtp.sent*2,margaux_stats.rtp.recv, unsigned long long, "%llu");
422 423

		}
424 425

		unlink(recorded_file);
426 427
		free(recorded_file);
		free(hello_file);
428 429 430
	} else {
		ms_warning("srtp not available, skiping...");
	}
jehan's avatar
jehan committed
431 432
	audio_stream_stop(marielle);
	audio_stream_stop(margaux);
433
	rtp_profile_destroy(profile);
434
}
jehan's avatar
jehan committed
435

436
static void encrypted_audio_stream(void) {
437 438
	encrypted_audio_stream_base(FALSE, FALSE, FALSE, TRUE,FALSE,MS_AES_128_SHA1_32);
	encrypted_audio_stream_base(FALSE, FALSE, FALSE, TRUE,FALSE,MS_AES_256_SHA1_80);
jehan's avatar
jehan committed
439
}
440 441

static void encrypted_audio_stream_with_2_srtp_stream(void) {
442 443
	encrypted_audio_stream_base(FALSE, FALSE, TRUE, TRUE,FALSE,MS_AES_128_SHA1_32);
	encrypted_audio_stream_base(FALSE, FALSE, TRUE, TRUE,FALSE,MS_AES_256_SHA1_80);
444 445
}

446
static void encrypted_audio_stream_with_2_srtp_stream_recv_first(void) {
447
	encrypted_audio_stream_base(FALSE, FALSE, TRUE, FALSE,FALSE,MS_AES_128_SHA1_32);
448 449
}

450
static void encrypted_audio_stream_with_key_change(void) {
451
	encrypted_audio_stream_base(FALSE, TRUE, FALSE, TRUE,FALSE,MS_AES_128_SHA1_32);
452
}
453

454
static void encrypted_audio_stream_with_ssrc_change(void) {
455
	encrypted_audio_stream_base(TRUE, FALSE, FALSE, TRUE,FALSE,MS_AES_128_SHA1_32);
456 457
}
static void encrypted_audio_stream_encryption_mandatory(void) {
458
	encrypted_audio_stream_base(FALSE, FALSE, TRUE, TRUE,TRUE,MS_AES_128_SHA1_32);
459 460 461
}

static void encrypted_audio_stream_with_key_change_encryption_mandatory(void) {
462
	encrypted_audio_stream_base(FALSE, TRUE, FALSE, TRUE,TRUE,MS_AES_128_SHA1_32);
463 464
}

465
static void codec_change_for_audio_stream(void) {
466
	AudioStream *marielle = audio_stream_new2(_factory, MARIELLE_IP, MARIELLE_RTP_PORT, MARIELLE_RTCP_PORT);
467
	stats_t marielle_stats;
468
	AudioStream *margaux = audio_stream_new2(_factory, MARGAUX_IP, MARGAUX_RTP_PORT, MARGAUX_RTCP_PORT);
469 470
	stats_t margaux_stats;
	RtpProfile *profile = rtp_profile_new("default profile");
471 472
	char* hello_file = bc_tester_res(HELLO_8K_1S_FILE);
	char* recorded_file = bc_tester_file(RECORDED_8K_1S_FILE);
473
	uint64_t marielle_rtp_sent = 0;
474 475 476 477 478 479 480 481
	int dummy=0;

	reset_stats(&marielle_stats);
	reset_stats(&margaux_stats);

	rtp_profile_set_payload(profile, 0, &payload_type_pcmu8000);
	rtp_profile_set_payload(profile, 8, &payload_type_pcma8000);

482 483
	BC_ASSERT_EQUAL(audio_stream_start_full(margaux, profile, MARIELLE_IP, MARIELLE_RTP_PORT, MARIELLE_IP, MARIELLE_RTCP_PORT,
		0, 50, NULL, recorded_file, NULL, NULL, 0), 0, int, "%d");
484

485 486
	BC_ASSERT_EQUAL(audio_stream_start_full(marielle, profile, MARGAUX_IP, MARGAUX_RTP_PORT, MARGAUX_IP, MARGAUX_RTCP_PORT,
		0, 50, hello_file, NULL, NULL, NULL, 0), 0, int, "%d");
487 488 489

	ms_filter_add_notify_callback(marielle->soundread, notify_cb, &marielle_stats, TRUE);

490
	BC_ASSERT_TRUE(wait_for_until(&marielle->ms, &margaux->ms, &marielle_stats.number_of_EndOfFile, 1, 12000));
491 492 493 494 495 496 497 498

	/*make sure packets can cross from sender to receiver*/
	wait_for_until(&marielle->ms, &margaux->ms, &dummy, 1, 500);

	audio_stream_get_local_rtp_stats(marielle, &marielle_stats.rtp);
	audio_stream_get_local_rtp_stats(margaux, &margaux_stats.rtp);

	/* No packet loss is assumed */
499
	BC_ASSERT_EQUAL(marielle_stats.rtp.sent, margaux_stats.rtp.recv, unsigned long long, "%llu");
500
	marielle_rtp_sent = marielle_stats.rtp.sent;
501 502 503 504

	audio_stream_stop(marielle);
	reset_stats(&marielle_stats);
	reset_stats(&margaux_stats);
505
	marielle = audio_stream_new2(_factory, MARIELLE_IP, MARIELLE_RTP_PORT, MARIELLE_RTCP_PORT);
506 507
	BC_ASSERT_EQUAL(audio_stream_start_full(marielle, profile, MARGAUX_IP, MARGAUX_RTP_PORT, MARGAUX_IP, MARGAUX_RTCP_PORT,
		8, 50, hello_file, NULL, NULL, NULL, 0), 0, int, "%d");
508 509 510

	ms_filter_add_notify_callback(marielle->soundread, notify_cb, &marielle_stats, TRUE);

511
	BC_ASSERT_TRUE(wait_for_until(&marielle->ms, &margaux->ms, &marielle_stats.number_of_EndOfFile, 1, 12000));
512 513 514 515 516 517 518 519

	/*make sure packets can cross from sender to receiver*/
	wait_for_until(&marielle->ms, &margaux->ms, &dummy, 1, 500);

	audio_stream_get_local_rtp_stats(marielle,&marielle_stats.rtp);
	audio_stream_get_local_rtp_stats(margaux, &margaux_stats.rtp);

	/* No packet loss is assumed */
520
	BC_ASSERT_EQUAL(marielle_stats.rtp.sent + marielle_rtp_sent, margaux_stats.rtp.recv, unsigned long long, "%llu");
521
	BC_ASSERT_EQUAL(strcasecmp(margaux->ms.decoder->desc->enc_fmt, "pcma"), 0, int, "%d");
522 523 524 525
	audio_stream_stop(marielle);
	audio_stream_stop(margaux);

	unlink(recorded_file);
526 527
	free(recorded_file);
	free(hello_file);
528
	rtp_profile_destroy(profile);
529
}
530

531
static void tmmbr_feedback_for_audio_stream(void) {
532
	AudioStream *marielle = audio_stream_new2(_factory, MARIELLE_IP, MARIELLE_RTP_PORT, MARIELLE_RTCP_PORT);
533
	stats_t marielle_stats;
534
	AudioStream *margaux = audio_stream_new2(_factory, MARGAUX_IP, MARGAUX_RTP_PORT, MARGAUX_RTCP_PORT);
535 536 537 538
	stats_t margaux_stats;
	RtpProfile *profile = rtp_profile_new("default profile");
	RtpSession *marielle_session;
	RtpSession *margaux_session;
539
	char* hello_file = bc_tester_res(HELLO_8K_1S_FILE);
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
	int dummy=0;

	reset_stats(&marielle_stats);
	reset_stats(&margaux_stats);

	rtp_profile_set_payload(profile, 0, &payload_type_pcmu8000);

	/* Activate AVPF and TMBRR. */
	payload_type_set_flag(&payload_type_pcmu8000, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
	marielle_session = audio_stream_get_rtp_session(marielle);
	rtp_session_enable_avpf_feature(marielle_session, ORTP_AVPF_FEATURE_TMMBR, TRUE);
	marielle_stats.q = ortp_ev_queue_new();
	rtp_session_register_event_queue(marielle->ms.sessions.rtp_session, marielle_stats.q);
	margaux_session = audio_stream_get_rtp_session(margaux);
	rtp_session_enable_avpf_feature(margaux_session, ORTP_AVPF_FEATURE_TMMBR, TRUE);
	margaux_stats.q = ortp_ev_queue_new();
	rtp_session_register_event_queue(margaux->ms.sessions.rtp_session, margaux_stats.q);

558 559
	BC_ASSERT_EQUAL(audio_stream_start_full(margaux, profile, MARIELLE_IP, MARIELLE_RTP_PORT, MARIELLE_IP, MARIELLE_RTCP_PORT,
		0, 50, hello_file, NULL, NULL, NULL, 0), 0, int, "%d");
560

561 562
	BC_ASSERT_EQUAL(audio_stream_start_full(marielle, profile, MARGAUX_IP, MARGAUX_RTP_PORT, MARGAUX_IP, MARGAUX_RTCP_PORT,
		0, 50, hello_file, NULL, NULL, NULL, 0), 0, int, "%d");
563 564 565 566 567 568 569 570 571 572

	ms_filter_add_notify_callback(margaux->soundread, notify_cb, &margaux_stats, TRUE);
	ms_filter_add_notify_callback(marielle->soundread, notify_cb, &marielle_stats, TRUE);

	/* Wait for 1s so that some RTP packets are exchanged before sending the TMMBR. */
	wait_for_until(&margaux->ms, &marielle->ms, &dummy, 1, 500);

	rtp_session_send_rtcp_fb_tmmbr(margaux_session, 100000);
	rtp_session_send_rtcp_fb_tmmbr(marielle_session, 200000);

573 574
	BC_ASSERT_TRUE(wait_for_until(&margaux->ms, &marielle->ms, &margaux_stats.number_of_EndOfFile, 1, 12000));
	BC_ASSERT_TRUE(wait_for_until(&marielle->ms, &margaux->ms, &marielle_stats.number_of_EndOfFile, 1, 12000));
575

576 577 578 579
	BC_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->ms, &margaux->ms, &marielle_stats.number_of_TMMBR, 1, 100, event_queue_cb, &marielle_stats, event_queue_cb, &margaux_stats));
	BC_ASSERT_TRUE(wait_for_until_with_parse_events(&margaux->ms, &marielle->ms, &margaux_stats.number_of_TMMBR, 1, 100, event_queue_cb, &margaux_stats, event_queue_cb, &marielle_stats));
	BC_ASSERT_EQUAL(marielle_stats.number_of_TMMBR, 1, int, "%d");
	BC_ASSERT_EQUAL(margaux_stats.number_of_TMMBR, 1, int, "%d");
580 581 582 583 584 585 586

	/*make sure packets can cross from sender to receiver*/
	wait_for_until(&marielle->ms, &margaux->ms, &dummy, 1, 500);

	audio_stream_stop(marielle);
	audio_stream_stop(margaux);

587
	free(hello_file);
588 589 590 591 592
	ortp_ev_queue_destroy(marielle_stats.q);
	ortp_ev_queue_destroy(margaux_stats.q);
	rtp_profile_destroy(profile);
}

Simon Morlat's avatar
Simon Morlat committed
593
#if 0
594
static void audio_stream_dtmf(int codec_payload, int initial_bitrate,int target_bw, int max_recv_rtcp_packet) {
Simon Morlat's avatar
Simon Morlat committed
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
	stream_manager_t * marielle = stream_manager_new();
	stream_manager_t * margaux = stream_manager_new();
	int pause_time=0;

	OrtpNetworkSimulatorParams params={0};
	params.enabled=TRUE;
	params.loss_rate=0;
	params.max_bandwidth=target_bw;
	params.max_buffer_size=initial_bitrate;
	float recv_send_bw_ratio;
	int rtcp_interval = 1000;
	float marielle_send_bw;

	media_stream_enable_adaptive_bitrate_control(&marielle->stream->ms,TRUE);


	stream_manager_start(marielle,codec_payload, margaux->local_rtp,initial_bitrate,HELLO_16K_1S_FILE,NULL);
	ms_filter_call_method(marielle->stream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);

	unlink("blibi.wav");
	stream_manager_start(margaux,codec_payload, marielle->local_rtp,-1,NULL,"blibi.wav");
	rtp_session_enable_network_simulation(margaux->stream->ms.session,&params);
	rtp_session_set_rtcp_report_interval(margaux->stream->ms.session, rtcp_interval);

	wait_for_until(&marielle->stream->ms,&margaux->stream->ms,&marielle->stats.number_of_EndOfFile,10,rtcp_interval*max_recv_rtcp_packet);

	marielle_send_bw=media_stream_get_up_bw(&marielle->stream->ms);
	recv_send_bw_ratio=params.max_bandwidth/marielle_send_bw;
	ms_message("marielle sent bw= [%f] , target was [%f] recv/send [%f]",marielle_send_bw,params.max_bandwidth,recv_send_bw_ratio);
624
	BC_ASSERT_TRUE(recv_send_bw_ratio>0.9);
Simon Morlat's avatar
Simon Morlat committed
625 626 627

	stream_manager_delete(marielle);
	stream_manager_delete(margaux);
628 629

}
Simon Morlat's avatar
Simon Morlat committed
630 631
#endif

632 633 634 635 636 637 638
static void symetric_rtp_with_wrong_addr(void)  {
	basic_audio_stream_base_2(  MARIELLE_IP
							  , "10.10.10.10" /*dummy ip*/
							  , MARIELLE_RTP_PORT
							  , MARGAUX_RTP_PORT
							  , MARIELLE_RTCP_PORT
							  , MARGAUX_RTCP_PORT
639

640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
							  , MARGAUX_IP
							  , MARIELLE_IP
							  , MARGAUX_RTP_PORT
							  , MARIELLE_RTP_PORT
							  , MARGAUX_RTCP_PORT
							  , MARIELLE_RTCP_PORT
							  ,5);
}

static void symetric_rtp_with_wrong_rtcp_port(void)  {
	basic_audio_stream_base_2(  MARIELLE_IP
							  , MARGAUX_IP
							  , MARIELLE_RTP_PORT
							  , MARGAUX_RTP_PORT
							  , MARIELLE_RTCP_PORT
							  , MARGAUX_RTCP_PORT
656

657 658 659 660 661 662 663 664 665
							  , MARGAUX_IP
							  , MARIELLE_IP
							  , MARGAUX_RTP_PORT
							  , MARIELLE_RTP_PORT
							  , MARGAUX_RTCP_PORT
							  , MARIELLE_RTCP_PORT +10 /*dummy port*/
							  ,5);
}

666

jehan's avatar
jehan committed
667
static test_t tests[] = {
668 669 670 671 672 673 674 675 676 677 678 679 680
	TEST_NO_TAG("Basic audio stream", basic_audio_stream),
	TEST_NO_TAG("Multicast audio stream", multicast_audio_stream),
	TEST_NO_TAG("Encrypted audio stream", encrypted_audio_stream),
	TEST_NO_TAG("Encrypted audio stream with 2 srtp context", encrypted_audio_stream_with_2_srtp_stream),
	TEST_NO_TAG("Encrypted audio stream with 2 srtp context, recv first", encrypted_audio_stream_with_2_srtp_stream_recv_first),
	TEST_NO_TAG("Encrypted audio stream with ssrc changes", encrypted_audio_stream_with_ssrc_change),
	TEST_NO_TAG("Encrypted audio stream with key change", encrypted_audio_stream_with_key_change),
	TEST_NO_TAG("Encrypted audio stream, encryption mandatory", encrypted_audio_stream_encryption_mandatory),
	TEST_NO_TAG("Encrypted audio stream with key change + encryption mandatory", encrypted_audio_stream_with_key_change_encryption_mandatory),
	TEST_NO_TAG("Codec change for audio stream", codec_change_for_audio_stream),
	TEST_NO_TAG("TMMBR feedback for audio stream", tmmbr_feedback_for_audio_stream),
	TEST_NO_TAG("Symetric rtp with wrong address", symetric_rtp_with_wrong_addr),
	TEST_NO_TAG("Symetric rtp with wrong rtcp port", symetric_rtp_with_wrong_rtcp_port),
jehan's avatar
jehan committed
681 682 683 684
};

test_suite_t audio_stream_test_suite = {
	"AudioStream",
685 686 687 688
	tester_before_all,
	tester_after_all,
	NULL,
	NULL,
jehan's avatar
jehan committed
689 690 691
	sizeof(tests) / sizeof(tests[0]),
	tests
};