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(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(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); 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, V18_MODE_NONE = 0,
/* V.18 Annex A - Weitbrecht TDD at 45.45bps (US TTY), half-duplex, 5 bit baudot (USA). */ /* 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). */ /* V.18 Annex A - Weitbrecht TDD at 50bps (International TTY), half-duplex, 5 bit baudot (UK, Australia and others). */
V18_MODE_5BIT_50 = 2, V18_MODE_5BIT_50 = 2,
/* V.18 Annex B - DTMF encoding of ASCII (Denmark, Holland and others). */ /* V.18 Annex B - DTMF encoding of ASCII (Denmark, Holland and others). */
@ -55,6 +55,7 @@ enum
V18_MODE_V21TEXTPHONE = 7, V18_MODE_V21TEXTPHONE = 7,
/* V.18 Annex G - V.18 text telephone mode. */ /* V.18 Annex G - V.18 text telephone mode. */
V18_MODE_V18TEXTPHONE = 8, V18_MODE_V18TEXTPHONE = 8,
V18_MODE_5BIT_476 = 9,
/* Use repetitive shift characters where character set shifts are used */ /* Use repetitive shift characters where character set shifts are used */
V18_MODE_REPETITIVE_SHIFTS_OPTION = 0x1000 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. */ invalid, this function will return -1. */
SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len); 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 /*! \brief Return a short name for an V.18 mode
\param mode The code for the V.18 mode. \param mode The code for the V.18 mode.
\return A pointer to the name. \return A pointer to the name.

View File

@ -132,18 +132,19 @@ static const res_table_t y_res_table[] =
{ -1.00f, -1} { -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}, /* x = 100 102 200 204 300 400 408 600 1200 */
{T4_RESOLUTION_100_100, 0, T4_RESOLUTION_200_100, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, T4_RESOLUTION_R8_STANDARD, 0, 0, 0, 0, 0}, /* y = 3.85/mm */
{ 0, 0, 0, T4_RESOLUTION_R8_FINE, 0, 0, 0, 0, 0, 0}, {T4_RESOLUTION_100_100, 0, T4_RESOLUTION_200_100, 0, 0, 0, 0, 0, 0}, /* y = 100 */
{ 0, 0, T4_RESOLUTION_200_200, 0, 0, 0, 0, 0, 0, 0}, { 0, 0, 0, T4_RESOLUTION_R8_FINE, 0, 0, 0, 0, 0}, /* y = 7.7/mm */
{ 0, 0, 0, 0, T4_RESOLUTION_300_300, 0, 0, 0, 0, 0}, { 0, 0, T4_RESOLUTION_200_200, 0, 0, 0, 0, 0, 0}, /* y = 200 */
{ 0, 0, 0, T4_RESOLUTION_R8_SUPERFINE, 0, 0, T4_RESOLUTION_R16_SUPERFINE, 0, 0, 0}, { 0, 0, 0, 0, T4_RESOLUTION_300_300, 0, 0, 0, 0}, /* y = 300 */
{ 0, 0, T4_RESOLUTION_200_400, 0, 0, T4_RESOLUTION_400_400, 0, 0, 0, 0}, { 0, 0, 0, T4_RESOLUTION_R8_SUPERFINE, 0, 0, T4_RESOLUTION_R16_SUPERFINE, 0, 0}, /* y = 154/mm */
{ 0, 0, 0, 0, T4_RESOLUTION_300_600, 0, 0, T4_RESOLUTION_600_600, 0, 0}, { 0, 0, T4_RESOLUTION_200_400, 0, 0, T4_RESOLUTION_400_400, 0, 0, 0}, /* y = 400 */
{ 0, 0, 0, 0, 0, T4_RESOLUTION_400_800, 0, 0, 0, 0}, { 0, 0, 0, 0, T4_RESOLUTION_300_600, 0, 0, T4_RESOLUTION_600_600, 0}, /* y = 600 */
{ 0, 0, 0, 0, 0, 0, 0, T4_RESOLUTION_600_1200, 0, T4_RESOLUTION_1200_1200}, { 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) #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_type = s->tiff.image_type;
t->image_width = s->tiff.image_width; t->image_width = s->tiff.image_width;
t->image_length = s->tiff.image_length; t->image_length = s->tiff.image_length;
t->image_x_resolution = s->tiff.x_resolution; t->image_x_resolution = s->tiff.x_resolution;
t->image_y_resolution = s->tiff.y_resolution; t->image_y_resolution = s->tiff.y_resolution;
t->x_resolution = s->metadata.x_resolution; t->x_resolution = s->metadata.x_resolution;
t->y_resolution = s->metadata.y_resolution/s->row_squashing_ratio; t->y_resolution = s->metadata.y_resolution/s->row_squashing_ratio;
t->compression = s->metadata.compression; t->compression = s->metadata.compression;
switch (s->metadata.compression) switch (s->metadata.compression)
{ {
case T4_COMPRESSION_T4_1D: 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); return t85_encode_image_complete(&s->encoder.t85);
#if defined(SPANDSP_SUPPORT_T88) #if defined(SPANDSP_SUPPORT_T88)
case T4_COMPRESSION_T88: case T4_COMPRESSION_T88:
break; return t88_encode_image_complete(&s->encoder.t88);
#endif #endif
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
case T4_COMPRESSION_SYCC_T81: case T4_COMPRESSION_SYCC_T81:
@ -1428,7 +1431,7 @@ SPAN_DECLARE(int) t4_tx_image_complete(t4_tx_state_t *s)
#endif #endif
#if defined(SPANDSP_SUPPORT_T45) #if defined(SPANDSP_SUPPORT_T45)
case T4_COMPRESSION_T45: case T4_COMPRESSION_T45:
break; return t45_encode_image_complete(&s->encoder.t45);
#endif #endif
} }
return SIG_STATUS_END_OF_DATA; 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) 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) switch (s->metadata.compression)
{ {
case T4_COMPRESSION_T4_1D: 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; break;
#endif #endif
} }
#endif
return 0; return 0;
} }
/*- End of function --------------------------------------------------------*/ /*- 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_T4_2D:
case T4_COMPRESSION_T6: case T4_COMPRESSION_T6:
t4_t6_encode_restart(&s->encoder.t4_t6, s->metadata.image_width, s->metadata.image_length); 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; break;
case T4_COMPRESSION_T85: case T4_COMPRESSION_T85:
case T4_COMPRESSION_T85_L0: case T4_COMPRESSION_T85_L0:
t85_encode_restart(&s->encoder.t85, s->metadata.image_width, s->metadata.image_length); 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; break;
#if defined(SPANDSP_SUPPORT_T88) #if defined(SPANDSP_SUPPORT_T88)
case T4_COMPRESSION_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; break;
#endif #endif
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
case T4_COMPRESSION_SYCC_T81: case T4_COMPRESSION_SYCC_T81:
t42_encode_restart(&s->encoder.t42, s->metadata.image_width, s->metadata.image_length); 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; break;
#if defined(SPANDSP_SUPPORT_T43) #if defined(SPANDSP_SUPPORT_T43)
case T4_COMPRESSION_T43: case T4_COMPRESSION_T43:
t43_encode_restart(&s->encoder.t43, s->metadata.image_width, s->metadata.image_length); 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; break;
#endif #endif
#if defined(SPANDSP_SUPPORT_T45) #if defined(SPANDSP_SUPPORT_T45)
case T4_COMPRESSION_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; break;
#endif #endif
default:
s->image_get_handler = NULL;
break;
} }
/* If there is a page header, create that first */ /* 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; s->header_row = 0;
set_row_read_handler(s, header_row_read_handler, (void *) s); 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); return t85_encode_release(&s->encoder.t85);
#if defined(SPANDSP_SUPPORT_T88) #if defined(SPANDSP_SUPPORT_T88)
case T4_COMPRESSION_T88: case T4_COMPRESSION_T88:
break; return t88_encode_release(&s->encoder.t88);
#endif #endif
case T4_COMPRESSION_T42_T81: case T4_COMPRESSION_T42_T81:
case T4_COMPRESSION_SYCC_T81: case T4_COMPRESSION_SYCC_T81:
@ -1645,7 +1675,7 @@ SPAN_DECLARE(int) t4_tx_release(t4_tx_state_t *s)
#endif #endif
#if defined(SPANDSP_SUPPORT_T45) #if defined(SPANDSP_SUPPORT_T45)
case T4_COMPRESSION_T45: case T4_COMPRESSION_T45:
break; return t45_encode_release(&s->encoder.t45);
#endif #endif
} }
return -1; return -1;

View File

@ -78,13 +78,13 @@
Silence for 0.5s then send TXP Silence for 0.5s then send TXP
DTMF DTMF
Proceed as Annex B Proceed as Annex B
1650Hz (V21 ch 2 low) 1650Hz (V21 ch 2 low) [1650Hz +-12Hz]
Proceed as Annex F in call mode Proceed as Annex F in call mode
1300Hz (Calling tone) 1300Hz (Calling tone) [1300Hz +-16Hz]
Proceed as Annex E in call mode 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 Detect rate and proceed as Annex A
980Hz/1180Hz (V21 ch 1) 980Hz/1180Hz (V21 ch 1) [980Hz +-12Hz, 1180Hz +-12Hz]
Start timer Tr Start timer Tr
2225Hz (Bell ANS) 2225Hz (Bell ANS)
Proceed as Annex D call mode Proceed as Annex D call mode
@ -98,21 +98,21 @@
Monitor as caller for 980Hz or 1300Hz Monitor as caller for 980Hz or 1300Hz
CI/XCI CI/XCI
Respond with ANSam Respond with ANSam
1300Hz 1300Hz [1300Hz +-16Hz]
Probe Probe
Timer Ta (3s) Timer Ta (3s)
Probe Probe
1400Hz/1800Hz (Weitbrecht) 1400Hz/1800Hz (Weitbrecht) [1400Hz +-5% and 1800Hz +-5%]
Detect rate and proceed as Annex A Detect rate and proceed as Annex A
DTMF DTMF
Proceed as Annex B Proceed as Annex B
980Hz (V21 ch 1 low) 980Hz (V21 ch 1 low) [980Hz +-12Hz]
Start timer Te Start timer Te
1270Hz (Bell103 ch 2 high) 1270Hz (Bell103 ch 2 high)
Proceed as Annex D answer mode Proceed as Annex D answer mode
2225Hz (Bell ANS) 2225Hz (Bell ANS)
Proceed as Annex D call mode Proceed as Annex D call mode
1650Hz (V21 ch 2 low) 1650Hz (V21 ch 2 low) [1650Hz +-12Hz]
Proceed as Annex F answer mode Proceed as Annex F answer mode
ANSam ANSam
Proceed as V.8 caller Annex G 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[] = static const struct dtmf_to_ascii_s dtmf_to_ascii[] =
{ {
{"###0", '!'},
{"###1", 'C'}, {"###1", 'C'},
{"###2", 'F'}, {"###2", 'F'},
{"###3", 'I'}, {"###3", 'I'},
@ -140,7 +141,6 @@ static const struct dtmf_to_ascii_s dtmf_to_ascii[] =
{"###7", 'U'}, {"###7", 'U'},
{"###8", 'X'}, {"###8", 'X'},
{"###9", ';'}, {"###9", ';'},
{"###0", '!'},
{"##*1", 'A'}, {"##*1", 'A'},
{"##*2", 'D'}, {"##*2", 'D'},
{"##*3", 'G'}, {"##*3", 'G'},
@ -373,71 +373,174 @@ static const uint8_t txp[] = "1111111111000101011100001101110000010101";
100 ms mark. */ 100 ms mark. */
static const uint8_t xci[] = "01111111110111111111"; 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; /* Dummy entry 0 */
const char *v; V18_MODE_5BIT_4545,
char *u; V18_MODE_BELL103,
V18_MODE_V21TEXTPHONE,
t = msg; V18_MODE_V23VIDEOTEX,
u = dtmf; V18_MODE_EDT,
while (*t) V18_MODE_DTMF
},
{ {
v = ascii_to_dtmf[*t & 0x7F]; /* Australia */
while (*v) V18_MODE_5BIT_50,
*u++ = *v++; V18_MODE_V21TEXTPHONE,
t++; V18_MODE_V23VIDEOTEX,
} V18_MODE_EDT,
*u = '\0'; V18_MODE_DTMF,
V18_MODE_BELL103
return u - dtmf; },
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) v18_decode_dtmf(v18_state_t *s, char msg[], const char dtmf[])
{ {
int entries; /* Ireland */
const char *t; V18_MODE_5BIT_50,
char *u; V18_MODE_V21TEXTPHONE,
struct dtmf_to_ascii_s *ss; 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
}
};
entries = sizeof(dtmf_to_ascii)/sizeof(dtmf_to_ascii[0]) - 1; static uint16_t encode_baudot(v18_state_t *s, uint8_t ch)
t = dtmf;
u = msg;
while (*t)
{
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++;
}
}
*u = '\0';
return u - msg;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch)
{ {
static const uint8_t conv[128] = 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, /* ENQ */
0xFF, /* ACK */ 0xFF, /* ACK */
0xFF, /* BEL */ 0xFF, /* BEL */
0x00, /* BS */ 0x40, /* BS */
0x44, /* HT >> SPACE */ 0x44, /* HT >> SPACE */
0x42, /* LF */ 0x42, /* LF */
0x42, /* VT >> 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; uint16_t shift;
if (ch == 0x7F) ch = conv[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];
/* Is it a non-existant code? */ /* Is it a non-existant code? */
if (ch == 0xFF) if (ch == 0xFF)
return 0; return 0;
@ -605,7 +701,7 @@ SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch)
} }
/*- End of function --------------------------------------------------------*/ /*- 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] = 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: default:
return conv[s->baudot_rx_shift][ch]; return conv[s->baudot_rx_shift][ch];
} }
/* return 0 if we did not produce a character */ /* Return 0xFF if we did not produce a character */
return 0; return 0xFF;
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -649,7 +745,7 @@ static int v18_tdd_get_async_byte(void *user_data)
if (s->tx_signal_on) if (s->tx_signal_on)
{ {
/* The FSK should now be switched off. */ /* The FSK should now be switched off. */
s->tx_signal_on = FALSE; s->tx_signal_on = 0;
} }
return 0x1F; return 0x1F;
} }
@ -659,14 +755,16 @@ static void v18_dtmf_get(void *user_data)
{ {
v18_state_t *s; v18_state_t *s;
int ch; int ch;
const char *v; int len;
const char *t;
s = (v18_state_t *) user_data; s = (v18_state_t *) user_data;
if ((ch = queue_read_byte(&s->queue.queue)) >= 0) if ((ch = queue_read_byte(&s->queue.queue)) >= 0)
{ {
v = ascii_to_dtmf[ch & 0x7F]; t = ascii_to_dtmf[ch & 0x7F];
dtmf_tx_put(&s->dtmf_tx, v, strlen(v)); len = strlen(t);
s->rx_suppression = ((300 + 100*strlen(v))*SAMPLE_RATE)/1000; dtmf_tx_put(&s->dtmf_tx, t, len);
s->rx_suppression = ((300 + 100*len)*SAMPLE_RATE)/1000;
} }
} }
/*- End of function --------------------------------------------------------*/ /*- End of function --------------------------------------------------------*/
@ -685,7 +783,7 @@ static int v18_edt_get_async_byte(void *user_data)
if (s->tx_signal_on) if (s->tx_signal_on)
{ {
/* The FSK should now be switched off. */ /* The FSK should now be switched off. */
s->tx_signal_on = FALSE; s->tx_signal_on = 0;
} }
return 0; return 0;
} }
@ -726,7 +824,7 @@ static void v18_tdd_put_async_byte(void *user_data, int byte)
return; return;
} }
span_log(&s->logging, SPAN_LOG_FLOW, "Rx byte %x\n", byte); 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; s->rx_msg[s->rx_msg_len++] = octet;
if (s->rx_msg_len >= 256) 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 --------------------------------------------------------*/ /*- 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) static void v18_dtmf_put(void *user_data, const char dtmf[], int len)
{ {
v18_state_t *s; v18_state_t *s;
char buf[128]; char buf[128];
int i; int i;
int matched;
s = (v18_state_t *) user_data; s = (v18_state_t *) user_data;
if (s->rx_suppression > 0) 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') if (dtmf[i] >= '0' && dtmf[i] <= '9')
{ {
s->rx_msg[s->rx_msg_len] = '\0'; 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->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 --------------------------------------------------------*/ /*- 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 (len < max_len)
{ {
if ((lenx = fsk_tx(&s->fsk_tx, amp + len, max_len - len)) <= 0) 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; len += lenx;
} }
break; break;
@ -894,12 +1042,12 @@ SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len)
} }
switch (s->mode) switch (s->mode)
{ {
case V18_MODE_5BIT_45: case V18_MODE_5BIT_4545:
case V18_MODE_5BIT_50: case V18_MODE_5BIT_50:
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
n = 0; n = 0;
if ((x = v18_encode_baudot(s, msg[i]))) if ((x = encode_baudot(s, msg[i])))
{ {
if ((x & 0x3E0)) if ((x & 0x3E0))
buf[n++] = (uint8_t) ((x >> 5) & 0x1F); 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 */ /* TODO: Deal with out of space condition */
if (queue_write(&s->queue.queue, (const uint8_t *) buf, n) < 0) if (queue_write(&s->queue.queue, (const uint8_t *) buf, n) < 0)
return i; return i;
s->tx_signal_on = TRUE; s->tx_signal_on = 1;
} }
} }
return len; 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) SPAN_DECLARE(const char *) v18_mode_to_str(int mode)
{ {
switch ((mode & 0xFF)) switch ((mode & 0xFFF))
{ {
case V18_MODE_NONE: case V18_MODE_NONE:
return "None"; return "None";
case V18_MODE_5BIT_45: case V18_MODE_5BIT_4545:
return "Weitbrecht TDD (45.45bps)"; return "Weitbrecht TDD (45.45bps)";
case V18_MODE_5BIT_476:
return "Weitbrecht TDD (47.6bps)";
case V18_MODE_5BIT_50: case V18_MODE_5BIT_50:
return "Weitbrecht TDD (50bps)"; return "Weitbrecht TDD (50bps)";
case V18_MODE_DTMF: 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, put_msg_func_t put_msg,
void *user_data) void *user_data)
{ {
if (nation < 0 || nation >= V18_AUTOMODING_END)
return NULL;
if (s == NULL) if (s == NULL)
{ {
if ((s = (v18_state_t *) malloc(sizeof(*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)); memset(s, 0, sizeof(*s));
s->calling_party = calling_party; s->calling_party = calling_party;
s->mode = mode & 0xFF; s->mode = mode & ~V18_MODE_REPETITIVE_SHIFTS_OPTION;
s->put_msg = put_msg; s->put_msg = put_msg;
s->user_data = user_data; s->user_data = user_data;
switch (s->mode) switch (s->mode)
{ {
case V18_MODE_5BIT_45: case V18_MODE_5BIT_4545:
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_4545], async_tx_get_bit, &s->async_tx); 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); 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 */ /* 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->baudot_rx_shift = 0;
s->next_byte = (uint8_t) 0xFF; s->next_byte = (uint8_t) 0xFF;
break; 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: 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); 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); 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 */ /* 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 # Colour/gray -> bilevel by not allowing ECM
for OPTS in "-p AA" "-p TT" "-p GG" "-p TG" "-p GT" for OPTS in "-p AA" "-p TT" "-p GG" "-p TG" "-p GT"
do do
IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif" echo Colour to bi-level tests disabled
OUT_FILE="${LOCALTESTS_DIR}/lenna-colour-bilevel.tif" # IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
run_colour_fax_test # OUT_FILE="${LOCALTESTS_DIR}/lenna-colour-bilevel.tif"
# run_colour_fax_test
IN_FILE="${LOCALTESTS_DIR}/lenna-bw.tif" # IN_FILE="${LOCALTESTS_DIR}/lenna-bw.tif"
OUT_FILE="${LOCALTESTS_DIR}/lenna-bw-bilevel.tif" # OUT_FILE="${LOCALTESTS_DIR}/lenna-bw-bilevel.tif"
run_colour_fax_test # run_colour_fax_test
IN_FILE="${TIFFFX_DIR}/c03x_02x.tif" # IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
OUT_FILE="${TIFFFX_DIR}/c03x_02x.tif" # OUT_FILE="${LOCALTESTS_DIR}/lenna-bw-bilevel.tif"
run_colour_fax_test # run_colour_fax_test
IN_FILE="${TIFFFX_DIR}/l02x_02x.tif" # IN_FILE="${TIFFFX_DIR}/c03x_02x.tif"
OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif" # OUT_FILE="${TIFFFX_DIR}/c03x_02x.tif"
run_colour_fax_test # run_colour_fax_test
IN_FILE="${TIFFFX_DIR}/l04x_02x.tif" # IN_FILE="${TIFFFX_DIR}/l02x_02x.tif"
OUT_FILE="${TIFFFX_DIR}/l04x_02x.tif" # OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif"
run_colour_fax_test # run_colour_fax_test
# IN_FILE="${TIFFFX_DIR}/l04x_02x.tif"
# OUT_FILE="${TIFFFX_DIR}/l04x_02x.tif"
# run_colour_fax_test
done done
# Colour/gray -> colour/gray by allowing ECM # 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" for OPTS in "-p AA -C -e" "-p TT -C -e" "-p GG -C -e" "-p TG -C -e" "-p GT -C -e"
do do
IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif" echo Colour to colour tests disabled
OUT_FILE="${LOCALTESTS_DIR}/lenna-colour.tif" # IN_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
run_colour_fax_test # OUT_FILE="${LOCALTESTS_DIR}/lenna-colour.tif"
# run_colour_fax_test
IN_FILE="${LOCALTESTS_DIR}/lenna-bw.tif" # IN_FILE="${LOCALTESTS_DIR}/lenna-bw.tif"
OUT_FILE="${LOCALTESTS_DIR}/lenna-bw.tif" # OUT_FILE="${LOCALTESTS_DIR}/lenna-bw.tif"
run_colour_fax_test # run_colour_fax_test
IN_FILE="${TIFFFX_DIR}/c03x_02x.tif" # IN_FILE="${TIFFFX_DIR}/c03x_02x.tif"
OUT_FILE="${TIFFFX_DIR}/c03x_02x.tif" # OUT_FILE="${TIFFFX_DIR}/c03x_02x.tif"
run_colour_fax_test # run_colour_fax_test
IN_FILE="${TIFFFX_DIR}/l02x_02x.tif" # IN_FILE="${TIFFFX_DIR}/l02x_02x.tif"
OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif" # OUT_FILE="${TIFFFX_DIR}/l02x_02x.tif"
run_colour_fax_test # run_colour_fax_test
IN_FILE="${TIFFFX_DIR}/l04x_02x.tif" # IN_FILE="${TIFFFX_DIR}/l04x_02x.tif"
OUT_FILE="${TIFFFX_DIR}/l04x_02x.tif" # OUT_FILE="${TIFFFX_DIR}/l04x_02x.tif"
run_colour_fax_test # run_colour_fax_test
done done
# Bi-level tests # 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); switch_channel_t *channel = switch_core_session_get_channel(session);
const char *var; 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 ((var = switch_channel_get_variable(channel, "v18_mode"))) {
if (!strcasecmp(var, "5BIT_45") || !strcasecmp(var, "baudot")) { if (!strcasecmp(var, "5BIT_45") || !strcasecmp(var, "baudot")) {
r = V18_MODE_5BIT_45; r = V18_MODE_5BIT_4545;
} else if (!strcasecmp(var, "5BIT_50")) { } else if (!strcasecmp(var, "5BIT_50")) {
r = V18_MODE_5BIT_50; r = V18_MODE_5BIT_50;
} else if (!strcasecmp(var, "DTMF")) { } else if (!strcasecmp(var, "DTMF")) {