mediastreamer2_video_stream_tester.c 27 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/*
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
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/msrtp.h"
#include "mediastreamer2_tester.h"
#include "mediastreamer2_tester_private.h"

#include <stdio.h>
#include "CUnit/Basic.h"


#ifdef _MSC_VER
#define unlink _unlink
#endif

static RtpProfile rtp_profile;

35 36 37 38 39 40 41 42 43



#define VP8_PAYLOAD_TYPE   103
#define H264_PAYLOAD_TYPE  104
#define MP4V_PAYLOAD_TYPE  105

MSWebCam* mediastreamer2_tester_get_mir_webcam() {
	MSWebCam *cam;
44 45 46
#ifdef _MSC_VER
extern __declspec(dllimport) MSWebCamDesc mire_desc;
#else
jehan's avatar
jehan committed
47
extern MSWebCamDesc mire_desc;
48
#endif
49
	cam = ms_web_cam_manager_get_cam(ms_web_cam_manager_get(), "Mire: Mire (synthetic moving picture)");
jehan's avatar
jehan committed
50

51 52 53 54
	if (cam == NULL) {
		cam=ms_web_cam_new(&mire_desc);
		ms_web_cam_manager_add_cam(ms_web_cam_manager_get(),cam);
	}
jehan's avatar
jehan committed
55

56 57
	return cam;
}
58 59 60 61 62 63

static int tester_init(void) {
	ms_init();
	ms_filter_enable_statistics(TRUE);
	ortp_init();
	rtp_profile_set_payload(&rtp_profile, VP8_PAYLOAD_TYPE, &payload_type_vp8);
jehan's avatar
jehan committed
64
	rtp_profile_set_payload(&rtp_profile, H264_PAYLOAD_TYPE, &payload_type_h264);
65
	rtp_profile_set_payload(&rtp_profile, MP4V_PAYLOAD_TYPE, &payload_type_mp4v);
66 67 68 69 70 71 72 73 74
	return 0;
}

static int tester_cleanup(void) {
	ms_exit();
	rtp_profile_clear_all(&rtp_profile);
	return 0;
}

75
#ifdef VIDEO_ENABLED
76 77 78 79 80 81 82 83 84 85

typedef struct _video_stream_tester_stats_t {
	OrtpEvQueue *q;
	rtp_stats_t rtp;
	int number_of_SR;
	int number_of_RR;
	int number_of_SDES;
	int number_of_PLI;
	int number_of_SLI;
	int number_of_RPSI;
86 87 88 89 90 91

	int number_of_decoder_decoding_error;
	int number_of_decoder_first_image_decoded;
	int number_of_decoder_send_pli;
	int number_of_decoder_send_sli;
	int number_of_decoder_send_rpsi;
92 93 94 95 96
} video_stream_tester_stats_t;

typedef struct _video_stream_tester_t {
	VideoStream *vs;
	video_stream_tester_stats_t stats;
jehan's avatar
jehan committed
97
	MSVideoConfiguration* vconf;
jehan's avatar
jehan committed
98 99 100
	char* local_ip;
	int local_rtp;
	int local_rtcp;
jehan's avatar
jehan committed
101
	MSWebCam * cam;
102
	int payload_type;
103 104
} video_stream_tester_t;

jehan's avatar
jehan committed
105 106 107 108 109 110
void video_stream_tester_set_local_ip(video_stream_tester_t* obj,const char*ip) {
	char* new_ip = ip?ms_strdup(ip):NULL;
	if (obj->local_ip) ms_free(obj->local_ip);
	obj->local_ip=new_ip;
}

jehan's avatar
jehan committed
111
video_stream_tester_t* video_stream_tester_new() {
jehan's avatar
jehan committed
112 113
	video_stream_tester_t* vst = ms_new0(video_stream_tester_t,1);
	video_stream_tester_set_local_ip(vst,"127.0.0.1");
jehan's avatar
jehan committed
114
	vst->cam = ms_web_cam_manager_get_cam(ms_web_cam_manager_get(), "StaticImage: Static picture");
jehan's avatar
jehan committed
115 116 117 118 119 120 121 122 123 124 125 126
	vst->local_rtp=-1; /*random*/
	vst->local_rtcp=-1; /*random*/
	return  vst;
}

