jbuf_test.c 10 KB

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