mediastreamer2_audio_stream_tester.c 25.6 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


33
static int tester_before_all(void) {
34
	//ms_init();
35 36 37
	_factory = ms_factory_new();
	ms_factory_init_voip(_factory);
	ms_factory_init_plugins(_factory);
38

39
	//ms_filter_enable_statistics(TRUE);
40
	ms_factory_enable_statistics(_factory, TRUE);
jehan's avatar
jehan committed
41 42 43 44 45
	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);
46
	rtp_profile_set_payload (&rtp_profile,PCMA8_PAYLOAD_TYPE,&payload_type_pcma8000);
jehan's avatar
jehan committed
47 48 49
	return 0;
}

50
static int tester_after_all(void) {
51 52
	//ms_exit();

53
	ms_factory_destroy(_factory);
jehan's avatar
jehan committed
54 55 56 57 58 59 60 61 62 63 64 65
	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"

66 67
#define HELLO_8K_1S_FILE  "sounds/hello8000-1s.wav"
#define HELLO_16K_1S_FILE  "sounds/hello16000-1s.wav"
68 69
#define RECORDED_8K_1S_FILE  "recorded_hello8000-1s.wav"
#define RECORDED_16K_1S_FILE  "recorded_hello16000-1s.wav"
jehan's avatar
jehan committed
70

jehan's avatar
jehan committed
71
#define MULTICAST_IP  "224.1.2.3"
72

jehan's avatar
jehan committed
73
typedef struct _stats_t {
74
	OrtpEvQueue *q;
jehan's avatar
jehan committed
75 76
	rtp_stats_t rtp;
	int number_of_EndOfFile;
77
	int number_of_TMMBR;
jehan's avatar
jehan committed
78
} stats_t;
79

jehan's avatar
jehan committed
80 81 82 83 84 85 86 87
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) {
88 89 90 91 92
		case MS_FILE_PLAYER_EOF: {
			ms_message("EndOfFile received");
			stats->number_of_EndOfFile++;
			break;
		}
jehan's avatar
jehan committed
93 94 95 96
		break;
	}
}

97 98 99 100 101 102 103 104
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);
105
			if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
				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);
		}
	}
}

123 124 125 126 127 128 129 130 131 132 133 134 135
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) {
136
	AudioStream * 	marielle = audio_stream_new2 (_factory, marielle_local_ip, marielle_local_rtp_port, marielle_local_rtcp_port);
jehan's avatar
jehan committed
137
	stats_t marielle_stats;
138
	AudioStream * 	margaux = audio_stream_new2 (_factory, margaux_local_ip, margaux_local_rtp_port,margaux_local_rtcp_port);
jehan's avatar
jehan committed
139 140
	stats_t margaux_stats;
	RtpProfile* profile = rtp_profile_new("default profile");
141 142
	char* hello_file = bc_tester_res(HELLO_8K_1S_FILE);
	char* recorded_file = bc_tester_file(RECORDED_8K_1S_FILE);
143
	uint64_t marielle_rtp_sent=0;
144

jehan's avatar
jehan committed
145
	rtp_session_set_multicast_loopback(marielle->ms.sessions.rtp_session,TRUE);
146
	rtp_session_set_multicast_loopback(margaux->ms.sessions.rtp_session,TRUE);
147 148
	rtp_session_set_rtcp_report_interval(marielle->ms.sessions.rtp_session, 1000);
	rtp_session_set_rtcp_report_interval(margaux->ms.sessions.rtp_session, 1000);
149

150
	reset_stats(&marielle_stats);
jehan's avatar
jehan committed
151 152
	reset_stats(&margaux_stats);

153
	rtp_profile_set_payload (profile,0,&payload_type_pcmu8000);
154

155
	BC_ASSERT_EQUAL(audio_stream_start_full(margaux
156
											, profile
157 158 159 160
											, 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
161
											, 0
162 163 164 165 166
											, 50
											, NULL
											, recorded_file
											, NULL
											, NULL
167 168
											, 0)
					,0, int, "%d");
169

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

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

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

189 190
	audio_stream_get_local_rtp_stats(marielle,&marielle_stats.rtp);
	audio_stream_get_local_rtp_stats(margaux,&margaux_stats.rtp);
191
	marielle_rtp_sent = marielle_stats.rtp.sent;
192 193


194
	if (rtp_session_rtcp_enabled(marielle->ms.sessions.rtp_session) && rtp_session_rtcp_enabled(margaux->ms.sessions.rtp_session)) {
195
		BC_ASSERT_GREATER_STRICT(rtp_session_get_round_trip_propagation(marielle->ms.sessions.rtp_session),0,float,"%f");
196
		BC_ASSERT_GREATER_STRICT(rtp_session_get_stats(marielle->ms.sessions.rtp_session)->recv_rtcp_packets,0,unsigned long long,"%llu");
197
	}
198

199
	audio_stream_stop(marielle);
200

201
	BC_ASSERT_TRUE(wait_for_until(&margaux->ms,NULL,(int*)&margaux_stats.rtp.hw_recv,(int)((marielle_rtp_sent*(100-lost_percentage))/100),2500));
202 203 204 205

	audio_stream_stop(margaux);

	unlink(recorded_file);
206 207
	free(recorded_file);
	free(hello_file);
208
	rtp_profile_destroy(profile);
209
}
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
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);
229

