mediastreamer2_adaptive_tester.c 21.1 KB
Newer Older
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.
18 19 20 21 22 23 24 25 26 27
*/

#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"
Ghislain MARY's avatar
Ghislain MARY committed
28
#include "qosanalyzer.h"
29
#include <math.h>
30
#include <sys/stat.h>
31 32 33 34

static RtpProfile rtp_profile;

#define OPUS_PAYLOAD_TYPE    121
35
#define SPEEX_PAYLOAD_TYPE 122
36 37
#define SILK16_PAYLOAD_TYPE  123
#define PCMA8_PAYLOAD_TYPE 8
38
#define BV16_PAYLOAD_TYPE 127
39 40 41 42
#define H263_PAYLOAD_TYPE 34
#define H264_PAYLOAD_TYPE 102
#define VP8_PAYLOAD_TYPE 103

43 44
#define EDGE_BW 10
#define THIRDGENERATION_BW 200
45

46
static MSFactory *_factory = NULL;
47
static int tester_before_all(void) {
48

49 50 51
	_factory = ms_factory_new();
	ms_factory_init_voip(_factory);
	ms_factory_init_plugins(_factory);
52 53

	//ms_filter_enable_statistics(TRUE);
54
	ms_factory_enable_statistics(_factory, TRUE);
55 56 57
	ortp_init();
	rtp_profile_set_payload (&rtp_profile,0,&payload_type_pcmu8000);
	rtp_profile_set_payload (&rtp_profile,OPUS_PAYLOAD_TYPE,&payload_type_opus);
58
	rtp_profile_set_payload (&rtp_profile,SPEEX_PAYLOAD_TYPE,&payload_type_speex_wb);
59 60 61 62 63 64 65 66 67
	rtp_profile_set_payload (&rtp_profile,SILK16_PAYLOAD_TYPE,&payload_type_silk_wb);
	rtp_profile_set_payload (&rtp_profile,PCMA8_PAYLOAD_TYPE,&payload_type_pcma8000);

	rtp_profile_set_payload (&rtp_profile,H263_PAYLOAD_TYPE,&payload_type_h263);
	rtp_profile_set_payload(&rtp_profile,H264_PAYLOAD_TYPE,&payload_type_h264);
	rtp_profile_set_payload(&rtp_profile, VP8_PAYLOAD_TYPE, &payload_type_vp8);
	return 0;
}

68
static int tester_after_all(void) {
69
	ortp_exit();
70

71
	ms_factory_destroy(_factory);
72 73 74 75
	rtp_profile_clear_all(&rtp_profile);
	return 0;
}

76
#define HELLO_16K_1S_FILE  "sounds/hello16000-1s.wav"
77
#define RECORDED_16K_1S_FILE  "recorded_hello16000-1s.wav"
Sandrine Avakian's avatar
Sandrine Avakian committed
78 79
//#define RECORDED_16K_1S_FILE  "recorded_hello16000-1sbv16.wav"
#define RECORDED_16K_1S_NO_PLC_FILE  "withoutplc_recorded_hello16000-1sbv16.wav"
80 81

typedef struct _stream_manager_t {
Simon Morlat's avatar
Simon Morlat committed
82
	MSFormatType type;
83 84 85 86 87 88 89
	int local_rtp;
	int local_rtcp;

	union{
		AudioStream* audio_stream;
		VideoStream* video_stream;
	};
90

91 92
	int rtcp_count;

93 94 95 96 97
	struct {
		float loss_estim;
		float congestion_bw_estim;
	} adaptive_stats;

98
	void* user_data;
99

100 101
} stream_manager_t ;

102
stream_manager_t * stream_manager_new(MSFormatType type) {
103 104 105 106
	stream_manager_t * mgr = ms_new0(stream_manager_t,1);
	mgr->type=type;
	mgr->local_rtp=(rand() % ((2^16)-1024) + 1024) & ~0x1;
	mgr->local_rtcp=mgr->local_rtp+1;
107
	mgr->user_data = 0;
108

Simon Morlat's avatar
Simon Morlat committed
109
	if (mgr->type==MSAudio){
110
		mgr->audio_stream=audio_stream_new (_factory, mgr->local_rtp, mgr->local_rtcp,FALSE);
111
	}else{
112
#if VIDEO_ENABLED
113
		mgr->video_stream=video_stream_new (_factory, mgr->local_rtp, mgr->local_rtcp,FALSE);
114
#else
115
		ms_fatal("Unsupported stream type [%s]",ms_format_type_to_string(mgr->type));
116 117
#endif

118 119 120
	}
	return mgr;
}
121

