From ac9656015acfb35152e5a56c33b515131bb26f48 Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Sun, 26 Aug 2012 19:30:42 +0800 Subject: [PATCH] More fax modem tweaks --- libs/spandsp/src/spandsp/image_translate.h | 5 + libs/spandsp/src/spandsp/private/fax_modems.h | 6 + .../spandsp/src/spandsp/private/t38_gateway.h | 4 - libs/spandsp/src/spandsp/private/t85.h | 2 +- libs/spandsp/src/spandsp/t85.h | 12 ++ libs/spandsp/src/t38_gateway.c | 113 ++++++++---------- libs/spandsp/src/t4_tx.c | 9 +- 7 files changed, 74 insertions(+), 77 deletions(-) diff --git a/libs/spandsp/src/spandsp/image_translate.h b/libs/spandsp/src/spandsp/image_translate.h index 7f91c2db0a..d98848f369 100644 --- a/libs/spandsp/src/spandsp/image_translate.h +++ b/libs/spandsp/src/spandsp/image_translate.h @@ -34,6 +34,11 @@ /*! \page image_translate_page Image translation \section image_translate_page_sec_1 What does it do? +The image translate functions allow an image to be translated and resized between +various colour an monochrome formats. It also allows a colour or gray-scale image +to be reduced to a bi-level monochrome image. This is useful for preparing images +to be sent as traditional bi-level FAX pages. + \section image_translate_page_sec_2 How does it work? \section image_translate_page_sec_3 How do I use it? diff --git a/libs/spandsp/src/spandsp/private/fax_modems.h b/libs/spandsp/src/spandsp/private/fax_modems.h index e9adaa47b6..b0df18c00c 100644 --- a/libs/spandsp/src/spandsp/private/fax_modems.h +++ b/libs/spandsp/src/spandsp/private/fax_modems.h @@ -115,9 +115,15 @@ struct fax_modems_state_s /*! \brief The current receive signal handler */ span_rx_handler_t rx_handler; + /*! \brief The current receive signal handler. Actual receiving hops between this + and a dummy receive routine. */ + span_rx_handler_t base_rx_handler; void *rx_user_data; /*! \brief The current receive missing signal fill-in handler */ span_rx_fillin_handler_t rx_fillin_handler; + /*! \brief The current receive signal fillin handler. Actual receiving hops between this + and a dummy receive routine. */ + span_rx_fillin_handler_t base_rx_fillin_handler; void *rx_fillin_user_data; /*! \brief The current transmit signal handler */ diff --git a/libs/spandsp/src/spandsp/private/t38_gateway.h b/libs/spandsp/src/spandsp/private/t38_gateway.h index af72e78213..fbe1409322 100644 --- a/libs/spandsp/src/spandsp/private/t38_gateway.h +++ b/libs/spandsp/src/spandsp/private/t38_gateway.h @@ -59,10 +59,6 @@ typedef struct { /*! \brief The FAX modem set for the audio side fo the gateway. */ fax_modems_state_t modems; - /*! \brief The current receive signal handler. Actual receiving hops between this - and a dummy receive routine. */ - span_rx_handler_t base_rx_handler; - span_rx_fillin_handler_t base_rx_fillin_handler; } t38_gateway_audio_state_t; /*! diff --git a/libs/spandsp/src/spandsp/private/t85.h b/libs/spandsp/src/spandsp/private/t85.h index 2d180c9baf..c3e62e8c83 100644 --- a/libs/spandsp/src/spandsp/private/t85.h +++ b/libs/spandsp/src/spandsp/private/t85.h @@ -62,7 +62,7 @@ struct t85_encode_state_s uint32_t xd; /*! The height of the full image, in pixels */ uint32_t yd; - /*! Then number of rows per stripe */ + /*! The number of rows per stripe */ uint32_t l0; /*! Maximum ATMOVE window size (0 - 127) */ int mx; diff --git a/libs/spandsp/src/spandsp/t85.h b/libs/spandsp/src/spandsp/t85.h index d599626eed..07dd88931f 100644 --- a/libs/spandsp/src/spandsp/t85.h +++ b/libs/spandsp/src/spandsp/t85.h @@ -87,6 +87,12 @@ SPAN_DECLARE(int) t85_encode_set_row_read_handler(t85_encode_state_t *s, t4_row_read_handler_t handler, void *user_data); +/*! Get the logging context associated with a T.85 encode context. + \brief Get the logging context associated with a T.85 encode context. + \param s The T.85 encode context. + \return A pointer to the logging context */ +SPAN_DECLARE(logging_state_t *) t85_encode_get_logging_state(t85_encode_state_t *s); + /*! \brief Prepare to encode an image in T.85 format. \param s The T.85 context. \param image_width Image width, in pixels. @@ -164,6 +170,12 @@ SPAN_DECLARE(int) t85_encode_get_compressed_image_size(t85_encode_state_t *s); \param s The T.85 context. */ SPAN_DECLARE(void) t85_encode_abort(t85_encode_state_t *s); +/*! Get the logging context associated with a T.85 decode context. + \brief Get the logging context associated with a T.85 decode context. + \param s The T.85 decode context. + \return A pointer to the logging context */ +SPAN_DECLARE(logging_state_t *) t85_decode_get_logging_state(t85_decode_state_t *s); + /*! \brief Prepare to decode an image in T.85 format. \param s The T.85 context. \param handler A callback routine to handle decoded image rows. diff --git a/libs/spandsp/src/t38_gateway.c b/libs/spandsp/src/t38_gateway.c index 570cbdc625..a4a5873e52 100644 --- a/libs/spandsp/src/t38_gateway.c +++ b/libs/spandsp/src/t38_gateway.c @@ -196,43 +196,31 @@ static void non_ecm_remove_fill_and_put_bit(void *user_data, int bit); static void non_ecm_push_residue(t38_gateway_state_t *s); static void tone_detected(void *user_data, int tone, int level, int delay); -static void set_rx_handler(t38_gateway_state_t *s, +static void set_rx_handler(fax_modems_state_t *s, span_rx_handler_t handler, void *user_data, span_rx_fillin_handler_t fillin_handler, - void *rx_fillin_user_data) + void *fillin_user_data) { - if (s->audio.modems.rx_handler != span_dummy_rx) - { - s->audio.modems.rx_handler = handler; - s->audio.modems.rx_fillin_handler = fillin_handler; - } + /* Only update the actual handlers if they are not currently sidelined to dummy targets */ + if (s->rx_handler != span_dummy_rx) + s->rx_handler = handler; /*endif*/ - s->audio.base_rx_handler = handler; - s->audio.base_rx_fillin_handler = fillin_handler; - s->audio.modems.rx_user_data = user_data; - s->audio.modems.rx_fillin_user_data = rx_fillin_user_data; -} -/*- End of function --------------------------------------------------------*/ + s->base_rx_handler = handler; + s->rx_user_data = user_data; -static void set_tx_handler(t38_gateway_state_t *s, span_tx_handler_t handler, void *user_data) -{ - s->audio.modems.tx_handler = handler; - s->audio.modems.tx_user_data = user_data; -} -/*- End of function --------------------------------------------------------*/ - -static void set_next_tx_handler(t38_gateway_state_t *s, span_tx_handler_t handler, void *user_data) -{ - s->audio.modems.next_tx_handler = handler; - s->audio.modems.next_tx_user_data = user_data; + if (s->rx_fillin_handler != span_dummy_rx_fillin) + s->rx_fillin_handler = fillin_handler; + /*endif*/ + s->base_rx_fillin_handler = fillin_handler; + s->rx_fillin_user_data = fillin_user_data; } /*- End of function --------------------------------------------------------*/ static void set_rx_active(t38_gateway_state_t *s, int active) { - s->audio.modems.rx_handler = (active) ? s->audio.base_rx_handler : span_dummy_rx; - s->audio.modems.rx_fillin_handler = (active) ? s->audio.base_rx_fillin_handler : span_dummy_rx_fillin; + s->audio.modems.rx_handler = (active) ? s->audio.modems.base_rx_handler : span_dummy_rx; + s->audio.modems.rx_fillin_handler = (active) ? s->audio.modems.base_rx_fillin_handler : span_dummy_rx_fillin; } /*- End of function --------------------------------------------------------*/ @@ -259,18 +247,17 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len) v17_rx(&s->fast_modems.v17_rx, amp, len); if (s->rx_trained) { - /* The fast modem has trained, so we no longer need to run the slow - one in parallel. */ - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->fast_modems.v17_rx)); - set_rx_handler(t, (span_rx_handler_t) &v17_rx, &s->fast_modems.v17_rx, (span_rx_fillin_handler_t) &v17_rx_fillin, &s->fast_modems.v17_rx); + /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ + span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->fast_modems.v17_rx)); + set_rx_handler(s, (span_rx_handler_t) &v17_rx, &s->fast_modems.v17_rx, (span_rx_fillin_handler_t) &v17_rx_fillin, &s->fast_modems.v17_rx); } else { fsk_rx(&s->v21_rx, amp, len); if (s->rx_signal_present) { - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); - set_rx_handler(t, (span_rx_handler_t) &fsk_rx, &s->v21_rx, (span_rx_fillin_handler_t) &fsk_rx_fillin, &s->v21_rx); + span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); + set_rx_handler(s, (span_rx_handler_t) &fsk_rx, &s->v21_rx, (span_rx_fillin_handler_t) &fsk_rx_fillin, &s->v21_rx); } /*endif*/ } @@ -302,18 +289,17 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len) v27ter_rx(&s->fast_modems.v27ter_rx, amp, len); if (s->rx_trained) { - /* The fast modem has trained, so we no longer need to run the slow - one in parallel. */ - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->fast_modems.v27ter_rx)); - set_rx_handler(t, (span_rx_handler_t) &v27ter_rx, &s->fast_modems.v27ter_rx, (span_rx_fillin_handler_t) &v27ter_v21_rx_fillin, &s->fast_modems.v27ter_rx); + /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ + span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->fast_modems.v27ter_rx)); + set_rx_handler(s, (span_rx_handler_t) &v27ter_rx, &s->fast_modems.v27ter_rx, (span_rx_fillin_handler_t) &v27ter_v21_rx_fillin, &s->fast_modems.v27ter_rx); } else { fsk_rx(&s->v21_rx, amp, len); if (s->rx_signal_present) { - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); - set_rx_handler(t, (span_rx_handler_t) &fsk_rx, &s->v21_rx, (span_rx_fillin_handler_t) &fsk_rx_fillin, &s->v21_rx); + span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); + set_rx_handler(s, (span_rx_handler_t) &fsk_rx, &s->v21_rx, (span_rx_fillin_handler_t) &fsk_rx_fillin, &s->v21_rx); } /*endif*/ } @@ -345,18 +331,17 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len) v29_rx(&s->fast_modems.v29_rx, amp, len); if (s->rx_trained) { - /* The fast modem has trained, so we no longer need to run the slow - one in parallel. */ - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->fast_modems.v29_rx)); - set_rx_handler(t, (span_rx_handler_t) &v29_rx, &s->fast_modems.v29_rx, (span_rx_fillin_handler_t) &v29_rx_fillin, &s->fast_modems.v29_rx); + /* The fast modem has trained, so we no longer need to run the slow one in parallel. */ + span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->fast_modems.v29_rx)); + set_rx_handler(s, (span_rx_handler_t) &v29_rx, &s->fast_modems.v29_rx, (span_rx_fillin_handler_t) &v29_rx_fillin, &s->fast_modems.v29_rx); } else { fsk_rx(&s->v21_rx, amp, len); if (s->rx_signal_present) { - span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); - set_rx_handler(t, (span_rx_handler_t) &fsk_rx, &s->v21_rx, (span_rx_fillin_handler_t) &fsk_rx_fillin, &s->v21_rx); + span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx)); + set_rx_handler(s, (span_rx_handler_t) &fsk_rx, &s->v21_rx, (span_rx_fillin_handler_t) &fsk_rx_fillin, &s->v21_rx); } /*endif*/ } @@ -434,8 +419,8 @@ static int set_next_tx_type(t38_gateway_state_t *s) if (t->next_tx_handler) { /* There is a handler queued, so that is the next one. */ - set_tx_handler(s, t->next_tx_handler, t->next_tx_user_data); - set_next_tx_handler(s, NULL, NULL); + fax_modems_set_tx_handler(t, t->next_tx_handler, t->next_tx_user_data); + fax_modems_set_next_tx_handler(t, NULL, NULL); if (t->tx_handler == (span_tx_handler_t) &silence_gen || t->tx_handler == (span_tx_handler_t) &tone_gen) @@ -485,23 +470,23 @@ static int set_next_tx_type(t38_gateway_state_t *s) t->tx_bit_rate = 0; /* Impose 75ms minimum on transmitted silence */ //silence_gen_set(&t->silence_gen, ms_to_samples(75)); - set_tx_handler(s, (span_tx_handler_t) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t) NULL, NULL); + fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(t, (span_tx_handler_t) NULL, NULL); set_rx_active(s, TRUE); break; case T38_IND_CNG: t->tx_bit_rate = 0; modem_connect_tones_tx_init(&t->connect_tx, MODEM_CONNECT_TONES_FAX_CNG); - set_tx_handler(s, (span_tx_handler_t) &modem_connect_tones_tx, &t->connect_tx); + fax_modems_set_tx_handler(t, (span_tx_handler_t) &modem_connect_tones_tx, &t->connect_tx); silence_gen_set(&t->silence_gen, 0); - set_next_tx_handler(s, (span_tx_handler_t) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen); set_rx_active(s, TRUE); break; case T38_IND_CED: t->tx_bit_rate = 0; modem_connect_tones_tx_init(&t->connect_tx, MODEM_CONNECT_TONES_FAX_CED); - set_tx_handler(s, (span_tx_handler_t) &modem_connect_tones_tx, &t->connect_tx); - set_next_tx_handler(s, (span_tx_handler_t) NULL, NULL); + fax_modems_set_tx_handler(t, (span_tx_handler_t) &modem_connect_tones_tx, &t->connect_tx); + fax_modems_set_next_tx_handler(t, (span_tx_handler_t) NULL, NULL); set_rx_active(s, TRUE); break; case T38_IND_V21_PREAMBLE: @@ -511,8 +496,8 @@ static int set_next_tx_type(t38_gateway_state_t *s) silence_gen_alter(&t->silence_gen, ms_to_samples(75)); u->buf[u->in].len = 0; fsk_tx_init(&t->v21_tx, &preset_fsk_specs[FSK_V21CH2], (get_bit_func_t) hdlc_tx_get_bit, &t->hdlc_tx); - set_tx_handler(s, (span_tx_handler_t) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t) &fsk_tx, &t->v21_tx); + fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(t, (span_tx_handler_t) &fsk_tx, &t->v21_tx); set_rx_active(s, TRUE); break; case T38_IND_V27TER_2400_TRAINING: @@ -522,8 +507,8 @@ static int set_next_tx_type(t38_gateway_state_t *s) silence_gen_alter(&t->silence_gen, ms_to_samples(75)); v27ter_tx_restart(&t->fast_modems.v27ter_tx, t->tx_bit_rate, t->use_tep); v27ter_tx_set_get_bit(&t->fast_modems.v27ter_tx, get_bit_func, get_bit_user_data); - set_tx_handler(s, (span_tx_handler_t) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t) &v27ter_tx, &t->fast_modems.v27ter_tx); + fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(t, (span_tx_handler_t) &v27ter_tx, &t->fast_modems.v27ter_tx); set_rx_active(s, TRUE); break; case T38_IND_V29_7200_TRAINING: @@ -533,8 +518,8 @@ static int set_next_tx_type(t38_gateway_state_t *s) silence_gen_alter(&t->silence_gen, ms_to_samples(75)); v29_tx_restart(&t->fast_modems.v29_tx, t->tx_bit_rate, t->use_tep); v29_tx_set_get_bit(&t->fast_modems.v29_tx, get_bit_func, get_bit_user_data); - set_tx_handler(s, (span_tx_handler_t) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t) &v29_tx, &t->fast_modems.v29_tx); + fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(t, (span_tx_handler_t) &v29_tx, &t->fast_modems.v29_tx); set_rx_active(s, TRUE); break; case T38_IND_V17_7200_SHORT_TRAINING: @@ -582,8 +567,8 @@ static int set_next_tx_type(t38_gateway_state_t *s) silence_gen_alter(&t->silence_gen, ms_to_samples(75)); v17_tx_restart(&t->fast_modems.v17_tx, t->tx_bit_rate, t->use_tep, short_train); v17_tx_set_get_bit(&t->fast_modems.v17_tx, get_bit_func, get_bit_user_data); - set_tx_handler(s, (span_tx_handler_t) &silence_gen, &t->silence_gen); - set_next_tx_handler(s, (span_tx_handler_t) &v17_tx, &t->fast_modems.v17_tx); + fax_modems_set_tx_handler(t, (span_tx_handler_t) &silence_gen, &t->silence_gen); + fax_modems_set_next_tx_handler(t, (span_tx_handler_t) &v17_tx, &t->fast_modems.v17_tx); set_rx_active(s, TRUE); break; case T38_IND_V8_ANSAM: @@ -2150,23 +2135,23 @@ static int restart_rx_modem(t38_gateway_state_t *s) case FAX_MODEM_V27TER_RX: v27ter_rx_restart(&t->fast_modems.v27ter_rx, s->core.fast_bit_rate, FALSE); v27ter_rx_set_put_bit(&t->fast_modems.v27ter_rx, put_bit_func, put_bit_user_data); - set_rx_handler(s, &v27ter_v21_rx, s, &v27ter_v21_rx_fillin, s); + set_rx_handler(t, &v27ter_v21_rx, s, &v27ter_v21_rx_fillin, s); s->core.fast_rx_active = FAX_MODEM_V27TER_RX; break; case FAX_MODEM_V29_RX: v29_rx_restart(&t->fast_modems.v29_rx, s->core.fast_bit_rate, FALSE); v29_rx_set_put_bit(&t->fast_modems.v29_rx, put_bit_func, put_bit_user_data); - set_rx_handler(s, &v29_v21_rx, s, &v29_v21_rx_fillin, s); + set_rx_handler(t, &v29_v21_rx, s, &v29_v21_rx_fillin, s); s->core.fast_rx_active = FAX_MODEM_V29_RX; break; case FAX_MODEM_V17_RX: v17_rx_restart(&t->fast_modems.v17_rx, s->core.fast_bit_rate, s->core.short_train); v17_rx_set_put_bit(&t->fast_modems.v17_rx, put_bit_func, put_bit_user_data); - set_rx_handler(s, &v17_v21_rx, s, &v17_v21_rx_fillin, s); + set_rx_handler(t, &v17_v21_rx, s, &v17_v21_rx_fillin, s); s->core.fast_rx_active = FAX_MODEM_V17_RX; break; default: - set_rx_handler(s, (span_rx_handler_t) &fsk_rx, &t->v21_rx, (span_rx_fillin_handler_t) &fsk_rx_fillin, &t->v21_rx); + set_rx_handler(t, (span_rx_handler_t) &fsk_rx, &t->v21_rx, (span_rx_fillin_handler_t) &fsk_rx_fillin, &t->v21_rx); s->core.fast_rx_active = FAX_MODEM_NONE; break; } diff --git a/libs/spandsp/src/t4_tx.c b/libs/spandsp/src/t4_tx.c index 37bffa23bf..f33effb577 100644 --- a/libs/spandsp/src/t4_tx.c +++ b/libs/spandsp/src/t4_tx.c @@ -260,14 +260,7 @@ static int get_tiff_directory_info(t4_tx_state_t *s) } t4_tx_set_image_width(s, s->image_width); t4_tx_set_image_length(s, s->image_length); - switch (s->line_encoding) - { - case T4_COMPRESSION_ITU_T4_1D: - case T4_COMPRESSION_ITU_T4_2D: - case T4_COMPRESSION_ITU_T6: - t4_t6_encode_set_max_2d_rows_per_1d_row(&s->encoder.t4_t6, -s->metadata.y_resolution); - break; - } + t4_tx_set_max_2d_rows_per_1d_row(s, -s->metadata.y_resolution); #if defined(SPANDSP_SUPPORT_TIFF_FX) if (TIFFGetField(t->tiff_file, TIFFTAG_PROFILETYPE, &parm32)) span_log(&s->logging, SPAN_LOG_FLOW, "Profile type %u\n", parm32);