video_stream_tester_t* video_stream_tester_create(const char* local_ip, int local_rtp, int local_rtcp) {
	video_stream_tester_t *vst = video_stream_tester_new();
	if (local_ip)
		video_stream_tester_set_local_ip(vst,local_ip);
	vst->local_rtp=local_rtp;
	vst->local_rtcp=local_rtcp;
	return vst;
jehan's avatar
jehan committed
127 128 129 130
}

void video_stream_tester_destroy(video_stream_tester_t* obj) {
	if (obj->vconf) ms_free(obj->vconf);
jehan's avatar
jehan committed
131
	if(obj->local_ip) ms_free(obj->local_ip);
jehan's avatar
jehan committed
132 133
	ms_free(obj);
}
134 135 136 137

static void reset_stats(video_stream_tester_stats_t *s) {
	memset(s, 0, sizeof(video_stream_tester_stats_t));
}
138 139
static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const unsigned int event_id, const void *args){
	video_stream_tester_t* vs_tester = (video_stream_tester_t*) user_pointer;
140
	const char* event_name;
141
	switch (event_id) {
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
	case MS_VIDEO_DECODER_DECODING_ERRORS:
		event_name="MS_VIDEO_DECODER_DECODING_ERRORS";
		vs_tester->stats.number_of_decoder_decoding_error++;
		break;
	case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED:
		event_name="MS_VIDEO_DECODER_FIRST_IMAGE_DECODED";
		vs_tester->stats.number_of_decoder_first_image_decoded++;
		break;
	case MS_VIDEO_DECODER_SEND_PLI:
		event_name="MS_VIDEO_DECODER_SEND_PLI";
		vs_tester->stats.number_of_decoder_send_pli++;
		break;
	case MS_VIDEO_DECODER_SEND_SLI:
		event_name="MS_VIDEO_DECODER_SEND_SLI";
		vs_tester->stats.number_of_decoder_send_sli++;
		break;
	case MS_VIDEO_DECODER_SEND_RPSI:
		vs_tester->stats.number_of_decoder_send_rpsi++;
		event_name="MS_VIDEO_DECODER_SEND_RPSI";
		/* Handled internally by mediastreamer2. */
		break;
	default:
		ms_warning("Unhandled event %i", event_id);
		event_name="UNKNOWN";
		break;
167
	}
168 169
	ms_message("Event [%s:%u] received on video stream [%p]",event_name,event_id,vs_tester);

170
}
171

172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
static void event_queue_cb(MediaStream *ms, void *user_pointer) {
	video_stream_tester_stats_t *st = (video_stream_tester_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_RTCP_PACKET_EMITTED) {
				do {
					if (rtcp_is_RR(d->packet)) {
						st->number_of_RR++;
					} else if (rtcp_is_SR(d->packet)) {
						st->number_of_SR++;
					} else if (rtcp_is_SDES(d->packet)) {
						st->number_of_SDES++;
					} else if (rtcp_is_PSFB(d->packet)) {
						switch (rtcp_PSFB_get_type(d->packet)) {
							case RTCP_PSFB_PLI:
								st->number_of_PLI++;
								break;
							case RTCP_PSFB_SLI:
								st->number_of_SLI++;
								break;
							case RTCP_PSFB_RPSI:
								st->number_of_RPSI++;
								break;
							default:
								break;
						}
					}
				} while (rtcp_next_packet(d->packet));
			}
			ortp_event_destroy(ev);
		}
	}
}

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
static void create_video_stream(video_stream_tester_t *vst, int payload_type) {
	vst->vs = video_stream_new2(vst->local_ip, vst->local_rtp, vst->local_rtcp);
	vst->vs->staticimage_webcam_fps_optimization = FALSE;
	vst->local_rtp = rtp_session_get_local_port(vst->vs->ms.sessions.rtp_session);
	vst->local_rtcp = rtp_session_get_local_rtcp_port(vst->vs->ms.sessions.rtp_session);
	reset_stats(&vst->stats);
	rtp_session_set_multicast_loopback(vst->vs->ms.sessions.rtp_session, TRUE);
	vst->stats.q = ortp_ev_queue_new();
	rtp_session_register_event_queue(vst->vs->ms.sessions.rtp_session, vst->stats.q);
	video_stream_set_event_callback(vst->vs, video_stream_event_cb, vst);
	if (vst->vconf) {
		PayloadType *pt = rtp_profile_get_payload(&rtp_profile, payload_type);
		CU_ASSERT_PTR_NOT_NULL_FATAL(pt);
		pt->normal_bitrate = vst->vconf->required_bitrate;
		video_stream_set_fps(vst->vs, vst->vconf->fps);
		video_stream_set_sent_video_size(vst->vs, vst->vconf->vsize);
	}
	vst->payload_type = payload_type;
}

