mediastreamer2_tester_private.c 11 KB
Newer Older
Ghislain MARY's avatar
Ghislain MARY 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.
Ghislain MARY's avatar
Ghislain MARY committed
18 19 20
*/

#include "mediastreamer2_tester_private.h"
21
#include <bctoolbox/tester.h>
Ghislain MARY's avatar
Ghislain MARY committed
22 23 24 25 26 27 28

#include "mediastreamer2/dtmfgen.h"
#include "mediastreamer2/msfileplayer.h"
#include "mediastreamer2/msfilerec.h"
#include "mediastreamer2/msrtp.h"
#include "mediastreamer2/mssndcard.h"
#include "mediastreamer2/mstonedetector.h"
29
#include "mediastreamer2/mswebcam.h"
Ghislain MARY's avatar
Ghislain MARY committed
30 31 32 33 34 35 36 37 38


typedef struct {
	MSDtmfGenCustomTone generated_tone;
	MSToneDetectorDef expected_tone;
} tone_test_def_t;


static tone_test_def_t tone_definition[] = {
39 40 41
	{ { "", 400, {2000,0}, 0.6f, 0, 0 }, { "", 2000, 300, 0.5f } },
	{ { "", 600, {1500,0}, 1.0f, 0, 0 }, { "", 1500, 500, 0.9f } },
	{ { "", 500,  {941,0}, 0.8f, 0, 0 }, { "",  941, 400, 0.7f } }
Ghislain MARY's avatar
Ghislain MARY committed
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
};


MSTicker *ms_tester_ticker = NULL;
MSFilter *ms_tester_fileplay = NULL;
MSFilter *ms_tester_filerec = NULL;
MSFilter *ms_tester_dtmfgen = NULL;
MSFilter *ms_tester_tonedet = NULL;
MSFilter *ms_tester_voidsource = NULL;
MSFilter *ms_tester_voidsink = NULL;
MSFilter *ms_tester_encoder = NULL;
MSFilter *ms_tester_decoder = NULL;
MSFilter *ms_tester_rtprecv = NULL;
MSFilter *ms_tester_rtpsend = NULL;
MSFilter *ms_tester_resampler = NULL;
MSFilter *ms_tester_soundwrite = NULL;
58
MSFilter *ms_tester_soundread = NULL;
59
MSFilter *ms_tester_videocapture = NULL;
60
char *ms_tester_codec_mime = "pcmu";
Ghislain MARY's avatar
Ghislain MARY committed
61 62 63 64 65 66 67 68 69 70 71 72
unsigned char ms_tester_tone_detected;


static MSTicker * create_ticker(void) {
	MSTickerParams params;
	params.name = "Tester MSTicker";
	params.prio = MS_TICKER_PRIO_NORMAL;
	return ms_ticker_new_with_params(&params);
}


void ms_tester_create_ticker(void) {
73
	BC_ASSERT_PTR_NULL(ms_tester_ticker);
Ghislain MARY's avatar
Ghislain MARY committed
74
	ms_tester_ticker = create_ticker();
75
	BC_ASSERT_PTR_NOT_NULL(ms_tester_ticker);
Ghislain MARY's avatar
Ghislain MARY committed
76 77 78 79 80 81 82 83 84
}

void ms_tester_destroy_ticker(void) {
	if (ms_tester_ticker) {
		ms_ticker_destroy(ms_tester_ticker);
		ms_tester_ticker = NULL;
	}
}

85
#define CREATE_FILTER(mask, filter, factory, id) \
Ghislain MARY's avatar
Ghislain MARY committed
86
	if (filter_mask & mask) { \
87
		BC_ASSERT_PTR_NULL(filter); \
88
		filter = ms_factory_create_filter(factory, id); \
89
		BC_ASSERT_PTR_NOT_NULL(filter); \
Ghislain MARY's avatar
Ghislain MARY committed
90 91
	}

92
void ms_tester_create_filter(MSFilter **filter, MSFilterId id, MSFactory *f) {
93 94
	BC_ASSERT_PTR_NOT_NULL(filter);
	BC_ASSERT_PTR_NULL(*filter);
95
	*filter = ms_factory_create_filter(f, id);
96
	BC_ASSERT_PTR_NOT_NULL(*filter);
97 98
}