122
static void stream_manager_delete(stream_manager_t * mgr) {
123

124 125 126 127 128
	if( mgr->user_data){
		ms_message("Destroying file %s", (char*)mgr->user_data);
		unlink((char*)mgr->user_data);
		ms_free(mgr->user_data);
	}
Simon Morlat's avatar
Simon Morlat committed
129
	if (mgr->type==MSAudio){
130 131
		audio_stream_stop(mgr->audio_stream);
	}else{
132
#if VIDEO_ENABLED
133
		video_stream_stop(mgr->video_stream);
134
#else
135
		ms_fatal("Unsupported stream type [%s]",ms_format_type_to_string(mgr->type));
136
#endif
137 138 139 140 141 142 143 144 145 146
	}
	ms_free(mgr);
}

static void audio_manager_start(stream_manager_t * mgr
								,int payload_type
								,int remote_port
								,int target_bitrate
								,const char* player_file
								,const char* recorder_file){
147

148 149
	media_stream_set_target_network_bitrate(&mgr->audio_stream->ms,target_bitrate);

150 151 152 153 154 155 156 157 158 159 160 161 162 163
	BC_ASSERT_EQUAL(audio_stream_start_full(mgr->audio_stream
											, &rtp_profile
											, "127.0.0.1"
											, remote_port
											, "127.0.0.1"
											, remote_port+1
											, payload_type
											, 50
											, player_file
											, recorder_file
											, NULL
											, NULL
											, 0)
					,0, int, "%d");
164 165
}

166
#if VIDEO_ENABLED
167 168 169 170 171
static void video_manager_start(	stream_manager_t * mgr
									,int payload_type
									,int remote_port
									,int target_bitrate
									,MSWebCam * cam) {
172
	int result;
173 174
	media_stream_set_target_network_bitrate(&mgr->video_stream->ms,target_bitrate);

175
	result=video_stream_start(mgr->video_stream
176 177 178 179 180 181 182 183
												, &rtp_profile
												, "127.0.0.1"
												, remote_port
												, "127.0.0.1"
												, remote_port+1
												, payload_type
												, 60
												, cam);
184
	BC_ASSERT_EQUAL(result,0, int, "%d");
185
}
186
#endif
187

188 189 190
static void qos_analyzer_on_action_suggested(void *user_data, int datac, const char** datav){
	stream_manager_t *mgr = (stream_manager_t*)user_data;
	mgr->rtcp_count++;
191

192 193 194 195
	if (mgr->type==MSVideo && mgr->video_stream->ms.rc_enable){
		const MSQosAnalyzer *analyzer=ms_bitrate_controller_get_qos_analyzer(mgr->video_stream->ms.rc);
		if (analyzer->type==MSQosAnalyzerAlgorithmStateful){
			const MSStatefulQosAnalyzer *stateful_analyzer=((const MSStatefulQosAnalyzer*)analyzer);
196 197
			mgr->adaptive_stats.loss_estim=(float)stateful_analyzer->network_loss_rate;
			mgr->adaptive_stats.congestion_bw_estim=(float)stateful_analyzer->congestion_bandwidth;
198 199 200 201
		}
	}
}

202
static void disable_plc_on_audio_stream(AudioStream *p1){
203

204 205 206 207 208 209 210
	if (p1 != NULL){
		uint32_t features_p1 = audio_stream_get_features(p1);
		features_p1 &= ~AUDIO_STREAM_FEATURE_PLC;
		audio_stream_set_features(p1, features_p1);
	}
}

