blob: 309459b0af015f2037ac1edea8e14584490616a6 [file] [log] [blame]
Alexandre Lision8af73cb2013-12-10 14:11:20 -05001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <stdio.h>
21#include <ctype.h>
22#include <pj/pool.h>
23#include "test.h"
24
25#define JB_INIT_PREFETCH 0
26#define JB_MIN_PREFETCH 0
27#define JB_MAX_PREFETCH 10
28#define JB_PTIME 20
29#define JB_BUF_SIZE 50
30
31//#define REPORT
32//#define PRINT_COMMENT
33
34typedef struct test_param_t {
35 pj_bool_t adaptive;
36 unsigned init_prefetch;
37 unsigned min_prefetch;
38 unsigned max_prefetch;
39} test_param_t;
40
41typedef struct test_cond_t {
42 int burst;
43 int discard;
44 int lost;
45 int empty;
46 int delay; /**< Average delay, in frames. */
47 int delay_min; /**< Minimum delay, in frames. */
48} test_cond_t;
49
50static pj_bool_t parse_test_headers(char *line, test_param_t *param,
51 test_cond_t *cond)
52{
53 char *p = line;
54
55 if (*p == '%') {
56 /* Test params. */
57 char mode_st[16];
58
59 sscanf(p+1, "%s %u %u %u", mode_st, &param->init_prefetch,
60 &param->min_prefetch, &param->max_prefetch);
61 param->adaptive = (pj_ansi_stricmp(mode_st, "adaptive") == 0);
62
63 } else if (*p == '!') {
64 /* Success condition. */
65 char cond_st[16];
66 unsigned cond_val;
67
68 sscanf(p+1, "%s %u", cond_st, &cond_val);
69 if (pj_ansi_stricmp(cond_st, "burst") == 0)
70 cond->burst = cond_val;
71 else if (pj_ansi_stricmp(cond_st, "delay") == 0)
72 cond->delay = cond_val;
73 else if (pj_ansi_stricmp(cond_st, "delay_min") == 0)
74 cond->delay_min = cond_val;
75 else if (pj_ansi_stricmp(cond_st, "discard") == 0)
76 cond->discard = cond_val;
77 else if (pj_ansi_stricmp(cond_st, "empty") == 0)
78 cond->empty = cond_val;
79 else if (pj_ansi_stricmp(cond_st, "lost") == 0)
80 cond->lost = cond_val;
81
82 } else if (*p == '=') {
83 /* Test title. */
84 ++p;
85 while (*p && isspace(*p)) ++p;
86 printf("%s", p);
87
88 } else if (*p == '#') {
89 /* Ignore comment line. */
90
91 } else {
92 /* Unknown header, perhaps this is the test data */
93
94 /* Skip spaces */
95 while (*p && isspace(*p)) ++p;
96
97 /* Test data started.*/
98 if (*p != 0)
99 return PJ_FALSE;
100 }
101
102 return PJ_TRUE;
103}
104
105static pj_bool_t process_test_data(char data, pjmedia_jbuf *jb,
106 pj_uint16_t *seq, pj_uint16_t *last_seq)
107{
108 char frame[1];
109 char f_type;
110 pj_bool_t print_state = PJ_TRUE;
111 pj_bool_t data_eos = PJ_FALSE;
112
113 switch (toupper(data)) {
114 case 'G': /* Get */
115 pjmedia_jbuf_get_frame(jb, frame, &f_type);
116 break;
117 case 'P': /* Put */
118 pjmedia_jbuf_put_frame(jb, (void*)frame, 1, *seq);
119 *last_seq = *seq;
120 ++*seq;
121 break;
122 case 'L': /* Lost */
123 *last_seq = *seq;
124 ++*seq;
125 printf("Lost\n");
126 break;
127 case 'R': /* Sequence restarts */
128 *seq = 1;
129 printf("Sequence restarting, from %u to %u\n", *last_seq, *seq);
130 break;
131 case 'J': /* Sequence jumps */
132 (*seq) += 20;
133 printf("Sequence jumping, from %u to %u\n", *last_seq, *seq);
134 break;
135 case 'D': /* Frame duplicated */
136 pjmedia_jbuf_put_frame(jb, (void*)frame, 1, *seq - 1);
137 break;
138 case 'O': /* Old/late frame */
139 pjmedia_jbuf_put_frame(jb, (void*)frame, 1, *seq - 10 - pj_rand()%40);
140 break;
141 case '.': /* End of test session. */
142 data_eos = PJ_TRUE;
143 break;
144 default:
145 print_state = PJ_FALSE;
146 printf("Unknown test data '%c'\n", data);
147 break;
148 }
149
150 if (data_eos)
151 return PJ_FALSE;
152
153#ifdef REPORT
154 if (print_state) {
155 pjmedia_jb_state state;
156
157 pjmedia_jbuf_get_state(jb, &state);
158 printf("seq=%d\t%c\tsize=%d\tprefetch=%d\n",
159 *last_seq, toupper(data), state.size, state.prefetch);
160 }
161#endif
162
163 return PJ_TRUE;
164}
165
166int jbuf_main(void)
167{
168 FILE *input;
169 pj_bool_t data_eof = PJ_FALSE;
170 int old_log_level;
171 int rc = 0;
172 const char* input_filename = "Jbtest.dat";
173 const char* input_search_path[] = {
174 "../build",
175 "pjmedia/build",
176 "build"
177 };
178
179 /* Try to open test data file in the working directory */
180 input = fopen(input_filename, "rt");
181
182 /* If that fails, try to open test data file in specified search paths */
183 if (input == NULL) {
184 char input_path[PJ_MAXPATH];
185 int i;
186
187 for (i = 0; !input && i < PJ_ARRAY_SIZE(input_search_path); ++i) {
188 pj_ansi_snprintf(input_path, PJ_MAXPATH, "%s/%s",
189 input_search_path[i],
190 input_filename);
191 input = fopen(input_path, "rt");
192 }
193 }
194
195 /* Failed to open test data file. */
196 if (input == NULL) {
197 printf("Failed to open test data file, Jbtest.dat\n");
198 return -1;
199 }
200
201 old_log_level = pj_log_get_level();
202 pj_log_set_level(5);
203
204 while (rc == 0 && !data_eof) {
205 pj_str_t jb_name = {"JBTEST", 6};
206 pjmedia_jbuf *jb;
207 pj_pool_t *pool;
208 pjmedia_jb_state state;
209 pj_uint16_t last_seq = 0;
210 pj_uint16_t seq = 1;
211 char line[1024], *p = NULL;
212
213 test_param_t param;
214 test_cond_t cond;
215
216 param.adaptive = PJ_TRUE;
217 param.init_prefetch = JB_INIT_PREFETCH;
218 param.min_prefetch = JB_MIN_PREFETCH;
219 param.max_prefetch = JB_MAX_PREFETCH;
220
221 cond.burst = -1;
222 cond.delay = -1;
223 cond.delay_min = -1;
224 cond.discard = -1;
225 cond.empty = -1;
226 cond.lost = -1;
227
228 printf("\n\n");
229
230 /* Parse test session title, param, and conditions */
231 do {
232 p = fgets(line, sizeof(line), input);
233 } while (p && parse_test_headers(line, &param, &cond));
234
235 /* EOF test data */
236 if (p == NULL)
237 break;
238
239 //printf("======================================================\n");
240
241 /* Initialize test session */
242 pool = pj_pool_create(mem, "JBPOOL", 256*16, 256*16, NULL);
243 pjmedia_jbuf_create(pool, &jb_name, 1, JB_PTIME, JB_BUF_SIZE, &jb);
244 pjmedia_jbuf_reset(jb);
245
246 if (param.adaptive) {
247 pjmedia_jbuf_set_adaptive(jb,
248 param.init_prefetch,
249 param.min_prefetch,
250 param.max_prefetch);
251 } else {
252 pjmedia_jbuf_set_fixed(jb, param.init_prefetch);
253 }
254
255#ifdef REPORT
256 pjmedia_jbuf_get_state(jb, &state);
257 printf("Initial\tsize=%d\tprefetch=%d\tmin.pftch=%d\tmax.pftch=%d\n",
258 state.size, state.prefetch, state.min_prefetch,
259 state.max_prefetch);
260#endif
261
262
263 /* Test session start */
264 while (1) {
265 char c;
266
267 /* Get next line of test data */
268 if (!p || *p == 0) {
269 p = fgets(line, sizeof(line), input);
270 if (p == NULL) {
271 data_eof = PJ_TRUE;
272 break;
273 }
274 }
275
276 /* Get next char of test data */
277 c = *p++;
278
279 /* Skip spaces */
280 if (isspace(c))
281 continue;
282
283 /* Print comment line */
284 if (c == '#') {
285#ifdef PRINT_COMMENT
286 while (*p && isspace(*p)) ++p;
287 if (*p) printf("..%s", p);
288#endif
289 *p = 0;
290 continue;
291 }
292
293 /* Process test data */
294 if (!process_test_data(c, jb, &seq, &last_seq))
295 break;
296 }
297
298 /* Print JB states */
299 pjmedia_jbuf_get_state(jb, &state);
300 printf("------------------------------------------------------\n");
301 printf("Summary:\n");
302 printf(" size=%d prefetch=%d\n", state.size, state.prefetch);
303 printf(" delay (min/max/avg/dev)=%d/%d/%d/%d ms\n",
304 state.min_delay, state.max_delay, state.avg_delay,
305 state.dev_delay);
306 printf(" lost=%d discard=%d empty=%d burst(avg)=%d\n",
307 state.lost, state.discard, state.empty, state.avg_burst);
308
309 /* Evaluate test session */
310 if (cond.burst >= 0 && (int)state.avg_burst > cond.burst) {
311 printf("! 'Burst' should be %d, it is %d\n",
312 cond.burst, state.avg_burst);
313 rc |= 1;
314 }
315 if (cond.delay >= 0 && (int)state.avg_delay/JB_PTIME > cond.delay) {
316 printf("! 'Delay' should be %d, it is %d\n",
317 cond.delay, state.avg_delay/JB_PTIME);
318 rc |= 2;
319 }
320 if (cond.delay_min >= 0 && (int)state.min_delay/JB_PTIME > cond.delay_min) {
321 printf("! 'Minimum delay' should be %d, it is %d\n",
322 cond.delay_min, state.min_delay/JB_PTIME);
323 rc |= 32;
324 }
325 if (cond.discard >= 0 && (int)state.discard > cond.discard) {
326 printf("! 'Discard' should be %d, it is %d\n",
327 cond.discard, state.discard);
328 rc |= 4;
329 }
330 if (cond.empty >= 0 && (int)state.empty > cond.empty) {
331 printf("! 'Empty' should be %d, it is %d\n",
332 cond.empty, state.empty);
333 rc |= 8;
334 }
335 if (cond.lost >= 0 && (int)state.lost > cond.lost) {
336 printf("! 'Lost' should be %d, it is %d\n",
337 cond.lost, state.lost);
338 rc |= 16;
339 }
340
341 pjmedia_jbuf_destroy(jb);
342 pj_pool_release(pool);
343 }
344
345 fclose(input);
346 pj_log_set_level(old_log_level);
347
348 return rc;
349}