1 /*
2  * SpanDSP - a series of DSP components for telephony
3  *
4  * t38_non_ecm_buffer.c - A rate adapting buffer for T.38 non-ECM image
5  *                        and TCF data
6  *
7  * Written by Steve Underwood <steveu@coppice.org>
8  *
9  * Copyright (C) 2005, 2006, 2007, 2008 Steve Underwood
10  *
11  * All rights reserved.
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU Lesser General Public License version 2.1,
15  * as published by the Free Software Foundation.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this program; if not, write to the Free Software
24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  */
26 
27 /*! \file */
28 
29 #if defined(HAVE_CONFIG_H)
30 #include "config.h"
31 #endif
32 
33 #include <inttypes.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <fcntl.h>
37 #include <time.h>
38 #include <string.h>
39 #if defined(HAVE_TGMATH_H)
40 #include <tgmath.h>
41 #endif
42 #if defined(HAVE_MATH_H)
43 #include <math.h>
44 #endif
45 #if defined(HAVE_STDBOOL_H)
46 #include <stdbool.h>
47 #else
48 #include "spandsp/stdbool.h"
49 #endif
50 #include "floating_fudge.h"
51 #include <assert.h>
52 
53 #include "spandsp/telephony.h"
54 #include "spandsp/alloc.h"
55 #include "spandsp/logging.h"
56 #include "spandsp/queue.h"
57 #include "spandsp/dc_restore.h"
58 #include "spandsp/bit_operations.h"
59 #include "spandsp/async.h"
60 #include "spandsp/t38_non_ecm_buffer.h"
61 
62 #include "spandsp/private/t38_non_ecm_buffer.h"
63 
64 /* Phases */
65 enum
66 {
67     TCF_AT_INITIAL_ALL_ONES = 0,
68     TCF_AT_ALL_ZEROS = 1,
69     IMAGE_WAITING_FOR_FIRST_EOL = 2,
70     IMAGE_IN_PROGRESS = 3
71 };
72 
restart_buffer(t38_non_ecm_buffer_state_t * s)73 static void restart_buffer(t38_non_ecm_buffer_state_t *s)
74 {
75     /* This should be called when draining the buffer is complete, which should
76        occur before any fresh data can possibly arrive to begin refilling it. */
77     s->octet = 0xFF;
78     s->flow_control_fill_octet = 0xFF;
79     s->input_phase = (s->image_data_mode)  ?  IMAGE_WAITING_FOR_FIRST_EOL  :  TCF_AT_INITIAL_ALL_ONES;
80     s->bit_stream = 0xFFFF;
81     s->out_ptr = 0;
82     s->in_ptr = 0;
83     s->latest_eol_ptr = 0;
84     s->data_finished = false;
85 }
86 /*- End of function --------------------------------------------------------*/
87 
t38_non_ecm_buffer_get_bit(void * user_data)88 SPAN_DECLARE(int) t38_non_ecm_buffer_get_bit(void *user_data)
89 {
90     t38_non_ecm_buffer_state_t *s;
91     int bit;
92 
93     s = (t38_non_ecm_buffer_state_t *) user_data;
94 
95     if (s->bit_no <= 0)
96     {
97         /* We need another byte */
98         if (s->out_ptr != s->latest_eol_ptr)
99         {
100             s->octet = s->data[s->out_ptr];
101             s->out_ptr = (s->out_ptr + 1) & (T38_NON_ECM_TX_BUF_LEN - 1);
102         }
103         else
104         {
105             if (s->data_finished)
106             {
107                 /* The queue is empty, and we have received the end of data signal. This must
108                    really be the end to transmission. */
109                 restart_buffer(s);
110                 return SIG_STATUS_END_OF_DATA;
111             }
112             /* The queue is blocked, but this does not appear to be the end of the data. Idle with
113                fill octets, which should be safe at this point. */
114             s->octet = s->flow_control_fill_octet;
115             s->flow_control_fill_octets++;
116         }
117         s->out_octets++;
118         s->bit_no = 8;
119     }
120     s->bit_no--;
121     bit = (s->octet >> 7) & 1;
122     s->octet <<= 1;
123     return bit;
124 }
125 /*- End of function --------------------------------------------------------*/
126 
t38_non_ecm_buffer_push(t38_non_ecm_buffer_state_t * s)127 SPAN_DECLARE(void) t38_non_ecm_buffer_push(t38_non_ecm_buffer_state_t *s)
128 {
129     /* Don't flow control the data any more. Just push out the remainder of the data
130        in the buffer as fast as we can, and shut down. */
131     s->latest_eol_ptr = s->in_ptr;
132     s->data_finished = true;
133 }
134 /*- End of function --------------------------------------------------------*/
135 
t38_non_ecm_buffer_inject(t38_non_ecm_buffer_state_t * s,const uint8_t * buf,int len)136 SPAN_DECLARE(void) t38_non_ecm_buffer_inject(t38_non_ecm_buffer_state_t *s, const uint8_t *buf, int len)
137 {
138     int i;
139     int upper;
140     int lower;
141 
142     /* TCF consists of:
143             - zero or more ones, followed by
144             - about 1.5s of zeros
145        There may be a little junk at the end, as the modem shuts down.
146 
147        We can stuff with extra ones in the initial period of all ones, and we can stuff with extra
148        zeros once the zeros start. The thing we need to be wary about is the odd zero bit in the
149        midst of the ones, due to a bit error. */
150 
151     /* Non-ECM image data consists of:
152             - zero or more ones, followed by
153             - zero or more zeros, followed by
154             - an EOL (end of line), which marks the start of the image, followed by
155             - a succession of data rows, with an EOL at the end of each, followed by
156             - an RTC (return to control)
157        There may be a little junk at the end, as the modem shuts down.
158 
159        An EOL 11 zeros followed by a one in a T.4 1D image or 11 zeros followed by a one followed
160        by a one or a zero in a T.4 2D image. An RTC consists of 6 EOLs in succession, with no
161        pixel data between them.
162 
163        We can stuff with ones until we get the first EOL into our buffer, then we can stuff with
164        zeros in front of each EOL at any point up the the RTC. We should not pad between the EOLs
165        which make up the RTC. Most FAX machines don't care about this, but a few will not recognise
166        the RTC if here is padding between the EOLs.
167 
168        We need to buffer whole rows before we output their beginning, so there is no possibility
169        of underflow mid-row. */
170 
171     /* FoIP has latency issues, because of the fairly tight timeouts in the T.30 spec. We must
172        ensure our buffering does everything needed to avoid underflows, and to meet the minimum
173        row length requirements imposed by many mechanical FAX machines. We cannot, however,
174        afford to bulk up the data, by sending superfluous bytes. The resulting loop delay could
175        provoke an erroneous timeout of the acknowledgement signal. */
176 
177     i = 0;
178     switch (s->input_phase)
179     {
180     case TCF_AT_INITIAL_ALL_ONES:
181         /* Dump initial 0xFF bytes. We will add enough of our own to makes things flow
182            smoothly. If we don't strip these off, we might end up delaying the start of
183            forwarding by a substantial amount, as we could end up with a large block of 0xFF
184            bytes before the real data begins. This is especially true with PC FAX
185            systems. This test is very simplistic, as bit errors could confuse it. */
186         for (  ;  i < len;  i++)
187         {
188             if (buf[i] != 0xFF)
189             {
190                 s->input_phase = TCF_AT_ALL_ZEROS;
191                 s->flow_control_fill_octet = 0x00;
192                 break;
193             }
194         }
195         /* Fall through */
196     case TCF_AT_ALL_ZEROS:
197         for (  ;  i < len;  i++)
198         {
199             s->data[s->in_ptr] = buf[i];
200             s->latest_eol_ptr = s->in_ptr;
201             /* TODO: We can't buffer overflow, since we wrap around. However, the tail could
202                      overwrite itself if things fall badly behind. */
203             s->in_ptr = (s->in_ptr + 1) & (T38_NON_ECM_TX_BUF_LEN - 1);
204             s->in_octets++;
205         }
206         break;
207     case IMAGE_WAITING_FOR_FIRST_EOL:
208         /* Dump anything up to the first EOL. Let the output side stuff with 0xFF bytes while waiting
209            for that first EOL. What occurs before the first EOL is expected to be a period of all ones
210            and then a period of all zeros. We really don't care what junk might be there. By definition,
211            the image only starts at the first EOL. */
212         for (  ;  i < len;  i++)
213         {
214             if (buf[i])
215             {
216                 /* There might be an EOL here. Look for at least 11 zeros, followed by a one, split
217                    between two octets. Between those two octets we can insert numerous zero octets
218                    as a means of flow control. Note that we stuff in blocks of 8 bits, and not at
219                    the minimal level. */
220                 /* Or'ing with 0x800 here is to avoid zero words looking like they have -1
221                    trailing zeros */
222                 upper = bottom_bit(s->bit_stream | 0x800);
223                 lower = top_bit(buf[i]);
224                 if ((upper - lower) > (11 - 8))
225                 {
226                     /* This is an EOL - our first row is beginning. */
227                     s->input_phase = IMAGE_IN_PROGRESS;
228                     /* Start a new row */
229                     s->row_bits = lower - 8;
230                     s->latest_eol_ptr = s->in_ptr;
231                     s->flow_control_fill_octet = 0x00;
232 
233                     /* If we push out two bytes of zero, and our latest non-zero byte
234                        we should definitely form a proper EOL to begin things, with a
235                        few harmless extra zero bits at the front. */
236                     s->data[s->in_ptr] = 0x00;
237                     s->in_ptr = (s->in_ptr + 1) & (T38_NON_ECM_TX_BUF_LEN - 1);
238                     s->data[s->in_ptr] = 0x00;
239                     s->in_ptr = (s->in_ptr + 1) & (T38_NON_ECM_TX_BUF_LEN - 1);
240                     s->data[s->in_ptr] = buf[i];
241                     s->in_ptr = (s->in_ptr + 1) & (T38_NON_ECM_TX_BUF_LEN - 1);
242                     s->in_octets += 3;
243                     s->bit_stream = (s->bit_stream << 8) | buf[i];
244                     i++;
245                     break;
246                 }
247             }
248             s->bit_stream = (s->bit_stream << 8) | buf[i];
249         }
250         if (i >= len)
251             break;
252         /* Fall through */
253     case IMAGE_IN_PROGRESS:
254         /* Now we have seen an EOL, we can stuff with zeros just in front of that EOL, or any
255            subsequent EOL that does not immediately follow a previous EOL (i.e. a candidate RTC).
256            We need to track our way through the image data, allowing the output side to only send
257            up to the last EOL. This prevents the possibility of underflow mid-row, where we cannot
258            safely stuff anything in the bit stream. */
259         for (  ;  i < len;  i++)
260         {
261             if (buf[i])
262             {
263                 /* There might be an EOL here. Look for at least 11 zeros, followed by a one, split
264                    between two octets. Between those two octets we can insert numerous zero octets
265                    as a means of flow control. Note that we stuff in blocks of 8 bits, and not at
266                    the minimal level. */
267                 /* Or'ing with 0x800 here is to avoid zero words looking like they have -1
268                    trailing zeros */
269                 upper = bottom_bit(s->bit_stream | 0x800);
270                 lower = top_bit(buf[i]);
271                 if ((upper - lower) > (11 - 8))
272                 {
273                     /* This is an EOL. */
274                     s->row_bits += (8 - lower);
275                     /* Make sure we don't stretch back to back EOLs, as that could spoil the RTC.
276                        This is a slightly crude check, as we don't know if we are processing a T.4 1D
277                        or T.4 2D image. Accepting 12 or 12 bits apart as meaning back to back is fine,
278                        as no 1D image row could be 1 bit long. */
279                     if (s->row_bits < 12  ||  s->row_bits > 13)
280                     {
281                         /* If the row is too short, extend it in chunks of a whole byte. */
282                         /* TODO: extend by the precise amount we should, instead of this
283                                  rough approach. */
284                         while (s->row_bits < s->min_bits_per_row)
285                         {
286                             s->min_row_bits_fill_octets++;
287                             s->data[s->in_ptr] = 0;
288                             s->row_bits += 8;
289                             /* TODO: We can't buffer overflow, since we wrap around. However,
290                                      the tail could overwrite itself if things fall badly behind. */
291                             s->in_ptr = (s->in_ptr + 1) & (T38_NON_ECM_TX_BUF_LEN - 1);
292                         }
293                         /* This is now the limit for the output side, before it starts
294                            stuffing. */
295                         s->latest_eol_ptr = s->in_ptr;
296                     }
297                     /* Start a new row */
298                     s->row_bits = lower - 8;
299                     s->in_rows++;
300                 }
301             }
302             s->bit_stream = (s->bit_stream << 8) | buf[i];
303             s->data[s->in_ptr] = buf[i];
304             s->row_bits += 8;
305             /* TODO: We can't buffer overflow, since we wrap around. However, the tail could overwrite
306                      itself if things fall badly behind. */
307             s->in_ptr = (s->in_ptr + 1) & (T38_NON_ECM_TX_BUF_LEN - 1);
308             s->in_octets++;
309         }
310         break;
311     }
312 }
313 /*- End of function --------------------------------------------------------*/
314 
t38_non_ecm_buffer_report_input_status(t38_non_ecm_buffer_state_t * s,logging_state_t * logging)315 SPAN_DECLARE(void) t38_non_ecm_buffer_report_input_status(t38_non_ecm_buffer_state_t *s, logging_state_t *logging)
316 {
317     if (s->in_octets  ||  s->min_row_bits_fill_octets)
318     {
319         span_log(logging,
320                  SPAN_LOG_FLOW,
321                  "%d+%d incoming non-ECM octets, %d rows.\n",
322                  s->in_octets,
323                  s->min_row_bits_fill_octets,
324                  s->in_rows);
325         s->in_octets = 0;
326         s->in_rows = 0;
327         s->min_row_bits_fill_octets = 0;
328     }
329 }
330 /*- End of function --------------------------------------------------------*/
331 
t38_non_ecm_buffer_report_output_status(t38_non_ecm_buffer_state_t * s,logging_state_t * logging)332 SPAN_DECLARE(void) t38_non_ecm_buffer_report_output_status(t38_non_ecm_buffer_state_t *s, logging_state_t *logging)
333 {
334     if (s->out_octets  ||  s->flow_control_fill_octets)
335     {
336         span_log(logging,
337                  SPAN_LOG_FLOW,
338                  "%d+%d outgoing non-ECM octets, %d rows.\n",
339                  s->out_octets - s->flow_control_fill_octets,
340                  s->flow_control_fill_octets,
341                  s->out_rows);
342         s->out_octets = 0;
343         s->out_rows = 0;
344         s->flow_control_fill_octets = 0;
345     }
346 }
347 /*- End of function --------------------------------------------------------*/
348 
t38_non_ecm_buffer_set_mode(t38_non_ecm_buffer_state_t * s,bool image_mode,int min_bits_per_row)349 SPAN_DECLARE(void) t38_non_ecm_buffer_set_mode(t38_non_ecm_buffer_state_t *s, bool image_mode, int min_bits_per_row)
350 {
351     s->image_data_mode = image_mode;
352     s->min_bits_per_row = min_bits_per_row;
353 }
354 /*- End of function --------------------------------------------------------*/
355 
t38_non_ecm_buffer_init(t38_non_ecm_buffer_state_t * s,bool image_mode,int min_bits_per_row)356 SPAN_DECLARE(t38_non_ecm_buffer_state_t *) t38_non_ecm_buffer_init(t38_non_ecm_buffer_state_t *s, bool image_mode, int min_bits_per_row)
357 {
358     if (s == NULL)
359     {
360         if ((s = (t38_non_ecm_buffer_state_t *) span_alloc(sizeof(*s))) == NULL)
361             return NULL;
362     }
363     memset(s, 0, sizeof(*s));
364     s->image_data_mode = image_mode;
365     s->min_bits_per_row = min_bits_per_row;
366     restart_buffer(s);
367     return s;
368 }
369 /*- End of function --------------------------------------------------------*/
370 
t38_non_ecm_buffer_release(t38_non_ecm_buffer_state_t * s)371 SPAN_DECLARE(int) t38_non_ecm_buffer_release(t38_non_ecm_buffer_state_t *s)
372 {
373     return 0;
374 }
375 /*- End of function --------------------------------------------------------*/
376 
t38_non_ecm_buffer_free(t38_non_ecm_buffer_state_t * s)377 SPAN_DECLARE(int) t38_non_ecm_buffer_free(t38_non_ecm_buffer_state_t *s)
378 {
379     if (s)
380         span_free(s);
381     return 0;
382 }
383 /*- End of function --------------------------------------------------------*/
384 /*- End of file ------------------------------------------------------------*/
385