211
void start_adaptive_stream(MSFormatType type, stream_manager_t ** pmarielle, stream_manager_t ** pmargaux,
212
	int payload, int initial_bitrate, int max_bw, float loss_rate, int latency, float dup_ratio, bool_t disable_plc) {
213
	int pause_time=0;
214
	PayloadType* pt;
215
	MediaStream *marielle_ms,*margaux_ms;
216
	OrtpNetworkSimulatorParams params={0};
Ghislain MARY's avatar
Ghislain MARY committed
217 218
	char* recorded_file = NULL;
	char* file = bc_tester_res(HELLO_16K_1S_FILE);
219
#if VIDEO_ENABLED
220
	MSWebCam * marielle_webcam=mediastreamer2_tester_get_mire_webcam(ms_factory_get_web_cam_manager(_factory));
221
#endif
222

223 224
	stream_manager_t *marielle=*pmarielle=stream_manager_new(type);
	stream_manager_t *margaux=*pmargaux=stream_manager_new(type);
225

226 227 228 229 230
	if(disable_plc){
		disable_plc_on_audio_stream(margaux->audio_stream);
		disable_plc_on_audio_stream(marielle->audio_stream);
	}
	if (!disable_plc ){
231 232
		recorded_file = bc_tester_file(RECORDED_16K_1S_FILE);
	}else{
233 234
		recorded_file = bc_tester_file(RECORDED_16K_1S_NO_PLC_FILE);
	}
235

236
	marielle->user_data = ms_strdup(recorded_file);
237 238
	params.enabled=TRUE;
	params.loss_rate=loss_rate;
239
	params.max_bandwidth=(float)max_bw;
240
	params.latency=latency;
241

Simon Morlat's avatar
Simon Morlat committed
242
	if (type == MSAudio){
243 244 245 246 247 248
		marielle_ms=&marielle->audio_stream->ms;
		margaux_ms=&margaux->audio_stream->ms;
	}else{
		marielle_ms=&marielle->video_stream->ms;
		margaux_ms=&margaux->video_stream->ms;
	}
249

250
	/* Disable avpf. */
251
	pt = rtp_profile_get_payload(&rtp_profile, VP8_PAYLOAD_TYPE);
252 253 254
	if (BC_ASSERT_PTR_NOT_NULL(pt)) {
		payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
	}
255 256

	media_stream_enable_adaptive_bitrate_control(marielle_ms,TRUE);
257
	media_stream_set_adaptive_bitrate_algorithm(marielle_ms, MSQosAnalyzerAlgorithmStateful);
258 259
	rtp_session_set_duplication_ratio(marielle_ms->sessions.rtp_session, dup_ratio);

Simon Morlat's avatar
Simon Morlat committed
260
	if (marielle->type == MSAudio){
261
		audio_manager_start(marielle,payload,margaux->local_rtp,initial_bitrate,file,NULL);
262 263
		ms_filter_call_method(marielle->audio_stream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);

264
		audio_manager_start(margaux,payload,marielle->local_rtp,0,NULL,recorded_file);
265
	}else{
266
#if VIDEO_ENABLED
267
		marielle->video_stream->staticimage_webcam_fps_optimization = FALSE;
268
		video_manager_start(marielle,payload,margaux->local_rtp,0,marielle_webcam);
269
		video_stream_set_direction(margaux->video_stream, MediaStreamRecvOnly);
270
		video_manager_start(margaux,payload,marielle->local_rtp,0,NULL);
271
#else
272
		ms_fatal("Unsupported stream type [%s]",ms_format_type_to_string(marielle->type));
273
#endif
274
	}
275

276 277 278
	ms_qos_analyzer_set_on_action_suggested(ms_bitrate_controller_get_qos_analyzer(marielle_ms->rc),
						qos_analyzer_on_action_suggested,
						*pmarielle);
279
	rtp_session_enable_network_simulation(margaux_ms->sessions.rtp_session,&params);
280

281 282
	free(recorded_file);
	free(file);
283
}
284

285
static void iterate_adaptive_stream(stream_manager_t * marielle, stream_manager_t * margaux,
286
	int timeout_ms, int* current, int expected){
287
	int retry=0;
288 289

	MediaStream *marielle_ms,*margaux_ms;
Simon Morlat's avatar
Simon Morlat committed
290
	if (marielle->type == MSAudio){
291 292 293 294 295 296 297
		marielle_ms=&marielle->audio_stream->ms;
		margaux_ms=&margaux->audio_stream->ms;
	}else{
		marielle_ms=&marielle->video_stream->ms;
		margaux_ms=&margaux->video_stream->ms;
	}

298
	while ((!current||*current<expected) && retry++/5 <timeout_ms/100) {
299 300
		media_stream_iterate(marielle_ms);
		media_stream_iterate(margaux_ms);
301
		// handle_queue_events(marielle);
302
		if (retry%50==0) {
303
			 ms_message("stream [%p] bandwidth usage: [d=%.1f,u=%.1f] kbit/sec"	,
304
				marielle_ms, media_stream_get_down_bw(marielle_ms)/1000, media_stream_get_up_bw(marielle_ms)/1000);
305
			 ms_message("stream [%p] bandwidth usage: [d=%.1f,u=%.1f] kbit/sec"	,
306
				margaux_ms, media_stream_get_down_bw(margaux_ms)/1000, media_stream_get_up_bw(margaux_ms)/1000);
307
		 }
308
		ms_usleep(20000);
309 310 311
	}
}