99
void ms_tester_create_filters(unsigned int filter_mask, MSFactory * f) {
100 101
	MSSndCardManager *snd_manager;
	MSWebCamManager *cam_manager;
Ghislain MARY's avatar
Ghislain MARY committed
102
	MSSndCard *playcard;
103
	MSSndCard *captcard;
104
	MSWebCam *camera;
Ghislain MARY's avatar
Ghislain MARY committed
105

106

107 108 109 110 111 112 113

	CREATE_FILTER(FILTER_MASK_FILEPLAY, ms_tester_fileplay,f, MS_FILE_PLAYER_ID);
	CREATE_FILTER(FILTER_MASK_FILEREC, ms_tester_filerec,f, MS_FILE_REC_ID);
	CREATE_FILTER(FILTER_MASK_DTMFGEN, ms_tester_dtmfgen, f,  MS_DTMF_GEN_ID);
	CREATE_FILTER(FILTER_MASK_TONEDET, ms_tester_tonedet, f, MS_TONE_DETECTOR_ID);
	CREATE_FILTER(FILTER_MASK_VOIDSOURCE, ms_tester_voidsource, f, MS_VOID_SOURCE_ID);
	CREATE_FILTER(FILTER_MASK_VOIDSINK, ms_tester_voidsink, f, MS_VOID_SINK_ID);
114
	if (filter_mask & FILTER_MASK_ENCODER) {
115
		BC_ASSERT_PTR_NULL(ms_tester_encoder);
116
		ms_tester_encoder = ms_factory_create_encoder(f, ms_tester_codec_mime);
117
		BC_ASSERT_PTR_NOT_NULL(ms_tester_encoder);
118 119
	}
	if (filter_mask & FILTER_MASK_DECODER) {
120
		BC_ASSERT_PTR_NULL(ms_tester_decoder);
121
		ms_tester_decoder = ms_factory_create_decoder(f, ms_tester_codec_mime);
122
		BC_ASSERT_PTR_NOT_NULL(ms_tester_decoder);
123
	}
124 125 126
	CREATE_FILTER(FILTER_MASK_RTPRECV, ms_tester_rtprecv, f, MS_RTP_RECV_ID);
	CREATE_FILTER(FILTER_MASK_RTPSEND, ms_tester_rtpsend, f ,MS_RTP_SEND_ID);
	CREATE_FILTER(FILTER_MASK_RESAMPLER, ms_tester_resampler, f, MS_RESAMPLE_ID);
Ghislain MARY's avatar
Ghislain MARY committed
127
	if (filter_mask & FILTER_MASK_SOUNDWRITE) {
128
		BC_ASSERT_PTR_NULL(ms_tester_soundwrite);
129
		snd_manager = ms_factory_get_snd_card_manager(f);
130
		playcard = ms_snd_card_manager_get_default_playback_card(snd_manager);
131
		BC_ASSERT_PTR_NOT_NULL(playcard);
Ghislain MARY's avatar
Ghislain MARY committed
132
		ms_tester_soundwrite = ms_snd_card_create_writer(playcard);
133
		BC_ASSERT_PTR_NOT_NULL(ms_tester_soundwrite);
Ghislain MARY's avatar
Ghislain MARY committed
134
	}
135
	if (filter_mask & FILTER_MASK_SOUNDREAD) {
136
		BC_ASSERT_PTR_NULL(ms_tester_soundread);
137
		snd_manager = ms_factory_get_snd_card_manager(f);
138
		captcard = ms_snd_card_manager_get_default_capture_card(snd_manager);
139
		BC_ASSERT_PTR_NOT_NULL(captcard);
140
		ms_tester_soundread = ms_snd_card_create_reader(captcard);
141
		BC_ASSERT_PTR_NOT_NULL(ms_tester_soundread);
142
	}
143
	if (filter_mask & FILTER_MASK_VIDEOCAPTURE) {
144
		BC_ASSERT_PTR_NULL(ms_tester_videocapture);
145
		cam_manager = ms_factory_get_web_cam_manager(f);
146
		camera = ms_web_cam_manager_get_default_cam(cam_manager);
147
		BC_ASSERT_PTR_NOT_NULL(camera);
148
		ms_tester_videocapture = ms_web_cam_create_reader(camera);
149
		BC_ASSERT_PTR_NOT_NULL(ms_tester_videocapture);
150
	}
Ghislain MARY's avatar
Ghislain MARY committed
151 152 153
}

#define DESTROY_FILTER(mask, filter) \
154
	if ((filter_mask & mask) && (filter != NULL)) { \
Ghislain MARY's avatar
Ghislain MARY committed
155
		ms_filter_destroy(filter); \
156
		filter = NULL; \
Ghislain MARY's avatar
Ghislain MARY committed
157 158
	} \