230
}
231
static void basic_audio_stream(void)  {
jehan's avatar
jehan committed
232 233 234 235
	basic_audio_stream_base(MARIELLE_IP,MARIELLE_RTP_PORT,MARIELLE_RTCP_PORT
							,MARGAUX_IP, MARGAUX_RTP_PORT, MARGAUX_RTCP_PORT);
}

236
static void multicast_audio_stream(void)  {
jehan's avatar
jehan committed
237 238 239
	basic_audio_stream_base("0.0.0.0",MARIELLE_RTP_PORT, 0
							,MULTICAST_IP, MARGAUX_RTP_PORT, 0);
}
240

241 242 243
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
244
										,bool_t send_key_first
245 246
										,bool_t encryption_mandatory,
										MSCryptoSuite suite) {
247 248
	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);
249
	RtpProfile* profile = rtp_profile_new("default profile");
250 251
	char* hello_file = bc_tester_res(HELLO_8K_1S_FILE);
	char* recorded_file = bc_tester_file(RECORDED_8K_1S_FILE);
252 253
	stats_t marielle_stats;
	stats_t margaux_stats;
254
	int dummy=0;
255
	uint64_t number_of_dropped_packets=0;
256

257 258 259
	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";
260

261 262 263
	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==";
264

François Grisez's avatar
François Grisez committed
265 266 267 268 269
	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);
270 271 272 273 274 275 276 277 278 279

	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:
280
		case MS_AES_CM_256_SHA1_80:
281 282 283 284
			send_key = aes_256_bits_send_key;
			send_key_2 = aes_256_bits_send_key_2;
			recv_key = aes_256_bits_recv_key;
			break;
285
		default:
François Grisez's avatar
François Grisez committed
286
			BC_FAIL("Unsupported suite");
287
			return;
288 289
	}

290

291
 	if (ms_srtp_supported()) {
292 293 294 295 296
		reset_stats(&marielle_stats);
		reset_stats(&margaux_stats);

		rtp_profile_set_payload (profile,0,&payload_type_pcmu8000);

297 298 299 300 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
		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");
326

327 328 329 330 331
		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);
332
			BC_ASSERT_EQUAL(margaux_stats.rtp.recv,0, unsigned long long, "%llu");
333 334 335
			number_of_dropped_packets=marielle_stats.rtp.packet_sent;
		}

336
		if (send_key_first) {
337
			BC_ASSERT_TRUE(ms_media_stream_sessions_set_srtp_send_key_b64(&(marielle->ms.sessions), suite, send_key) == 0);
338
			if (set_both_send_recv_key)
339
				BC_ASSERT_TRUE(ms_media_stream_sessions_set_srtp_send_key_b64(&(margaux->ms.sessions), suite, recv_key) == 0);
340

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

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

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

		}
355

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

366
		ms_filter_add_notify_callback(marielle->soundread, notify_cb, &marielle_stats,TRUE);
367 368
		if (change_send_key_in_the_middle) {
			wait_for_until(&marielle->ms,&margaux->ms,&dummy,1,2000);
369 370
			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);
371
		}
372
		BC_ASSERT_TRUE(wait_for_until(&marielle->ms,&margaux->ms,&marielle_stats.number_of_EndOfFile,1,12000));
373

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

377 378 379 380
		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 */
381 382
		if (change_send_key_in_the_middle) {
			/*we can accept one or 2 error in such case*/
383
			BC_ASSERT_TRUE((marielle_stats.rtp.packet_sent-margaux_stats.rtp.packet_recv-number_of_dropped_packets)<3);
384
		} else
385
			BC_ASSERT_EQUAL(marielle_stats.rtp.packet_sent,margaux_stats.rtp.packet_recv+number_of_dropped_packets, unsigned long long, "%llu");
386

387 388
		if (change_ssrc) {
			audio_stream_stop(marielle);
389
			marielle = audio_stream_new (_factory, MARIELLE_RTP_PORT, MARIELLE_RTCP_PORT,FALSE);
390 391 392 393 394 395 396 397 398 399 400 401 402 403
			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");
404
			BC_ASSERT(ms_media_stream_sessions_set_srtp_send_key_b64(&(marielle->ms.sessions), suite, send_key) == 0);
405 406 407

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

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

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

413 414 415 416
			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 */
417
			BC_ASSERT_EQUAL(marielle_stats.rtp.sent*2,margaux_stats.rtp.recv, unsigned long long, "%llu");
418 419

		}
420 421

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

432
static void encrypted_audio_stream(void) {
433 434
	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
435
}
436 437

static void encrypted_audio_stream_with_2_srtp_stream(void) {
438 439
	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);
440 441
}

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

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

450
static void encrypted_audio_stream_with_ssrc_change(void) {
451
	encrypted_audio_stream_base(TRUE, FALSE, FALSE, TRUE,FALSE,MS_AES_128_SHA1_32);
452 453
}
static void encrypted_audio_stream_encryption_mandatory(void) {
454
	encrypted_audio_stream_base(FALSE, FALSE, TRUE, TRUE,TRUE,MS_AES_128_SHA1_32);
455 456 457
}