312
static void stop_adaptive_stream(stream_manager_t *marielle, stream_manager_t *margaux, bool_t destroy_files){
313
	stream_manager_delete(marielle);
314
	stream_manager_delete(margaux);
315
}
316

317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
typedef struct {
		OrtpLossRateEstimator *estimator;
		OrtpEvQueue *q;
		int loss_rate;
}LossRateEstimatorCtx;
static void event_queue_cb(MediaStream *ms, void *user_pointer) {
	LossRateEstimatorCtx *ctx = (LossRateEstimatorCtx*)user_pointer;
	if (ctx->q != NULL) {
		OrtpEvent *ev = NULL;
		while ((ev = ortp_ev_queue_get(ctx->q)) != NULL) {
			OrtpEventType evt = ortp_event_get_type(ev);
			OrtpEventData *evd = ortp_event_get_data(ev);
			if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
				do {
					const report_block_t *rb=NULL;
					if (rtcp_is_SR(evd->packet)){
						rb=rtcp_SR_get_report_block(evd->packet,0);
					}else if (rtcp_is_RR(evd->packet)){
						rb=rtcp_RR_get_report_block(evd->packet,0);
					}

338
					if (rb&&ortp_loss_rate_estimator_process_report_block(ctx->estimator,ms->sessions.rtp_session,rb)){
339
						float diff = (float)fabs(ortp_loss_rate_estimator_get_value(ctx->estimator) - ctx->loss_rate);
340 341
						BC_ASSERT_GREATER(diff, 0, float, "%f");
						BC_ASSERT_LOWER(diff, 10, float, "%f");
342 343 344 345 346 347 348
					}
				} while (rtcp_next_packet(evd->packet));
			}
			ortp_event_destroy(ev);
		}
	}
}
349

350
/********************************** Tests are starting now ********************/
351
static void packet_duplication(void) {
352
	const rtp_stats_t *stats;
353
	float dup_ratio;
354 355
	stream_manager_t * marielle, * margaux;

356 357
	dup_ratio = 0.0f;
	start_adaptive_stream(MSAudio, &marielle, &margaux, SPEEX_PAYLOAD_TYPE, 32000, 0, 0.0f, 50, dup_ratio, FALSE);
358
	media_stream_enable_adaptive_bitrate_control(&marielle->audio_stream->ms,FALSE);
359
	iterate_adaptive_stream(marielle, margaux, 10000, NULL, 0);
360
	stats=rtp_session_get_stats(margaux->video_stream->ms.sessions.rtp_session);
361
	BC_ASSERT_EQUAL(stats->packet_dup_recv, dup_ratio ? (uint64_t)(stats->packet_recv / (dup_ratio+1)) : 0, unsigned long long, "%llu");
362 363 364
	/*in theory, cumulative loss should be the invert of duplicated count, but
	since cumulative loss is computed only on received RTCP report and duplicated
	count is updated on each RTP packet received, we cannot accurately compare these values*/
365
	BC_ASSERT_LOWER(stats->cum_packet_loss, (int64_t)(-.5*stats->packet_dup_recv), long long, "%lld");
366
	stop_adaptive_stream(marielle,margaux,TRUE);
367

368 369
	dup_ratio = 1.0f;
	start_adaptive_stream(MSAudio, &marielle, &margaux, SPEEX_PAYLOAD_TYPE, 32000, 0, 0.0f, 50, dup_ratio, FALSE);
370
	media_stream_enable_adaptive_bitrate_control(&marielle->audio_stream->ms,FALSE);
371
	iterate_adaptive_stream(marielle, margaux, 10000, NULL, 0);
372
	stats=rtp_session_get_stats(margaux->video_stream->ms.sessions.rtp_session);
373
	BC_ASSERT_EQUAL(stats->packet_dup_recv, dup_ratio ? (uint64_t)(stats->packet_recv / (dup_ratio+1)) : 0, unsigned long long, "%llu");
374
	BC_ASSERT_LOWER(stats->cum_packet_loss, (int64_t)(-.5*stats->packet_dup_recv), long long, "%lld");
375
	stop_adaptive_stream(marielle,margaux,TRUE);
376 377
}