static void destroy_video_stream(video_stream_tester_t *vst) {
	video_stream_stop(vst->vs);
	ortp_ev_queue_destroy(vst->stats.q);
}

static void init_video_streams(video_stream_tester_t *vst1, video_stream_tester_t *vst2, bool_t avpf, bool_t one_way, OrtpNetworkSimulatorParams *params, int payload_type) {
236
	PayloadType *pt;
237 238 239

	create_video_stream(vst1, payload_type);
	create_video_stream(vst2, payload_type);
240

241
	/* Enable/disable avpf. */
jehan's avatar
jehan committed
242
	pt = rtp_profile_get_payload(&rtp_profile, payload_type);
243 244 245 246 247 248 249 250 251
	CU_ASSERT_PTR_NOT_NULL_FATAL(pt);
	if (avpf == TRUE) {
		payload_type_set_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
	} else {
		payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED);
	}

	/* Configure network simulator. */
	if ((params != NULL) && (params->enabled == TRUE)) {
252 253
		rtp_session_enable_network_simulation(vst1->vs->ms.sessions.rtp_session, params);
		rtp_session_enable_network_simulation(vst2->vs->ms.sessions.rtp_session, params);
254 255
	}

256
	if (one_way == TRUE) {
257
		video_stream_set_direction(vst1->vs, VideoStreamRecvOnly);
jehan's avatar
jehan committed
258 259
	}

260 261
	CU_ASSERT_EQUAL(video_stream_start(vst1->vs, &rtp_profile, vst2->local_ip, vst2->local_rtp, vst2->local_ip, vst2->local_rtcp, payload_type, 50, vst1->cam), 0);
	CU_ASSERT_EQUAL(video_stream_start(vst2->vs, &rtp_profile, vst1->local_ip, vst1->local_rtp, vst1->local_ip, vst1->local_rtcp, payload_type, 50, vst2->cam), 0);
262 263
}

264
static void uninit_video_streams(video_stream_tester_t *vst1, video_stream_tester_t *vst2) {
265
	float rtcp_send_bandwidth;
266 267 268 269 270 271 272 273 274
	PayloadType *vst1_pt;
	PayloadType *vst2_pt;

	vst1_pt = rtp_profile_get_payload(&rtp_profile, vst1->payload_type);
	CU_ASSERT_PTR_NOT_NULL_FATAL(vst1_pt);
	vst2_pt = rtp_profile_get_payload(&rtp_profile, vst2->payload_type);
	CU_ASSERT_PTR_NOT_NULL_FATAL(vst2_pt);

	rtcp_send_bandwidth = rtp_session_get_rtcp_send_bandwidth(vst1->vs->ms.sessions.rtp_session);
275 276
	ms_message("vst1: rtcp_send_bandwidth=%f, payload_type_bitrate=%d, rtcp_target_bandwidth=%f",
		rtcp_send_bandwidth, payload_type_get_bitrate(vst1_pt), 0.06 * payload_type_get_bitrate(vst1_pt));
277 278
	CU_ASSERT_TRUE(rtcp_send_bandwidth <= (0.06 * payload_type_get_bitrate(vst1_pt)));
	rtcp_send_bandwidth = rtp_session_get_rtcp_send_bandwidth(vst2->vs->ms.sessions.rtp_session);
279 280
	ms_message("vst2: rtcp_send_bandwidth=%f, payload_type_bitrate=%d, rtcp_target_bandwidth=%f",
		rtcp_send_bandwidth, payload_type_get_bitrate(vst2_pt), 0.06 * payload_type_get_bitrate(vst2_pt));
281 282 283 284 285
	CU_ASSERT_TRUE(rtcp_send_bandwidth <= (0.06 * payload_type_get_bitrate(vst2_pt)));

	destroy_video_stream(vst1);
	destroy_video_stream(vst2);
}
286

