static void adaptive_vp8() {
	stream_manager_t * marielle, * margaux;

	start_adaptive_stream(VideoStreamType, &marielle, &margaux, VP8_PAYLOAD_TYPE, 300000, 0, 25, 50, 0);
	iterate_adaptive_stream(marielle, margaux, 100000, &marielle->rtcp_count, 12);
	CU_ASSERT_IN_RANGE(marielle->adaptive_stats.loss_estim, 20, 30);
	CU_ASSERT_TRUE(marielle->adaptive_stats.congestion_bw_estim > 200);
	stop_adaptive_stream(marielle,margaux);

	start_adaptive_stream(VideoStreamType, &marielle, &margaux, VP8_PAYLOAD_TYPE, 300000, 45000, 0, 50,0);
	iterate_adaptive_stream(marielle, margaux, 100000, &marielle->rtcp_count, 12);
	CU_ASSERT_IN_RANGE(marielle->adaptive_stats.loss_estim, 0, 2);
	CU_ASSERT_IN_RANGE(marielle->adaptive_stats.congestion_bw_estim, 30, 60);
	stop_adaptive_stream(marielle,margaux);

	start_adaptive_stream(VideoStreamType, &marielle, &margaux, VP8_PAYLOAD_TYPE, 300000, 70000,0, 50,0);
	iterate_adaptive_stream(marielle, margaux, 100000, &marielle->rtcp_count, 12);
	CU_ASSERT_IN_RANGE(marielle->adaptive_stats.loss_estim, 0, 2);
	CU_ASSERT_IN_RANGE(marielle->adaptive_stats.congestion_bw_estim, 50, 95);
	stop_adaptive_stream(marielle,margaux);

	start_adaptive_stream(VideoStreamType, &marielle, &margaux, VP8_PAYLOAD_TYPE, 300000, 100000,15, 50,0);
	iterate_adaptive_stream(marielle, margaux, 100000, &marielle->rtcp_count, 12);
	CU_ASSERT_IN_RANGE(marielle->adaptive_stats.loss_estim, 10, 20);
	CU_ASSERT_IN_RANGE(marielle->adaptive_stats.congestion_bw_estim, 80, 125);
	stop_adaptive_stream(marielle,margaux);
}
static void adaptive_opus_audio_stream()  {
	bool_t supported = ms_filter_codec_supported("opus");
	if( supported ) {
		// at 8KHz -> 24kb/s
		// at 48KHz -> 48kb/s
		float bw_usage;
		stream_manager_t * marielle, * margaux;

		// on EDGEBW, both should be overconsumming
		start_adaptive_stream(AudioStreamType, &marielle, &margaux, OPUS_PAYLOAD_TYPE, 8000, EDGE_BW, 0, 0, 0);
		iterate_adaptive_stream(marielle, margaux, 10000, NULL, 0);
		bw_usage=media_stream_get_up_bw(&marielle->audio_stream->ms)*1./EDGE_BW;
		CU_ASSERT_IN_RANGE(bw_usage, 2.f, 3.f); // bad! since this codec cant change its ptime and it is the lower bitrate, no improvement can occur
		stop_adaptive_stream(marielle,margaux);

		start_adaptive_stream(AudioStreamType, &marielle, &margaux, OPUS_PAYLOAD_TYPE, 48000, EDGE_BW, 0, 0, 0);
		iterate_adaptive_stream(marielle, margaux, 10000, NULL, 0);
		bw_usage=media_stream_get_up_bw(&marielle->audio_stream->ms)*1./EDGE_BW;
		CU_ASSERT_IN_RANGE(bw_usage, 1.f, 1.4f); // bad!
		stop_adaptive_stream(marielle,margaux);

		// on 3G BW, both should be at max
		start_adaptive_stream(AudioStreamType, &marielle, &margaux, OPUS_PAYLOAD_TYPE, 8000, THIRDGENERATION_BW, 0, 0, 0);
		iterate_adaptive_stream(marielle, margaux, 10000, NULL, 0);
		bw_usage=media_stream_get_up_bw(&marielle->audio_stream->ms)*1./THIRDGENERATION_BW;
		CU_ASSERT_IN_RANGE(bw_usage, .1f, .15f);
		stop_adaptive_stream(marielle,margaux);

		start_adaptive_stream(AudioStreamType, &marielle, &margaux, OPUS_PAYLOAD_TYPE, 48000, THIRDGENERATION_BW, 0, 0, 0);
		iterate_adaptive_stream(marielle, margaux, 10000, NULL, 0);
		bw_usage=media_stream_get_up_bw(&marielle->audio_stream->ms)*1./THIRDGENERATION_BW;
		CU_ASSERT_IN_RANGE(bw_usage, .2f, .3f);
		stop_adaptive_stream(marielle,margaux);
	}
}
/********************************** Tests are starting now ********************/
static void packet_duplication() {
	const rtp_stats_t *stats;
	double dup_ratio;
	stream_manager_t * marielle, * margaux;

	dup_ratio = 0;
	start_adaptive_stream(MSAudio, &marielle, &margaux, SPEEX_PAYLOAD_TYPE, 32000, 0, 0, 50,dup_ratio);
	media_stream_enable_adaptive_bitrate_control(&marielle->audio_stream->ms,FALSE);
	iterate_adaptive_stream(marielle, margaux, 10000, NULL, 0);
	stats=rtp_session_get_stats(margaux->video_stream->ms.sessions.rtp_session);
	CU_ASSERT_EQUAL(stats->packet_dup_recv, dup_ratio ? stats->packet_recv / (dup_ratio+1) : 0);
	/*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*/
	CU_ASSERT_TRUE(stats->cum_packet_loss <= -.5*stats->packet_dup_recv);
	stop_adaptive_stream(marielle,margaux);

	dup_ratio = 1;
	start_adaptive_stream(MSAudio, &marielle, &margaux, SPEEX_PAYLOAD_TYPE, 32000, 0, 0, 50,dup_ratio);
	media_stream_enable_adaptive_bitrate_control(&marielle->audio_stream->ms,FALSE);
	iterate_adaptive_stream(marielle, margaux, 10000, NULL, 0);
	stats=rtp_session_get_stats(margaux->video_stream->ms.sessions.rtp_session);
	CU_ASSERT_EQUAL(stats->packet_dup_recv, dup_ratio ? stats->packet_recv / (dup_ratio+1) : 0);
	CU_ASSERT_TRUE(stats->cum_packet_loss <= -.5*stats->packet_dup_recv);
	stop_adaptive_stream(marielle,margaux);
}
static void stability_network_detection() {
	stream_manager_t * marielle, * margaux;
	start_adaptive_stream(VideoStreamType, &marielle, &margaux, VP8_PAYLOAD_TYPE, 300000, 0, 0, 500, 0);
	iterate_adaptive_stream(marielle, margaux, 100000, &marielle->rtcp_count, 9);
	CU_ASSERT_EQUAL(marielle->adaptive_stats.network_state, MSQosAnalyzerNetworkFine);
	stop_adaptive_stream(marielle,margaux);

	start_adaptive_stream(VideoStreamType, &marielle, &margaux, VP8_PAYLOAD_TYPE, 300000, 70000, 0, 250,0);
	iterate_adaptive_stream(marielle, margaux, 100000, &marielle->rtcp_count, 9);
	CU_ASSERT_EQUAL(marielle->adaptive_stats.network_state, MSQosAnalyzerNetworkCongested);
	stop_adaptive_stream(marielle,margaux);

	start_adaptive_stream(VideoStreamType, &marielle, &margaux, VP8_PAYLOAD_TYPE, 300000, 0, 15, 250,0);
	iterate_adaptive_stream(marielle, margaux, 100000, &marielle->rtcp_count, 9);
	CU_ASSERT_EQUAL(marielle->adaptive_stats.network_state, MSQosAnalyzerNetworkLossy);
	stop_adaptive_stream(marielle,margaux);
}
static void adaptive_pcma_audio_stream() {
	bool_t supported = ms_filter_codec_supported("pcma");
	if( supported ) {
		// at 8KHz -> 80 kb/s
		float bw_usage;
		stream_manager_t * marielle, * margaux;

		// yet non-adaptative codecs cannot respect low throughput limitations
		start_adaptive_stream(AudioStreamType, &marielle, &margaux, PCMA8_PAYLOAD_TYPE, 8000, EDGE_BW, 0, 0, 0);
		iterate_adaptive_stream(marielle, margaux, 10000, NULL, 0);
		bw_usage=media_stream_get_up_bw(&marielle->audio_stream->ms)*1./EDGE_BW;
		CU_ASSERT_IN_RANGE(bw_usage,6.f, 8.f); // this is bad!
		stop_adaptive_stream(marielle,margaux);

		start_adaptive_stream(AudioStreamType, &marielle, &margaux, PCMA8_PAYLOAD_TYPE, 8000, THIRDGENERATION_BW, 0, 0, 0);
		iterate_adaptive_stream(marielle, margaux, 10000, NULL, 0);
		bw_usage=media_stream_get_up_bw(&marielle->audio_stream->ms)*1./THIRDGENERATION_BW;
		CU_ASSERT_IN_RANGE(bw_usage, .3f, .5f);
		stop_adaptive_stream(marielle,margaux);
	}
}
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) {
	bool_t supported = ms_filter_codec_supported("VP8");
	if( supported ) {
		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);
		BC_ASSERT_TRUE(marielle->adaptive_stats.loss_estim >= exp_min_loss);
		BC_ASSERT_TRUE(marielle->adaptive_stats.loss_estim <= exp_max_loss);
		BC_ASSERT_TRUE(marielle->adaptive_stats.congestion_bw_estim >= exp_min_bw);
		BC_ASSERT_TRUE(marielle->adaptive_stats.congestion_bw_estim <= exp_max_bw);
		stop_adaptive_stream(marielle,margaux);
	}
}
static void adaptive_speex16_audio_stream()  {
	bool_t supported = ms_filter_codec_supported("speex");
	if( supported ) {
		// at 16KHz -> 20 kb/s
		// at 32KHz -> 30 kb/s
		float bw_usage;
		stream_manager_t * marielle, * margaux;

		start_adaptive_stream(AudioStreamType, &marielle, &margaux, SPEEX16_PAYLOAD_TYPE, 32000, EDGE_BW / 2., 0, 0, 0);
		iterate_adaptive_stream(marielle, margaux, 10000, NULL, 0);
		bw_usage=media_stream_get_up_bw(&marielle->audio_stream->ms)*1./(EDGE_BW / 2.);
		CU_ASSERT_IN_RANGE(bw_usage, 1.f, 5.f);
		stop_adaptive_stream(marielle,margaux);
	}
}
void upload_bitrate(const char* codec, int payload, int target_bw, int expect_bw) {
	bool_t supported = ms_filter_codec_supported(codec);
	if( supported ) {
		float upload_bw;
		stream_manager_t * marielle, * margaux;

		start_adaptive_stream(MSAudio, &marielle, &margaux, payload, target_bw*1000, target_bw*1000, 0, 50,0);
		//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);
		iterate_adaptive_stream(marielle, margaux, 15000, NULL, 0);
		upload_bw=media_stream_get_up_bw(&marielle->audio_stream->ms) / 1000;
		CU_ASSERT_IN_RANGE(upload_bw, expect_bw-2, expect_bw+2);
		stop_adaptive_stream(marielle,margaux);
	}
}
static void upload_bandwidth_computation() {
	bool_t supported = ms_filter_codec_supported("pcma");
	if( supported ) {
		stream_manager_t * marielle, * margaux;
		int i;

		start_adaptive_stream(AudioStreamType, &marielle, &margaux, PCMA8_PAYLOAD_TYPE, 8000, 0, 0, 0, 0);
		media_stream_enable_adaptive_bitrate_control(&marielle->audio_stream->ms,FALSE);

		for (i = 0; i < 5; i++){
			rtp_session_set_duplication_ratio(marielle->audio_stream->ms.sessions.rtp_session, i);
			iterate_adaptive_stream(marielle, margaux, 100000, &marielle->rtcp_count, 2*(i+1));
			/*since PCMA uses 80kbit/s, upload bandwidth should just be 80+80*duplication_ratio kbit/s */
			CU_ASSERT_TRUE(fabs(rtp_session_get_send_bandwidth(marielle->audio_stream->ms.sessions.rtp_session)/1000. - 80.*(i+1)) < 1.f);
		}
		stop_adaptive_stream(marielle,margaux);
	}
}
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) {
	bool_t supported = ms_filter_codec_supported("VP8");
	if( supported ) {
		bool_t has_cam  = ms_web_cam_manager_get_default_cam(ms_web_cam_manager_get())
							!= ms_web_cam_manager_get_cam(ms_web_cam_manager_get(), "StaticImage: Static picture");
		if (has_cam) {
			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);
			CU_ASSERT_IN_RANGE(marielle->adaptive_stats.loss_estim, exp_min_loss, exp_max_loss);
			CU_ASSERT_IN_RANGE(marielle->adaptive_stats.congestion_bw_estim, exp_min_bw, exp_max_bw);
			stop_adaptive_stream(marielle,margaux);
		} else {
			/*ortp_loss_estimator rely on the fact that we receive some packets: however when
			using static picture camera, there is a traffic of around 1 packet per second which
			is totally unlikely leading in no QoS possibility*/
			ms_warning("%s test disabled because no real camera is available", __FUNCTION__);
		}
	}
}