378
static void upload_bandwidth_computation(void) {
379 380

	//bool_t supported = ms_filter_codec_supported("pcma");
381
	bool_t supported = ms_factory_codec_supported(_factory, "pcma");
382

383 384 385
	if( supported ) {
		stream_manager_t * marielle, * margaux;
		int i;
386

387
		start_adaptive_stream(MSAudio, &marielle, &margaux, PCMA8_PAYLOAD_TYPE, 8000, 0, 0, 0, 0,0);
388 389 390
		media_stream_enable_adaptive_bitrate_control(&marielle->audio_stream->ms,FALSE);

		for (i = 0; i < 5; i++){
391
			rtp_session_set_duplication_ratio(marielle->audio_stream->ms.sessions.rtp_session, (float)i);
392 393
			iterate_adaptive_stream(marielle, margaux, 5000, NULL, 0);
			/*since PCMA uses 80kbit/s, upload bandwidth should just be 80+80*duplication_ratio kbit/s */
394
			BC_ASSERT_LOWER((float)fabs(rtp_session_get_send_bandwidth(marielle->audio_stream->ms.sessions.rtp_session)/1000. - 80.*(i+1)), 5.f, float, "%f");
395
		}
396
		stop_adaptive_stream(marielle,margaux,TRUE);
397 398
	}
}
399

400 401
off_t fsize(const char *filename) {
	struct stat st;
402

403 404
	if (stat(filename, &st) == 0)
		return st.st_size;
405

406 407 408 409 410 411 412
	return -1;
}

static void loss_rate_estimation_bv16(void){
	bool_t supported = ms_factory_codec_supported(_factory, "bv16");
	int plc_disabled=0 ;
	int size_with_plc = 0, size_no_plc= 0;
Ghislain MARY's avatar
Ghislain MARY committed
413 414
	int result;

415 416 417 418 419 420
	rtp_profile_set_payload(&rtp_profile,BV16_PAYLOAD_TYPE,&payload_type_bv16);
	if( supported ) {
		LossRateEstimatorCtx ctx;
		stream_manager_t * marielle, * margaux;
		int loss_rate = 15;
		for (plc_disabled = 0; plc_disabled <=1; plc_disabled++){
421
			start_adaptive_stream(MSAudio, &marielle, &margaux, BV16_PAYLOAD_TYPE, 8000, 0, (float)loss_rate, 0, 0.0f, (bool_t)plc_disabled);
422 423 424 425 426

			ctx.estimator=ortp_loss_rate_estimator_new(120, 2500, marielle->audio_stream->ms.sessions.rtp_session);
			ctx.q = ortp_ev_queue_new();
			rtp_session_register_event_queue(marielle->audio_stream->ms.sessions.rtp_session, ctx.q);
			ctx.loss_rate = loss_rate;
427

428 429
			/*loss rate should be the initial one*/
			wait_for_until_with_parse_events(&marielle->audio_stream->ms, &margaux->audio_stream->ms, &loss_rate, 100, 10000, event_queue_cb,&ctx,NULL,NULL);
430

431
			stop_adaptive_stream(marielle,margaux,FALSE);
432 433 434 435
			ortp_loss_rate_estimator_destroy(ctx.estimator);
			ortp_ev_queue_destroy(ctx.q);
		}
		/*file without plc must be approx 15% smaller in size than with plc */
Sandrine Avakian's avatar
Sandrine Avakian committed
436 437
		size_with_plc= fsize(bc_tester_file(RECORDED_16K_1S_FILE));
		size_no_plc = fsize(bc_tester_file(RECORDED_16K_1S_NO_PLC_FILE));
Ghislain MARY's avatar
Ghislain MARY committed
438
		result = (size_with_plc*loss_rate/100 + size_no_plc) ;
439 440

		BC_ASSERT_GREATER(result, size_with_plc, int, "%d");
441 442 443 444 445
		// if test worked, remove files
		if (result >= size_with_plc) {
			unlink(RECORDED_16K_1S_FILE);
			unlink(RECORDED_16K_1S_NO_PLC_FILE);
		}
446 447
	}
}
448