287 288
static void change_codec(video_stream_tester_t *vst1, video_stream_tester_t *vst2, int payload_type) {
	MSWebCam *no_webcam = ms_web_cam_manager_get_cam(ms_web_cam_manager_get(), "StaticImage: Static picture");
289

290
	if (vst1->payload_type == payload_type) return;
291

292 293 294
	destroy_video_stream(vst1);
	create_video_stream(vst1, payload_type);
	CU_ASSERT_EQUAL(video_stream_start(vst1->vs, &rtp_profile, vst2->local_ip, vst2->local_rtp, vst2->local_ip, vst2->local_rtcp, payload_type, 50, no_webcam), 0);
295 296 297
}

static void basic_video_stream(void) {
jehan's avatar
jehan committed
298 299
	video_stream_tester_t* marielle=video_stream_tester_new();
	video_stream_tester_t* margaux=video_stream_tester_new();
300
	bool_t supported = ms_filter_codec_supported("vp8");
301

302
	if (supported) {
jehan's avatar
jehan committed
303
		init_video_streams(marielle, margaux, FALSE, FALSE, NULL,VP8_PAYLOAD_TYPE);
304

jehan's avatar
jehan committed
305
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_SR, 2, 15000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
306

jehan's avatar
jehan committed
307 308
		video_stream_get_local_rtp_stats(marielle->vs, &marielle->stats.rtp);
		video_stream_get_local_rtp_stats(margaux->vs, &margaux->stats.rtp);
309

jehan's avatar
jehan committed
310
		uninit_video_streams(marielle, margaux);
311 312 313
	} else {
		ms_error("VP8 codec is not supported!");
	}
314 315
}

316
static void basic_one_way_video_stream(void) {
jehan's avatar
jehan committed
317 318
	video_stream_tester_t* marielle=video_stream_tester_new();
	video_stream_tester_t* margaux=video_stream_tester_new();
319
	bool_t supported = ms_filter_codec_supported("vp8");
320

321
	if (supported) {
jehan's avatar
jehan committed
322
		init_video_streams(marielle, margaux, FALSE, TRUE, NULL,VP8_PAYLOAD_TYPE);
323

jehan's avatar
jehan committed
324 325 326 327
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_RR, 2, 15000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
		video_stream_get_local_rtp_stats(marielle->vs, &marielle->stats.rtp);
		video_stream_get_local_rtp_stats(margaux->vs, &margaux->stats.rtp);
		uninit_video_streams(marielle, margaux);
328 329 330
	} else {
		ms_error("VP8 codec is not supported!");
	}
jehan's avatar
jehan committed
331 332
	video_stream_tester_destroy(marielle);
	video_stream_tester_destroy(margaux);
333 334
}

335 336 337 338 339
static void codec_change_for_video_stream(void) {
	video_stream_tester_t *marielle = video_stream_tester_new();
	video_stream_tester_t *margaux = video_stream_tester_new();
	bool_t vp8_supported = ms_filter_codec_supported("vp8");
	bool_t h264_supported = ms_filter_codec_supported("h264");
340
	bool_t mp4v_supported = ms_filter_codec_supported("mp4v-es");
341 342 343 344 345 346

	if (vp8_supported) {
		init_video_streams(marielle, margaux, FALSE, FALSE, NULL, VP8_PAYLOAD_TYPE);
		CU_ASSERT_TRUE(wait_for_until(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_decoder_first_image_decoded, 1, 2000));
		CU_ASSERT_TRUE(wait_for_until(&marielle->vs->ms, &margaux->vs->ms, &margaux->stats.number_of_decoder_first_image_decoded, 1, 2000));
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_SR, 2, 15000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
347 348 349
		if (h264_supported || mp4v_supported) {
			if (h264_supported) change_codec(marielle, margaux, H264_PAYLOAD_TYPE);
			else change_codec(marielle, margaux, MP4V_PAYLOAD_TYPE);
350 351
			CU_ASSERT_TRUE(wait_for_until(&marielle->vs->ms, &margaux->vs->ms, &margaux->stats.number_of_decoder_first_image_decoded, 2, 2000));
			CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_SR, 2, 15000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
352 353 354 355 356
			if (h264_supported) {
				CU_ASSERT_EQUAL(strcasecmp(margaux->vs->ms.decoder->desc->enc_fmt, "h264"), 0);
			} else {
				CU_ASSERT_EQUAL(strcasecmp(margaux->vs->ms.decoder->desc->enc_fmt, "mp4v-es"), 0);
			}
357 358 359
		} else {
			ms_error("H264 codec is not supported!");
		}
360 361
		destroy_video_stream(marielle);
		destroy_video_stream(margaux);
362 363 364 365 366 367 368 369
	} else {
		ms_error("VP8 codec is not supported!");
	}

	video_stream_tester_destroy(marielle);
	video_stream_tester_destroy(margaux);
}