159
void ms_tester_destroy_filter(MSFilter **filter) {
160
	BC_ASSERT_PTR_NOT_NULL(filter);
161 162 163 164 165 166
	if (*filter != NULL) {
		ms_filter_destroy(*filter);
		*filter = NULL;
	}
}

Ghislain MARY's avatar
Ghislain MARY committed
167
void ms_tester_destroy_filters(unsigned int filter_mask) {
168 169 170 171 172 173 174 175 176 177 178 179 180 181
	DESTROY_FILTER(FILTER_MASK_FILEPLAY, ms_tester_fileplay)
	DESTROY_FILTER(FILTER_MASK_FILEREC, ms_tester_filerec)
	DESTROY_FILTER(FILTER_MASK_DTMFGEN, ms_tester_dtmfgen)
	DESTROY_FILTER(FILTER_MASK_TONEDET, ms_tester_tonedet)
	DESTROY_FILTER(FILTER_MASK_VOIDSOURCE, ms_tester_voidsource)
	DESTROY_FILTER(FILTER_MASK_VOIDSINK, ms_tester_voidsink)
	DESTROY_FILTER(FILTER_MASK_ENCODER, ms_tester_encoder)
	DESTROY_FILTER(FILTER_MASK_DECODER, ms_tester_decoder)
	DESTROY_FILTER(FILTER_MASK_RTPRECV, ms_tester_rtprecv)
	DESTROY_FILTER(FILTER_MASK_RTPSEND, ms_tester_rtpsend)
	DESTROY_FILTER(FILTER_MASK_RESAMPLER, ms_tester_resampler)
	DESTROY_FILTER(FILTER_MASK_SOUNDWRITE, ms_tester_soundwrite)
	DESTROY_FILTER(FILTER_MASK_SOUNDREAD, ms_tester_soundread)
	DESTROY_FILTER(FILTER_MASK_VIDEOCAPTURE, ms_tester_videocapture)
Ghislain MARY's avatar
Ghislain MARY committed
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
}

void ms_tester_tone_generation_loop(void) {
	unsigned int i;

	for (i = 0; i < (sizeof(tone_definition) / sizeof(tone_definition[0])); i++) {
		ms_filter_call_method(ms_tester_dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM, &tone_definition[i].generated_tone);
		ms_sleep(1);
	}
}

void ms_tester_tone_detection_loop(void) {
	unsigned int i;

	for (i = 0; i < (sizeof(tone_definition) / sizeof(tone_definition[0])); i++) {
		ms_tester_tone_detected = FALSE;
		ms_filter_call_method(ms_tester_tonedet, MS_TONE_DETECTOR_CLEAR_SCANS, NULL);
		ms_filter_call_method(ms_tester_tonedet, MS_TONE_DETECTOR_ADD_SCAN, &tone_definition[i].expected_tone);
		ms_sleep(1);
201
		BC_ASSERT_EQUAL(ms_tester_tone_detected, TRUE, int, "%d");
Ghislain MARY's avatar
Ghislain MARY committed
202 203 204 205 206 207 208 209
	}
}

void ms_tester_tone_generation_and_detection_loop(void) {
	unsigned int i;

	for (i = 0; i < (sizeof(tone_definition) / sizeof(tone_definition[0])); i++) {
		ms_tester_tone_detected = FALSE;
210 211 212
		BC_ASSERT_EQUAL(0,ms_filter_call_method(ms_tester_tonedet, MS_TONE_DETECTOR_CLEAR_SCANS, NULL), int, "%d");
		BC_ASSERT_EQUAL(0,ms_filter_call_method(ms_tester_tonedet, MS_TONE_DETECTOR_ADD_SCAN, &tone_definition[i].expected_tone), int, "%d");
		BC_ASSERT_EQUAL(0,ms_filter_call_method(ms_tester_dtmfgen, MS_DTMF_GEN_PLAY_CUSTOM, &tone_definition[i].generated_tone), int, "%d");
Ghislain MARY's avatar
Ghislain MARY committed
213
		ms_sleep(1);
214
		BC_ASSERT_EQUAL(ms_tester_tone_detected, TRUE, int, "%d");
Ghislain MARY's avatar
Ghislain MARY committed
215 216 217
	}
}

218 219 220 221 222 223 224 225 226 227 228 229 230 231 232