449
static void loss_rate_estimation(void) {
450

451
	bool_t supported = ms_factory_codec_supported(_factory, "pcma");
452 453 454 455
	if( supported ) {
		LossRateEstimatorCtx ctx;
		stream_manager_t * marielle, * margaux;
		int loss_rate = 15;
456
		start_adaptive_stream(MSAudio, &marielle, &margaux, PCMA8_PAYLOAD_TYPE, 8000, 0, (float)loss_rate, 0, 0.0f, FALSE);
457

Simon Morlat's avatar
Simon Morlat committed
458
		ctx.estimator=ortp_loss_rate_estimator_new(120, 2500, marielle->audio_stream->ms.sessions.rtp_session);
459 460 461 462 463 464 465 466 467 468 469
		ctx.q = ortp_ev_queue_new();
		rtp_session_register_event_queue(marielle->audio_stream->ms.sessions.rtp_session, ctx.q);
		ctx.loss_rate = loss_rate;

		/*loss rate should be the initial one*/
		wait_for_until_with_parse_events(&marielle->audio_stream->ms, &margaux->audio_stream->ms, &loss_rate, 100, 10000, event_queue_cb,&ctx,NULL,NULL);

		/*let's set some duplication. loss rate should NOT be changed */
		rtp_session_set_duplication_ratio(marielle->audio_stream->ms.sessions.rtp_session, 10);
		wait_for_until_with_parse_events(&marielle->audio_stream->ms, &margaux->audio_stream->ms, &loss_rate, 100, 10000, event_queue_cb,&ctx,NULL,NULL);

470
		stop_adaptive_stream(marielle,margaux,TRUE);
471 472 473 474 475
		ortp_loss_rate_estimator_destroy(ctx.estimator);
		ortp_ev_queue_destroy(ctx.q);
	}
}

476
void upload_bitrate(const char* codec, int payload, int target_bw, int expect_bw) {
477
	//bool_t supported = ms_filter_codec_supported("pcma");
Simon Morlat's avatar
Simon Morlat committed
478
	bool_t supported = ms_factory_codec_supported(_factory, codec);
479
	if( supported ) {
480
		float upload_bw;
481 482
		stream_manager_t * marielle, * margaux;

483
		start_adaptive_stream(MSAudio, &marielle, &margaux, payload, target_bw*1000, target_bw*1000, 0, 50,0,0);
484 485 486
		//these tests check that encoders stick to the guidelines, so we must use NOT
		//the adaptive algorithm which would modify these guidelines
		media_stream_enable_adaptive_bitrate_control(&marielle->audio_stream->ms,FALSE);
487
		iterate_adaptive_stream(marielle, margaux, 15000, NULL, 0);
488
		upload_bw=media_stream_get_up_bw(&marielle->audio_stream->ms) / 1000;
489 490
		BC_ASSERT_GREATER(upload_bw, (float)(expect_bw-2), float, "%f");
		BC_ASSERT_LOWER(upload_bw, (float)(expect_bw+2), float, "%f");
491
		stop_adaptive_stream(marielle,margaux,TRUE);
492 493 494
	}
}

495
static void upload_bitrate_pcma_3g(void) {
496 497 498 499
	// pcma codec bitrate is always 64 kbits, only ptime can change from 20ms to 100ms.
	// ptime=20  ms -> network bitrate=80 kbits/s
	// ptime=100 ms -> network bitrate=67 kbits/s
	upload_bitrate("pcma", PCMA8_PAYLOAD_TYPE, THIRDGENERATION_BW, 80);
500 501
}

502
static void upload_bitrate_speex_low(void)  {
503 504 505 506
	// speex codec bitrate can vary from 16 kbits/s to 42 kbits/s
	// bitrate=42 kbits/s ptime=20  ms -> network bitrate=58 kbits/s
	// bitrate=16 kbits/s ptime=100 ms -> network bitrate=19 kbits/s
	upload_bitrate("speex", SPEEX_PAYLOAD_TYPE, 25, 25);
507
}
508

509
static void upload_bitrate_speex_3g(void) {
510
	upload_bitrate("speex", SPEEX_PAYLOAD_TYPE, THIRDGENERATION_BW, 59);
511 512 513
}