jehan's avatar
jehan committed
370 371
static void multicast_video_stream(void) {
	video_stream_tester_t* marielle=video_stream_tester_new();
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
372 373
	video_stream_tester_t* margaux=video_stream_tester_new();
	bool_t supported = ms_filter_codec_supported("vp8");
jehan's avatar
jehan committed
374 375 376 377
	video_stream_tester_set_local_ip(marielle,"224.1.2.3");
	marielle->local_rtcp=0; /*no rtcp*/
	video_stream_tester_set_local_ip(margaux,"0.0.0.0");

jehan's avatar
jehan committed
378

jehan's avatar
jehan committed
379
	if (supported) {
jehan's avatar
jehan committed
380
		int dummy=0;
jehan's avatar
jehan committed
381 382 383
		init_video_streams(marielle, margaux, FALSE, TRUE, NULL,VP8_PAYLOAD_TYPE);

		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &margaux->stats.number_of_SR, 2, 15000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
jehan's avatar
jehan committed
384 385 386 387 388

		ms_ticker_detach(margaux->vs->ms.sessions.ticker,margaux->vs->source); /*to stop sending*/
		/*make sure packets can cross from sender to receiver*/
		wait_for_until(&marielle->vs->ms,&margaux->vs->ms,&dummy,1,500);

jehan's avatar
jehan committed
389
		video_stream_get_local_rtp_stats(marielle->vs, &marielle->stats.rtp);
jehan's avatar
jehan committed
390
		video_stream_get_local_rtp_stats(margaux->vs, &marielle->stats.rtp);
jehan's avatar
jehan committed
391
		CU_ASSERT_EQUAL(margaux->stats.rtp.sent,marielle->stats.rtp.recv);
jehan's avatar
jehan committed
392

jehan's avatar
jehan committed
393 394 395 396 397 398 399 400
		uninit_video_streams(marielle, margaux);
	} else {
		ms_error("VP8 codec is not supported!");
	}
	video_stream_tester_destroy(marielle);
	video_stream_tester_destroy(margaux);
}

401
static void avpf_video_stream(void) {
jehan's avatar
jehan committed
402 403
	video_stream_tester_t* marielle=video_stream_tester_new();
	video_stream_tester_t* margaux=video_stream_tester_new();
404
	OrtpNetworkSimulatorParams params = { 0 };
405
	bool_t supported = ms_filter_codec_supported("vp8");
406

407 408 409
	if (supported) {
		params.enabled = TRUE;
		params.loss_rate = 5.;
jehan's avatar
jehan committed
410
		init_video_streams(marielle, margaux, TRUE, FALSE, &params,VP8_PAYLOAD_TYPE);
411

jehan's avatar
jehan committed
412
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_SR, 2, 15000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
413
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_SLI, 1, 5000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
414
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_RPSI, 1, 15000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
415

jehan's avatar
jehan committed
416
		uninit_video_streams(marielle, margaux);
417 418 419
	} else {
		ms_error("VP8 codec is not supported!");
	}
jehan's avatar
jehan committed
420 421
	video_stream_tester_destroy(marielle);
	video_stream_tester_destroy(margaux);
422 423
}

