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