1 /*
2  * SpanDSP - a series of DSP components for telephony
3  *
4  * t38_decode.c
5  *
6  * Written by Steve Underwood <steveu@coppice.org>
7  *
8  * Copyright (C) 2010 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 
26 /*! \file */
27 
28 #if defined(HAVE_CONFIG_H)
29 #include "config.h"
30 #endif
31 
32 #include <stdlib.h>
33 #include <inttypes.h>
34 #include <stdio.h>
35 #include <fcntl.h>
36 #include <string.h>
37 #include <assert.h>
38 #include <errno.h>
39 #include <time.h>
40 #if !defined(_WIN32)
41 #include <unistd.h>
42 #endif
43 
44 #include "udptl.h"
45 #include "spandsp.h"
46 #include "spandsp-sim.h"
47 
48 #include "fax_utils.h"
49 #include "pcap_parse.h"
50 
51 #define INPUT_FILE_NAME         "t38.pcap"
52 #define INPUT_TIFF_FILE_NAME    "../test-data/itu/fax/itutests.tif"
53 #define OUTPUT_TIFF_FILE_NAME   "t38pcap.tif"
54 
55 #define OUTPUT_WAVE_FILE_NAME   "t38_decode2.wav"
56 
57 #define SAMPLES_PER_CHUNK       160
58 
59 static t38_core_state_t *t38_core;
60 static t38_terminal_state_t *t38_terminal_state;
61 static t38_gateway_state_t *t38_gateway_state;
62 static fax_state_t *fax_state;
63 static struct timeval now;
64 static SNDFILE *wave_handle;
65 
66 static int log_audio;
67 static int use_transmit_on_idle;
68 static int done = false;
69 
70 static int started = false;
71 static int64_t current = 0;
72 
phase_b_handler(void * user_data,int result)73 static int phase_b_handler(void *user_data, int result)
74 {
75     int ch;
76     t30_state_t *s;
77     char tag[20];
78 
79     ch = 'A';
80     s = (t30_state_t *) user_data;
81     snprintf(tag, sizeof(tag), "%c: Phase B", ch);
82     printf("%c: Phase B handler on channel %c - (0x%X) %s\n", ch, ch, result, t30_frametype(result));
83     fax_log_rx_parameters(s, tag);
84     return T30_ERR_OK;
85 }
86 /*- End of function --------------------------------------------------------*/
87 
phase_d_handler(void * user_data,int result)88 static int phase_d_handler(void *user_data, int result)
89 {
90     int ch;
91     t30_state_t *s;
92     char tag[20];
93 
94     ch = 'A';
95     s = (t30_state_t *) user_data;
96     snprintf(tag, sizeof(tag), "%c: Phase D", ch);
97     printf("%c: Phase D handler on channel %c - (0x%X) %s\n", ch, ch, result, t30_frametype(result));
98     fax_log_page_transfer_statistics(s, tag);
99     fax_log_tx_parameters(s, tag);
100     fax_log_rx_parameters(s, tag);
101     return T30_ERR_OK;
102 }
103 /*- End of function --------------------------------------------------------*/
104 
phase_e_handler(void * user_data,int result)105 static void phase_e_handler(void *user_data, int result)
106 {
107     int ch;
108     t30_stats_t t;
109     t30_state_t *s;
110     char tag[20];
111 
112     ch = 'A';
113     s = (t30_state_t *) user_data;
114     snprintf(tag, sizeof(tag), "%c: Phase E", ch);
115     printf("%c: Phase E handler on channel %c - (%d) %s\n", ch, ch, result, t30_completion_code_to_str(result));
116     fax_log_final_transfer_statistics(s, tag);
117     fax_log_tx_parameters(s, tag);
118     fax_log_rx_parameters(s, tag);
119     t30_get_transfer_statistics(s, &t);
120 }
121 /*- End of function --------------------------------------------------------*/
122 
tx_packet_handler(t38_core_state_t * s,void * user_data,const uint8_t * buf,int len,int count)123 static int tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
124 {
125     return 0;
126 }
127 /*- End of function --------------------------------------------------------*/
128 
t38_terminal_timing_update(void * user_data,struct timeval * ts)129 static int t38_terminal_timing_update(void *user_data, struct timeval *ts)
130 {
131     t30_state_t *t30;
132     logging_state_t *logging;
133     int samples;
134     int partial;
135     int64_t when;
136     int64_t diff;
137 
138     memcpy(&now, ts, sizeof(now));
139 
140     when = ts->tv_sec*1000000LL + ts->tv_usec;
141     if (current == 0)
142     {
143         if (started)
144             current = when;
145         return 0;
146     }
147 
148     diff = when - current;
149     samples = diff/125LL;
150     while (samples > 0)
151     {
152         partial = (samples > SAMPLES_PER_CHUNK)  ?  SAMPLES_PER_CHUNK  :  samples;
153         //fprintf(stderr, "Update time by %d samples\n", partial);
154         logging = t38_terminal_get_logging_state(t38_terminal_state);
155         span_log_bump_samples(logging, partial);
156         logging = t38_core_get_logging_state(t38_core);
157         span_log_bump_samples(logging, partial);
158         t30 = t38_terminal_get_t30_state(t38_terminal_state);
159         logging = t30_get_logging_state(t30);
160         span_log_bump_samples(logging, partial);
161 
162         t38_terminal_send_timeout(t38_terminal_state, partial);
163         current = when;
164         samples -= partial;
165     }
166     return 0;
167 }
168 /*- End of function --------------------------------------------------------*/
169 
t38_gateway_timing_update(void * user_data,struct timeval * ts)170 static int t38_gateway_timing_update(void *user_data, struct timeval *ts)
171 {
172     t30_state_t *t30;
173     logging_state_t *logging;
174     int samples;
175     int partial;
176     int64_t when;
177     int64_t diff;
178     int16_t t38_amp[SAMPLES_PER_CHUNK];
179     int16_t t30_amp[SAMPLES_PER_CHUNK];
180     int16_t out_amp[2*SAMPLES_PER_CHUNK];
181     int t38_len;
182     int t30_len;
183     int outframes;
184     int i;
185 
186     memcpy(&now, ts, sizeof(now));
187 
188     when = ts->tv_sec*1000000LL + ts->tv_usec;
189     if (current == 0)
190     {
191         if (started)
192             current = when;
193         return 0;
194     }
195 
196     diff = when - current;
197     samples = diff/125LL;
198     while (samples > 0)
199     {
200         partial = (samples > SAMPLES_PER_CHUNK)  ?  SAMPLES_PER_CHUNK  :  samples;
201         //fprintf(stderr, "Update time by %d samples\n", partial);
202         logging = t38_gateway_get_logging_state(t38_gateway_state);
203         span_log_bump_samples(logging, partial);
204         logging = t38_core_get_logging_state(t38_core);
205         span_log_bump_samples(logging, partial);
206         logging = fax_get_logging_state(fax_state);
207         span_log_bump_samples(logging, partial);
208         t30 = fax_get_t30_state(fax_state);
209         logging = t30_get_logging_state(t30);
210         span_log_bump_samples(logging, partial);
211 
212         memset(out_amp, 0, sizeof(out_amp));
213 
214         t30_len = fax_tx(fax_state, t30_amp, partial);
215         if (!use_transmit_on_idle)
216         {
217             /* The receive side always expects a full block of samples, but the
218                transmit side may not be sending any when it doesn't need to. We
219                may need to pad with some silence. */
220             if (t30_len < partial)
221             {
222                 memset(t30_amp + t30_len, 0, sizeof(int16_t)*(partial - t30_len));
223                 t30_len = partial;
224             }
225         }
226         if (log_audio)
227         {
228             for (i = 0;  i < t30_len;  i++)
229                 out_amp[2*i + 1] = t30_amp[i];
230         }
231         if (t38_gateway_rx(t38_gateway_state, t30_amp, t30_len))
232             break;
233 
234         t38_len = t38_gateway_tx(t38_gateway_state, t38_amp, partial);
235         if (!use_transmit_on_idle)
236         {
237             if (t38_len < partial)
238             {
239                 memset(t38_amp + t38_len, 0, sizeof(int16_t)*(partial - t38_len));
240                 t38_len = partial;
241             }
242         }
243         if (log_audio)
244         {
245             for (i = 0;  i < t38_len;  i++)
246                 out_amp[2*i] = t38_amp[i];
247         }
248         if (fax_rx(fax_state, t38_amp, partial))
249             break;
250 
251         if (log_audio)
252         {
253             outframes = sf_writef_short(wave_handle, out_amp, partial);
254             if (outframes != partial)
255                 break;
256         }
257 
258         if (done)
259             break;
260 
261         current = when;
262         samples -= partial;
263     }
264     return 0;
265 }
266 /*- End of function --------------------------------------------------------*/
267 
ifp_handler(void * user_data,const uint8_t msg[],int len,int seq_no)268 static int ifp_handler(void *user_data, const uint8_t msg[], int len, int seq_no)
269 {
270     int i;
271 
272     started = true;
273 
274     printf("%5d >>> ", seq_no);
275     for (i = 0;  i < len;  i++)
276         printf("%02X ", msg[i]);
277     printf("\n");
278 
279     t38_core_rx_ifp_packet(t38_core, msg, len, seq_no);
280 
281     return 0;
282 }
283 /*- End of function --------------------------------------------------------*/
284 
process_packet(void * user_data,const uint8_t * pkt,int len)285 static int process_packet(void *user_data, const uint8_t *pkt, int len)
286 {
287     static udptl_state_t *state = NULL;
288 
289     if (state == NULL)
290         state = udptl_init(NULL, UDPTL_ERROR_CORRECTION_REDUNDANCY, 3, 3, ifp_handler, NULL);
291 
292     udptl_rx_packet(state, pkt, len);
293     return 0;
294 }
295 /*- End of function --------------------------------------------------------*/
296 
parse_inet_addr(const char * s)297 static uint32_t parse_inet_addr(const char *s)
298 {
299     int i;
300     uint32_t a;
301     uint32_t b;
302     uint32_t c;
303     uint32_t d;
304 
305     a = 0;
306     b = 0;
307     c = 0;
308     d = 0;
309     i = sscanf(s, "%" PRIu32 ".%" PRIu32 ".%" PRIu32 ".%" PRIu32, &a, &b, &c, &d);
310     switch (i)
311     {
312     case 4:
313         c = (c << 8) | d;
314     case 3:
315         b = (b << 16) | c;
316     case 2:
317         a = (a << 24) | b;
318     }
319     return a;
320 }
321 /*- End of function --------------------------------------------------------*/
322 
main(int argc,char * argv[])323 int main(int argc, char *argv[])
324 {
325     t30_state_t *t30;
326     logging_state_t *logging;
327     const char *input_file_name;
328     const char *input_tiff_file_name;
329     int t38_version;
330     int caller;
331     int use_ecm;
332     int use_tep;
333     int options;
334     int supported_modems;
335     int fill_removal;
336     int opt;
337     int t38_terminal_operation;
338     uint32_t src_addr;
339     uint16_t src_port;
340     uint32_t dest_addr;
341     uint16_t dest_port;
342 
343     caller = false;
344     use_ecm = false;
345     t38_version = 0;
346     options = 0;
347     input_file_name = INPUT_FILE_NAME;
348     input_tiff_file_name = INPUT_TIFF_FILE_NAME;
349     fill_removal = false;
350     use_tep = false;
351     use_transmit_on_idle = true;
352     supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
353     t38_terminal_operation = true;
354     log_audio = false;
355     src_addr = 0;
356     src_port = 0;
357     dest_addr = 0;
358     dest_port = 0;
359     while ((opt = getopt(argc, argv, "cD:d:eFGi:lm:oS:s:T:tv:")) != -1)
360     {
361         switch (opt)
362         {
363         case 'c':
364             caller = true;
365             break;
366         case 'D':
367             dest_addr = parse_inet_addr(optarg);
368             break;
369         case 'd':
370             dest_port = atoi(optarg);
371             break;
372         case 'e':
373             use_ecm = true;
374             break;
375         case 'F':
376             fill_removal = true;
377             break;
378         case 'G':
379             t38_terminal_operation = false;
380             break;
381         case 'i':
382             input_file_name = optarg;
383             break;
384         case 'l':
385             log_audio = true;
386             break;
387         case 'm':
388             supported_modems = atoi(optarg);
389             break;
390         case 'o':
391             options = atoi(optarg);
392             break;
393         case 'S':
394             src_addr = parse_inet_addr(optarg);
395             break;
396         case 's':
397             src_port = atoi(optarg);
398             break;
399         case 'T':
400             input_tiff_file_name = optarg;
401             break;
402         case 't':
403             use_tep = true;
404             break;
405         case 'v':
406             t38_version = atoi(optarg);
407             break;
408         default:
409             //usage();
410             exit(2);
411             break;
412         }
413     }
414 
415     printf("Using T.38 version %d\n", t38_version);
416 
417     if (t38_terminal_operation)
418     {
419         if ((t38_terminal_state = t38_terminal_init(NULL, caller, tx_packet_handler, NULL)) == NULL)
420         {
421             fprintf(stderr, "Cannot start the T.38 channel\n");
422             exit(2);
423         }
424         t30 = t38_terminal_get_t30_state(t38_terminal_state);
425         t38_core = t38_terminal_get_t38_core_state(t38_terminal_state);
426         t38_set_t38_version(t38_core, t38_version);
427         t38_terminal_set_config(t38_terminal_state, options);
428         t38_terminal_set_tep_mode(t38_terminal_state, use_tep);
429         t38_terminal_set_fill_bit_removal(t38_terminal_state, fill_removal);
430 
431         logging = t38_terminal_get_logging_state(t38_terminal_state);
432         span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
433         span_log_set_tag(logging, "T.38");
434 
435         logging = t38_core_get_logging_state(t38_core);
436         span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
437         span_log_set_tag(logging, "T.38");
438 
439         logging = t30_get_logging_state(t30);
440         span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
441         span_log_set_tag(logging, "T.38");
442 
443         t30_set_supported_modems(t30, supported_modems);
444         t30_set_tx_ident(t30, "11111111");
445         t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
446         if (caller)
447             t30_set_tx_file(t30, input_tiff_file_name, -1, -1);
448         else
449             t30_set_rx_file(t30, OUTPUT_TIFF_FILE_NAME, -1);
450         t30_set_phase_b_handler(t30, phase_b_handler, (void *) t30);
451         t30_set_phase_d_handler(t30, phase_d_handler, (void *) t30);
452         t30_set_phase_e_handler(t30, phase_e_handler, (void *) t30);
453         t30_set_ecm_capability(t30, use_ecm);
454         t30_set_supported_compressions(t30,
455                                        T4_COMPRESSION_T4_1D
456                                      | T4_COMPRESSION_T4_2D
457                                      | T4_COMPRESSION_T6
458                                      | T4_COMPRESSION_T85
459                                      | T4_COMPRESSION_T85_L0
460                                      | T4_COMPRESSION_T42_T81
461                                      | T4_COMPRESSION_COLOUR);
462         t30_set_supported_bilevel_resolutions(t30,
463                                               T4_RESOLUTION_R8_STANDARD
464                                             | T4_RESOLUTION_R8_FINE
465                                             | T4_RESOLUTION_R8_SUPERFINE
466                                             | T4_RESOLUTION_R16_SUPERFINE
467                                             | T4_RESOLUTION_200_100
468                                             | T4_RESOLUTION_200_200
469                                             | T4_RESOLUTION_200_400
470                                             | T4_RESOLUTION_300_300
471                                             | T4_RESOLUTION_300_600
472                                             | T4_RESOLUTION_400_400
473                                             | T4_RESOLUTION_400_800
474                                             | T4_RESOLUTION_600_600
475                                             | T4_RESOLUTION_600_1200
476                                             | T4_RESOLUTION_1200_1200);
477         t30_set_supported_colour_resolutions(t30,
478                                              T4_RESOLUTION_100_100
479                                            | T4_RESOLUTION_200_200
480                                            | T4_RESOLUTION_300_300
481                                            | T4_RESOLUTION_400_400
482                                            | T4_RESOLUTION_600_600
483                                            | T4_RESOLUTION_1200_1200);
484 
485         if (pcap_scan_pkts(input_file_name, src_addr, src_port, dest_addr, dest_port, t38_terminal_timing_update, process_packet, NULL))
486             exit(2);
487         /* Push the time along, to flush out any remaining activity from the application. */
488         now.tv_sec += 60;
489         t38_terminal_timing_update(NULL, &now);
490     }
491     else
492     {
493         wave_handle = NULL;
494         if (log_audio)
495         {
496             if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL)
497             {
498                 fprintf(stderr, "    Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
499                 exit(2);
500             }
501         }
502 
503         if ((t38_gateway_state = t38_gateway_init(NULL, tx_packet_handler, NULL)) == NULL)
504         {
505             fprintf(stderr, "Cannot start the T.38 channel\n");
506             exit(2);
507         }
508         t38_core = t38_gateway_get_t38_core_state(t38_gateway_state);
509         t38_gateway_set_transmit_on_idle(t38_gateway_state, use_transmit_on_idle);
510         t38_set_t38_version(t38_core, t38_version);
511         t38_gateway_set_ecm_capability(t38_gateway_state, use_ecm);
512 
513         logging = t38_gateway_get_logging_state(t38_gateway_state);
514         span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
515         span_log_set_tag(logging, "T.38");
516 
517         logging = t38_core_get_logging_state(t38_core);
518         span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
519         span_log_set_tag(logging, "T.38");
520 
521         if ((fax_state = fax_init(NULL, caller)) == NULL)
522         {
523             fprintf(stderr, "Cannot start FAX\n");
524             exit(2);
525         }
526         t30 = fax_get_t30_state(fax_state);
527         fax_set_transmit_on_idle(fax_state, use_transmit_on_idle);
528         fax_set_tep_mode(fax_state, use_tep);
529         t30_set_supported_modems(t30, supported_modems);
530         t30_set_tx_ident(t30, "22222222");
531         t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
532         if (caller)
533             t30_set_tx_file(t30, input_tiff_file_name, -1, -1);
534         else
535             t30_set_rx_file(t30, OUTPUT_TIFF_FILE_NAME, -1);
536         t30_set_phase_b_handler(t30, phase_b_handler, (void *) t30);
537         t30_set_phase_d_handler(t30, phase_d_handler, (void *) t30);
538         t30_set_phase_e_handler(t30, phase_e_handler, (void *) t30);
539         t30_set_ecm_capability(t30, use_ecm);
540         t30_set_supported_compressions(t30,
541                                        T4_COMPRESSION_T4_1D
542                                      | T4_COMPRESSION_T4_2D
543                                      | T4_COMPRESSION_T6
544                                      | T4_COMPRESSION_T85
545                                      | T4_COMPRESSION_T85_L0
546                                      | T4_COMPRESSION_T42_T81
547                                      | T4_COMPRESSION_COLOUR);
548         t30_set_supported_bilevel_resolutions(t30,
549                                               T4_RESOLUTION_R8_STANDARD
550                                             | T4_RESOLUTION_R8_FINE
551                                             | T4_RESOLUTION_R8_SUPERFINE
552                                             | T4_RESOLUTION_R16_SUPERFINE
553                                             | T4_RESOLUTION_200_100
554                                             | T4_RESOLUTION_200_200
555                                             | T4_RESOLUTION_200_400
556                                             | T4_RESOLUTION_300_300
557                                             | T4_RESOLUTION_300_600
558                                             | T4_RESOLUTION_400_400
559                                             | T4_RESOLUTION_400_800
560                                             | T4_RESOLUTION_600_600
561                                             | T4_RESOLUTION_600_1200
562                                             | T4_RESOLUTION_1200_1200);
563         t30_set_supported_colour_resolutions(t30,
564                                              T4_RESOLUTION_100_100
565                                            | T4_RESOLUTION_200_200
566                                            | T4_RESOLUTION_300_300
567                                            | T4_RESOLUTION_400_400
568                                            | T4_RESOLUTION_600_600
569                                            | T4_RESOLUTION_1200_1200);
570 
571         logging = fax_get_logging_state(fax_state);
572         span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
573         span_log_set_tag(logging, "FAX ");
574 
575         logging = t30_get_logging_state(t30);
576         span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
577         span_log_set_tag(logging, "FAX ");
578 
579         if (pcap_scan_pkts(input_file_name, src_addr, src_port, dest_addr, dest_port, t38_gateway_timing_update, process_packet, NULL))
580             exit(2);
581         /* Push the time along, to flush out any remaining activity from the application. */
582         now.tv_sec += 60;
583         t38_gateway_timing_update(NULL, &now);
584 
585         fax_release(fax_state);
586         t38_gateway_release(t38_gateway_state);
587         if (log_audio)
588         {
589             if (sf_close_telephony(wave_handle))
590             {
591                 fprintf(stderr, "    Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
592                 exit(2);
593             }
594         }
595     }
596 }
597 /*- End of function --------------------------------------------------------*/
598 /*- End of file ------------------------------------------------------------*/
599