jehan's avatar
jehan committed
424 425 426 427 428 429 430 431
static void avpf_rpsi_count(void) {
	video_stream_tester_t* marielle=video_stream_tester_new();
	video_stream_tester_t* margaux=video_stream_tester_new();
	OrtpNetworkSimulatorParams params = { 0 };
	bool_t supported = ms_filter_codec_supported("vp8");
	int dummy=0;
	int delay = 11000;
	marielle->vconf=ms_new0(MSVideoConfiguration,1);
432
	marielle->vconf->bitrate_limit=marielle->vconf->required_bitrate=256000;
jehan's avatar
jehan committed
433 434 435
	marielle->vconf->fps=15;
	marielle->vconf->vsize.height=MS_VIDEO_SIZE_CIF_H;
	marielle->vconf->vsize.width=MS_VIDEO_SIZE_CIF_W;
436
	marielle->cam = mediastreamer2_tester_get_mir_webcam();
jehan's avatar
jehan committed
437 438 439


	margaux->vconf=ms_new0(MSVideoConfiguration,1);
440
	margaux->vconf->bitrate_limit=margaux->vconf->required_bitrate=256000;
jehan's avatar
jehan committed
441 442 443
	margaux->vconf->fps=5; /*to save cpu resource*/
	margaux->vconf->vsize.height=MS_VIDEO_SIZE_CIF_H;
	margaux->vconf->vsize.width=MS_VIDEO_SIZE_CIF_W;
444
	margaux->cam = mediastreamer2_tester_get_mir_webcam();
jehan's avatar
jehan committed
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464

	if (supported) {
		init_video_streams(marielle, margaux, TRUE, FALSE, &params,VP8_PAYLOAD_TYPE);
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms,  &marielle->stats.number_of_decoder_first_image_decoded, 1, 10000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms,  &margaux->stats.number_of_decoder_first_image_decoded, 1, 10000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));

		/*wait for 4 rpsi*/
		wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms,  &dummy, 1, delay, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats);
		CU_ASSERT_EQUAL(marielle->stats.number_of_RPSI,4);
		CU_ASSERT_EQUAL(margaux->stats.number_of_RPSI,4);
		CU_ASSERT_TRUE(fabs(video_stream_get_received_framerate(marielle->vs)-margaux->vconf->fps) <2);
		CU_ASSERT_TRUE(fabs(video_stream_get_received_framerate(margaux->vs)-marielle->vconf->fps) <2);
		uninit_video_streams(marielle, margaux);
	} else {
		ms_error("VP8 codec is not supported!");
	}
	video_stream_tester_destroy(marielle);
	video_stream_tester_destroy(margaux);
}

465
static void video_stream_first_iframe_lost_vp8(void) {
jehan's avatar
jehan committed
466 467
	video_stream_tester_t* marielle=video_stream_tester_new();
	video_stream_tester_t* margaux=video_stream_tester_new();
468 469 470 471 472
	OrtpNetworkSimulatorParams params = { 0 };
	bool_t supported = ms_filter_codec_supported("vp8");

	if (supported) {
		int dummy=0;
473
		/* Make sure first Iframe is lost. */
jehan's avatar
jehan committed
474
		params.enabled = TRUE;
475 476
		params.loss_rate = 100.;
		init_video_streams(marielle, margaux, FALSE, FALSE, &params, VP8_PAYLOAD_TYPE);
jehan's avatar
jehan committed
477 478
		wait_for_until(&marielle->vs->ms, &margaux->vs->ms,&dummy,1,1000);

479
		/* Use 10% packet lost to be sure to have decoding errors. */
jehan's avatar
jehan committed
480
		params.enabled=TRUE;
481
		params.loss_rate = 10.;
jehan's avatar
jehan committed
482 483
		rtp_session_enable_network_simulation(marielle->vs->ms.sessions.rtp_session, &params);
		rtp_session_enable_network_simulation(margaux->vs->ms.sessions.rtp_session, &params);
jehan's avatar
jehan committed
484 485
		wait_for_until(&marielle->vs->ms, &margaux->vs->ms,&dummy,1,2000);

486 487 488 489
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_decoder_decoding_error,
			1, 1000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &margaux->stats.number_of_decoder_decoding_error,
			1, 1000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
490

491 492 493 494 495 496 497 498 499 500 501 502
		/* Remove the lost to be sure the forced iframe is going through. */
		params.enabled=TRUE;
		params.loss_rate = 0.;
		rtp_session_enable_network_simulation(marielle->vs->ms.sessions.rtp_session, &params);
		rtp_session_enable_network_simulation(margaux->vs->ms.sessions.rtp_session, &params);
		wait_for_until(&marielle->vs->ms, &margaux->vs->ms,&dummy,1,2000);
		video_stream_send_vfu(marielle->vs);
		video_stream_send_vfu(margaux->vs);
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_decoder_first_image_decoded,
			1, 5000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &margaux->stats.number_of_decoder_first_image_decoded,
			1, 5000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
503

jehan's avatar
jehan committed
504
		uninit_video_streams(marielle, margaux);
505 506 507
	} else {
		ms_error("VP8 codec is not supported!");
	}
jehan's avatar
jehan committed
508 509
	video_stream_tester_destroy(marielle);
	video_stream_tester_destroy(margaux);
510
}
jehan's avatar
jehan committed
511

