1 
2 /*
3 mediastreamer2 library - modular sound and video processing and streaming
4 Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
5 
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20 
21 
22 #include "mediastreamer2/msticker.h"
23 
24 #include "mediastreamer2/msrtp.h"
25 #include "mediastreamer2/msfileplayer.h"
26 #include "mediastreamer2/msfilerec.h"
27 
28 #include <signal.h>
29 
30 #define MAX_RTP_SIZE	1500
31 
32 static int run=1;
33 
stop(int signum)34 static void stop(int signum){
35 	run=0;
36 }
37 
38 struct test_session {
39 	RtpSession *rtps;
40 
41 	MSFilter *fplayer;
42 	MSFilter *encoder;
43 	MSFilter *rtpsend;
44 
45 	MSFilter *rtprecv;
46 	MSFilter *decoder;
47 	MSFilter *frecorder;
48 };
49 
50 struct bench_config {
51 	int num_session;
52 	int num_session_record;
53 
54 	int port_origin;
55 	char *ip_destination;
56 	int port_destination;
57 
58 	int payload;
59 	int rate;
60 	int ptime;
61 	char *wavfile;
62 
63 	MSFactory *factory;
64 	MSTicker *ticker;
65 	bctbx_list_t *tsessions; /* list of struct test_session */
66 };
67 
68 #define NUM_SESSION 50 /* num of session to start per block */
69 #define NUM_SESSION_RECORD 1
70 
71 struct bench_config cfg[] = {
72 	{	NUM_SESSION,NUM_SESSION_RECORD,
73 		8000,"127.0.0.1",9000,
74 		8,8000,20,"test1.wav",
75 		NULL,NULL,NULL	},
76 
77 	{	NUM_SESSION,NUM_SESSION_RECORD,
78 		9000,"127.0.0.1",8000,
79 		8,8000,20,"test1.wav",
80 		NULL,NULL,NULL	},
81 
82 	{	NUM_SESSION,NUM_SESSION_RECORD,
83 		10000,"127.0.0.1",11000,
84 		8,8000,20,"test1.wav",
85 		NULL,NULL,NULL	},
86 
87 	{	NUM_SESSION,NUM_SESSION_RECORD,
88 		11000,"127.0.0.1",10000,
89 		8,8000,20,"test1.wav",
90 		NULL,NULL,NULL	},
91 
92 	{	0,0,0,"",0,0,0,0,NULL,NULL,NULL,NULL	},
93 };
94 
create_duplex_rtpsession(int locport)95 static RtpSession *create_duplex_rtpsession(int locport){
96 	RtpSession *rtpr;
97 	rtpr=rtp_session_new(RTP_SESSION_SENDRECV);
98 	rtp_session_set_recv_buf_size(rtpr,MAX_RTP_SIZE);
99 	rtp_session_set_scheduling_mode(rtpr,0);
100 	rtp_session_set_blocking_mode(rtpr,0);
101 	rtp_session_enable_adaptive_jitter_compensation(rtpr,FALSE);
102 	rtp_session_set_symmetric_rtp(rtpr,TRUE);
103 	rtp_session_set_local_addr(rtpr,"0.0.0.0",locport,locport+1);
104 	rtp_session_signal_connect(rtpr,"timestamp_jump",(RtpCallback)rtp_session_resync,NULL);
105 	rtp_session_signal_connect(rtpr,"ssrc_changed",(RtpCallback)rtp_session_resync,NULL);
106 	return rtpr;
107 }
108 
init_bench(struct bench_config * bench)109 static int init_bench(struct bench_config *bench)
110 {
111 	PayloadType *pt;
112 	int pos;
113 	int val;
114 	int count;
115 
116 	bench->factory = ms_factory_new_with_voip();
117 	bench->ticker=ms_ticker_new();
118 
119 	count = 0;
120 	/* creates the couple of encoder/decoder */
121 	pt=rtp_profile_get_payload(&av_profile,bench->payload);
122 	if (pt==NULL){
123 		ms_error("audiostream.c: undefined payload type.");
124 		return count;
125 	}
126 	if (pt->clock_rate!=8000 && pt->clock_rate!=16000 && pt->clock_rate!=32000){
127 		ms_error("audiostream.c: wrong rate.");
128 		return count;
129 	}
130 	for (pos=0;pos<bench->num_session;pos++)
131 		{
132 			struct test_session *ts = (struct test_session *)ortp_malloc(sizeof(struct test_session));
133 			memset(ts, 0, sizeof(struct test_session));
134 
135 			ts->rtps = create_duplex_rtpsession(bench->port_origin+pos*2);
136 			if (ts->rtps==NULL)
137 				{
138 					ms_error("bench.c: cannot create rtp_session!");
139 					ortp_free(ts);
140 					return count;
141 				}
142 
143 			rtp_session_set_payload_type(ts->rtps,bench->payload);
144 			rtp_session_set_remote_addr_full(ts->rtps,
145 											 bench->ip_destination,
146 											 bench->port_destination+pos*2,
147 											 bench->ip_destination,
148 											 bench->port_destination+1+pos*2);
149 
150 			ts->fplayer = ms_factory_create_filter(bench->factory, MS_FILE_PLAYER_ID);
151 			if (strstr(bench->wavfile, ".au")==NULL)
152 				ts->encoder = ms_factory_create_encoder(bench->factory, pt->mime_type);
153 			ts->rtpsend = ms_factory_create_filter(bench->factory, MS_RTP_SEND_ID);
154 
155 			ts->rtprecv = ms_factory_create_filter(bench->factory, MS_RTP_RECV_ID);
156 			ts->decoder = ms_factory_create_decoder(bench->factory, pt->mime_type);
157 			ts->frecorder = ms_factory_create_filter(bench->factory, MS_FILE_REC_ID);
158 
159 			if ((ts->encoder==NULL && strstr(bench->wavfile, ".au")==NULL)
160 				|| (ts->decoder==NULL )){
161 				ms_error("bench.c: No decoder available for payload %i.",bench->payload);
162 				if (ts->fplayer) ms_filter_destroy(ts->fplayer);
163 				if (ts->encoder) ms_filter_destroy(ts->encoder);
164 				if (ts->rtpsend) ms_filter_destroy(ts->rtpsend);
165 				if (ts->rtprecv) ms_filter_destroy(ts->rtprecv);
166 				if (ts->decoder) ms_filter_destroy(ts->decoder);
167 				if (ts->frecorder) ms_filter_destroy(ts->frecorder);
168 				ortp_free(ts);
169 				return count;
170 			}
171 			if (ts->fplayer==NULL){
172 				ms_error("bench.c: missing player filter.");
173 				if (ts->fplayer) ms_filter_destroy(ts->fplayer);
174 				if (ts->encoder) ms_filter_destroy(ts->encoder);
175 				if (ts->rtpsend) ms_filter_destroy(ts->rtpsend);
176 				if (ts->rtprecv) ms_filter_destroy(ts->rtprecv);
177 				if (ts->decoder) ms_filter_destroy(ts->decoder);
178 				if (ts->frecorder) ms_filter_destroy(ts->frecorder);
179 				ortp_free(ts);
180 				return count;
181 			}
182 			if (ts->frecorder==NULL){
183 				ms_error("bench.c: missing recorder filter.");
184 				if (ts->fplayer) ms_filter_destroy(ts->fplayer);
185 				if (ts->encoder) ms_filter_destroy(ts->encoder);
186 				if (ts->rtpsend) ms_filter_destroy(ts->rtpsend);
187 				if (ts->rtprecv) ms_filter_destroy(ts->rtprecv);
188 				if (ts->decoder) ms_filter_destroy(ts->decoder);
189 				if (ts->frecorder) ms_filter_destroy(ts->frecorder);
190 				ortp_free(ts);
191 				return count;
192 			}
193 			if (ts->rtpsend==NULL){
194 				ms_error("bench.c: missing rtpsend filter.");
195 				if (ts->fplayer) ms_filter_destroy(ts->fplayer);
196 				if (ts->encoder) ms_filter_destroy(ts->encoder);
197 				if (ts->rtpsend) ms_filter_destroy(ts->rtpsend);
198 				if (ts->rtprecv) ms_filter_destroy(ts->rtprecv);
199 				if (ts->decoder) ms_filter_destroy(ts->decoder);
200 				if (ts->frecorder) ms_filter_destroy(ts->frecorder);
201 				ortp_free(ts);
202 				return count;
203 			}
204 			if (ts->rtprecv==NULL){
205 				ms_error("bench.c: missing rtprecv filter.");
206 				if (ts->fplayer) ms_filter_destroy(ts->fplayer);
207 				if (ts->encoder) ms_filter_destroy(ts->encoder);
208 				if (ts->rtpsend) ms_filter_destroy(ts->rtpsend);
209 				if (ts->rtprecv) ms_filter_destroy(ts->rtprecv);
210 				if (ts->decoder) ms_filter_destroy(ts->decoder);
211 				if (ts->frecorder) ms_filter_destroy(ts->frecorder);
212 				ortp_free(ts);
213 				return count;
214 			}
215 
216 			ms_filter_call_method(ts->rtpsend,MS_RTP_SEND_SET_SESSION,ts->rtps);
217 			ms_filter_call_method(ts->rtprecv,MS_RTP_RECV_SET_SESSION,ts->rtps);
218 
219 			ms_filter_call_method (ts->rtprecv, MS_FILTER_SET_SAMPLE_RATE,
220 								   &pt->clock_rate);
221 
222 			ms_filter_call_method (ts->frecorder, MS_FILTER_SET_SAMPLE_RATE,
223 								   &pt->clock_rate);
224 
225 			val = ms_filter_call_method(ts->fplayer,MS_FILE_PLAYER_OPEN,(void*)bench->wavfile);
226 			if (val!=0)
227 				{
228 					ms_error("bench.c: Cannot open wav file (%s)", bench->wavfile);
229 					if (ts->fplayer) ms_filter_destroy(ts->fplayer);
230 					if (ts->encoder) ms_filter_destroy(ts->encoder);
231 					if (ts->rtpsend) ms_filter_destroy(ts->rtpsend);
232 					if (ts->rtprecv) ms_filter_destroy(ts->rtprecv);
233 					if (ts->decoder) ms_filter_destroy(ts->decoder);
234 					if (ts->frecorder) ms_filter_destroy(ts->frecorder);
235 					ortp_free(ts);
236 					return count;
237 				}
238 
239 			val=0;
240 			ms_filter_call_method (ts->fplayer, MS_FILTER_GET_SAMPLE_RATE,
241 								   &val);
242 			if (val!=pt->clock_rate)
243 				{
244 					ms_error("bench.c: unsupported rate for wav file: codec=%i / file=%i",
245 							 pt->clock_rate, val);
246 					if (ts->fplayer) ms_filter_destroy(ts->fplayer);
247 					if (ts->encoder) ms_filter_destroy(ts->encoder);
248 					if (ts->rtpsend) ms_filter_destroy(ts->rtpsend);
249 					if (ts->rtprecv) ms_filter_destroy(ts->rtprecv);
250 					if (ts->decoder) ms_filter_destroy(ts->decoder);
251 					if (ts->frecorder) ms_filter_destroy(ts->frecorder);
252 					ortp_free(ts);
253 					return count;
254 				}
255 			ms_filter_call_method (ts->fplayer, MS_FILTER_GET_NCHANNELS,
256 								   &val);
257 
258 			if (val!=1)
259 				{
260 					ms_error("bench.c: unsupported number of channel for wav file: codec=1 / file=%i",
261 							 val);
262 					if (ts->fplayer) ms_filter_destroy(ts->fplayer);
263 					if (ts->encoder) ms_filter_destroy(ts->encoder);
264 					if (ts->rtpsend) ms_filter_destroy(ts->rtpsend);
265 					if (ts->rtprecv) ms_filter_destroy(ts->rtprecv);
266 					if (ts->decoder) ms_filter_destroy(ts->decoder);
267 					if (ts->frecorder) ms_filter_destroy(ts->frecorder);
268 					ortp_free(ts);
269 					return count;
270 				}
271 			ms_filter_call_method_noarg(ts->fplayer,MS_FILE_PLAYER_START);
272 
273 			if (strstr(bench->wavfile, ".au")==NULL)
274 				{
275 					ms_filter_link(ts->fplayer,0,ts->encoder,0);
276 					ms_filter_link(ts->encoder,0,ts->rtpsend,0);
277 				}
278 			else
279 				{
280 					ms_filter_link(ts->fplayer,0,ts->rtpsend,0);
281 				}
282 
283 			ms_filter_link(ts->rtprecv,0,ts->decoder,0);
284 			ms_filter_link(ts->decoder,0,ts->frecorder,0);
285 
286 			ms_ticker_attach(bench->ticker,ts->fplayer);
287 			ms_ticker_attach(bench->ticker,ts->rtprecv);
288 
289 			if (pos < bench->num_session_record)
290 			{
291 				char rec_file[128];
292 				snprintf(rec_file, sizeof(rec_file), "rec_%s_%i.wav",
293 						 bench->ip_destination,
294 						 bench->port_destination+pos*2);
295 				ms_filter_call_method(ts->frecorder,MS_FILE_REC_OPEN,(void*)rec_file);
296 				ms_filter_call_method_noarg(ts->frecorder,MS_FILE_REC_START);
297 			}
298 
299 			bench->tsessions = bctbx_list_append(bench->tsessions, (void*)ts);
300 			count++;
301 		}
302 
303 	return count;
304 }
305 
uninit_bench(struct bench_config * bench)306 static int uninit_bench(struct bench_config *bench)
307 {
308 	bctbx_list_t *it;
309 	for(it=bench->tsessions;it!=NULL;it=bench->tsessions){
310 		struct test_session *ts = (struct test_session *)it->data;
311 		bench->tsessions = bctbx_list_erase_link(bench->tsessions, it);
312 
313 		ms_ticker_detach(bench->ticker,ts->fplayer);
314 		ms_ticker_detach(bench->ticker,ts->rtprecv);
315 
316 		ms_filter_call_method_noarg(ts->frecorder,MS_FILE_REC_CLOSE);
317 
318 		if (strstr(bench->wavfile, ".au")==NULL)
319 			{
320 				ms_filter_unlink(ts->fplayer,0,ts->encoder,0);
321 				ms_filter_unlink(ts->encoder,0,ts->rtpsend,0);
322 			}
323 		else
324 			{
325 				ms_filter_unlink(ts->fplayer,0,ts->rtpsend,0);
326 			}
327 
328 		ms_filter_unlink(ts->rtprecv,0,ts->decoder,0);
329 		ms_filter_unlink(ts->decoder,0,ts->frecorder,0);
330 
331 		if (ts->fplayer) ms_filter_destroy(ts->fplayer);
332 		if (ts->encoder) ms_filter_destroy(ts->encoder);
333 		if (ts->rtpsend) ms_filter_destroy(ts->rtpsend);
334 
335 		if (ts->rtprecv) ms_filter_destroy(ts->rtprecv);
336 		if (ts->decoder) ms_filter_destroy(ts->decoder);
337 		if (ts->frecorder) ms_filter_destroy(ts->frecorder);
338 
339 		ortp_free(ts);
340 	}
341 
342 	ms_ticker_destroy(bench->ticker);
343 	ms_factory_destroy(bench->factory);
344 	return 0;
345 }
346 
347 
main(int argc,char * argv[])348 int main(int argc, char *argv[]){
349 	int pos;
350 	int count;
351 	ortp_init();
352 	ortp_set_log_level_mask(ORTP_LOG_DOMAIN, ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
353 
354 
355 
356 	rtp_profile_set_payload(&av_profile,115,&payload_type_lpc1015);
357 	rtp_profile_set_payload(&av_profile,110,&payload_type_speex_nb);
358 	rtp_profile_set_payload(&av_profile,111,&payload_type_speex_wb);
359 	rtp_profile_set_payload(&av_profile,112,&payload_type_ilbc);
360 
361 	signal(SIGINT,stop);
362 
363 	count=0;
364 	for (pos=0;cfg[pos].num_session!=0;pos++)
365 		{
366 			count = count + init_bench( &cfg[pos]);
367 			ms_sleep(10);
368 		}
369 
370 	ms_message("Number of session started: %i.", count);
371 
372 	while(run)
373 		ms_sleep(1);
374 
375 	for (pos=0;cfg[pos].num_session!=0;pos++)
376 		{
377 			uninit_bench(&cfg[pos]);
378 		}
379 
380 
381 
382 	return 0;
383 }
384 
385