514
static void upload_bitrate_opus_edge(void) {
515 516 517 518 519 520 521
	// opus codec bitrate can vary from 6 kbits/s to 184 kbits/s
	// bitrate=6   kbits/s and ptime=100  ms -> network bitrate=  9 kbits/s
	// bitrate=184 kbits/s and ptime=20   ms -> network bitrate=200 kbits/s
	// upload_bitrate("opus", OPUS_PAYLOAD_TYPE, EDGE_BW, 9);
	ms_warning("%s TODO: fix me. ptime in preprocess should be computed to stick the guidelines", __FUNCTION__);
	//until ptime is correctly set on startup, this will not work: currently ptime is set to 40ms but this
	// is not sufficient to match the guidelines without adaptive algorithm.
522
}
523

524
static void upload_bitrate_opus_3g(void) {
525
	upload_bitrate("opus", OPUS_PAYLOAD_TYPE, THIRDGENERATION_BW, 200);
526
}
527

528
#if VIDEO_ENABLED && 0
529
void adaptive_video(int max_bw, int exp_min_bw, int exp_max_bw, int loss_rate, int exp_min_loss, int exp_max_loss) {
530
	bool_t supported = ms_filter_codec_supported("VP8");
531
	if( supported ) {
532 533 534
		stream_manager_t * marielle, * margaux;
		start_adaptive_stream(MSVideo, &marielle, &margaux, VP8_PAYLOAD_TYPE, 300*1000, max_bw*1000, loss_rate, 50,0);
		iterate_adaptive_stream(marielle, margaux, 100000, &marielle->rtcp_count, 7);
535 536 537 538
		BC_ASSERT_GREATER(marielle->adaptive_stats.loss_estim, exp_min_loss, int, "%d");
		BC_ASSERT_LOWER(marielle->adaptive_stats.loss_estim, exp_max_loss, int, "%d");
		BC_ASSERT_GREATER(marielle->adaptive_stats.congestion_bw_estim, exp_min_bw, int, "%d");
		BC_ASSERT_LOWER(marielle->adaptive_stats.congestion_bw_estim, exp_max_bw, int, "%d");
539
		stop_adaptive_stream(marielle,margaux,TRUE);
540 541
	}
}
542

543
static void adaptive_vp8_ideal() {
544
	adaptive_video(0, 200, 10000, 0, 0, 1);
545 546
}
static void adaptive_vp8_lossy() {
547
	adaptive_video(0, 200, 10000, 25, 20, 30);
548 549 550 551 552 553 554 555
}
static void adaptive_vp8_congestion() {
	adaptive_video(70, 50, 95, 0, 0, 2);
}
static void adaptive_vp8_lossy_congestion() {
	ms_warning("Disabled yet, too much instable");
	// adaptive_video(130, 110, 150, 7, 4, 10);
}
556
#endif
557

558 559

static test_t tests[] = {
560 561 562 563
	TEST_NO_TAG("Packet duplication", packet_duplication),
	TEST_NO_TAG("Upload bandwidth computation", upload_bandwidth_computation),
	TEST_NO_TAG("Loss rate estimation", loss_rate_estimation),
	TEST_NO_TAG("Loss rate estimationBV16", loss_rate_estimation_bv16),
564

565 566 567 568 569
	TEST_NO_TAG("Upload bitrate [pcma] - 3g", upload_bitrate_pcma_3g),
	TEST_NO_TAG("Upload bitrate [speex] - low", upload_bitrate_speex_low),
	TEST_NO_TAG("Upload bitrate [speex] - 3g", upload_bitrate_speex_3g),
	TEST_NO_TAG("Upload bitrate [opus] - edge", upload_bitrate_opus_edge),
	TEST_NO_TAG("Upload bitrate [opus] - 3g", upload_bitrate_opus_3g),
570

571
#if VIDEO_ENABLED && 0
572 573 574 575
	TEST_NO_TAG("Network detection [VP8] - ideal", adaptive_vp8_ideal),
	TEST_NO_TAG("Network detection [VP8] - lossy", adaptive_vp8_lossy),
	TEST_NO_TAG("Network detection [VP8] - congested", adaptive_vp8_congestion),
	TEST_NO_TAG("Network detection [VP8] - lossy congested", adaptive_vp8_lossy_congestion),
576
#endif
577 578 579
};

test_suite_t adaptive_test_suite = {
580
	"AdaptiveAlgorithm",
581 582 583 584
	tester_before_all,
	tester_after_all,
	NULL,
	NULL,
585 586 587
	sizeof(tests) / sizeof(tests[0]),
	tests
};