Spandsp tweaks

This commit is contained in:
Steve Underwood 2013-07-23 20:44:46 +08:00
parent 8d005a4138
commit c741332dcd
7 changed files with 782 additions and 590 deletions

View File

@ -76,16 +76,6 @@ SPAN_DECLARE(void) set_lab_gamut2(lab_params_t *s, int L_P, int L_Q, int a_P, in
SPAN_DECLARE(void) get_lab_gamut2(lab_params_t *s, int *L_P, int *L_Q, int *a_P, int *a_Q, int *b_P, int *b_Q);
SPAN_DECLARE(int) t42_itulab_to_itulab(logging_state_t *logging, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t width, uint32_t height);
SPAN_DECLARE(int) t42_itulab_to_jpeg(logging_state_t *logging, lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen);
SPAN_DECLARE(int) t42_jpeg_to_itulab(logging_state_t *logging, lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen);
SPAN_DECLARE(int) t42_srgb_to_itulab(logging_state_t *logging, lab_params_t *s, tdata_t *dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t width, uint32_t height);
SPAN_DECLARE(int) t42_itulab_to_srgb(logging_state_t *logging, lab_params_t *s, tdata_t dst, tsize_t *dstlen, tdata_t src, tsize_t srclen, uint32_t *width, uint32_t *height);
SPAN_DECLARE(void) t42_encode_set_options(t42_encode_state_t *s, uint32_t l0, int quality, int options);
SPAN_DECLARE(int) t42_encode_set_image_width(t42_encode_state_t *s, uint32_t image_width);

View File

@ -40,7 +40,7 @@ enum
{
V18_MODE_NONE = 0,
/* V.18 Annex A - Weitbrecht TDD at 45.45bps (US TTY), half-duplex, 5 bit baudot (USA). */
V18_MODE_5BIT_45 = 1,
V18_MODE_5BIT_4545 = 1,
/* V.18 Annex A - Weitbrecht TDD at 50bps (International TTY), half-duplex, 5 bit baudot (UK, Australia and others). */
V18_MODE_5BIT_50 = 2,
/* V.18 Annex B - DTMF encoding of ASCII (Denmark, Holland and others). */
@ -55,6 +55,7 @@ enum
V18_MODE_V21TEXTPHONE = 7,
/* V.18 Annex G - V.18 text telephone mode. */
V18_MODE_V18TEXTPHONE = 8,
V18_MODE_5BIT_476 = 9,
/* Use repetitive shift characters where character set shifts are used */
V18_MODE_REPETITIVE_SHIFTS_OPTION = 0x1000
};
@ -171,28 +172,6 @@ SPAN_DECLARE_NONSTD(int) v18_rx_fillin(v18_state_t *s, int len);
invalid, this function will return -1. */
SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len);
/*! Convert a text string to a V.18 DTMF string.
\brief Convert a text string to a V.18 DTMF string.
\param s The V.18 context.
\param dtmf The resulting DTMF string.
\param msg The text string to be converted.
\return The length of the DTMF string.
*/
SPAN_DECLARE(int) v18_encode_dtmf(v18_state_t *s, char dtmf[], const char msg[]);
/*! Convert a V.18 DTMF string to a text string.
\brief Convert a V.18 DTMF string to a text string.
\param s The V.18 context.
\param msg The resulting test string.
\param dtmf The DTMF string to be converted.
\return The length of the text string.
*/
SPAN_DECLARE(int) v18_decode_dtmf(v18_state_t *s, char msg[], const char dtmf[]);
SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch);
SPAN_DECLARE(uint8_t) v18_decode_baudot(v18_state_t *s, uint8_t ch);
/*! \brief Return a short name for an V.18 mode
\param mode The code for the V.18 mode.
\return A pointer to the name.

View File

@ -132,18 +132,19 @@ static const res_table_t y_res_table[] =
{ -1.00f, -1}
};
static const int resolution_map[10][10] =
static const int resolution_map[10][9] =
{
{ 0, 0, 0, T4_RESOLUTION_R8_STANDARD, 0, 0, 0, 0, 0, 0},
{T4_RESOLUTION_100_100, 0, T4_RESOLUTION_200_100, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, T4_RESOLUTION_R8_FINE, 0, 0, 0, 0, 0, 0},
{ 0, 0, T4_RESOLUTION_200_200, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, T4_RESOLUTION_300_300, 0, 0, 0, 0, 0},
{ 0, 0, 0, T4_RESOLUTION_R8_SUPERFINE, 0, 0, T4_RESOLUTION_R16_SUPERFINE, 0, 0, 0},
{ 0, 0, T4_RESOLUTION_200_400, 0, 0, T4_RESOLUTION_400_400, 0, 0, 0, 0},
{ 0, 0, 0, 0, T4_RESOLUTION_300_600, 0, 0, T4_RESOLUTION_600_600, 0, 0},
{ 0, 0, 0, 0, 0, T4_RESOLUTION_400_800, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, T4_RESOLUTION_600_1200, 0, T4_RESOLUTION_1200_1200},
/* x = 100 102 200 204 300 400 408 600 1200 */
{ 0, 0, 0, T4_RESOLUTION_R8_STANDARD, 0, 0, 0, 0, 0}, /* y = 3.85/mm */
{T4_RESOLUTION_100_100, 0, T4_RESOLUTION_200_100, 0, 0, 0, 0, 0, 0}, /* y = 100 */
{ 0, 0, 0, T4_RESOLUTION_R8_FINE, 0, 0, 0, 0, 0}, /* y = 7.7/mm */
{ 0, 0, T4_RESOLUTION_200_200, 0, 0, 0, 0, 0, 0}, /* y = 200 */
{ 0, 0, 0, 0, T4_RESOLUTION_300_300, 0, 0, 0, 0}, /* y = 300 */
{ 0, 0, 0, T4_RESOLUTION_R8_SUPERFINE, 0, 0, T4_RESOLUTION_R16_SUPERFINE, 0, 0}, /* y = 154/mm */
{ 0, 0, T4_RESOLUTION_200_400, 0, 0, T4_RESOLUTION_400_400, 0, 0, 0}, /* y = 400 */
{ 0, 0, 0, 0, T4_RESOLUTION_300_600, 0, 0, T4_RESOLUTION_600_600, 0}, /* y = 600 */
{ 0, 0, 0, 0, 0, T4_RESOLUTION_400_800, 0, 0, 0}, /* y = 800 */
{ 0, 0, 0, 0, 0, 0, 0, T4_RESOLUTION_600_1200, T4_RESOLUTION_1200_1200} /* y = 1200 */
};
#if defined(SPANDSP_SUPPORT_TIFF_FX)
@ -1354,12 +1355,14 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t
t->image_type = s->tiff.image_type;
t->image_width = s->tiff.image_width;
t->image_length = s->tiff.image_length;
t->image_x_resolution = s->tiff.x_resolution;
t->image_y_resolution = s->tiff.y_resolution;
t->x_resolution = s->metadata.x_resolution;
t->y_resolution = s->metadata.y_resolution/s->row_squashing_ratio;
t->compression = s->metadata.compression;
switch (s->metadata.compression)
{
case T4_COMPRESSION_T4_1D:
@ -1417,7 +1420,7 @@ SPAN_DECLARE(int) t4_tx_image_complete(t4_tx_state_t *s)
return t85_encode_image_complete(&s->encoder.t85);
#if defined(SPANDSP_SUPPORT_T88)
case T4_COMPRESSION_T88:
break;
return t88_encode_image_complete(&s->encoder.t88);
#endif
case T4_COMPRESSION_T42_T81:
case T4_COMPRESSION_SYCC_T81:
@ -1428,7 +1431,7 @@ SPAN_DECLARE(int) t4_tx_image_complete(t4_tx_state_t *s)
#endif
#if defined(SPANDSP_SUPPORT_T45)
case T4_COMPRESSION_T45:
break;
return t45_encode_image_complete(&s->encoder.t45);
#endif
}
return SIG_STATUS_END_OF_DATA;
@ -1444,6 +1447,19 @@ SPAN_DECLARE(int) t4_tx_get_bit(t4_tx_state_t *s)
SPAN_DECLARE(int) t4_tx_get(t4_tx_state_t *s, uint8_t buf[], size_t max_len)
{
#if 0
if (s->pre_encoded_len > 0)
{
if (max_len > (s->pre_encoded_len - s->pre_encoded_ptr))
max_len = s->pre_encoded_len - s->pre_encoded_ptr;
memcpy(buf, &s->pre_encoded_buf[s->pre_encoded_ptr], max_len);
s->pre_encoded_ptr += max_len;
return max_len;
}
if (s->image_get_handler)
return s->image_get_handler((void *) &s->encoder, buf, max_len);
#else
switch (s->metadata.compression)
{
case T4_COMPRESSION_T4_1D:
@ -1469,6 +1485,7 @@ SPAN_DECLARE(int) t4_tx_get(t4_tx_state_t *s, uint8_t buf[], size_t max_len)
break;
#endif
}
#endif
return 0;
}
/*- End of function --------------------------------------------------------*/
@ -1497,31 +1514,44 @@ SPAN_DECLARE(int) t4_tx_start_page(t4_tx_state_t *s)
case T4_COMPRESSION_T4_2D:
case T4_COMPRESSION_T6:
t4_t6_encode_restart(&s->encoder.t4_t6, s->metadata.image_width, s->metadata.image_length);
s->image_get_handler = (t4_image_get_handler_t) t4_t6_encode_get;
break;
case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0:
t85_encode_restart(&s->encoder.t85, s->metadata.image_width, s->metadata.image_length);
s->image_get_handler = (t4_image_get_handler_t) t85_encode_get;
break;
#if defined(SPANDSP_SUPPORT_T88)
case T4_COMPRESSION_T88:
t88_encode_restart(&s->encoder.t88, s->metadata.image_width, s->metadata.image_length);
s->image_get_handler = (t4_image_get_handler_t) t88_encode_get;
break;
#endif
case T4_COMPRESSION_T42_T81:
case T4_COMPRESSION_SYCC_T81:
t42_encode_restart(&s->encoder.t42, s->metadata.image_width, s->metadata.image_length);
s->image_get_handler = (t4_image_get_handler_t) t42_encode_get;
break;
#if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43:
t43_encode_restart(&s->encoder.t43, s->metadata.image_width, s->metadata.image_length);
s->image_get_handler = (t4_image_get_handler_t) t43_encode_get;
break;
#endif
#if defined(SPANDSP_SUPPORT_T45)
case T4_COMPRESSION_T45:
t45_encode_restart(&s->encoder.t45, s->metadata.image_width, s->metadata.image_length);
s->image_get_handler = (t4_image_get_handler_t) t45_encode_get;
break;
#endif
default:
s->image_get_handler = NULL;
break;
}
/* If there is a page header, create that first */
if (s->tiff.image_type == T4_IMAGE_TYPE_BILEVEL && s->header_info && s->header_info[0] && make_header(s) == 0)
if (s->metadata.image_type == T4_IMAGE_TYPE_BILEVEL && s->header_info && s->header_info[0] && make_header(s) == 0)
//if (s->header_info && s->header_info[0] && make_header(s) == 0)
{
s->header_row = 0;
set_row_read_handler(s, header_row_read_handler, (void *) s);
@ -1634,7 +1664,7 @@ SPAN_DECLARE(int) t4_tx_release(t4_tx_state_t *s)
return t85_encode_release(&s->encoder.t85);
#if defined(SPANDSP_SUPPORT_T88)
case T4_COMPRESSION_T88:
break;
return t88_encode_release(&s->encoder.t88);
#endif
case T4_COMPRESSION_T42_T81:
case T4_COMPRESSION_SYCC_T81:
@ -1645,7 +1675,7 @@ SPAN_DECLARE(int) t4_tx_release(t4_tx_state_t *s)
#endif
#if defined(SPANDSP_SUPPORT_T45)
case T4_COMPRESSION_T45:
break;
return t45_encode_release(&s->encoder.t45);
#endif
}
return -1;