512
static void avpf_video_stream_first_iframe_lost_vp8(void) {
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
	video_stream_tester_t* marielle=video_stream_tester_new();
	video_stream_tester_t* margaux=video_stream_tester_new();
	OrtpNetworkSimulatorParams params = { 0 };
	bool_t supported = ms_filter_codec_supported("vp8");

	if (supported) {
		int dummy=0;
		/* Make sure first Iframe is lost. */
		params.enabled = TRUE;
		params.loss_rate = 100.;
		init_video_streams(marielle, margaux, TRUE, FALSE, &params, VP8_PAYLOAD_TYPE);
		wait_for_until(&marielle->vs->ms, &margaux->vs->ms,&dummy,1,1000);

		/* Remove the lost to be sure that a PLI will be sent and not a SLI. */
		params.enabled=TRUE;
		params.loss_rate = 0.;
		rtp_session_enable_network_simulation(marielle->vs->ms.sessions.rtp_session, &params);
		rtp_session_enable_network_simulation(margaux->vs->ms.sessions.rtp_session, &params);
		wait_for_until(&marielle->vs->ms, &margaux->vs->ms,&dummy,1,2000);

		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_PLI,
			1, 1000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &margaux->stats.number_of_PLI,
			1, 1000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_decoder_first_image_decoded,
			1, 5000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &margaux->stats.number_of_decoder_first_image_decoded,
			1, 5000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));

		uninit_video_streams(marielle, margaux);
	} else {
		ms_error("VP8 codec is not supported!");
	}
	video_stream_tester_destroy(marielle);
	video_stream_tester_destroy(margaux);
548
}
549

550
static void avpf_high_loss_video_stream_base(float rate) {
jehan's avatar
jehan committed
551 552
	video_stream_tester_t* marielle=video_stream_tester_new();
	video_stream_tester_t* margaux=video_stream_tester_new();
553
	OrtpNetworkSimulatorParams params = { 0 };
554
	bool_t supported = ms_filter_codec_supported("vp8");
555

556 557
	if (supported) {
		params.enabled = TRUE;
558
		params.loss_rate = rate;
jehan's avatar
jehan committed
559
		init_video_streams(marielle, margaux, TRUE, FALSE, &params,VP8_PAYLOAD_TYPE);
560
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_SR, 10, 15000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
561
		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_SLI, 1, 5000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
562 563 564
		if (rate <= 10) {
			CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_RPSI, 1, 15000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));
		}
