Mercurial > hg > audiostuff
comparison spandsp-0.0.6pre17/tests/t38_terminal_tests.c @ 4:26cd8f1ef0b1
import spandsp-0.0.6pre17
| author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
|---|---|
| date | Fri, 25 Jun 2010 15:50:58 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 3:c6c5a16ce2f2 | 4:26cd8f1ef0b1 |
|---|---|
| 1 /* | |
| 2 * SpanDSP - a series of DSP components for telephony | |
| 3 * | |
| 4 * t38_terminal_tests.c - Tests for the T.38 FoIP terminal module. | |
| 5 * | |
| 6 * Written by Steve Underwood <steveu@coppice.org> | |
| 7 * | |
| 8 * Copyright (C) 2005, 2006 Steve Underwood | |
| 9 * | |
| 10 * All rights reserved. | |
| 11 * | |
| 12 * This program is free software; you can redistribute it and/or modify | |
| 13 * it under the terms of the GNU General Public License version 2, as | |
| 14 * published by the Free Software Foundation. | |
| 15 * | |
| 16 * This program is distributed in the hope that it will be useful, | |
| 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 * GNU General Public License for more details. | |
| 20 * | |
| 21 * You should have received a copy of the GNU General Public License | |
| 22 * along with this program; if not, write to the Free Software | |
| 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
| 24 * | |
| 25 * $Id: t38_terminal_tests.c,v 1.67.4.1 2009/12/19 09:47:57 steveu Exp $ | |
| 26 */ | |
| 27 | |
| 28 /*! \file */ | |
| 29 | |
| 30 /*! \page t38_terminal_tests_page T.38 termination tests | |
| 31 \section t38_terminal_tests_page_sec_1 What does it do? | |
| 32 These tests exercise the path | |
| 33 | |
| 34 T.38 termination <-> T.38 termination | |
| 35 */ | |
| 36 | |
| 37 //#define WITH_SPANDSP_INTERNALS | |
| 38 | |
| 39 #if defined(HAVE_CONFIG_H) | |
| 40 #include <config.h> | |
| 41 #endif | |
| 42 | |
| 43 #if defined(HAVE_FL_FL_H) && defined(HAVE_FL_FL_CARTESIAN_H) && defined(HAVE_FL_FL_AUDIO_METER_H) | |
| 44 #define ENABLE_GUI | |
| 45 #endif | |
| 46 | |
| 47 #include <stdlib.h> | |
| 48 #include <stdio.h> | |
| 49 #include <fcntl.h> | |
| 50 #include <string.h> | |
| 51 #include <assert.h> | |
| 52 #include <errno.h> | |
| 53 #if !defined(_WIN32) | |
| 54 #include <unistd.h> | |
| 55 #endif | |
| 56 | |
| 57 //#if defined(WITH_SPANDSP_INTERNALS) | |
| 58 #define SPANDSP_EXPOSE_INTERNAL_STRUCTURES | |
| 59 //#endif | |
| 60 | |
| 61 #include "spandsp.h" | |
| 62 #include "spandsp-sim.h" | |
| 63 | |
| 64 #if defined(ENABLE_GUI) | |
| 65 #include "media_monitor.h" | |
| 66 #endif | |
| 67 #include "fax_utils.h" | |
| 68 | |
| 69 #define SAMPLES_PER_CHUNK 160 | |
| 70 | |
| 71 #define INPUT_FILE_NAME "../test-data/itu/fax/itutests.tif" | |
| 72 #define OUTPUT_FILE_NAME "t38.tif" | |
| 73 | |
| 74 t38_terminal_state_t *t38_state_a; | |
| 75 t38_terminal_state_t *t38_state_b; | |
| 76 | |
| 77 g1050_state_t *path_a_to_b; | |
| 78 g1050_state_t *path_b_to_a; | |
| 79 | |
| 80 double when = 0.0; | |
| 81 | |
| 82 int done[2] = {FALSE, FALSE}; | |
| 83 int succeeded[2] = {FALSE, FALSE}; | |
| 84 | |
| 85 int simulate_incrementing_repeats = FALSE; | |
| 86 | |
| 87 static int phase_b_handler(t30_state_t *s, void *user_data, int result) | |
| 88 { | |
| 89 int i; | |
| 90 char tag[20]; | |
| 91 | |
| 92 i = (int) (intptr_t) user_data; | |
| 93 snprintf(tag, sizeof(tag), "%c: Phase B", i); | |
| 94 printf("%c: Phase B handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result)); | |
| 95 log_rx_parameters(s, tag); | |
| 96 return T30_ERR_OK; | |
| 97 } | |
| 98 /*- End of function --------------------------------------------------------*/ | |
| 99 | |
| 100 static int phase_d_handler(t30_state_t *s, void *user_data, int result) | |
| 101 { | |
| 102 int i; | |
| 103 char tag[20]; | |
| 104 | |
| 105 i = (int) (intptr_t) user_data; | |
| 106 snprintf(tag, sizeof(tag), "%c: Phase D", i); | |
| 107 printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result)); | |
| 108 log_transfer_statistics(s, tag); | |
| 109 log_tx_parameters(s, tag); | |
| 110 log_rx_parameters(s, tag); | |
| 111 return T30_ERR_OK; | |
| 112 } | |
| 113 /*- End of function --------------------------------------------------------*/ | |
| 114 | |
| 115 static void phase_e_handler(t30_state_t *s, void *user_data, int result) | |
| 116 { | |
| 117 int i; | |
| 118 t30_stats_t t; | |
| 119 char tag[20]; | |
| 120 | |
| 121 i = (int) (intptr_t) user_data; | |
| 122 snprintf(tag, sizeof(tag), "%c: Phase E", i); | |
| 123 printf("%c: Phase E handler on channel %c - (%d) %s\n", i, i, result, t30_completion_code_to_str(result)); | |
| 124 log_transfer_statistics(s, tag); | |
| 125 log_tx_parameters(s, tag); | |
| 126 log_rx_parameters(s, tag); | |
| 127 t30_get_transfer_statistics(s, &t); | |
| 128 succeeded[i - 'A'] = (result == T30_ERR_OK) && (t.pages_tx == 12 || t.pages_rx == 12); | |
| 129 //done[i - 'A'] = TRUE; | |
| 130 } | |
| 131 /*- End of function --------------------------------------------------------*/ | |
| 132 | |
| 133 static int tx_packet_handler_a(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count) | |
| 134 { | |
| 135 t38_terminal_state_t *t; | |
| 136 int i; | |
| 137 static int subst_seq = 0; | |
| 138 | |
| 139 /* This routine queues messages between two instances of T.38 processing */ | |
| 140 t = (t38_terminal_state_t *) user_data; | |
| 141 if (simulate_incrementing_repeats) | |
| 142 { | |
| 143 for (i = 0; i < count; i++) | |
| 144 { | |
| 145 span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d\n", subst_seq, len); | |
| 146 | |
| 147 if (g1050_put(path_a_to_b, buf, len, subst_seq, when) < 0) | |
| 148 printf("Lost packet %d\n", subst_seq); | |
| 149 subst_seq = (subst_seq + 1) & 0xFFFF; | |
| 150 } | |
| 151 } | |
| 152 else | |
| 153 { | |
| 154 span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d, count %d\n", s->tx_seq_no, len, count); | |
| 155 | |
| 156 for (i = 0; i < count; i++) | |
| 157 { | |
| 158 if (g1050_put(path_a_to_b, buf, len, s->tx_seq_no, when) < 0) | |
| 159 printf("Lost packet %d\n", s->tx_seq_no); | |
| 160 } | |
| 161 } | |
| 162 return 0; | |
| 163 } | |
| 164 /*- End of function --------------------------------------------------------*/ | |
| 165 | |
| 166 static int tx_packet_handler_b(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count) | |
| 167 { | |
| 168 t38_terminal_state_t *t; | |
| 169 int i; | |
| 170 static int subst_seq = 0; | |
| 171 | |
| 172 /* This routine queues messages between two instances of T.38 processing */ | |
| 173 t = (t38_terminal_state_t *) user_data; | |
| 174 if (simulate_incrementing_repeats) | |
| 175 { | |
| 176 for (i = 0; i < count; i++) | |
| 177 { | |
| 178 span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d\n", subst_seq, len); | |
| 179 | |
| 180 g1050_put(path_b_to_a, buf, len, subst_seq, when); | |
| 181 subst_seq = (subst_seq + 1) & 0xFFFF; | |
| 182 } | |
| 183 } | |
| 184 else | |
| 185 { | |
| 186 span_log(&s->logging, SPAN_LOG_FLOW, "Send seq %d, len %d, count %d\n", s->tx_seq_no, len, count); | |
| 187 | |
| 188 for (i = 0; i < count; i++) | |
| 189 g1050_put(path_b_to_a, buf, len, s->tx_seq_no, when); | |
| 190 } | |
| 191 return 0; | |
| 192 } | |
| 193 /*- End of function --------------------------------------------------------*/ | |
| 194 | |
| 195 int main(int argc, char *argv[]) | |
| 196 { | |
| 197 int msg_len; | |
| 198 uint8_t msg[1024]; | |
| 199 int t38_version; | |
| 200 int seq_no; | |
| 201 int use_ecm; | |
| 202 int without_pacing; | |
| 203 int use_tep; | |
| 204 int model_no; | |
| 205 int speed_pattern_no; | |
| 206 const char *input_file_name; | |
| 207 double tx_when; | |
| 208 double rx_when; | |
| 209 int use_gui; | |
| 210 int supported_modems; | |
| 211 int opt; | |
| 212 t30_state_t *t30; | |
| 213 t38_core_state_t *t38_core; | |
| 214 logging_state_t *logging; | |
| 215 | |
| 216 t38_version = 1; | |
| 217 without_pacing = FALSE; | |
| 218 use_tep = FALSE; | |
| 219 input_file_name = INPUT_FILE_NAME; | |
| 220 use_ecm = FALSE; | |
| 221 simulate_incrementing_repeats = FALSE; | |
| 222 model_no = 0; | |
| 223 speed_pattern_no = 1; | |
| 224 use_gui = FALSE; | |
| 225 supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17; | |
| 226 while ((opt = getopt(argc, argv, "efgi:Im:M:ps:tv:")) != -1) | |
| 227 { | |
| 228 switch (opt) | |
| 229 { | |
| 230 case 'e': | |
| 231 use_ecm = TRUE; | |
| 232 break; | |
| 233 case 'g': | |
| 234 #if defined(ENABLE_GUI) | |
| 235 use_gui = TRUE; | |
| 236 #else | |
| 237 fprintf(stderr, "Graphical monitoring not available\n"); | |
| 238 exit(2); | |
| 239 #endif | |
| 240 break; | |
| 241 case 'i': | |
| 242 input_file_name = optarg; | |
| 243 break; | |
| 244 case 'I': | |
| 245 simulate_incrementing_repeats = TRUE; | |
| 246 break; | |
| 247 case 'm': | |
| 248 supported_modems = atoi(optarg); | |
| 249 break; | |
| 250 case 'M': | |
| 251 model_no = optarg[0] - 'A' + 1; | |
| 252 break; | |
| 253 case 'p': | |
| 254 without_pacing = TRUE; | |
| 255 break; | |
| 256 case 's': | |
| 257 speed_pattern_no = atoi(optarg); | |
| 258 break; | |
| 259 case 't': | |
| 260 use_tep = TRUE; | |
| 261 break; | |
| 262 case 'v': | |
| 263 t38_version = atoi(optarg); | |
| 264 break; | |
| 265 default: | |
| 266 //usage(); | |
| 267 exit(2); | |
| 268 break; | |
| 269 } | |
| 270 } | |
| 271 | |
| 272 printf("Using T.38 version %d\n", t38_version); | |
| 273 if (use_ecm) | |
| 274 printf("Using ECM\n"); | |
| 275 | |
| 276 srand48(0x1234567); | |
| 277 if ((path_a_to_b = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL) | |
| 278 { | |
| 279 fprintf(stderr, "Failed to start IP network path model\n"); | |
| 280 exit(2); | |
| 281 } | |
| 282 if ((path_b_to_a = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL) | |
| 283 { | |
| 284 fprintf(stderr, "Failed to start IP network path model\n"); | |
| 285 exit(2); | |
| 286 } | |
| 287 | |
| 288 if ((t38_state_a = t38_terminal_init(NULL, TRUE, tx_packet_handler_a, t38_state_b)) == NULL) | |
| 289 { | |
| 290 fprintf(stderr, "Cannot start the T.38 channel\n"); | |
| 291 exit(2); | |
| 292 } | |
| 293 t30 = t38_terminal_get_t30_state(t38_state_a); | |
| 294 t38_core = t38_terminal_get_t38_core_state(t38_state_a); | |
| 295 t38_set_t38_version(t38_core, t38_version); | |
| 296 t38_terminal_set_config(t38_state_a, without_pacing); | |
| 297 t38_terminal_set_tep_mode(t38_state_a, use_tep); | |
| 298 | |
| 299 logging = t38_terminal_get_logging_state(t38_state_a); | |
| 300 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); | |
| 301 span_log_set_tag(logging, "T.38-A"); | |
| 302 | |
| 303 logging = t38_core_get_logging_state(t38_core); | |
| 304 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); | |
| 305 span_log_set_tag(logging, "T.38-A"); | |
| 306 | |
| 307 logging = t30_get_logging_state(t30); | |
| 308 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); | |
| 309 span_log_set_tag(logging, "T.38-A"); | |
| 310 | |
| 311 t30_set_supported_modems(t30, supported_modems); | |
| 312 t30_set_tx_ident(t30, "11111111"); | |
| 313 t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); | |
| 314 t30_set_tx_file(t30, input_file_name, -1, -1); | |
| 315 t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A'); | |
| 316 t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A'); | |
| 317 t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A'); | |
| 318 t30_set_ecm_capability(t30, use_ecm); | |
| 319 if (use_ecm) | |
| 320 t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); | |
| 321 | |
| 322 if ((t38_state_b = t38_terminal_init(NULL, FALSE, tx_packet_handler_b, t38_state_a)) == NULL) | |
| 323 { | |
| 324 fprintf(stderr, "Cannot start the T.38 channel\n"); | |
| 325 exit(2); | |
| 326 } | |
| 327 t30 = t38_terminal_get_t30_state(t38_state_b); | |
| 328 t38_core = t38_terminal_get_t38_core_state(t38_state_b); | |
| 329 t38_set_t38_version(t38_core, t38_version); | |
| 330 t38_terminal_set_config(t38_state_b, without_pacing); | |
| 331 t38_terminal_set_tep_mode(t38_state_b, use_tep); | |
| 332 | |
| 333 logging = t38_terminal_get_logging_state(t38_state_b); | |
| 334 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); | |
| 335 span_log_set_tag(logging, "T.38-B"); | |
| 336 | |
| 337 logging = t38_core_get_logging_state(t38_core); | |
| 338 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); | |
| 339 span_log_set_tag(logging, "T.38-B"); | |
| 340 | |
| 341 logging = t30_get_logging_state(t30); | |
| 342 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME); | |
| 343 span_log_set_tag(logging, "T.38-B"); | |
| 344 | |
| 345 t30_set_supported_modems(t30, supported_modems); | |
| 346 t30_set_tx_ident(t30, "22222222"); | |
| 347 t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12); | |
| 348 t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1); | |
| 349 t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'B'); | |
| 350 t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'B'); | |
| 351 t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'B'); | |
| 352 t30_set_ecm_capability(t30, use_ecm); | |
| 353 if (use_ecm) | |
| 354 t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); | |
| 355 | |
| 356 #if defined(ENABLE_GUI) | |
| 357 if (use_gui) | |
| 358 start_media_monitor(); | |
| 359 #endif | |
| 360 for (;;) | |
| 361 { | |
| 362 logging = t38_terminal_get_logging_state(t38_state_a); | |
| 363 span_log_bump_samples(logging, SAMPLES_PER_CHUNK); | |
| 364 t38_core = t38_terminal_get_t38_core_state(t38_state_a); | |
| 365 logging = t38_core_get_logging_state(t38_core); | |
| 366 span_log_bump_samples(logging, SAMPLES_PER_CHUNK); | |
| 367 t30 = t38_terminal_get_t30_state(t38_state_a); | |
| 368 logging = t30_get_logging_state(t30); | |
| 369 span_log_bump_samples(logging, SAMPLES_PER_CHUNK); | |
| 370 logging = t38_terminal_get_logging_state(t38_state_b); | |
| 371 span_log_bump_samples(logging, SAMPLES_PER_CHUNK); | |
| 372 t38_core = t38_terminal_get_t38_core_state(t38_state_b); | |
| 373 logging = t38_core_get_logging_state(t38_core); | |
| 374 span_log_bump_samples(logging, SAMPLES_PER_CHUNK); | |
| 375 t30 = t38_terminal_get_t30_state(t38_state_b); | |
| 376 logging = t30_get_logging_state(t30); | |
| 377 span_log_bump_samples(logging, SAMPLES_PER_CHUNK); | |
| 378 | |
| 379 done[0] = t38_terminal_send_timeout(t38_state_a, SAMPLES_PER_CHUNK); | |
| 380 done[1] = t38_terminal_send_timeout(t38_state_b, SAMPLES_PER_CHUNK); | |
| 381 | |
| 382 when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE; | |
| 383 | |
| 384 while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) | |
| 385 { | |
| 386 #if defined(ENABLE_GUI) | |
| 387 if (use_gui) | |
| 388 media_monitor_rx(seq_no, tx_when, rx_when); | |
| 389 #endif | |
| 390 t38_core = t38_terminal_get_t38_core_state(t38_state_b); | |
| 391 t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); | |
| 392 } | |
| 393 while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0) | |
| 394 { | |
| 395 #if defined(ENABLE_GUI) | |
| 396 if (use_gui) | |
| 397 media_monitor_rx(seq_no, tx_when, rx_when); | |
| 398 #endif | |
| 399 t38_core = t38_terminal_get_t38_core_state(t38_state_a); | |
| 400 t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no); | |
| 401 } | |
| 402 if (done[0] && done[1]) | |
| 403 break; | |
| 404 #if defined(ENABLE_GUI) | |
| 405 if (use_gui) | |
| 406 media_monitor_update_display(); | |
| 407 #endif | |
| 408 } | |
| 409 t38_terminal_release(t38_state_a); | |
| 410 t38_terminal_release(t38_state_b); | |
| 411 if (!succeeded[0] || !succeeded[1]) | |
| 412 { | |
| 413 printf("Tests failed\n"); | |
| 414 exit(2); | |
| 415 } | |
| 416 printf("Tests passed\n"); | |
| 417 return 0; | |
| 418 } | |
| 419 /*- End of function --------------------------------------------------------*/ | |
| 420 /*- End of file ------------------------------------------------------------*/ |