View File

@ -78,13 +78,13 @@
Silence for 0.5s then send TXP
DTMF
Proceed as Annex B
1650Hz (V21 ch 2 low)
1650Hz (V21 ch 2 low) [1650Hz +-12Hz]
Proceed as Annex F in call mode
1300Hz (Calling tone)
1300Hz (Calling tone) [1300Hz +-16Hz]
Proceed as Annex E in call mode
1400Hz/1800Hz (Weitbrecht)
1400Hz/1800Hz (Weitbrecht) [1400Hz +-5% and 1800Hz +-5%]
Detect rate and proceed as Annex A
980Hz/1180Hz (V21 ch 1)
980Hz/1180Hz (V21 ch 1) [980Hz +-12Hz, 1180Hz +-12Hz]
Start timer Tr
2225Hz (Bell ANS)
Proceed as Annex D call mode
@ -98,21 +98,21 @@
Monitor as caller for 980Hz or 1300Hz
CI/XCI
Respond with ANSam
1300Hz
1300Hz [1300Hz +-16Hz]
Probe
Timer Ta (3s)
Probe
1400Hz/1800Hz (Weitbrecht)
1400Hz/1800Hz (Weitbrecht) [1400Hz +-5% and 1800Hz +-5%]
Detect rate and proceed as Annex A
DTMF
Proceed as Annex B
980Hz (V21 ch 1 low)
980Hz (V21 ch 1 low) [980Hz +-12Hz]
Start timer Te
1270Hz (Bell103 ch 2 high)
Proceed as Annex D answer mode
2225Hz (Bell ANS)
Proceed as Annex D call mode
1650Hz (V21 ch 2 low)
1650Hz (V21 ch 2 low) [1650Hz +-12Hz]
Proceed as Annex F answer mode
ANSam
Proceed as V.8 caller Annex G
@ -131,6 +131,7 @@ struct dtmf_to_ascii_s
static const struct dtmf_to_ascii_s dtmf_to_ascii[] =
{
{"###0", '!'},
{"###1", 'C'},
{"###2", 'F'},
{"###3", 'I'},
@ -140,7 +141,6 @@ static const struct dtmf_to_ascii_s dtmf_to_ascii[] =
{"###7", 'U'},
{"###8", 'X'},
{"###9", ';'},
{"###0", '!'},
{"##*1", 'A'},
{"##*2", 'D'},
{"##*3", 'G'},
@ -373,71 +373,174 @@ static const uint8_t txp[] = "1111111111000101011100001101110000010101";
100 ms mark. */
static const uint8_t xci[] = "01111111110111111111";
static int cmp(const void *s, const void *t)
/* The entries here must match the order in which the related names are defined in v18.h */
static const int automoding_sequences[][6] =
{
const char *ss;
struct dtmf_to_ascii_s *tt;
ss = (const char *) s;
tt = (struct dtmf_to_ascii_s *) t;
return strncmp(ss, tt->dtmf, strlen(tt->dtmf));
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) v18_encode_dtmf(v18_state_t *s, char dtmf[], const char msg[])
{
const char *t;
const char *v;
char *u;
t = msg;
u = dtmf;
while (*t)
{
v = ascii_to_dtmf[*t & 0x7F];
while (*v)
*u++ = *v++;
t++;
}
*u = '\0';
return u - dtmf;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) v18_decode_dtmf(v18_state_t *s, char msg[], const char dtmf[])
{
int entries;
const char *t;
char *u;
struct dtmf_to_ascii_s *ss;
entries = sizeof(dtmf_to_ascii)/sizeof(dtmf_to_ascii[0]) - 1;
t = dtmf;
u = msg;
while (*t)
/* Dummy entry 0 */
V18_MODE_5BIT_4545,
V18_MODE_BELL103,
V18_MODE_V21TEXTPHONE,
V18_MODE_V23VIDEOTEX,
V18_MODE_EDT,
V18_MODE_DTMF
},
{
ss = bsearch(t, dtmf_to_ascii, entries, sizeof(dtmf_to_ascii[0]), cmp);
if (ss)
{
t += strlen(ss->dtmf);
*u++ = ss->ascii;
}
else
{
/* Can't match the code. Let's assume this is a code we just don't know, and skip over it */
while (*t == '#' || *t == '*')
t++;
if (*t)
t++;
}
/* Australia */
V18_MODE_5BIT_50,
V18_MODE_V21TEXTPHONE,
V18_MODE_V23VIDEOTEX,
V18_MODE_EDT,
V18_MODE_DTMF,
V18_MODE_BELL103
},
{
/* Ireland */
V18_MODE_5BIT_50,
V18_MODE_V21TEXTPHONE,
V18_MODE_V23VIDEOTEX,
V18_MODE_EDT,
V18_MODE_DTMF,
V18_MODE_BELL103
},
{
/* Germany */
V18_MODE_EDT,
V18_MODE_V21TEXTPHONE,
V18_MODE_V23VIDEOTEX,
V18_MODE_5BIT_50,
V18_MODE_DTMF,
V18_MODE_BELL103
},
{
/* Switzerland */
V18_MODE_EDT,
V18_MODE_V21TEXTPHONE,
V18_MODE_V23VIDEOTEX,
V18_MODE_5BIT_50,
V18_MODE_DTMF,
V18_MODE_BELL103
},
{
/* Italy */
V18_MODE_EDT,
V18_MODE_V21TEXTPHONE,
V18_MODE_V23VIDEOTEX,
V18_MODE_5BIT_50,
V18_MODE_DTMF,
V18_MODE_BELL103
},
{
/* Spain */
V18_MODE_EDT,
V18_MODE_V21TEXTPHONE,
V18_MODE_V23VIDEOTEX,
V18_MODE_5BIT_50,
V18_MODE_DTMF,
V18_MODE_BELL103
},
{
/* Austria */
V18_MODE_EDT,
V18_MODE_V21TEXTPHONE,
V18_MODE_V23VIDEOTEX,
V18_MODE_5BIT_50,
V18_MODE_DTMF,
V18_MODE_BELL103
},
{
/* Netherlands */
V18_MODE_DTMF,
V18_MODE_V21TEXTPHONE,
V18_MODE_V23VIDEOTEX,
V18_MODE_5BIT_50,
V18_MODE_EDT,
V18_MODE_BELL103
},
{
/* Iceland */
V18_MODE_V21TEXTPHONE,
V18_MODE_DTMF,
V18_MODE_5BIT_50,
V18_MODE_EDT,
V18_MODE_V23VIDEOTEX,
V18_MODE_BELL103
},
{
/* Norway */
V18_MODE_V21TEXTPHONE,
V18_MODE_DTMF,
V18_MODE_5BIT_50,
V18_MODE_EDT,
V18_MODE_V23VIDEOTEX,
V18_MODE_BELL103
},
{
/* Sweden */
V18_MODE_V21TEXTPHONE,
V18_MODE_DTMF,
V18_MODE_5BIT_50,
V18_MODE_EDT,
V18_MODE_V23VIDEOTEX,
V18_MODE_BELL103
},
{
/* Finland */
V18_MODE_V21TEXTPHONE,
V18_MODE_DTMF,
V18_MODE_5BIT_50,
V18_MODE_EDT,
V18_MODE_V23VIDEOTEX,
V18_MODE_BELL103
},
{
/* Denmark */
V18_MODE_V21TEXTPHONE,
V18_MODE_DTMF,
V18_MODE_5BIT_50,
V18_MODE_EDT,
V18_MODE_V23VIDEOTEX,
V18_MODE_BELL103
},
{
/* UK */
V18_MODE_V21TEXTPHONE,
V18_MODE_5BIT_50,
V18_MODE_V23VIDEOTEX,
V18_MODE_EDT,
V18_MODE_DTMF,
V18_MODE_BELL103
},
{
/* USA */
V18_MODE_5BIT_4545,
V18_MODE_BELL103,
V18_MODE_V21TEXTPHONE,
V18_MODE_V23VIDEOTEX,
V18_MODE_EDT,
V18_MODE_DTMF
},
{
/* France */
V18_MODE_V23VIDEOTEX,
V18_MODE_EDT,
V18_MODE_DTMF,
V18_MODE_5BIT_50,
V18_MODE_V21TEXTPHONE,
V18_MODE_BELL103
},
{
/* Belgium */
V18_MODE_V23VIDEOTEX,
V18_MODE_EDT,
V18_MODE_DTMF,
V18_MODE_5BIT_50,
V18_MODE_V21TEXTPHONE,
V18_MODE_BELL103
}
*u = '\0';
return u - msg;
}
/*- End of function --------------------------------------------------------*/
};
SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch)
static uint16_t encode_baudot(v18_state_t *s, uint8_t ch)
{
static const uint8_t conv[128] =
{
@ -449,7 +552,7 @@ SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch)
0xFF, /* ENQ */
0xFF, /* ACK */
0xFF, /* BEL */
0x00, /* BS */
0x40, /* BS */
0x44, /* HT >> SPACE */
0x42, /* LF */
0x42, /* VT >> LF */
@ -572,14 +675,7 @@ SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch)
};
uint16_t shift;
if (ch == 0x7F)
{
/* DLE is a special character meaning "force a
change to the letter character set */
shift = BAUDOT_LETTER_SHIFT;
return 0;
}
ch = conv[ch];
ch = conv[ch & 0x7F];
/* Is it a non-existant code? */
if (ch == 0xFF)
return 0;
@ -605,7 +701,7 @@ SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(uint8_t) v18_decode_baudot(v18_state_t *s, uint8_t ch)
static uint8_t decode_baudot(v18_state_t *s, uint8_t ch)
{
static const uint8_t conv[2][32] =
{
@ -624,8 +720,8 @@ SPAN_DECLARE(uint8_t) v18_decode_baudot(v18_state_t *s, uint8_t ch)
default:
return conv[s->baudot_rx_shift][ch];
}
/* return 0 if we did not produce a character */
return 0;
/* Return 0xFF if we did not produce a character */
return 0xFF;
}
/*- End of function --------------------------------------------------------*/
@ -649,7 +745,7 @@ static int v18_tdd_get_async_byte(void *user_data)
if (s->tx_signal_on)
{
/* The FSK should now be switched off. */
s->tx_signal_on = FALSE;
s->tx_signal_on = 0;
}
return 0x1F;
}
@ -659,14 +755,16 @@ static void v18_dtmf_get(void *user_data)
{
v18_state_t *s;
int ch;
const char *v;
int len;
const char *t;
s = (v18_state_t *) user_data;
if ((ch = queue_read_byte(&s->queue.queue)) >= 0)
{
v = ascii_to_dtmf[ch & 0x7F];
dtmf_tx_put(&s->dtmf_tx, v, strlen(v));
s->rx_suppression = ((300 + 100*strlen(v))*SAMPLE_RATE)/1000;
t = ascii_to_dtmf[ch & 0x7F];
len = strlen(t);
dtmf_tx_put(&s->dtmf_tx, t, len);
s->rx_suppression = ((300 + 100*len)*SAMPLE_RATE)/1000;
}
}
/*- End of function --------------------------------------------------------*/
@ -685,7 +783,7 @@ static int v18_edt_get_async_byte(void *user_data)
if (s->tx_signal_on)
{
/* The FSK should now be switched off. */
s->tx_signal_on = FALSE;
s->tx_signal_on = 0;
}
return 0;
}
@ -726,7 +824,7 @@ static void v18_tdd_put_async_byte(void *user_data, int byte)
return;
}
span_log(&s->logging, SPAN_LOG_FLOW, "Rx byte %x\n", byte);
if ((octet = v18_decode_baudot(s, byte)))
if ((octet = decode_baudot(s, byte)) != 0xFF)
s->rx_msg[s->rx_msg_len++] = octet;
if (s->rx_msg_len >= 256)
{
@ -738,11 +836,55 @@ static void v18_tdd_put_async_byte(void *user_data, int byte)
}
/*- End of function --------------------------------------------------------*/
static int decode_dtmf_cmp(const void *s, const void *t)
{
const char *ss;
struct dtmf_to_ascii_s *tt;
ss = (const char *) s;
tt = (struct dtmf_to_ascii_s *) t;
return strncmp(ss, tt->dtmf, strlen(tt->dtmf));
}
/*- End of function --------------------------------------------------------*/
static int decode_dtmf(v18_state_t *s, char msg[], const char dtmf[])
{
int entries;
int len;
const char *t;
char *u;
struct dtmf_to_ascii_s *ss;
entries = sizeof(dtmf_to_ascii)/sizeof(dtmf_to_ascii[0]) - 1;
t = dtmf;
u = msg;
while (*t)
{
ss = bsearch(t, dtmf_to_ascii, entries, sizeof(dtmf_to_ascii[0]), decode_dtmf_cmp);
if (ss)
{
len = strlen(ss->dtmf);
t += len;
*u++ = ss->ascii;
return len;
}
/* Can't match the code. Let's assume this is a code we just don't know, and skip over it */
while (*t == '#' || *t == '*')
t++;
if (*t)
t++;
}
*u = '\0';
return u - msg;
}
/*- End of function --------------------------------------------------------*/
static void v18_dtmf_put(void *user_data, const char dtmf[], int len)
{
v18_state_t *s;
char buf[128];
int i;
int matched;
s = (v18_state_t *) user_data;
if (s->rx_suppression > 0)
@ -753,11 +895,17 @@ static void v18_dtmf_put(void *user_data, const char dtmf[], int len)
if (dtmf[i] >= '0' && dtmf[i] <= '9')
{
s->rx_msg[s->rx_msg_len] = '\0';
if (v18_decode_dtmf(s, buf, (const char *) s->rx_msg) > 0)
if ((matched = decode_dtmf(s, buf, (const char *) s->rx_msg)) > 0)
{
buf[1] = '\0';
s->put_msg(s->user_data, (const uint8_t *) buf, 1);
s->rx_msg_len = 0;
}
if (s->rx_msg_len > matched)
memcpy(&s->rx_msg[0], &s->rx_msg[matched], s->rx_msg_len - matched);
s->rx_msg_len -= matched;
}
}
s->in_progress = 5*SAMPLE_RATE;
}
/*- End of function --------------------------------------------------------*/
@ -815,7 +963,7 @@ SPAN_DECLARE_NONSTD(int) v18_tx(v18_state_t *s, int16_t *amp, int max_len)
if (len < max_len)
{
if ((lenx = fsk_tx(&s->fsk_tx, amp + len, max_len - len)) <= 0)
s->tx_signal_on = FALSE;
s->tx_signal_on = 0;
len += lenx;
}
break;
@ -894,12 +1042,12 @@ SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len)
}
switch (s->mode)
{
case V18_MODE_5BIT_45:
case V18_MODE_5BIT_4545:
case V18_MODE_5BIT_50:
for (i = 0; i < len; i++)
{
n = 0;
if ((x = v18_encode_baudot(s, msg[i])))
if ((x = encode_baudot(s, msg[i])))
{
if ((x & 0x3E0))
buf[n++] = (uint8_t) ((x >> 5) & 0x1F);
@ -907,7 +1055,7 @@ SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len)
/* TODO: Deal with out of space condition */
if (queue_write(&s->queue.queue, (const uint8_t *) buf, n) < 0)
return i;
s->tx_signal_on = TRUE;
s->tx_signal_on = 1;
}
}
return len;
@ -920,12 +1068,14 @@ SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len)
SPAN_DECLARE(const char *) v18_mode_to_str(int mode)
{
switch ((mode & 0xFF))
switch ((mode & 0xFFF))
{
case V18_MODE_NONE:
return "None";
case V18_MODE_5BIT_45:
case V18_MODE_5BIT_4545:
return "Weitbrecht TDD (45.45bps)";
case V18_MODE_5BIT_476:
return "Weitbrecht TDD (47.6bps)";
case V18_MODE_5BIT_50:
return "Weitbrecht TDD (50bps)";
case V18_MODE_DTMF:
@ -958,6 +1108,9 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
put_msg_func_t put_msg,
void *user_data)
{
if (nation < 0 || nation >= V18_AUTOMODING_END)
return NULL;
if (s == NULL)
{
if ((s = (v18_state_t *) malloc(sizeof(*s))) == NULL)
@ -965,14 +1118,14 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
}
memset(s, 0, sizeof(*s));
s->calling_party = calling_party;
s->mode = mode & 0xFF;
s->mode = mode & ~V18_MODE_REPETITIVE_SHIFTS_OPTION;
s->put_msg = put_msg;
s->user_data = user_data;
switch (s->mode)
{
case V18_MODE_5BIT_45:
s->repeat_shifts = mode & 0x100;
case V18_MODE_5BIT_4545:
s->repeat_shifts = mode & V18_MODE_REPETITIVE_SHIFTS_OPTION;
fsk_tx_init(&s->fsk_tx, &preset_fsk_specs[FSK_WEITBRECHT_4545], async_tx_get_bit, &s->async_tx);
async_tx_init(&s->async_tx, 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
/* Schedule an explicit shift at the start of baudot transmission */
@ -983,8 +1136,20 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
s->baudot_rx_shift = 0;
s->next_byte = (uint8_t) 0xFF;
break;
case V18_MODE_5BIT_476:
s->repeat_shifts = mode & V18_MODE_REPETITIVE_SHIFTS_OPTION;
fsk_tx_init(&s->fsk_tx, &preset_fsk_specs[FSK_WEITBRECHT_476], async_tx_get_bit, &s->async_tx);
async_tx_init(&s->async_tx, 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
/* Schedule an explicit shift at the start of baudot transmission */
s->baudot_tx_shift = 2;
/* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
ride over the fraction. */
fsk_rx_init(&s->fsk_rx, &preset_fsk_specs[FSK_WEITBRECHT_476], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
s->baudot_rx_shift = 0;
s->next_byte = (uint8_t) 0xFF;
break;
case V18_MODE_5BIT_50:
s->repeat_shifts = mode & 0x100;
s->repeat_shifts = mode & V18_MODE_REPETITIVE_SHIFTS_OPTION;
fsk_tx_init(&s->fsk_tx, &preset_fsk_specs[FSK_WEITBRECHT_50], async_tx_get_bit, &s->async_tx);
async_tx_init(&s->async_tx, 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
/* Schedule an explicit shift at the start of baudot transmission */

View File

@ -70,49 +70,55 @@ LOCALTESTS_DIR=../test-data/local
# Colour/gray -> bilevel by not allowing ECM
for OPTS in "-p AA" "-p TT" "-p GG" "-p TG" "-p GT"
do
IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
OUT_FILE="${LOCALTESTS_DIR}/lenna-colour-bilevel.tif"
run_colour_fax_test
echo Colour to bi-level tests disabled
# IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
# OUT_FILE="${LOCALTESTS_DIR}/lenna-colour-bilevel.tif"
# run_colour_fax_test
IN_FILE="${LOCALTESTS_DIR}/lenna-bw.tif"
OUT_FILE="${LOCALTESTS_DIR}/lenna-bw-bilevel.tif"
run_colour_fax_test
# IN_FILE="${LOCALTESTS_DIR}/lenna-bw.tif"
# OUT_FILE="${LOCALTESTS_DIR}/lenna-bw-bilevel.tif"
# run_colour_fax_test
IN_FILE="${TIFFFX_DIR}/c03x_02x.tif"
OUT_FILE="${TIFFFX_DIR}/c03x_02x.tif"
run_colour_fax_test
# IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
# OUT_FILE="${LOCALTESTS_DIR}/lenna-bw-bilevel.tif"
# run_colour_fax_test
IN_FILE="${TIFFFX_DIR}/l02x_02x.tif"
OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif"
run_colour_fax_test
# IN_FILE="${TIFFFX_DIR}/c03x_02x.tif"
# OUT_FILE="${TIFFFX_DIR}/c03x_02x.tif"
# run_colour_fax_test
IN_FILE="${TIFFFX_DIR}/l04x_02x.tif"
OUT_FILE="${TIFFFX_DIR}/l04x_02x.tif"
run_colour_fax_test
# IN_FILE="${TIFFFX_DIR}/l02x_02x.tif"
# OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif"
# run_colour_fax_test
# IN_FILE="${TIFFFX_DIR}/l04x_02x.tif"
# OUT_FILE="${TIFFFX_DIR}/l04x_02x.tif"
# run_colour_fax_test
done
# Colour/gray -> colour/gray by allowing ECM
for OPTS in "-p AA -C -e" "-p TT -C -e" "-p GG -C -e" "-p TG -C -e" "-p GT -C -e"
do
IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
OUT_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
run_colour_fax_test
echo Colour to colour tests disabled
# IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
# OUT_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
# run_colour_fax_test
IN_FILE="${LOCALTESTS_DIR}/lenna-bw.tif"
OUT_FILE="${LOCALTESTS_DIR}/lenna-bw.tif"
run_colour_fax_test
# IN_FILE="${LOCALTESTS_DIR}/lenna-bw.tif"
# OUT_FILE="${LOCALTESTS_DIR}/lenna-bw.tif"
# run_colour_fax_test
IN_FILE="${TIFFFX_DIR}/c03x_02x.tif"
OUT_FILE="${TIFFFX_DIR}/c03x_02x.tif"
run_colour_fax_test
# IN_FILE="${TIFFFX_DIR}/c03x_02x.tif"
# OUT_FILE="${TIFFFX_DIR}/c03x_02x.tif"
# run_colour_fax_test
IN_FILE="${TIFFFX_DIR}/l02x_02x.tif"
OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif"
run_colour_fax_test
# IN_FILE="${TIFFFX_DIR}/l02x_02x.tif"
# OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif"
# run_colour_fax_test
IN_FILE="${TIFFFX_DIR}/l04x_02x.tif"
OUT_FILE="${TIFFFX_DIR}/l04x_02x.tif"
run_colour_fax_test
# IN_FILE="${TIFFFX_DIR}/l04x_02x.tif"
# OUT_FILE="${TIFFFX_DIR}/l04x_02x.tif"
# run_colour_fax_test
done
# Bi-level tests

File diff suppressed because it is too large Load Diff

View File

@ -150,11 +150,11 @@ static int get_v18_mode(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *var;
int r = V18_MODE_5BIT_45;
int r = V18_MODE_5BIT_4545;
if ((var = switch_channel_get_variable(channel, "v18_mode"))) {
if (!strcasecmp(var, "5BIT_45") || !strcasecmp(var, "baudot")) {
r = V18_MODE_5BIT_45;
r = V18_MODE_5BIT_4545;
} else if (!strcasecmp(var, "5BIT_50")) {
r = V18_MODE_5BIT_50;
} else if (!strcasecmp(var, "DTMF")) {