jehan's avatar
jehan committed
565 566 567 568 569 570 571
		uninit_video_streams(marielle, margaux);
	} else {
		ms_error("VP8 codec is not supported!");
	}
	video_stream_tester_destroy(marielle);
	video_stream_tester_destroy(margaux);
}
572 573 574 575 576 577
static void avpf_very_high_loss_video_stream(void) {
	avpf_high_loss_video_stream_base(25.);
}
static void avpf_high_loss_video_stream(void) {
	avpf_high_loss_video_stream_base(10.);
}
jehan's avatar
jehan committed
578 579 580 581 582 583 584 585 586 587 588 589
static void video_configuration_stream_base(MSVideoConfiguration* asked, MSVideoConfiguration* expected_result, int payload_type) {
	video_stream_tester_t* marielle=video_stream_tester_new();
	video_stream_tester_t* margaux=video_stream_tester_new();
	PayloadType* pt = rtp_profile_get_payload(&rtp_profile, payload_type);
	bool_t supported = pt?ms_filter_codec_supported(pt->mime_type):FALSE;

	if (supported) {
		margaux->vconf=ms_new0(MSVideoConfiguration,1);
		margaux->vconf->required_bitrate=asked->required_bitrate;
		margaux->vconf->bitrate_limit=asked->bitrate_limit;
		margaux->vconf->vsize=asked->vsize;
		margaux->vconf->fps=asked->fps;
590

jehan's avatar
jehan committed
591 592 593 594 595 596 597
		init_video_streams(marielle, margaux, FALSE, TRUE, NULL,payload_type);

		CU_ASSERT_TRUE(wait_for_until_with_parse_events(&marielle->vs->ms, &margaux->vs->ms, &marielle->stats.number_of_RR, 4, 30000, event_queue_cb, &marielle->stats, event_queue_cb, &margaux->stats));

		video_stream_get_local_rtp_stats(marielle->vs, &marielle->stats.rtp);
		video_stream_get_local_rtp_stats(margaux->vs, &margaux->stats.rtp);

598 599 600

		CU_ASSERT_TRUE(ms_video_size_equal(video_stream_get_received_video_size(marielle->vs),
			margaux->vconf->vsize));
601
		CU_ASSERT_TRUE(fabs(video_stream_get_received_framerate(marielle->vs)-margaux->vconf->fps) <2);
jehan's avatar
jehan committed
602 603
		if (ms_web_cam_manager_get_cam(ms_web_cam_manager_get(), "StaticImage: Static picture")
				!= ms_web_cam_manager_get_default_cam(ms_web_cam_manager_get())) {
604
			// CU_ASSERT_TRUE(abs(media_stream_get_down_bw((MediaStream*)marielle->vs) - margaux->vconf->required_bitrate) < 0.20f * margaux->vconf->required_bitrate);
jehan's avatar
jehan committed
605 606 607 608
		} /*else this test require a real webcam*/


		uninit_video_streams(marielle, margaux);
609 610 611
	} else {
		ms_error("VP8 codec is not supported!");
	}
jehan's avatar
jehan committed
612 613 614
	video_stream_tester_destroy(marielle);
	video_stream_tester_destroy(margaux);

615
}
jehan's avatar
jehan committed
616 617 618 619 620 621
static void video_configuration_stream(void) {
	MSVideoConfiguration asked;
	MSVideoConfiguration expected;
	asked.bitrate_limit=expected.bitrate_limit=1024000;
	asked.required_bitrate=expected.required_bitrate=1024000;
	asked.fps=expected.fps=12;
622 623
	asked.vsize.width=expected.vsize.width=MS_VIDEO_SIZE_VGA_W;
	asked.vsize.height=expected.vsize.height=MS_VIDEO_SIZE_VGA_H;
jehan's avatar
jehan committed
624 625
	video_configuration_stream_base(&asked,&expected,VP8_PAYLOAD_TYPE);

626 627 628
	/*Test video rotation (inverted height <-> width). Not supported on desktop
	because no real use case yet.*/
#if defined(ANDROID) || defined(TARGET_OS_IPHONE)
jehan's avatar
jehan committed
629 630 631 632 633 634
	asked.bitrate_limit=expected.bitrate_limit=1024000;
	asked.required_bitrate=expected.required_bitrate=1024000;
	asked.fps=expected.fps=12;
	asked.vsize.height=expected.vsize.height=MS_VIDEO_SIZE_VGA_W;
	asked.vsize.width=expected.vsize.width=MS_VIDEO_SIZE_VGA_H;
	video_configuration_stream_base(&asked,&expected,VP8_PAYLOAD_TYPE);
635
#endif
jehan's avatar
jehan committed
636
}
637 638 639

static test_t tests[] = {
	{ "Basic video stream", basic_video_stream },
640
	{ "Multicast video stream",multicast_video_stream },
641
	{ "Basic one-way video stream", basic_one_way_video_stream },
642
	{ "Codec change for video stream", codec_change_for_video_stream },
643
	{ "AVPF video stream", avpf_video_stream },
644
	{ "AVPF high-loss video stream", avpf_high_loss_video_stream },
645
	{ "AVPF very high-loss video stream", avpf_very_high_loss_video_stream },
646 647
	{ "AVPF video stream first iframe lost", avpf_video_stream_first_iframe_lost_vp8 },
	{ "AVP video stream first iframe lost", video_stream_first_iframe_lost_vp8 },
648
	{ "Video configuration", video_configuration_stream },
jehan's avatar
jehan committed
649
	{ "AVPF RPSI count", avpf_rpsi_count}
650
};
651 652 653
#else
static test_t tests[] = {};
#endif
654 655 656 657 658 659 660
test_suite_t video_stream_test_suite = {
	"VideoStream",
	tester_init,
	tester_cleanup,
	sizeof(tests) / sizeof(tests[0]),
	tests
};