static void encrypted_audio_stream_with_key_change_encryption_mandatory(void) {
458
	encrypted_audio_stream_base(FALSE, TRUE, FALSE, TRUE,TRUE,MS_AES_128_SHA1_32);
459 460
}

461
static void codec_change_for_audio_stream(void) {
462
	AudioStream *marielle = audio_stream_new2(_factory, MARIELLE_IP, MARIELLE_RTP_PORT, MARIELLE_RTCP_PORT);
463
	stats_t marielle_stats;
464
	AudioStream *margaux = audio_stream_new2(_factory, MARGAUX_IP, MARGAUX_RTP_PORT, MARGAUX_RTCP_PORT);
465 466
	stats_t margaux_stats;
	RtpProfile *profile = rtp_profile_new("default profile");
467 468
	char* hello_file = bc_tester_res(HELLO_8K_1S_FILE);
	char* recorded_file = bc_tester_file(RECORDED_8K_1S_FILE);
469
	uint64_t marielle_rtp_sent = 0;
470 471 472 473 474 475 476 477
	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);

478 479
	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");
480

481 482
	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");
483 484 485

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

486
	BC_ASSERT_TRUE(wait_for_until(&marielle->ms, &margaux->ms, &marielle_stats.number_of_EndOfFile, 1, 12000));
487 488 489 490 491 492 493 494

	/*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 */
495
	BC_ASSERT_EQUAL(marielle_stats.rtp.sent, margaux_stats.rtp.recv, unsigned long long, "%llu");
496
	marielle_rtp_sent = marielle_stats.rtp.sent;
497 498 499 500

	audio_stream_stop(marielle);
	reset_stats(&marielle_stats);
	reset_stats(&margaux_stats);
501
	marielle = audio_stream_new2(_factory, MARIELLE_IP, MARIELLE_RTP_PORT, MARIELLE_RTCP_PORT);
502 503
	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");
504 505 506

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

507
	BC_ASSERT_TRUE(wait_for_until(&marielle->ms, &margaux->ms, &marielle_stats.number_of_EndOfFile, 1, 12000));
508 509 510 511 512 513 514 515

	/*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 */
516
	BC_ASSERT_EQUAL(marielle_stats.rtp.sent + marielle_rtp_sent, margaux_stats.rtp.recv, unsigned long long, "%llu");
517
	BC_ASSERT_EQUAL(strcasecmp(margaux->ms.decoder->desc->enc_fmt, "pcma"), 0, int, "%d");
518 519 520 521
	audio_stream_stop(marielle);
	audio_stream_stop(margaux);

	unlink(recorded_file);
522 523
	free(recorded_file);
	free(hello_file);
524
	rtp_profile_destroy(profile);
525
}
526

527
static void tmmbr_feedback_for_audio_stream(void) {
528
	AudioStream *marielle = audio_stream_new2(_factory, MARIELLE_IP, MARIELLE_RTP_PORT, MARIELLE_RTCP_PORT);
529
	stats_t marielle_stats;
530
	AudioStream *margaux = audio_stream_new2(_factory, MARGAUX_IP, MARGAUX_RTP_PORT, MARGAUX_RTCP_PORT);
531 532 533 534
	stats_t margaux_stats;
	RtpProfile *profile = rtp_profile_new("default profile");
	RtpSession *marielle_session;
	RtpSession *margaux_session;
535
	char* hello_file = bc_tester_res(HELLO_8K_1S_FILE);
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553
	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);

554 555
	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");
556

557 558
	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");
559 560 561 562 563 564 565 566 567 568

	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);

569 570
	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));
571

572 573 574 575
	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");
576 577 578 579 580 581 582

	/*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);

583
	free(hello_file);
584 585 586 587 588
	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
589
#if 0
590
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
591 592 593 594 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
	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);
620
	BC_ASSERT_TRUE(recv_send_bw_ratio>0.9);
Simon Morlat's avatar
Simon Morlat committed
621 622 623

	stream_manager_delete(marielle);
	stream_manager_delete(margaux);
624 625

}
Simon Morlat's avatar
Simon Morlat committed
626 627
#endif

628 629 630 631 632 633 634
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
635

636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
							  , 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
652

653 654 655 656 657 658 659 660 661
							  , MARGAUX_IP
							  , MARIELLE_IP
							  , MARGAUX_RTP_PORT
							  , MARIELLE_RTP_PORT
							  , MARGAUX_RTCP_PORT
							  , MARIELLE_RTCP_PORT +10 /*dummy port*/
							  ,5);
}

662

jehan's avatar
jehan committed
663
static test_t tests[] = {
664 665 666 667 668 669 670 671 672 673 674 675 676
	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
677 678 679 680
};

test_suite_t audio_stream_test_suite = {
	"AudioStream",
681 682 683 684
	tester_before_all,
	tester_after_all,
	NULL,
	NULL,
jehan's avatar
jehan committed
685 686 687
	sizeof(tests) / sizeof(tests[0]),
	tests
};