RtpProfile *ms_tester_create_rtp_profile(void) {
	RtpProfile * profile = rtp_profile_new("Tester profile");
	rtp_profile_set_payload(profile,PCMU8_PAYLOAD_TYPE,&payload_type_pcmu8000);
	rtp_profile_set_payload(profile,PCMA8_PAYLOAD_TYPE,&payload_type_pcma8000);
	rtp_profile_set_payload(profile,H263_PAYLOAD_TYPE,&payload_type_h263);
	rtp_profile_set_payload(profile,H264_PAYLOAD_TYPE,&payload_type_h264);
	rtp_profile_set_payload(profile,VP8_PAYLOAD_TYPE,&payload_type_vp8);
	rtp_profile_set_payload(profile,MP4V_PAYLOAD_TYPE, &payload_type_mp4v);
	rtp_profile_set_payload(profile,OPUS_PAYLOAD_TYPE,&payload_type_opus);
	rtp_profile_set_payload(profile,SPEEX_PAYLOAD_TYPE,&payload_type_speex_wb);
	rtp_profile_set_payload(profile,SILK_PAYLOAD_TYPE,&payload_type_silk_wb);
	return profile;
}

233
bool_t wait_for_list(bctbx_list_t *mss, int *counter, int value, int timeout_ms) {
234 235 236
	return wait_for_list_with_parse_events(mss, counter, value, timeout_ms, NULL, NULL);
}

237 238 239 240
bool_t wait_for_list_with_parse_events(bctbx_list_t *mss, int *counter, int value, int timeout_ms, bctbx_list_t *cbs, bctbx_list_t *ptrs) {
	bctbx_list_t *msi;
	bctbx_list_t *cbi;
	bctbx_list_t *ptri;
241 242 243 244 245 246 247 248
	int retry = 0;

	while ((*counter < value) && (retry++ < (timeout_ms / 100))) {
		for (msi = mss, cbi = cbs, ptri = ptrs; msi != NULL; msi = msi->next) {
			MediaStream *stream = (MediaStream *)msi->data;
			ms_tester_iterate_cb cb = NULL;
			media_stream_iterate(stream);
			if ((retry % 10) == 0) {
jehan's avatar
jehan committed
249 250 251 252 253 254 255 256
				ms_message("stream [%p] bandwidth usage: rtp [d=%.1f,u=%.1f] kbit/sec",
													stream,
													media_stream_get_down_bw(stream) / 1000,
													media_stream_get_up_bw(stream) / 1000);
				ms_message("stream [%p] bandwidth usage: rtcp[d=%.1f,u=%.1f] kbit/sec",
													stream,
													media_stream_get_rtcp_down_bw(stream) / 1000,
													media_stream_get_rtcp_up_bw(stream) / 1000);
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
			}
			if (cbi && ptri) {
				cb = (ms_tester_iterate_cb)cbi->data;
				cb(stream, ptri->data);
			}
			if (cbi) cbi = cbi->next;
			if (ptri) ptri = ptri->next;
		}
		ms_usleep(100000);
	}

	if (*counter < value)
		return FALSE;
	return TRUE;
}

bool_t wait_for_until(MediaStream *ms_1, MediaStream *ms_2, int *counter, int value, int timeout_ms) {
	return wait_for_until_with_parse_events(ms_1, ms_2, counter, value, timeout_ms, NULL, NULL, NULL, NULL);
}

bool_t wait_for_until_with_parse_events(MediaStream *ms1, MediaStream *ms2, int *counter, int value, int timeout_ms, ms_tester_iterate_cb cb1, void *ptr1, ms_tester_iterate_cb cb2, void *ptr2) {
278 279 280
	bctbx_list_t *mss = NULL;
	bctbx_list_t *cbs = NULL;
	bctbx_list_t *ptrs = NULL;
281 282 283
	bool_t result;

	if (ms1) {
284
		mss = bctbx_list_append(mss, ms1);
285
		if (cb1 && ptr1) {
286 287
			cbs = bctbx_list_append(cbs, cb1);
			ptrs = bctbx_list_append(ptrs, ptr1);
288 289 290
		}
	}
	if (ms2) {
291
		mss = bctbx_list_append(mss, ms2);
292
		if (cb2 && ptr2) {
293 294
			cbs = bctbx_list_append(cbs, cb2);
			ptrs = bctbx_list_append(ptrs, ptr2);
295 296 297
		}
	}
	result = wait_for_list_with_parse_events(mss, counter, value, timeout_ms, cbs, ptrs);
298 299 300
	bctbx_list_free(mss);
	bctbx_list_free(cbs);
	bctbx_list_free(ptrs);
301 302 303 304 305 306
	return result;
}

bool_t wait_for(MediaStream* ms_1, MediaStream* ms_2, int *counter, int value) {
	return wait_for_until(ms_1, ms_2, counter, value, 2000);
}