From f758d53ef5c61f2e089a3299c639020b19a26c7b Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Tue, 2 Apr 2013 20:31:19 +0800 Subject: [PATCH] Some preparations for colour FAX --- libs/spandsp/src/ademco_contactid.c | 20 +- libs/spandsp/src/dtmf.c | 12 +- libs/spandsp/src/spandsp/private/t30.h | 12 +- libs/spandsp/src/spandsp/private/v18.h | 4 +- libs/spandsp/src/spandsp/t30.h | 59 +- libs/spandsp/src/spandsp/t4_rx.h | 4 +- libs/spandsp/src/t30.c | 732 +++++++++++------- libs/spandsp/src/t30_api.c | 22 +- libs/spandsp/src/t4_rx.c | 36 +- libs/spandsp/src/t4_tx.c | 20 +- libs/spandsp/src/v18.c | 133 +++- .../itu/fax/generate_striped_pages.c | 2 +- libs/spandsp/tests/async_tests.c | 60 +- libs/spandsp/tests/fax_tests.c | 26 +- libs/spandsp/tests/fax_tests.sh | 13 + libs/spandsp/tests/tsb85_tests.c | 26 +- .../mod_spandsp/mod_spandsp_fax.c | 4 +- 17 files changed, 761 insertions(+), 424 deletions(-) diff --git a/libs/spandsp/src/ademco_contactid.c b/libs/spandsp/src/ademco_contactid.c index 6862567184..6aaf99c382 100644 --- a/libs/spandsp/src/ademco_contactid.c +++ b/libs/spandsp/src/ademco_contactid.c @@ -437,18 +437,17 @@ static const struct ademco_code_s ademco_codes[] = {-1, "???"} }; +#define GOERTZEL_SAMPLES_PER_BLOCK 55 /* We need to detect over a +-5% range */ + #if defined(SPANDSP_USE_FIXED_POINT) -#define GOERTZEL_SAMPLES_PER_BLOCK 55 /* We need to detect over a +-5% range */ -#define DETECTION_THRESHOLD 16439 /* -42dBm0 [((GOERTZEL_SAMPLES_PER_BLOCK*GOERTZEL_SAMPLES_PER_BLOCK*32768.0/(1.4142*128.0))*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2] */ -#define TONE_TWIST 4 /* 6dB */ -#define TONE_TO_TOTAL_ENERGY 64 /* -3dB */ +#define DETECTION_THRESHOLD 3035 /* -42dBm0 */ +#define TONE_TO_TOTAL_ENERGY 45.2233f /* -0.85dB */ #else -#define GOERTZEL_SAMPLES_PER_BLOCK 55 /* We need to detect over a +-5% range */ -#define DETECTION_THRESHOLD 2104205.6f /* -42dBm0 [((GOERTZEL_SAMPLES_PER_BLOCK*GOERTZEL_SAMPLES_PER_BLOCK*32768.0/1.4142)*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2] */ -#define TONE_TWIST 3.981f /* 6dB */ -#define TONE_TO_TOTAL_ENERGY 1.995f /* 3dB */ +#define DETECTION_THRESHOLD 49728296.6f /* -42dBm0 [((GOERTZEL_SAMPLES_PER_BLOCK*32768.0/1.4142)*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2] */ +#define TONE_TO_TOTAL_ENERGY 45.2233f /* -0.85dB [GOERTZEL_SAMPLES_PER_BLOCK*10^(-0.85/10.0)] */ #endif +static int tone_rx_init = FALSE; static goertzel_descriptor_t tone_1400_desc; static goertzel_descriptor_t tone_2300_desc; @@ -1083,8 +1082,6 @@ SPAN_DECLARE(ademco_contactid_sender_state_t *) ademco_contactid_sender_init(ade tone_report_func_t callback, void *user_data) { - static int initialised = FALSE; - if (s == NULL) { if ((s = (ademco_contactid_sender_state_t *) malloc(sizeof (*s))) == NULL) @@ -1094,10 +1091,11 @@ SPAN_DECLARE(ademco_contactid_sender_state_t *) ademco_contactid_sender_init(ade span_log_init(&s->logging, SPAN_LOG_NONE, NULL); span_log_set_protocol(&s->logging, "Ademco"); - if (!initialised) + if (!tone_rx_init) { make_goertzel_descriptor(&tone_1400_desc, 1400.0f, GOERTZEL_SAMPLES_PER_BLOCK); make_goertzel_descriptor(&tone_2300_desc, 2300.0f, GOERTZEL_SAMPLES_PER_BLOCK); + tone_rx_init = TRUE; } goertzel_init(&s->tone_1400, &tone_1400_desc); goertzel_init(&s->tone_2300, &tone_2300_desc); diff --git a/libs/spandsp/src/dtmf.c b/libs/spandsp/src/dtmf.c index 6884d2b770..991f3d6a85 100644 --- a/libs/spandsp/src/dtmf.c +++ b/libs/spandsp/src/dtmf.c @@ -62,6 +62,8 @@ #define DEFAULT_DTMF_TX_ON_TIME 50 #define DEFAULT_DTMF_TX_OFF_TIME 55 +#define DTMF_SAMPLES_PER_BLOCK 102 + #if defined(SPANDSP_USE_FIXED_POINT) #define DTMF_THRESHOLD 10438 /* -42dBm0 */ #define DTMF_NORMAL_TWIST 6.309f /* 8dB */ @@ -70,16 +72,14 @@ #define DTMF_RELATIVE_PEAK_COL 6.309f /* 8dB */ #define DTMF_TO_TOTAL_ENERGY 83.868f /* -0.85dB */ #define DTMF_POWER_OFFSET 68.251f /* 10*log(256.0*256.0*DTMF_SAMPLES_PER_BLOCK) */ -#define DTMF_SAMPLES_PER_BLOCK 102 #else -#define DTMF_THRESHOLD 171032462.0f /* -42dBm0 [((DTMF_SAMPLES_PER_BLOCK*32768.0/1.4142)*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2 => 171032462.0] */ +#define DTMF_THRESHOLD 171032462.0f /* -42dBm0 [((DTMF_SAMPLES_PER_BLOCK*32768.0/1.4142)*10^((-42 - DBM0_MAX_SINE_POWER)/20.0))^2] */ #define DTMF_NORMAL_TWIST 6.309f /* 8dB [10^(8/10) => 6.309] */ #define DTMF_REVERSE_TWIST 2.512f /* 4dB */ #define DTMF_RELATIVE_PEAK_ROW 6.309f /* 8dB */ #define DTMF_RELATIVE_PEAK_COL 6.309f /* 8dB */ #define DTMF_TO_TOTAL_ENERGY 83.868f /* -0.85dB [DTMF_SAMPLES_PER_BLOCK*10^(-0.85/10.0)] */ #define DTMF_POWER_OFFSET 110.395f /* 10*log(32768.0*32768.0*DTMF_SAMPLES_PER_BLOCK) */ -#define DTMF_SAMPLES_PER_BLOCK 102 #endif static const float dtmf_row[] = @@ -93,6 +93,7 @@ static const float dtmf_col[] = static const char dtmf_positions[] = "123A" "456B" "789C" "*0#D"; +static int dtmf_rx_inited = FALSE; static goertzel_descriptor_t dtmf_detect_row[4]; static goertzel_descriptor_t dtmf_detect_col[4]; @@ -409,7 +410,6 @@ SPAN_DECLARE(dtmf_rx_state_t *) dtmf_rx_init(dtmf_rx_state_t *s, void *user_data) { int i; - static int initialised = FALSE; if (s == NULL) { @@ -431,14 +431,14 @@ SPAN_DECLARE(dtmf_rx_state_t *) dtmf_rx_init(dtmf_rx_state_t *s, s->in_digit = 0; s->last_hit = 0; - if (!initialised) + if (!dtmf_rx_inited) { for (i = 0; i < 4; i++) { make_goertzel_descriptor(&dtmf_detect_row[i], dtmf_row[i], DTMF_SAMPLES_PER_BLOCK); make_goertzel_descriptor(&dtmf_detect_col[i], dtmf_col[i], DTMF_SAMPLES_PER_BLOCK); } - initialised = TRUE; + dtmf_rx_inited = TRUE; } for (i = 0; i < 4; i++) { diff --git a/libs/spandsp/src/spandsp/private/t30.h b/libs/spandsp/src/spandsp/private/t30.h index b1bef5d112..933995d46b 100644 --- a/libs/spandsp/src/spandsp/private/t30.h +++ b/libs/spandsp/src/spandsp/private/t30.h @@ -52,8 +52,10 @@ struct t30_state_s int supported_modems; /*! \brief A bit mask of the currently supported image compression modes. */ int supported_compressions; - /*! \brief A bit mask of the currently supported image resolutions. */ - int supported_resolutions; + /*! \brief A bit mask of the currently supported bi-level image resolutions. */ + int supported_bilevel_resolutions; + /*! \brief A bit mask of the currently supported colour image resolutions. */ + int supported_colour_resolutions; /*! \brief A bit mask of the currently supported image sizes. */ int supported_image_sizes; /*! \brief A bit mask of the currently supported T.30 special features. */ @@ -218,6 +220,12 @@ struct t30_state_s /*! \brief TRUE if a local T.30 interrupt is pending. */ int local_interrupt_pending; + /*! \brief The common ground in compression schemes between the local and far ends. */ + int mutual_compressions; + /*! \brief The common group supported bi-level image resolutions. */ + int mutual_bilevel_resolutions; + /*! \brief The common group supported colour image resolutions. */ + int mutual_colour_resolutions; /*! \brief The image coding to be used on the line for non-bilevel images. */ int multilevel_line_encoding; /*! \brief The image coding being used on the line. */ diff --git a/libs/spandsp/src/spandsp/private/v18.h b/libs/spandsp/src/spandsp/private/v18.h index 086262c720..3639ca6715 100644 --- a/libs/spandsp/src/spandsp/private/v18.h +++ b/libs/spandsp/src/spandsp/private/v18.h @@ -33,6 +33,7 @@ struct v18_state_s int mode; put_msg_func_t put_msg; void *user_data; + int repeat_shifts; union { @@ -46,6 +47,7 @@ struct v18_state_s async_tx_state_t asynctx; int baudot_tx_shift; int tx_signal_on; + uint8_t next_byte; int byte_no; fsk_rx_state_t fskrx; @@ -56,7 +58,7 @@ struct v18_state_s int rx_msg_len; int bit_pos; int in_progress; - int repeat_shifts; + int rx_suppression; /*! \brief Error and flow logging control */ logging_state_t logging; diff --git a/libs/spandsp/src/spandsp/t30.h b/libs/spandsp/src/spandsp/t30.h index 813ca28a67..7970051f73 100644 --- a/libs/spandsp/src/spandsp/t30.h +++ b/libs/spandsp/src/spandsp/t30.h @@ -369,7 +369,7 @@ enum /*! T.45 run length colour compression */ T30_SUPPORT_COMPRESSION_T45 = 0x80, /*! T.81 + T.30 Annex E colour JPEG compression */ - T30_SUPPORT_COMPRESSION_T81 = 0x100, + T30_SUPPORT_COMPRESSION_T42_T81 = 0x100, /*! T.81 + T.30 Annex K colour sYCC-JPEG compression */ T30_SUPPORT_COMPRESSION_SYCC_T81 = 0x200, /*! T.88 monochrome JBIG2 compression */ @@ -382,34 +382,37 @@ enum enum { - /*! Support standard FAX Y-resolution 98/100dpi */ - T30_SUPPORT_STANDARD_RESOLUTION = 0x01, - /*! Support fine FAX Y-resolution 196/200dpi */ - T30_SUPPORT_FINE_RESOLUTION = 0x02, - /*! Support super-fine FAX Y-resolution 392/400dpi */ - T30_SUPPORT_SUPERFINE_RESOLUTION = 0x04, + /*! Standard FAX resolution 204dpi x 98dpi - bi-level only */ + T30_SUPPORT_RESOLUTION_R8_STANDARD = 0x1, + /*! Fine FAX resolution 204dpi x 196dpi - bi-level only */ + T30_SUPPORT_RESOLUTION_R8_FINE = 0x2, + /*! Super-fine FAX resolution 204dpi x 391dpi - bi-level only */ + T30_SUPPORT_RESOLUTION_R8_SUPERFINE = 0x4, + /*! Double FAX resolution 408dpi x 391dpi - bi-level only */ + T30_SUPPORT_RESOLUTION_R16_SUPERFINE = 0x8, - /*! Support half FAX X-resolution 100/102dpi */ - T30_SUPPORT_R4_RESOLUTION = 0x10000, - /*! Support standard FAX X-resolution 200/204dpi */ - T30_SUPPORT_R8_RESOLUTION = 0x20000, - /*! Support double FAX X-resolution 400dpi */ - T30_SUPPORT_R16_RESOLUTION = 0x40000, - - /*! Support 300dpi x 300 dpi */ - T30_SUPPORT_300_300_RESOLUTION = 0x100000, - /*! Support 400dpi x 400 dpi */ - T30_SUPPORT_400_400_RESOLUTION = 0x200000, - /*! Support 600dpi x 600 dpi */ - T30_SUPPORT_600_600_RESOLUTION = 0x400000, - /*! Support 1200dpi x 1200 dpi */ - T30_SUPPORT_1200_1200_RESOLUTION = 0x800000, - /*! Support 300dpi x 600 dpi */ - T30_SUPPORT_300_600_RESOLUTION = 0x1000000, - /*! Support 400dpi x 800 dpi */ - T30_SUPPORT_400_800_RESOLUTION = 0x2000000, - /*! Support 600dpi x 1200 dpi */ - T30_SUPPORT_600_1200_RESOLUTION = 0x4000000 + /*! 100dpi x 100 dpi - gray scale and colour only */ + T30_SUPPORT_RESOLUTION_100_100 = 0x10, + /*! 200dpi x 100 dpi - bi-level only */ + T30_SUPPORT_RESOLUTION_200_100 = 0x20, + /*! 200dpi x 200 dpi */ + T30_SUPPORT_RESOLUTION_200_200 = 0x40, + /*! 200dpi x 400 dpi - bi-level only */ + T30_SUPPORT_RESOLUTION_200_400 = 0x80, + /*! 300dpi x 300 dpi */ + T30_SUPPORT_RESOLUTION_300_300 = 0x100, + /*! 300dpi x 600 dpi - bi-level only */ + T30_SUPPORT_RESOLUTION_300_600 = 0x200, + /*! 400dpi x 400 dpi */ + T30_SUPPORT_RESOLUTION_400_400 = 0x400, + /*! 400dpi x 800 dpi - bi-level only */ + T30_SUPPORT_RESOLUTION_400_800 = 0x800, + /*! 600dpi x 600 dpi */ + T30_SUPPORT_RESOLUTION_600_600 = 0x1000, + /*! 600dpi x 1200 dpi - bi-level only */ + T30_SUPPORT_RESOLUTION_600_1200 = 0x2000, + /*! 1200dpi x 1200 dpi */ + T30_SUPPORT_RESOLUTION_1200_1200 = 0x4000 }; enum diff --git a/libs/spandsp/src/spandsp/t4_rx.h b/libs/spandsp/src/spandsp/t4_rx.h index 3002578cfc..5ec633e928 100644 --- a/libs/spandsp/src/spandsp/t4_rx.h +++ b/libs/spandsp/src/spandsp/t4_rx.h @@ -65,9 +65,9 @@ typedef enum /*! T.45 run length colour compression */ T4_COMPRESSION_T45 = 7, /*! T.42 + T.81 + T.30 Annex E colour JPEG coding */ - T4_COMPRESSION_T42 = 8, + T4_COMPRESSION_T42_T81 = 8, /*! T.42 + T.81 + T.30 Annex K colour sYCC-JPEG coding */ - T4_COMPRESSION_SYCC_T42 = 9 + T4_COMPRESSION_SYCC_T81 = 9 } t4_image_compression_t; /*! Image type */ diff --git a/libs/spandsp/src/t30.c b/libs/spandsp/src/t30.c index 9d29d5aebe..c8a16c3d96 100644 --- a/libs/spandsp/src/t30.c +++ b/libs/spandsp/src/t30.c @@ -1178,22 +1178,24 @@ int t30_build_dis_or_dtc(t30_state_t *s) /* V.17 is only valid when combined with V.29 and V.27ter, so if we enable V.17 we force the others too. */ if ((s->supported_modems & T30_SUPPORT_V17)) s->local_dis_dtc_frame[4] |= (DISBIT6 | DISBIT4 | DISBIT3); - if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION)) - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE); - if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T4_2D)) - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE); + /* 215mm wide is always supported */ if ((s->supported_image_sizes & T30_SUPPORT_303MM_WIDTH)) set_ctrl_bit(s->local_dis_dtc_frame, 18); else if ((s->supported_image_sizes & T30_SUPPORT_255MM_WIDTH)) set_ctrl_bit(s->local_dis_dtc_frame, 17); + /* A4 is always supported. */ if ((s->supported_image_sizes & T30_SUPPORT_UNLIMITED_LENGTH)) set_ctrl_bit(s->local_dis_dtc_frame, 20); else if ((s->supported_image_sizes & T30_SUPPORT_B4_LENGTH)) set_ctrl_bit(s->local_dis_dtc_frame, 19); + /* No scan-line padding required, but some may be specified by the application. */ set_ctrl_bits(s->local_dis_dtc_frame, s->local_min_scan_time_code, 21); + + if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T4_2D)) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE); if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_NONE)) set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_UNCOMPRESSED_CAPABLE); if (s->ecm_allowed) @@ -1204,21 +1206,29 @@ int t30_build_dis_or_dtc(t30_state_t *s) also offering the ECM option needed to support them. */ if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T6)) set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE); - if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T43)) - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE); - if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T45)) - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T45_CAPABLE); - if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T81)) - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE); - if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_SYCC_T81)) - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_SYCC_T81_CAPABLE); if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T85)) { + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE); /* Bit 79 set with bit 78 clear is invalid, so only check for L0 support here. */ if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T85_L0)) set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE); - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE); + } + + if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T42_T81)) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE); + if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T43)) + { + /* Note 25 of table 2/T.30 */ + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE); + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE); + } + if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T45)) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T45_CAPABLE); + if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_SYCC_T81)) + { + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE); + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_SYCC_T81_CAPABLE); } //if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T89)) // set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T89_CAPABLE); @@ -1232,14 +1242,6 @@ int t30_build_dis_or_dtc(t30_state_t *s) /* No plane interleave */ /* No G.726 */ /* No extended voice coding */ - if ((s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION)) - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE); - if ((s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION)) - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE); - if ((s->supported_resolutions & (T30_SUPPORT_400_400_RESOLUTION | T30_SUPPORT_R16_RESOLUTION))) - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE); - /* Metric */ - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED); /* Superfine minimum scan line time pattern follows fine */ if ((s->supported_t30_features & T30_SUPPORT_SELECTIVE_POLLING)) set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_SELECTIVE_POLLING_CAPABLE); @@ -1281,26 +1283,64 @@ int t30_build_dis_or_dtc(t30_state_t *s) /* No alternative hashing system number 3 */ /* No T.44 (mixed raster content) */ /* No page length maximum strip size for T.44 (mixed raster content) */ - /* No colour/grey scale 300x300 or 400x400 */ - /* No colour/grey scale 100x100 */ /* No simple phase C BFT negotiations */ /* No extended BFT negotiations */ if ((s->supported_t30_features & T30_SUPPORT_INTERNET_SELECTIVE_POLLING_ADDRESS)) set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_INTERNET_SELECTIVE_POLLING_ADDRESS); if ((s->supported_t30_features & T30_SUPPORT_INTERNET_ROUTING_ADDRESS)) set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_INTERNET_ROUTING_ADDRESS); - if ((s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION)) - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE); - if ((s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION)) + + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_1200_1200)) + { set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_1200_1200_CAPABLE); - if ((s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION)) - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE); - if ((s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION)) - set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_400_800_CAPABLE); - if ((s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION)) + if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_1200_1200)) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_1200_1200_CAPABLE); + } + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_600_1200)) set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_600_1200_CAPABLE); - /* No colour/grey scale 600x600 */ - /* No colour/grey scale 1200x1200 */ + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_600_600)) + { + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE); + if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_600_600)) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_600_600_CAPABLE); + } + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_400_800)) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_400_800_CAPABLE); + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R16_SUPERFINE)) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE); + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_400_400)) + { + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE); + if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_400_400)) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_300_300_400_400_CAPABLE); + } + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_300_600)) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE); + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_300_300)) + { + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE); + if ((s->supported_colour_resolutions & T4_RESOLUTION_300_300)) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_300_300_400_400_CAPABLE); + } + if ((s->supported_bilevel_resolutions & (T30_SUPPORT_RESOLUTION_200_400 | T30_SUPPORT_RESOLUTION_R8_SUPERFINE))) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE); + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R8_FINE)) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE); + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_200_200)) + { + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE); + //if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_200_200)) + // set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_???_CAPABLE); + } + /* Standard FAX resolution bi-level image support goes without saying */ + if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_100_100)) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_100_100_CAPABLE); + + if ((s->supported_bilevel_resolutions & (T30_SUPPORT_RESOLUTION_R8_STANDARD | T30_SUPPORT_RESOLUTION_R8_FINE | T30_SUPPORT_RESOLUTION_R8_SUPERFINE | T30_SUPPORT_RESOLUTION_R16_SUPERFINE))) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED); + if ((s->supported_bilevel_resolutions & (T30_SUPPORT_RESOLUTION_200_100 | T30_SUPPORT_RESOLUTION_200_200 | T30_SUPPORT_RESOLUTION_200_400 | T30_SUPPORT_RESOLUTION_300_300 | T30_SUPPORT_RESOLUTION_300_600 | T30_SUPPORT_RESOLUTION_400_400 | T30_SUPPORT_RESOLUTION_400_800 | T30_SUPPORT_RESOLUTION_600_600 | T30_SUPPORT_RESOLUTION_600_1200 | T30_SUPPORT_RESOLUTION_1200_1200))) + set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED); + /* No double sided printing (alternate mode) */ /* No double sided printing (continuous mode) */ /* No black and white mixed raster content profile */ @@ -1370,7 +1410,7 @@ static int build_dcs(t30_state_t *s) /* Select the compression to use. */ switch (s->line_encoding) { - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE); set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, 21); break; @@ -1413,17 +1453,17 @@ static int build_dcs(t30_state_t *s) case T4_Y_RESOLUTION_1200: switch (s->x_resolution) { - case T4_X_RESOLUTION_600: - if ((s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_1200_CAPABLE)) + case T4_X_RESOLUTION_1200: + if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_1200_1200)) { - set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200); + set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200); bad = T30_ERR_OK; } break; - case T4_X_RESOLUTION_1200: - if ((s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_1200_1200_CAPABLE)) + case T4_X_RESOLUTION_600: + if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_600_1200)) { - set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200); + set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200); bad = T30_ERR_OK; } break; @@ -1433,7 +1473,7 @@ static int build_dcs(t30_state_t *s) switch (s->x_resolution) { case T4_X_RESOLUTION_R16: - if ((s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_800_CAPABLE)) + if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_400_800)) { set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800); bad = T30_ERR_OK; @@ -1444,17 +1484,17 @@ static int build_dcs(t30_state_t *s) case T4_Y_RESOLUTION_600: switch (s->x_resolution) { - case T4_X_RESOLUTION_300: - if ((s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE)) + case T4_X_RESOLUTION_600: + if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_600_600)) { - set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600); + set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600); bad = T30_ERR_OK; } break; - case T4_X_RESOLUTION_600: - if ((s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE)) + case T4_X_RESOLUTION_300: + if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_300_600)) { - set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600); + set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600); bad = T30_ERR_OK; } break; @@ -1464,7 +1504,7 @@ static int build_dcs(t30_state_t *s) switch (s->x_resolution) { case T4_X_RESOLUTION_300: - if ((s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE)) + if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_300_300)) { set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300); bad = T30_ERR_OK; @@ -1473,15 +1513,37 @@ static int build_dcs(t30_state_t *s) } break; case T4_Y_RESOLUTION_SUPERFINE: - if ((s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION)) + case T4_Y_RESOLUTION_400: + if (s->x_resolution == T4_X_RESOLUTION_400 && s->y_resolution == T4_Y_RESOLUTION_400) { - if (s->x_resolution == T4_X_RESOLUTION_R16 && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE)) + if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_400_400)) { set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400); bad = T30_ERR_OK; break; } - if (s->x_resolution == T4_X_RESOLUTION_R8 && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE)) + } + else if (s->x_resolution == T4_X_RESOLUTION_R16 && s->y_resolution == T4_Y_RESOLUTION_SUPERFINE) + { + if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R16_SUPERFINE)) + { + set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400); + bad = T30_ERR_OK; + break; + } + } + else if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_400) + { + if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_200_400)) + { + set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400); + bad = T30_ERR_OK; + break; + } + } + else if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_SUPERFINE) + { + if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R8_SUPERFINE)) { set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400); bad = T30_ERR_OK; @@ -1491,24 +1553,38 @@ static int build_dcs(t30_state_t *s) row_squashing_ratio <<= 1; /* Fall through */ case T4_Y_RESOLUTION_FINE: - if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE)) + case T4_Y_RESOLUTION_200: + if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_200) { - switch (s->x_resolution) + if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_200_200)) + { + set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200); + bad = T30_ERR_OK; + break; + } + } + else if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_FINE) + { + if ((s->mutual_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R8_FINE)) { - case T4_X_RESOLUTION_R8: set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200); bad = T30_ERR_OK; break; } - break; } row_squashing_ratio <<= 1; /* Fall through */ default: case T4_Y_RESOLUTION_STANDARD: - switch (s->x_resolution) + case T4_Y_RESOLUTION_100: + if (s->x_resolution == T4_X_RESOLUTION_R8 && s->y_resolution == T4_Y_RESOLUTION_STANDARD) + { + /* No bits to set for this */ + bad = T30_ERR_OK; + break; + } + else if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_100) { - case T4_X_RESOLUTION_R8: /* No bits to set for this */ bad = T30_ERR_OK; break; @@ -1528,11 +1604,11 @@ static int build_dcs(t30_state_t *s) bad = T30_ERR_OK; /* The following treats a width field of 11 like 10, which does what note 6 of Table 2/T.30 says we should do with the invalid value 11. */ - if (((s->image_width == T4_WIDTH_R8_A4) && (s->x_resolution == T4_X_RESOLUTION_R8)) + if (((s->image_width == T4_WIDTH_200_A4) && (s->x_resolution == T4_X_RESOLUTION_200 || s->x_resolution == T4_X_RESOLUTION_R8)) || ((s->image_width == T4_WIDTH_300_A4) && (s->x_resolution == T4_X_RESOLUTION_300)) || - ((s->image_width == T4_WIDTH_R16_A4) && (s->x_resolution == T4_X_RESOLUTION_R16)) + ((s->image_width == T4_WIDTH_400_A4) && (s->x_resolution == T4_X_RESOLUTION_400 || s->x_resolution == T4_X_RESOLUTION_R16)) || ((s->image_width == T4_WIDTH_600_A4) && (s->x_resolution == T4_X_RESOLUTION_600)) || @@ -1541,15 +1617,15 @@ static int build_dcs(t30_state_t *s) span_log(&s->logging, SPAN_LOG_FLOW, "Image width is A4\n"); /* No width related bits need to be set. */ } - else if (((s->image_width == T4_WIDTH_R8_B4) && (s->x_resolution == T4_X_RESOLUTION_R8)) - || - ((s->image_width == T4_WIDTH_300_B4) && (s->x_resolution == T4_X_RESOLUTION_300)) - || - ((s->image_width == T4_WIDTH_R16_B4) && (s->x_resolution == T4_X_RESOLUTION_R16)) - || - ((s->image_width == T4_WIDTH_600_B4) && (s->x_resolution == T4_X_RESOLUTION_600)) - || - ((s->image_width == T4_WIDTH_1200_B4) && (s->x_resolution == T4_X_RESOLUTION_1200))) + else if (((s->image_width == T4_WIDTH_200_B4) && (s->x_resolution == T4_X_RESOLUTION_200 || s->x_resolution == T4_X_RESOLUTION_R8)) + || + ((s->image_width == T4_WIDTH_300_B4) && (s->x_resolution == T4_X_RESOLUTION_300)) + || + ((s->image_width == T4_WIDTH_400_B4) && (s->x_resolution == T4_X_RESOLUTION_400 || s->x_resolution == T4_X_RESOLUTION_R16)) + || + ((s->image_width == T4_WIDTH_600_B4) && (s->x_resolution == T4_X_RESOLUTION_600)) + || + ((s->image_width == T4_WIDTH_1200_B4) && (s->x_resolution == T4_X_RESOLUTION_1200))) { if (((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) >= 1) && @@ -1564,15 +1640,15 @@ static int build_dcs(t30_state_t *s) bad = T30_ERR_NOSIZESUPPORT; } } - else if (((s->image_width == T4_WIDTH_R8_A3) && (s->x_resolution == T4_X_RESOLUTION_R8)) - || - ((s->image_width == T4_WIDTH_300_A3) && (s->x_resolution == T4_X_RESOLUTION_300)) - || - ((s->image_width == T4_WIDTH_R16_A3) && (s->x_resolution == T4_X_RESOLUTION_R16)) - || - ((s->image_width == T4_WIDTH_600_A3) && (s->x_resolution == T4_X_RESOLUTION_600)) - || - ((s->image_width == T4_WIDTH_1200_A3) && (s->x_resolution == T4_X_RESOLUTION_1200))) + else if (((s->image_width == T4_WIDTH_200_A3) && (s->x_resolution == T4_X_RESOLUTION_200 || s->x_resolution == T4_X_RESOLUTION_R8)) + || + ((s->image_width == T4_WIDTH_300_A3) && (s->x_resolution == T4_X_RESOLUTION_300)) + || + ((s->image_width == T4_WIDTH_400_A3) && (s->x_resolution == T4_X_RESOLUTION_400 || s->x_resolution == T4_X_RESOLUTION_R16)) + || + ((s->image_width == T4_WIDTH_600_A3) && (s->x_resolution == T4_X_RESOLUTION_600)) + || + ((s->image_width == T4_WIDTH_1200_A3) && (s->x_resolution == T4_X_RESOLUTION_1200))) { if (((s->far_dis_dtc_frame[5] & (DISBIT2 | DISBIT1)) >= 2) && @@ -1618,6 +1694,7 @@ static int build_dcs(t30_state_t *s) if ((s->iaf & T30_IAF_MODE_FLOW_CONTROL) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T38_FLOW_CONTROL_CAPABLE)) set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T38_FLOW_CONTROL_CAPABLE); + if ((s->iaf & T30_IAF_MODE_CONTINUOUS_FLOW) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T38_FAX_CAPABLE)) { /* Clear the modem type bits, in accordance with note 77 of Table 2/T.30 */ @@ -1984,7 +2061,11 @@ static int start_sending_document(t30_state_t *s) t4_tx_set_header_tz(&s->t4.tx, &s->tz); if (tx_start_page(s)) + { + span_log(&s->logging, SPAN_LOG_WARNING, "Something seems to be wrong in the file\n"); + t30_set_status(s, T30_ERR_FILEERROR); return -1; + } s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx); s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx); @@ -2082,63 +2163,119 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len) s->error_correcting_mode = (s->ecm_allowed && (s->far_dis_dtc_frame[6] & DISBIT3) != 0); /* 256 octets per ECM frame */ s->octets_per_ecm_frame = 256; - /* Now we know if we are going to use ECM, select the compression to use. */ + /* Now we know if we are going to use ECM, select the compressions which we can use. */ + s->mutual_compressions = s->supported_compressions; if (!s->error_correcting_mode) { - /* Without error correction our choices are very limited */ - if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T4_2D) - && - test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE)) - { - s->line_encoding = T4_COMPRESSION_T4_2D; - } - else - { - s->line_encoding = T4_COMPRESSION_T4_1D; - } + /* Remove any compression schemes which need error correction to work. */ + s->mutual_compressions &= (0xF0000000 | T30_SUPPORT_COMPRESSION_NONE | T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D); + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE)) + s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T4_2D; } else { -#if defined(SPANDSP_SUPPORT_T42x) || defined(SPANDSP_SUPPORT_T43) - /* With error correction colour may be possible/required */ - if ((0 & (T30_SUPPORT_COMPRESSION_T43 | T30_SUPPORT_COMPRESSION_T45 | T30_SUPPORT_COMPRESSION_T81 | T30_SUPPORT_COMPRESSION_SYCC_T81))) - { - s->line_encoding = T4_COMPRESSION_T85_L0; - } - else -#endif - { - if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T85_L0) - && - test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE)) - { - s->line_encoding = T4_COMPRESSION_T85_L0; - } - else if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T85) - && - test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE)) - { - s->line_encoding = T4_COMPRESSION_T85; - } - else if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T6) - && - test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE)) - { - s->line_encoding = T4_COMPRESSION_T6; - } - else if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T4_2D) - && - test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE)) - { - s->line_encoding = T4_COMPRESSION_T4_2D; - } - else - { - s->line_encoding = T4_COMPRESSION_T4_1D; - } - } + /* Check the bi-level capabilities */ + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE)) + s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T4_2D; + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE)) + s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T6; + /* T.85 L0 capable without T.85 capable is an invalid combination, so let + just zap both capabilities if the far end is not T.85 capable. */ + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE)) + s->mutual_compressions &= ~(T30_SUPPORT_COMPRESSION_T85 | T30_SUPPORT_COMPRESSION_T85_L0); + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE)) + s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T85_L0; } + + /* Choose a compression scheme from amongst those mutually available */ + if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T85_L0)) + s->line_encoding = T4_COMPRESSION_T85_L0; + else if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T85)) + s->line_encoding = T4_COMPRESSION_T85; + else if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T6)) + s->line_encoding = T4_COMPRESSION_T6; + else if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T4_2D)) + s->line_encoding = T4_COMPRESSION_T4_2D; + else + s->line_encoding = T4_COMPRESSION_T4_1D; + span_log(&s->logging, SPAN_LOG_FLOW, "Choose compression %s (%d)\n", t4_encoding_to_str(s->line_encoding), s->line_encoding); + + + s->mutual_bilevel_resolutions = s->supported_bilevel_resolutions; + s->mutual_colour_resolutions = s->supported_colour_resolutions; + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_1200_1200_CAPABLE)) + { + s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_1200_1200; + s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_1200_1200; + } + else + { + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_1200_1200_CAPABLE)) + s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_1200_1200; + } + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_1200_CAPABLE)) + s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_600_1200; + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_600_600_CAPABLE)) + { + s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_600_600; + s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_600_600; + } + else + { + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_600_600_CAPABLE)) + s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_600_600; + } + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_800_CAPABLE)) + s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_400_800; + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_400_400_CAPABLE)) + { + s->mutual_bilevel_resolutions &= ~(T30_SUPPORT_RESOLUTION_400_400 | T30_SUPPORT_RESOLUTION_R16_SUPERFINE); + s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_400_400; + } + else + { + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_300_300_400_400_CAPABLE)) + s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_400_400; + } + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_600_CAPABLE)) + s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_300_600; + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_300_300_CAPABLE)) + { + s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_300_300; + s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_300_300; + } + else + { + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_300_300_400_400_CAPABLE)) + s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_300_300; + } + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE)) + { + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED)) + s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_200_400; + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED)) + s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_R8_SUPERFINE; + } + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE)) + { + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED)) + s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_200_200; + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_METRIC_RESOLUTION_PREFERRED)) + s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_R8_FINE; + s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_200_200; + } + else + { + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED)) + s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_200_200; + } + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_INCH_RESOLUTION_PREFERRED)) + s->mutual_bilevel_resolutions &= ~T30_SUPPORT_RESOLUTION_200_100; + /* Never suppress T30_SUPPORT_RESOLUTION_R8_STANDARD */ + if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_COLOUR_GRAY_100_100_CAPABLE)) + s->mutual_colour_resolutions &= ~T30_SUPPORT_RESOLUTION_100_100; + switch (s->far_dis_dtc_frame[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3)) { case (DISBIT6 | DISBIT4 | DISBIT3): @@ -2192,60 +2329,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len) return -1; } } -#if 0 - /* T.4 1D is always available */ - bi_level_support = T30_SUPPORT_COMPRESSION_T4_1D; - if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE)) - bi_level_support |= T30_SUPPORT_COMPRESSION_T4_2D; - if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE)) - bi_level_support |= T30_SUPPORT_COMPRESSION_T6; - /* Bit 79 set with bit 78 clear is invalid, so let's completely ignore 79 - if 78 is clear. */ - if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE)) - { - bi_level_support |= T30_SUPPORT_COMPRESSION_T85; - if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE) - bi_level_support |= T30_SUPPORT_COMPRESSION_T85_L0; - } - gray_support = 0; - colour_support = 0; - if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE) && test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE)) - { - /* Multi-level coding available */ - gray_support |= T30_SUPPORT_COMPRESSION_T81; - if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE)) - gray_support |= T30_SUPPORT_COMPRESSION_T81_12BIT; - if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE)) - { - gray_support |= T30_SUPPORT_COMPRESSION_T43; - if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE)) - gray_support |= T30_SUPPORT_COMPRESSION_T43_12BIT; - } - - if (test_ctrl_bit(s->far_dis_dtc_frame, bit69)) - { - /* Colour coding available */ - colour_support |= T30_SUPPORT_COMPRESSION_T81; - if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE)) - colour_support |= T30_SUPPORT_COMPRESSION_T81_12BIT; - if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING)) - { - colour_support |= T30_SUPPORT_COMPRESSION_T81_SUBSAMPLING; - if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE)) - colour_support |= T30_SUPPORT_COMPRESSION_T81_SUBSAMPLING_12BIT; - } - if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE)) - { - colour_support |= T30_SUPPORT_COMPRESSION_T43; - if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE)) - colour_support |= T30_SUPPORT_COMPRESSION_T43_12BIT; - } - } - /* bit74 custom illuminant */ - /* bit75 custom gamut range */ - } -#endif queue_phase(s, T30_PHASE_B_TX); /* Try to send something */ if (s->tx_file[0]) @@ -2310,10 +2394,10 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len) { static const int widths[6][4] = { - { T4_WIDTH_R4_A4, T4_WIDTH_R4_B4, T4_WIDTH_R4_A3, -1}, /* R4 resolution - no longer used in recent versions of T.30 */ - { T4_WIDTH_R8_A4, T4_WIDTH_R8_B4, T4_WIDTH_R8_A3, -1}, /* R8 resolution */ + { T4_WIDTH_100_A4, T4_WIDTH_100_B4, T4_WIDTH_100_A3, -1}, /* 100/inch */ + { T4_WIDTH_200_A4, T4_WIDTH_200_B4, T4_WIDTH_200_A3, -1}, /* 200/inch / R8 resolution */ { T4_WIDTH_300_A4, T4_WIDTH_300_B4, T4_WIDTH_300_A3, -1}, /* 300/inch resolution */ - { T4_WIDTH_R16_A4, T4_WIDTH_R16_B4, T4_WIDTH_R16_A3, -1}, /* R16 resolution */ + { T4_WIDTH_400_A4, T4_WIDTH_400_B4, T4_WIDTH_400_A3, -1}, /* 400/inch / R16 resolution */ { T4_WIDTH_600_A4, T4_WIDTH_600_B4, T4_WIDTH_600_A3, -1}, /* 600/inch resolution */ {T4_WIDTH_1200_A4, T4_WIDTH_1200_B4, T4_WIDTH_1200_A3, -1} /* 1200/inch resolution */ }; @@ -2353,93 +2437,221 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len) s->x_resolution = -1; s->y_resolution = -1; + //s->current_page_resolution = 0; x = -1; - if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_1200_1200)) + if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE)) { - if ((s->supported_resolutions & T30_SUPPORT_1200_1200_RESOLUTION)) + /* Gray scale or colour image */ + if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_COLOUR_GRAY_1200_1200)) { - s->x_resolution = T4_X_RESOLUTION_1200; - s->y_resolution = T4_Y_RESOLUTION_1200; - x = 5; + if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_1200_1200)) + { + s->x_resolution = T4_X_RESOLUTION_1200; + s->y_resolution = T4_Y_RESOLUTION_1200; + //s->current_page_resolution = T4_RESOLUTION_1200_1200; + x = 5; + } } - } - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200)) - { - if ((s->supported_resolutions & T30_SUPPORT_600_1200_RESOLUTION)) + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_COLOUR_GRAY_600_600)) { - s->x_resolution = T4_X_RESOLUTION_600; - s->y_resolution = T4_Y_RESOLUTION_1200; - x = 4; + if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_600_600)) + { + s->x_resolution = T4_X_RESOLUTION_600; + s->y_resolution = T4_Y_RESOLUTION_600; + //s->current_page_resolution = T4_RESOLUTION_600_600; + x = 4; + } } - } - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600)) - { - if ((s->supported_resolutions & T30_SUPPORT_600_600_RESOLUTION)) + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400)) { - s->x_resolution = T4_X_RESOLUTION_600; - s->y_resolution = T4_Y_RESOLUTION_600; - x = 4; + if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_400_400)) + { + s->x_resolution = T4_X_RESOLUTION_400; + s->y_resolution = T4_Y_RESOLUTION_400; + //s->current_page_resolution = T4_RESOLUTION_400_400; + x = 3; + } } - } - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_800)) - { - if ((s->supported_resolutions & T30_SUPPORT_400_800_RESOLUTION)) + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_300)) { - s->x_resolution = T4_X_RESOLUTION_R16; - s->y_resolution = T4_Y_RESOLUTION_800; - x = 3; + if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_300_300)) + { + s->x_resolution = T4_X_RESOLUTION_300; + s->y_resolution = T4_Y_RESOLUTION_300; + //s->current_page_resolution = T4_RESOLUTION_300_300; + x = 2; + } } - } - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400)) - { - if ((s->supported_resolutions & T30_SUPPORT_400_400_RESOLUTION)) + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_200)) { - s->x_resolution = T4_X_RESOLUTION_R16; - s->y_resolution = T4_Y_RESOLUTION_SUPERFINE; - x = 3; + if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_200_200)) + { + s->x_resolution = T4_X_RESOLUTION_200; + s->y_resolution = T4_Y_RESOLUTION_200; + //s->current_page_resolution = T4_RESOLUTION_200_200; + x = 1; + } } - } - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600)) - { - if ((s->supported_resolutions & T30_SUPPORT_300_600_RESOLUTION)) + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_COLOUR_GRAY_100_100)) { - s->x_resolution = T4_X_RESOLUTION_300; - s->y_resolution = T4_Y_RESOLUTION_600; - x = 2; - } - } - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_300)) - { - if ((s->supported_resolutions & T30_SUPPORT_300_300_RESOLUTION)) - { - s->x_resolution = T4_X_RESOLUTION_300; - s->y_resolution = T4_Y_RESOLUTION_300; - x = 2; - } - } - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_400)) - { - if ((s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION)) - { - s->x_resolution = T4_X_RESOLUTION_R8; - s->y_resolution = T4_Y_RESOLUTION_SUPERFINE; - x = 1; - } - } - else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_200)) - { - if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION)) - { - s->x_resolution = T4_X_RESOLUTION_R8; - s->y_resolution = T4_Y_RESOLUTION_FINE; - x = 1; + if ((s->supported_colour_resolutions & T30_SUPPORT_RESOLUTION_100_100)) + { + s->x_resolution = T4_X_RESOLUTION_100; + s->y_resolution = T4_Y_RESOLUTION_100; + //s->current_page_resolution = T4_RESOLUTION_100_100; + x = 0; + } } } else { - s->x_resolution = T4_X_RESOLUTION_R8; - s->y_resolution = T4_Y_RESOLUTION_STANDARD; - x = 1; + /* Bi-level image */ + if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_1200_1200)) + { + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_1200_1200)) + { + s->x_resolution = T4_X_RESOLUTION_1200; + s->y_resolution = T4_Y_RESOLUTION_1200; + //s->current_page_resolution = T4_RESOLUTION_1200_1200; + x = 5; + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_1200)) + { + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_600_1200)) + { + s->x_resolution = T4_X_RESOLUTION_600; + s->y_resolution = T4_Y_RESOLUTION_1200; + //s->current_page_resolution = T4_RESOLUTION_600_1200; + x = 4; + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_600_600)) + { + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_600_600)) + { + s->x_resolution = T4_X_RESOLUTION_600; + s->y_resolution = T4_Y_RESOLUTION_600; + //s->current_page_resolution = T4_RESOLUTION_600_600; + x = 4; + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_800)) + { + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_400_800)) + { + s->x_resolution = T4_X_RESOLUTION_400; + s->y_resolution = T4_Y_RESOLUTION_800; + //s->current_page_resolution = T4_RESOLUTION_400_800; + x = 3; + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_400_400)) + { + if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_INCH_RESOLUTION)) + { + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_400_400)) + { + s->x_resolution = T4_X_RESOLUTION_400; + s->y_resolution = T4_Y_RESOLUTION_400; + //s->current_page_resolution = T4_RESOLUTION_400_400; + x = 3; + } + } + else + { + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R16_SUPERFINE)) + { + s->x_resolution = T4_X_RESOLUTION_R16; + s->y_resolution = T4_Y_RESOLUTION_SUPERFINE; + //s->current_page_resolution = T4_RESOLUTION_R16_SUPERFINE; + x = 3; + } + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_600)) + { + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_300_600)) + { + s->x_resolution = T4_X_RESOLUTION_300; + s->y_resolution = T4_Y_RESOLUTION_600; + //s->current_page_resolution = T4_RESOLUTION_300_600; + x = 2; + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_300_300)) + { + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_300_300)) + { + s->x_resolution = T4_X_RESOLUTION_300; + s->y_resolution = T4_Y_RESOLUTION_300; + //s->current_page_resolution = T4_RESOLUTION_300_300; + x = 2; + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_400)) + { + if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_INCH_RESOLUTION)) + { + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_200_400)) + { + s->x_resolution = T4_X_RESOLUTION_200; + s->y_resolution = T4_Y_RESOLUTION_400; + //s->current_page_resolution = T4_RESOLUTION_200_400; + x = 1; + } + } + else + { + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R8_SUPERFINE)) + { + s->x_resolution = T4_X_RESOLUTION_R8; + s->y_resolution = T4_Y_RESOLUTION_SUPERFINE; + //s->current_page_resolution = T4_RESOLUTION_R8_SUPERFINE; + x = 1; + } + } + } + else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_200_200)) + { + if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_INCH_RESOLUTION)) + { + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_200_200)) + { + s->x_resolution = T4_X_RESOLUTION_200; + s->y_resolution = T4_Y_RESOLUTION_200; + //s->current_page_resolution = T4_RESOLUTION_200_200; + x = 1; + } + } + else + { + if ((s->supported_bilevel_resolutions & T30_SUPPORT_RESOLUTION_R8_FINE)) + { + s->x_resolution = T4_X_RESOLUTION_R8; + s->y_resolution = T4_Y_RESOLUTION_FINE; + //s->current_page_resolution = T4_RESOLUTION_R8_FINE; + x = 1; + } + } + } + else + { + if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_INCH_RESOLUTION)) + { + s->x_resolution = T4_X_RESOLUTION_200; + s->y_resolution = T4_Y_RESOLUTION_100; + //s->current_page_resolution = T4_RESOLUTION_200_100; + x = 1; + } + else + { + s->x_resolution = T4_X_RESOLUTION_R8; + s->y_resolution = T4_Y_RESOLUTION_STANDARD; + //s->current_page_resolution = T4_RESOLUTION_R8_STANDARD; + x = 1; + } + } } if (x < 0) @@ -2454,7 +2666,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len) #if defined(SPANDSP_SUPPORT_T42) if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE)) { - s->line_encoding = T4_COMPRESSION_T42; + s->line_encoding = T4_COMPRESSION_T42_T81; } else #endif @@ -3693,8 +3905,7 @@ static void process_state_r(t30_state_t *s, const uint8_t *msg, int len) process_rx_dcs(s, msg, len); break; case T30_DCN: - /* Received a DCN while waiting for a DIS */ - t30_set_status(s, T30_ERR_TX_GOTDCN); + t30_set_status(s, T30_ERR_RX_DCNWHY); disconnect(s); break; case T30_CRP: @@ -3722,7 +3933,7 @@ static void process_state_t(t30_state_t *s, const uint8_t *msg, int len) process_rx_dis_dtc(s, msg, len); break; case T30_DCN: - t30_set_status(s, T30_ERR_RX_DCNWHY); + t30_set_status(s, T30_ERR_TX_GOTDCN); disconnect(s); break; case T30_CRP: @@ -6420,10 +6631,9 @@ SPAN_DECLARE(t30_state_t *) t30_init(t30_state_t *s, /* Default to the basic modems. */ s->supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17; s->supported_compressions = T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D; - s->supported_resolutions = T30_SUPPORT_STANDARD_RESOLUTION - | T30_SUPPORT_FINE_RESOLUTION - | T30_SUPPORT_SUPERFINE_RESOLUTION - | T30_SUPPORT_R8_RESOLUTION; + s->supported_bilevel_resolutions = T30_SUPPORT_RESOLUTION_R8_STANDARD + | T30_SUPPORT_RESOLUTION_R8_FINE + | T30_SUPPORT_RESOLUTION_R8_SUPERFINE; s->supported_image_sizes = T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH diff --git a/libs/spandsp/src/t30_api.c b/libs/spandsp/src/t30_api.c index ea429fe6e7..cc55efea49 100644 --- a/libs/spandsp/src/t30_api.c +++ b/libs/spandsp/src/t30_api.c @@ -693,20 +693,18 @@ SPAN_DECLARE(int) t30_set_supported_modems(t30_state_t *s, int supported_modems) SPAN_DECLARE(int) t30_set_supported_compressions(t30_state_t *s, int supported_compressions) { - int mask; - /* Mask out the ones we actually support today. */ - mask = T30_SUPPORT_COMPRESSION_T4_1D - | T30_SUPPORT_COMPRESSION_T4_2D - | T30_SUPPORT_COMPRESSION_T6 - //| T30_SUPPORT_COMPRESSION_T81 + supported_compressions &= T30_SUPPORT_COMPRESSION_T4_1D + | T30_SUPPORT_COMPRESSION_T4_2D + | T30_SUPPORT_COMPRESSION_T6 + //| T30_SUPPORT_COMPRESSION_T81 #if defined(SPANDSP_SUPPORT_T43) - | T30_SUPPORT_COMPRESSION_T43 + | T30_SUPPORT_COMPRESSION_T43 #endif - | T30_SUPPORT_COMPRESSION_T85 - | T30_SUPPORT_COMPRESSION_T85_L0 - | 0; - s->supported_compressions = supported_compressions & mask; + | T30_SUPPORT_COMPRESSION_T85 + | T30_SUPPORT_COMPRESSION_T85_L0 + | 0; + s->supported_compressions = supported_compressions; t30_build_dis_or_dtc(s); return 0; } @@ -714,7 +712,7 @@ SPAN_DECLARE(int) t30_set_supported_compressions(t30_state_t *s, int supported_c SPAN_DECLARE(int) t30_set_supported_resolutions(t30_state_t *s, int supported_resolutions) { - s->supported_resolutions = supported_resolutions; + s->supported_bilevel_resolutions = supported_resolutions; t30_build_dis_or_dtc(s); return 0; } diff --git a/libs/spandsp/src/t4_rx.c b/libs/spandsp/src/t4_rx.c index e026517d32..dec06eb1ed 100644 --- a/libs/spandsp/src/t4_rx.c +++ b/libs/spandsp/src/t4_rx.c @@ -97,18 +97,18 @@ SPAN_DECLARE(const char *) t4_encoding_to_str(int encoding) return "T.4 2-D"; case T4_COMPRESSION_T6: return "T.6"; - case T4_COMPRESSION_T42: - return "T.42"; - case T4_COMPRESSION_SYCC_T42: - return "sYCC T.42"; - case T4_COMPRESSION_T43: - return "T.43"; - case T4_COMPRESSION_T45: - return "T.45"; case T4_COMPRESSION_T85: return "T.85"; case T4_COMPRESSION_T85_L0: return "T.85(L0)"; + case T4_COMPRESSION_T42_T81: + return "T.81"; + case T4_COMPRESSION_SYCC_T81: + return "sYCC T.81"; + case T4_COMPRESSION_T43: + return "T.43"; + case T4_COMPRESSION_T45: + return "T.45"; } return "???"; } @@ -171,7 +171,7 @@ static int set_tiff_directory_info(t4_rx_state_t *s) output_compression = COMPRESSION_CCITT_T6; break; #if defined(SPANDSP_SUPPORT_T42) - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: output_compression = COMPRESSION_JPEG; bits_per_sample = 8; samples_per_pixel = 3; @@ -299,7 +299,7 @@ static int set_tiff_directory_info(t4_rx_state_t *s) case T4_COMPRESSION_T6: image_length = t4_t6_decode_get_image_length(&s->decoder.t4_t6); break; - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: image_length = t42_decode_get_image_length(&s->decoder.t42); break; #if defined(SPANDSP_SUPPORT_T43) @@ -454,7 +454,7 @@ SPAN_DECLARE(int) t4_rx_put(t4_rx_state_t *s, const uint8_t buf[], size_t len) case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T6: return t4_t6_decode_put(&s->decoder.t4_t6, buf, len); - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: return t42_decode_put(&s->decoder.t42, buf, len); #if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: @@ -529,10 +529,10 @@ SPAN_DECLARE(int) t4_rx_set_rx_encoding(t4_rx_state_t *s, int encoding) } s->line_encoding = encoding; return t4_t6_decode_set_encoding(&s->decoder.t4_t6, encoding); - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: switch (s->line_encoding) { - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: break; default: t42_decode_init(&s->decoder.t42, s->row_handler, s->row_handler_user_data); @@ -599,7 +599,7 @@ SPAN_DECLARE(int) t4_rx_set_row_write_handler(t4_rx_state_t *s, t4_row_write_han case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T6: return t4_t6_decode_set_row_write_handler(&s->decoder.t4_t6, handler, user_data); - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: return t42_decode_set_row_write_handler(&s->decoder.t42, handler, user_data); #if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: @@ -638,7 +638,7 @@ SPAN_DECLARE(void) t4_rx_get_transfer_statistics(t4_rx_state_t *s, t4_stats_t *t t->bad_rows = s->decoder.t4_t6.bad_rows; t->longest_bad_row_run = s->decoder.t4_t6.longest_bad_row_run; break; - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: t->type = 0; t->width = t42_decode_get_image_width(&s->decoder.t42); t->length = t42_decode_get_image_length(&s->decoder.t42); @@ -683,7 +683,7 @@ SPAN_DECLARE(int) t4_rx_start_page(t4_rx_state_t *s) case T4_COMPRESSION_T6: t4_t6_decode_restart(&s->decoder.t4_t6, s->image_width); break; - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: t42_decode_restart(&s->decoder.t42); break; #if defined(SPANDSP_SUPPORT_T43) @@ -740,7 +740,7 @@ SPAN_DECLARE(int) t4_rx_end_page(t4_rx_state_t *s) t4_t6_decode_put(&s->decoder.t4_t6, NULL, 0); length = t4_t6_decode_get_image_length(&s->decoder.t4_t6); break; - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: t42_decode_put(&s->decoder.t42, NULL, 0); length = t42_decode_get_image_length(&s->decoder.t42); break; @@ -840,7 +840,7 @@ SPAN_DECLARE(int) t4_rx_release(t4_rx_state_t *s) case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T6: return t4_t6_decode_release(&s->decoder.t4_t6); - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: return t42_decode_release(&s->decoder.t42); #if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: diff --git a/libs/spandsp/src/t4_tx.c b/libs/spandsp/src/t4_tx.c index 40166b8858..3bb2a03932 100644 --- a/libs/spandsp/src/t4_tx.c +++ b/libs/spandsp/src/t4_tx.c @@ -642,7 +642,7 @@ static int set_row_read_handler(t4_tx_state_t *s, t4_row_read_handler_t handler, case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T6: return t4_t6_encode_set_row_read_handler(&s->encoder.t4_t6, handler, user_data); - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: return t42_encode_set_row_read_handler(&s->encoder.t42, handler, user_data); #if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: @@ -812,10 +812,10 @@ SPAN_DECLARE(int) t4_tx_set_tx_encoding(t4_tx_state_t *s, int encoding) } s->line_encoding = encoding; return t4_t6_encode_set_encoding(&s->encoder.t4_t6, encoding); - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: switch (s->line_encoding) { - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: break; default: t42_encode_init(&s->encoder.t42, s->image_width, s->image_length, s->row_handler, s->row_handler_user_data); @@ -877,7 +877,7 @@ SPAN_DECLARE(void) t4_tx_set_image_width(t4_tx_state_t *s, int image_width) case T4_COMPRESSION_T6: t4_t6_encode_set_image_width(&s->encoder.t4_t6, image_width); break; - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: t42_encode_set_image_width(&s->encoder.t42, image_width); break; #if defined(SPANDSP_SUPPORT_T43) @@ -898,7 +898,7 @@ static void t4_tx_set_image_length(t4_tx_state_t *s, int image_length) s->image_length = image_length; switch (s->line_encoding) { - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: t42_encode_set_image_length(&s->encoder.t42, image_length); break; #if defined(SPANDSP_SUPPORT_T43) @@ -1014,7 +1014,7 @@ SPAN_DECLARE(void) t4_tx_get_transfer_statistics(t4_tx_state_t *s, t4_stats_t *t t->length = t4_t6_encode_get_image_length(&s->encoder.t4_t6)/s->row_squashing_ratio; t->line_image_size = t4_t6_encode_get_compressed_image_size(&s->encoder.t4_t6)/8; break; - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: t->type = 0; t->width = t42_encode_get_image_width(&s->encoder.t42); t->length = t42_encode_get_image_length(&s->encoder.t42)/s->row_squashing_ratio; @@ -1047,7 +1047,7 @@ SPAN_DECLARE(int) t4_tx_image_complete(t4_tx_state_t *s) case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T6: return t4_t6_encode_image_complete(&s->encoder.t4_t6); - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: return t42_encode_image_complete(&s->encoder.t42); #if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: @@ -1076,7 +1076,7 @@ SPAN_DECLARE(int) t4_tx_get(t4_tx_state_t *s, uint8_t buf[], size_t max_len) case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T6: return t4_t6_encode_get(&s->encoder.t4_t6, buf, max_len); - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: return t42_encode_get(&s->encoder.t42, buf, max_len); #if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: @@ -1115,7 +1115,7 @@ SPAN_DECLARE(int) t4_tx_start_page(t4_tx_state_t *s) case T4_COMPRESSION_T6: t4_t6_encode_restart(&s->encoder.t4_t6, s->image_width); break; - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: t42_encode_restart(&s->encoder.t42, s->image_width, s->image_length); break; #if defined(SPANDSP_SUPPORT_T43) @@ -1237,7 +1237,7 @@ SPAN_DECLARE(int) t4_tx_release(t4_tx_state_t *s) case T4_COMPRESSION_T4_2D: case T4_COMPRESSION_T6: return t4_t6_encode_release(&s->encoder.t4_t6); - case T4_COMPRESSION_T42: + case T4_COMPRESSION_T42_T81: return t42_encode_release(&s->encoder.t42); #if defined(SPANDSP_SUPPORT_T43) case T4_COMPRESSION_T43: diff --git a/libs/spandsp/src/v18.c b/libs/spandsp/src/v18.c index 3529fe6f0d..16f5da5ac6 100644 --- a/libs/spandsp/src/v18.c +++ b/libs/spandsp/src/v18.c @@ -629,22 +629,21 @@ SPAN_DECLARE(uint8_t) v18_decode_baudot(v18_state_t *s, uint8_t ch) } /*- End of function --------------------------------------------------------*/ -static void v18_rx_dtmf(void *user_data, const char digits[], int len) -{ -#if 0 - v18_state_t *s; - - s = (v18_state_t *) user_data; -#endif -} -/*- End of function --------------------------------------------------------*/ - static int v18_tdd_get_async_byte(void *user_data) { v18_state_t *s; int ch; + unsigned int x; s = (v18_state_t *) user_data; + + if (s->next_byte != 0xFF) + { + s->rx_suppression = (300*SAMPLE_RATE)/1000; + x = s->next_byte; + s->next_byte = (uint8_t) 0xFF; + return x; + } if ((ch = queue_read_byte(&s->queue.queue)) >= 0) return ch; if (s->tx_signal_on) @@ -656,8 +655,38 @@ static int v18_tdd_get_async_byte(void *user_data) } /*- End of function --------------------------------------------------------*/ +static void v18_dtmf_get(void *user_data) +{ + v18_state_t *s; + int ch; + const char *v; + + 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->dtmftx, v, strlen(v)); + s->rx_suppression = ((300 + 100*strlen(v))*SAMPLE_RATE)/1000; + } +} +/*- End of function --------------------------------------------------------*/ + static int v18_edt_get_async_byte(void *user_data) { + v18_state_t *s; + int ch; + + s = (v18_state_t *) user_data; + if ((ch = queue_read_byte(&s->queue.queue)) >= 0) + { + s->rx_suppression = (300*SAMPLE_RATE)/1000; + return ch; + } + if (s->tx_signal_on) + { + /* The FSK should now be switched off. */ + s->tx_signal_on = FALSE; + } return 0; } /*- End of function --------------------------------------------------------*/ @@ -709,23 +738,62 @@ static void v18_tdd_put_async_byte(void *user_data, int byte) } /*- 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; + + s = (v18_state_t *) user_data; + if (s->rx_suppression > 0) + return; + for (i = 0; i < len; i++) + { + s->rx_msg[s->rx_msg_len++] = dtmf[i]; + 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) + s->put_msg(s->user_data, (const uint8_t *) buf, 1); + s->rx_msg_len = 0; + } + } +} +/*- End of function --------------------------------------------------------*/ + static void v18_edt_put_async_byte(void *user_data, int byte) { + v18_state_t *s; + s = (v18_state_t *) user_data; + if (s->rx_suppression > 0) + return; } /*- End of function --------------------------------------------------------*/ static void v18_bell103_put_async_byte(void *user_data, int byte) { + v18_state_t *s; + s = (v18_state_t *) user_data; + if (s->rx_suppression > 0) + return; } /*- End of function --------------------------------------------------------*/ static void v18_videotex_put_async_byte(void *user_data, int byte) { + v18_state_t *s; + s = (v18_state_t *) user_data; + if (s->rx_suppression > 0) + return; } /*- End of function --------------------------------------------------------*/ static void v18_textphone_put_async_byte(void *user_data, int byte) { + v18_state_t *s; + s = (v18_state_t *) user_data; + if (s->rx_suppression > 0) + return; } /*- End of function --------------------------------------------------------*/ @@ -759,6 +827,13 @@ SPAN_DECLARE_NONSTD(int) v18_tx(v18_state_t *s, int16_t *amp, int max_len) SPAN_DECLARE_NONSTD(int) v18_rx(v18_state_t *s, const int16_t amp[], int len) { + if (s->rx_suppression > 0) + { + if (s->rx_suppression > len) + s->rx_suppression -= len; + else + s->rx_suppression = 0; + } switch (s->mode) { case V18_MODE_DTMF: @@ -776,6 +851,32 @@ SPAN_DECLARE_NONSTD(int) v18_rx(v18_state_t *s, const int16_t amp[], int len) } /*- End of function --------------------------------------------------------*/ +SPAN_DECLARE_NONSTD(int) v18_rx_fillin(v18_state_t *s, int len) +{ + if (s->rx_suppression > 0) + { + if (s->rx_suppression > len) + s->rx_suppression -= len; + else + s->rx_suppression = 0; + } + switch (s->mode) + { + case V18_MODE_DTMF: + /* Apply a message timeout. */ + //s->in_progress -= len; + //if (s->in_progress <= 0) + // s->rx_msg_len = 0; + dtmf_rx_fillin(&s->dtmfrx, len); + break; + default: + fsk_rx_fillin(&s->fskrx, len); + break; + } + return 0; +} +/*- End of function --------------------------------------------------------*/ + SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len) { char buf[256 + 1]; @@ -819,7 +920,7 @@ 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 & 0xFF)) { case V18_MODE_NONE: return "None"; @@ -870,6 +971,7 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s, switch (s->mode) { case V18_MODE_5BIT_45: + s->repeat_shifts = mode & 0x100; fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &s->asynctx); async_tx_init(&s->asynctx, 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s); /* Schedule an explicit shift at the start of baudot transmission */ @@ -878,9 +980,10 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s, ride over the fraction. */ fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s); s->baudot_rx_shift = 0; - s->repeat_shifts = mode & 0x100; + s->next_byte = (uint8_t) 0xFF; break; case V18_MODE_5BIT_50: + s->repeat_shifts = mode & 0x100; fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_WEITBRECHT50], async_tx_get_bit, &s->asynctx); async_tx_init(&s->asynctx, 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s); /* Schedule an explicit shift at the start of baudot transmission */ @@ -889,11 +992,11 @@ SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s, ride over the fraction. */ fsk_rx_init(&s->fskrx, &preset_fsk_specs[FSK_WEITBRECHT50], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s); s->baudot_rx_shift = 0; - s->repeat_shifts = mode & 0x100; + s->next_byte = (uint8_t) 0xFF; break; case V18_MODE_DTMF: - dtmf_tx_init(&s->dtmftx, NULL, NULL); - dtmf_rx_init(&s->dtmfrx, v18_rx_dtmf, s); + dtmf_tx_init(&s->dtmftx, v18_dtmf_get, s); + dtmf_rx_init(&s->dtmfrx, v18_dtmf_put, s); break; case V18_MODE_EDT: fsk_tx_init(&s->fsktx, &preset_fsk_specs[FSK_V21CH1_110], async_tx_get_bit, &s->asynctx); diff --git a/libs/spandsp/test-data/itu/fax/generate_striped_pages.c b/libs/spandsp/test-data/itu/fax/generate_striped_pages.c index 63b8e755c7..1232ca6896 100644 --- a/libs/spandsp/test-data/itu/fax/generate_striped_pages.c +++ b/libs/spandsp/test-data/itu/fax/generate_striped_pages.c @@ -108,7 +108,7 @@ int main(int argc, char *argv[]) image_size = IMAGE_WIDTH*ROWS_PER_STRIPE/8; memset(image_buffer, 0x18, image_size); - for (i = 0; i < IMAGE_LENGTH/ROWS_PER_STRIPE; i++) + for (i = 0; i*ROWS_PER_STRIPE < IMAGE_LENGTH; i++) { if (IMAGE_LENGTH > (i + 1)*ROWS_PER_STRIPE) image_size = IMAGE_WIDTH*ROWS_PER_STRIPE/8; diff --git a/libs/spandsp/tests/async_tests.c b/libs/spandsp/tests/async_tests.c index bd1a7d9d07..49010c3a73 100644 --- a/libs/spandsp/tests/async_tests.c +++ b/libs/spandsp/tests/async_tests.c @@ -59,6 +59,7 @@ int v14_test_async_tx_get_bit(void *user_data) { async_tx_state_t *s; int bit; + int parity_bit; static int destuff = 0; /* Special routine to test V.14 rate adaption, by randomly skipping @@ -66,42 +67,39 @@ int v14_test_async_tx_get_bit(void *user_data) s = (async_tx_state_t *) user_data; if (s->bitpos == 0) { + s->byte_in_progress = s->get_byte(s->user_data); + s->byte_in_progress &= (0xFFFF >> (16 - s->data_bits)); + if (s->parity) + { + parity_bit = parity8(s->byte_in_progress); + if (s->parity == ASYNC_PARITY_ODD) + parity_bit ^= 1; + s->byte_in_progress |= (parity_bit << s->data_bits); + s->byte_in_progress |= (0xFFFF << (s->data_bits + 1)); + } + else + { + s->byte_in_progress |= (0xFFFF << s->data_bits); + } /* Start bit */ bit = 0; - s->byte_in_progress = s->get_byte(s->user_data); - s->parity_bit = 0; s->bitpos++; } - else if (s->bitpos <= s->data_bits) - { - bit = s->byte_in_progress & 1; - s->byte_in_progress >>= 1; - s->parity_bit ^= bit; - s->bitpos++; - if (!s->parity && s->bitpos == s->data_bits + 1) - { - /* Drop the stop bit on every fourth character for V.14 simulation*/ - if ((++destuff & 3) == 0) - s->bitpos = 0; - } - } - else if (s->parity && s->bitpos == s->data_bits + 1) - { - if (s->parity == ASYNC_PARITY_ODD) - s->parity_bit ^= 1; - bit = s->parity_bit; - s->bitpos++; - /* Drop the stop bit on every fourth character for V.14 simulation */ - if ((++destuff & 3) == 0) - s->bitpos = 0; - } else { - /* Stop bit(s) */ - bit = 1; - s->bitpos++; - if (s->bitpos > s->data_bits + s->stop_bits) - s->bitpos = 0; + bit = s->byte_in_progress & 1; + s->byte_in_progress >>= 1; + /* Drop the stop bit on every fourth character for V.14 simulation */ + if ((++destuff & 3) == 0) + { + if (++s->bitpos > s->total_bits - 1) + s->bitpos = 0; + } + else + { + if (++s->bitpos > s->total_bits) + s->bitpos = 0; + } } return bit; } @@ -207,7 +205,7 @@ int main(int argc, char *argv[]) async_rx_put_bit(&rx_async, bit); } printf("Chars=%d/%d, PE=%d, FE=%d\n", tx_async_chars, rx_async_chars, rx_async.parity_errors, rx_async.framing_errors); - if (tx_async_chars != rx_async_chars + 1 + if (tx_async_chars != rx_async_chars || rx_async.parity_errors || diff --git a/libs/spandsp/tests/fax_tests.c b/libs/spandsp/tests/fax_tests.c index 4e98c3beff..622d2fb4de 100644 --- a/libs/spandsp/tests/fax_tests.c +++ b/libs/spandsp/tests/fax_tests.c @@ -846,18 +846,20 @@ int main(int argc, char *argv[]) | T30_SUPPORT_255MM_WIDTH | T30_SUPPORT_303MM_WIDTH); t30_set_supported_resolutions(t30_state[i], - T30_SUPPORT_STANDARD_RESOLUTION - | T30_SUPPORT_FINE_RESOLUTION - | T30_SUPPORT_SUPERFINE_RESOLUTION - | T30_SUPPORT_R8_RESOLUTION - | T30_SUPPORT_R16_RESOLUTION - | T30_SUPPORT_300_300_RESOLUTION - | T30_SUPPORT_400_400_RESOLUTION - | T30_SUPPORT_600_600_RESOLUTION - | T30_SUPPORT_1200_1200_RESOLUTION - | T30_SUPPORT_300_600_RESOLUTION - | T30_SUPPORT_400_800_RESOLUTION - | T30_SUPPORT_600_1200_RESOLUTION); + T30_SUPPORT_RESOLUTION_R8_STANDARD + | T30_SUPPORT_RESOLUTION_R8_FINE + | T30_SUPPORT_RESOLUTION_R8_SUPERFINE + | T30_SUPPORT_RESOLUTION_R16_SUPERFINE + | T30_SUPPORT_RESOLUTION_200_100 + | T30_SUPPORT_RESOLUTION_200_200 + | T30_SUPPORT_RESOLUTION_200_400 + | T30_SUPPORT_RESOLUTION_300_300 + | T30_SUPPORT_RESOLUTION_300_600 + | T30_SUPPORT_RESOLUTION_400_400 + | T30_SUPPORT_RESOLUTION_400_800 + | T30_SUPPORT_RESOLUTION_600_600 + | T30_SUPPORT_RESOLUTION_600_1200 + | T30_SUPPORT_RESOLUTION_1200_1200); //t30_set_rx_encoding(t30_state[i], T4_COMPRESSION_T85); t30_set_ecm_capability(t30_state[i], use_ecm); if (use_ecm) diff --git a/libs/spandsp/tests/fax_tests.sh b/libs/spandsp/tests/fax_tests.sh index a6f762c020..564cdaa4ba 100755 --- a/libs/spandsp/tests/fax_tests.sh +++ b/libs/spandsp/tests/fax_tests.sh @@ -43,6 +43,19 @@ ITUTESTS_DIR=../test-data/itu/fax for OPTS in "-p AA" "-p AA -e" "-p TT" "-p TT -e" "-p GG" "-p GG -e" "-p TG" "-p TG -e" "-p GT" "-p GT -e" do + FILE="${ITUTESTS_DIR}/itutests.tif" + run_fax_test + + FILE="${ITUTESTS_DIR}/100pages.tif" + run_fax_test + + FILE="${ITUTESTS_DIR}/striped.tif" + run_fax_test + + + FILE="${ITUTESTS_DIR}/mixed_size_pages.tif" + run_fax_test + FILE="${ITUTESTS_DIR}/bilevel_R8_385_A4.tif" run_fax_test diff --git a/libs/spandsp/tests/tsb85_tests.c b/libs/spandsp/tests/tsb85_tests.c index a4293eafed..14d37f4604 100644 --- a/libs/spandsp/tests/tsb85_tests.c +++ b/libs/spandsp/tests/tsb85_tests.c @@ -393,18 +393,20 @@ static void fax_prepare(void) | T30_SUPPORT_255MM_WIDTH | T30_SUPPORT_303MM_WIDTH); t30_set_supported_resolutions(t30, - T30_SUPPORT_STANDARD_RESOLUTION - | T30_SUPPORT_FINE_RESOLUTION - | T30_SUPPORT_SUPERFINE_RESOLUTION - | T30_SUPPORT_R8_RESOLUTION - | T30_SUPPORT_R16_RESOLUTION - | T30_SUPPORT_300_300_RESOLUTION - | T30_SUPPORT_400_400_RESOLUTION - | T30_SUPPORT_600_600_RESOLUTION - | T30_SUPPORT_1200_1200_RESOLUTION - | T30_SUPPORT_300_600_RESOLUTION - | T30_SUPPORT_400_800_RESOLUTION - | T30_SUPPORT_600_1200_RESOLUTION); + T30_SUPPORT_RESOLUTION_R8_STANDARD + | T30_SUPPORT_RESOLUTION_R8_FINE + | T30_SUPPORT_RESOLUTION_R8_SUPERFINE + | T30_SUPPORT_RESOLUTION_R16_SUPERFINE + | T30_SUPPORT_RESOLUTION_200_100 + | T30_SUPPORT_RESOLUTION_200_200 + | T30_SUPPORT_RESOLUTION_200_400 + | T30_SUPPORT_RESOLUTION_300_300 + | T30_SUPPORT_RESOLUTION_300_600 + | T30_SUPPORT_RESOLUTION_400_400 + | T30_SUPPORT_RESOLUTION_400_800 + | T30_SUPPORT_RESOLUTION_600_600 + | T30_SUPPORT_RESOLUTION_600_1200 + | T30_SUPPORT_RESOLUTION_1200_1200); t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17); t30_set_supported_compressions(t30, T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D | T30_SUPPORT_COMPRESSION_T6); t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A'); diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c index 10da2ab642..a5766021c5 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c @@ -876,8 +876,8 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode) T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH | T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH | T30_SUPPORT_303MM_WIDTH); t30_set_supported_resolutions(t30, - T30_SUPPORT_STANDARD_RESOLUTION | T30_SUPPORT_FINE_RESOLUTION | T30_SUPPORT_SUPERFINE_RESOLUTION - | T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION); + T30_SUPPORT_RESOLUTION_R8_STANDARD | T30_SUPPORT_RESOLUTION_R8_FINE | T30_SUPPORT_RESOLUTION_R8_SUPERFINE + | T30_SUPPORT_RESOLUTION_R16_SUPERFINE); if (pvt->disable_v17) { t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER);