More movement towards colour FAXing
This commit is contained in:
parent
8e49f7a556
commit
88b3b54ef4
|
@ -261,6 +261,8 @@ fi
|
||||||
SPANDSP_SUPPORT_T42="#undef SPANDSP_SUPPORT_T42"
|
SPANDSP_SUPPORT_T42="#undef SPANDSP_SUPPORT_T42"
|
||||||
#AC_DEFINE([SPANDSP_SUPPORT_T43], [1], [Support T.43 JBIG gray and colour compression])
|
#AC_DEFINE([SPANDSP_SUPPORT_T43], [1], [Support T.43 JBIG gray and colour compression])
|
||||||
SPANDSP_SUPPORT_T43="#undef SPANDSP_SUPPORT_T43"
|
SPANDSP_SUPPORT_T43="#undef SPANDSP_SUPPORT_T43"
|
||||||
|
#AC_DEFINE([SPANDSP_SUPPORT_V32BIS], [1], [Support the V.32bis modem])
|
||||||
|
SPANDSP_SUPPORT_V32BIS="#undef SPANDSP_SUPPORT_V32BIS"
|
||||||
#AC_DEFINE([SPANDSP_SUPPORT_V34], [1], [Support the V.34 FAX modem])
|
#AC_DEFINE([SPANDSP_SUPPORT_V34], [1], [Support the V.34 FAX modem])
|
||||||
SPANDSP_SUPPORT_V34="#undef SPANDSP_SUPPORT_V34"
|
SPANDSP_SUPPORT_V34="#undef SPANDSP_SUPPORT_V34"
|
||||||
|
|
||||||
|
@ -567,6 +569,7 @@ AC_SUBST(SPANDSP_MISALIGNED_ACCESS_FAILS)
|
||||||
AC_SUBST(SPANDSP_USE_EXPORT_CAPABILITY)
|
AC_SUBST(SPANDSP_USE_EXPORT_CAPABILITY)
|
||||||
AC_SUBST(SPANDSP_SUPPORT_T42)
|
AC_SUBST(SPANDSP_SUPPORT_T42)
|
||||||
AC_SUBST(SPANDSP_SUPPORT_T43)
|
AC_SUBST(SPANDSP_SUPPORT_T43)
|
||||||
|
AC_SUBST(SPANDSP_SUPPORT_V32BIS)
|
||||||
AC_SUBST(SPANDSP_SUPPORT_V34)
|
AC_SUBST(SPANDSP_SUPPORT_V34)
|
||||||
AC_SUBST(SPANDSP_SUPPORT_TIFF_FX)
|
AC_SUBST(SPANDSP_SUPPORT_TIFF_FX)
|
||||||
AC_SUBST(INSERT_INTTYPES_HEADER)
|
AC_SUBST(INSERT_INTTYPES_HEADER)
|
||||||
|
|
|
@ -22,28 +22,17 @@ AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
|
||||||
DISTCLEANFILES = $(srcdir)/at_interpreter_dictionary.h \
|
DISTCLEANFILES = $(srcdir)/at_interpreter_dictionary.h \
|
||||||
$(srcdir)/cielab_luts.h \
|
$(srcdir)/cielab_luts.h \
|
||||||
$(srcdir)/math_fixed_tables.h \
|
$(srcdir)/math_fixed_tables.h \
|
||||||
$(srcdir)/v17_v32bis_rx_fixed_rrc.h \
|
$(srcdir)/v17_v32bis_rx_rrc.h \
|
||||||
$(srcdir)/v17_v32bis_rx_floating_rrc.h \
|
$(srcdir)/v17_v32bis_tx_rrc.h \
|
||||||
$(srcdir)/v17_v32bis_tx_fixed_rrc.h \
|
$(srcdir)/v22bis_rx_1200_rrc.h \
|
||||||
$(srcdir)/v17_v32bis_tx_floating_rrc.h \
|
$(srcdir)/v22bis_rx_2400_rrc.h \
|
||||||
$(srcdir)/v22bis_rx_1200_fixed_rrc.h \
|
$(srcdir)/v22bis_tx_rrc.h \
|
||||||
$(srcdir)/v22bis_rx_2400_fixed_rrc.h \
|
$(srcdir)/v27ter_rx_2400_rrc.h \
|
||||||
$(srcdir)/v22bis_rx_1200_floating_rrc.h \
|
$(srcdir)/v27ter_rx_4800_rrc.h \
|
||||||
$(srcdir)/v22bis_rx_2400_floating_rrc.h \
|
$(srcdir)/v27ter_tx_2400_rrc.h \
|
||||||
$(srcdir)/v22bis_tx_fixed_rrc.h \
|
$(srcdir)/v27ter_tx_4800_rrc.h \
|
||||||
$(srcdir)/v22bis_tx_floating_rrc.h \
|
$(srcdir)/v29rx_rrc.h \
|
||||||
$(srcdir)/v27ter_rx_2400_fixed_rrc.h \
|
$(srcdir)/v29tx_rrc.h
|
||||||
$(srcdir)/v27ter_rx_4800_fixed_rrc.h \
|
|
||||||
$(srcdir)/v27ter_rx_2400_floating_rrc.h \
|
|
||||||
$(srcdir)/v27ter_rx_4800_floating_rrc.h \
|
|
||||||
$(srcdir)/v27ter_tx_2400_fixed_rrc.h \
|
|
||||||
$(srcdir)/v27ter_tx_4800_fixed_rrc.h \
|
|
||||||
$(srcdir)/v27ter_tx_2400_floating_rrc.h \
|
|
||||||
$(srcdir)/v27ter_tx_4800_floating_rrc.h \
|
|
||||||
$(srcdir)/v29rx_fixed_rrc.h \
|
|
||||||
$(srcdir)/v29rx_floating_rrc.h \
|
|
||||||
$(srcdir)/v29tx_fixed_rrc.h \
|
|
||||||
$(srcdir)/v29tx_floating_rrc.h
|
|
||||||
|
|
||||||
CLEANFILES = ${DISTCLEANFILES}
|
CLEANFILES = ${DISTCLEANFILES}
|
||||||
MOSTLYCLEANFILES = ${DISTCLEANFILES}
|
MOSTLYCLEANFILES = ${DISTCLEANFILES}
|
||||||
|
@ -160,6 +149,7 @@ libspandsp_la_SOURCES = ademco_contactid.c \
|
||||||
t4_rx.c \
|
t4_rx.c \
|
||||||
t4_tx.c \
|
t4_tx.c \
|
||||||
t42.c \
|
t42.c \
|
||||||
|
t43.c \
|
||||||
t81_t82_arith_coding.c \
|
t81_t82_arith_coding.c \
|
||||||
t85_decode.c \
|
t85_decode.c \
|
||||||
t85_encode.c \
|
t85_encode.c \
|
||||||
|
@ -251,6 +241,7 @@ nobase_include_HEADERS = spandsp/ademco_contactid.h \
|
||||||
spandsp/t4_t6_decode.h \
|
spandsp/t4_t6_decode.h \
|
||||||
spandsp/t4_t6_encode.h \
|
spandsp/t4_t6_encode.h \
|
||||||
spandsp/t42.h \
|
spandsp/t42.h \
|
||||||
|
spandsp/t43.h \
|
||||||
spandsp/t81_t82_arith_coding.h \
|
spandsp/t81_t82_arith_coding.h \
|
||||||
spandsp/t85.h \
|
spandsp/t85.h \
|
||||||
spandsp/telephony.h \
|
spandsp/telephony.h \
|
||||||
|
@ -318,6 +309,7 @@ nobase_include_HEADERS = spandsp/ademco_contactid.h \
|
||||||
spandsp/private/t4_t6_decode.h \
|
spandsp/private/t4_t6_decode.h \
|
||||||
spandsp/private/t4_t6_encode.h \
|
spandsp/private/t4_t6_encode.h \
|
||||||
spandsp/private/t42.h \
|
spandsp/private/t42.h \
|
||||||
|
spandsp/private/t43.h \
|
||||||
spandsp/private/t81_t82_arith_coding.h \
|
spandsp/private/t81_t82_arith_coding.h \
|
||||||
spandsp/private/t85.h \
|
spandsp/private/t85.h \
|
||||||
spandsp/private/time_scale.h \
|
spandsp/private/time_scale.h \
|
||||||
|
|
|
@ -511,6 +511,9 @@ SPAN_DECLARE(fax_modems_state_t *) fax_modems_init(fax_modems_state_t *s,
|
||||||
s->use_tep = use_tep;
|
s->use_tep = use_tep;
|
||||||
|
|
||||||
modem_connect_tones_tx_init(&s->connect_tx, MODEM_CONNECT_TONES_FAX_CNG);
|
modem_connect_tones_tx_init(&s->connect_tx, MODEM_CONNECT_TONES_FAX_CNG);
|
||||||
|
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
|
||||||
|
span_log_set_protocol(&s->logging, "FAX modems");
|
||||||
|
|
||||||
s->tone_callback = tone_callback;
|
s->tone_callback = tone_callback;
|
||||||
s->tone_callback_user_data = user_data;
|
s->tone_callback_user_data = user_data;
|
||||||
if (tone_callback)
|
if (tone_callback)
|
||||||
|
@ -521,9 +524,6 @@ SPAN_DECLARE(fax_modems_state_t *) fax_modems_init(fax_modems_state_t *s,
|
||||||
s->tone_callback_user_data);
|
s->tone_callback_user_data);
|
||||||
}
|
}
|
||||||
/*endif*/
|
/*endif*/
|
||||||
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
|
|
||||||
span_log_set_protocol(&s->logging, "FAX modems");
|
|
||||||
|
|
||||||
dc_restore_init(&s->dc_restore);
|
dc_restore_init(&s->dc_restore);
|
||||||
|
|
||||||
s->get_bit = non_ecm_get_bit;
|
s->get_bit = non_ecm_get_bit;
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
@SPANDSP_SUPPORT_T42@
|
@SPANDSP_SUPPORT_T42@
|
||||||
@SPANDSP_SUPPORT_T43@
|
@SPANDSP_SUPPORT_T43@
|
||||||
|
@SPANDSP_SUPPORT_V32BIS@
|
||||||
@SPANDSP_SUPPORT_V34@
|
@SPANDSP_SUPPORT_V34@
|
||||||
@SPANDSP_SUPPORT_TIFF_FX@
|
@SPANDSP_SUPPORT_TIFF_FX@
|
||||||
|
|
||||||
|
@ -96,11 +97,15 @@
|
||||||
#include <spandsp/v29tx.h>
|
#include <spandsp/v29tx.h>
|
||||||
#include <spandsp/v17rx.h>
|
#include <spandsp/v17rx.h>
|
||||||
#include <spandsp/v17tx.h>
|
#include <spandsp/v17tx.h>
|
||||||
/*#include <spandsp/v32bis.h>*/
|
#if defined(SPANDSP_SUPPORT_V32BIS)
|
||||||
|
#include <spandsp/v32bis.h>
|
||||||
|
#endif
|
||||||
#include <spandsp/v22bis.h>
|
#include <spandsp/v22bis.h>
|
||||||
#include <spandsp/v27ter_rx.h>
|
#include <spandsp/v27ter_rx.h>
|
||||||
#include <spandsp/v27ter_tx.h>
|
#include <spandsp/v27ter_tx.h>
|
||||||
/*#include <spandsp/v34.h>*/
|
#if defined(SPANDSP_SUPPORT_V34)
|
||||||
|
#include <spandsp/v34.h>
|
||||||
|
#endif
|
||||||
#include <spandsp/v18.h>
|
#include <spandsp/v18.h>
|
||||||
#include <spandsp/timezone.h>
|
#include <spandsp/timezone.h>
|
||||||
#include <spandsp/t4_rx.h>
|
#include <spandsp/t4_rx.h>
|
||||||
|
@ -111,7 +116,9 @@
|
||||||
#include <spandsp/t81_t82_arith_coding.h>
|
#include <spandsp/t81_t82_arith_coding.h>
|
||||||
#include <spandsp/t85.h>
|
#include <spandsp/t85.h>
|
||||||
#include <spandsp/t42.h>
|
#include <spandsp/t42.h>
|
||||||
/*#include <spandsp/t43.h>*/
|
#if defined(SPANDSP_SUPPORT_T43)
|
||||||
|
#include <spandsp/t43.h>
|
||||||
|
#endif
|
||||||
#include <spandsp/t30.h>
|
#include <spandsp/t30.h>
|
||||||
#include <spandsp/t30_api.h>
|
#include <spandsp/t30_api.h>
|
||||||
#include <spandsp/t30_fcf.h>
|
#include <spandsp/t30_fcf.h>
|
||||||
|
|
|
@ -35,6 +35,10 @@ struct fax_modems_state_s
|
||||||
{
|
{
|
||||||
/*! TRUE is talker echo protection should be sent for the image modems */
|
/*! TRUE is talker echo protection should be sent for the image modems */
|
||||||
int use_tep;
|
int use_tep;
|
||||||
|
/*! \brief The callback function used to report detected tones. */
|
||||||
|
tone_report_func_t tone_callback;
|
||||||
|
/*! \brief A user specified opaque pointer passed to the tone_callback function. */
|
||||||
|
void *tone_callback_user_data;
|
||||||
|
|
||||||
/*! If TRUE, transmit silence when there is nothing else to transmit. If FALSE return only
|
/*! If TRUE, transmit silence when there is nothing else to transmit. If FALSE return only
|
||||||
the actual generated audio. Note that this only affects untimed silences. Timed silences
|
the actual generated audio. Note that this only affects untimed silences. Timed silences
|
||||||
|
@ -82,11 +86,6 @@ struct fax_modems_state_s
|
||||||
/*! \brief */
|
/*! \brief */
|
||||||
dc_restore_state_t dc_restore;
|
dc_restore_state_t dc_restore;
|
||||||
|
|
||||||
/*! \brief The callback function used to report detected tones. */
|
|
||||||
tone_report_func_t tone_callback;
|
|
||||||
/*! \brief A user specified opaque pointer passed to the tone_callback function. */
|
|
||||||
void *tone_callback_user_data;
|
|
||||||
|
|
||||||
/*! \brief The fast modem type currently in use */
|
/*! \brief The fast modem type currently in use */
|
||||||
int fast_modem;
|
int fast_modem;
|
||||||
|
|
||||||
|
|
|
@ -50,8 +50,12 @@ struct t30_state_s
|
||||||
int iaf;
|
int iaf;
|
||||||
/*! \brief A bit mask of the currently supported modem types. */
|
/*! \brief A bit mask of the currently supported modem types. */
|
||||||
int supported_modems;
|
int supported_modems;
|
||||||
/*! \brief A bit mask of the currently supported image compression modes. */
|
/*! \brief A bit mask of the currently supported image compression modes for use
|
||||||
|
between FAX entities. */
|
||||||
int supported_compressions;
|
int supported_compressions;
|
||||||
|
/*! \brief A bit mask of the currently supported image compression modes for the output
|
||||||
|
of received page images. */
|
||||||
|
int supported_output_compressions;
|
||||||
/*! \brief A bit mask of the currently supported bi-level image resolutions. */
|
/*! \brief A bit mask of the currently supported bi-level image resolutions. */
|
||||||
int supported_bilevel_resolutions;
|
int supported_bilevel_resolutions;
|
||||||
/*! \brief A bit mask of the currently supported gray-scale and colour image resolutions. */
|
/*! \brief A bit mask of the currently supported gray-scale and colour image resolutions. */
|
||||||
|
|
|
@ -497,6 +497,12 @@
|
||||||
#define T30_DCS_BIT_T38_FAX_MODE 123
|
#define T30_DCS_BIT_T38_FAX_MODE 123
|
||||||
|
|
||||||
/* Bits 124 to 126 specify the T.89 applications profile. */
|
/* Bits 124 to 126 specify the T.89 applications profile. */
|
||||||
|
#define T30_DIS_BIT_T88_CAPABILITY_1 124
|
||||||
|
#define T30_DCS_BIT_T88_MODE_1 124
|
||||||
|
#define T30_DIS_BIT_T88_CAPABILITY_2 125
|
||||||
|
#define T30_DCS_BIT_T88_MODE_2 125
|
||||||
|
#define T30_DIS_BIT_T88_CAPABILITY_3 126
|
||||||
|
#define T30_DCS_BIT_T88_MODE_3 126
|
||||||
|
|
||||||
/* When either bit of 31, 36, 38, 51, 53, 54, 55, 57, 59, 60, 62, 65, 68, 78, 79, 115, 116 and 127 is
|
/* When either bit of 31, 36, 38, 51, 53, 54, 55, 57, 59, 60, 62, 65, 68, 78, 79, 115, 116 and 127 is
|
||||||
set to "1", ECM must be used. If the value of bit field 92 to 94 is non-zero, then ECM must be used.
|
set to "1", ECM must be used. If the value of bit field 92 to 94 is non-zero, then ECM must be used.
|
||||||
|
|
|
@ -66,10 +66,6 @@ typedef struct
|
||||||
{
|
{
|
||||||
/*! \brief The FAX modem set for the audio side fo the gateway. */
|
/*! \brief The FAX modem set for the audio side fo the gateway. */
|
||||||
fax_modems_state_t modems;
|
fax_modems_state_t modems;
|
||||||
/*! \brief CED detector */
|
|
||||||
modem_connect_tones_rx_state_t connect_rx_ced;
|
|
||||||
/*! \brief CNG detector */
|
|
||||||
modem_connect_tones_rx_state_t connect_rx_cng;
|
|
||||||
} t38_gateway_audio_state_t;
|
} t38_gateway_audio_state_t;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* SpanDSP - a series of DSP components for telephony
|
||||||
|
*
|
||||||
|
* private/t43.h - ITU T.43 JBIG for gray and colour FAX image processing
|
||||||
|
*
|
||||||
|
* Written by Steve Underwood <steveu@coppice.org>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Steve Underwood
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License version 2.1,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(_SPANDSP_PRIVATE_T43_H_)
|
||||||
|
#define _SPANDSP_PRIVATE_T43_H_
|
||||||
|
|
||||||
|
/* State of a working instance of the T.43 JBIG for gray and colour FAX encoder */
|
||||||
|
struct t43_encode_state_s
|
||||||
|
{
|
||||||
|
/*! \brief Callback function to read a row of pixels from the image source. */
|
||||||
|
t4_row_read_handler_t row_read_handler;
|
||||||
|
/*! \brief Opaque pointer passed to row_read_handler. */
|
||||||
|
void *row_read_user_data;
|
||||||
|
|
||||||
|
struct lab_params_s lab;
|
||||||
|
struct t85_encode_state_s t85;
|
||||||
|
|
||||||
|
int bit_planes[4];
|
||||||
|
|
||||||
|
int colour_map_entries;
|
||||||
|
uint8_t colour_map[3*256];
|
||||||
|
|
||||||
|
/*! The width of the full image, in pixels */
|
||||||
|
uint32_t xd;
|
||||||
|
/*! The height of the full image, in pixels */
|
||||||
|
uint32_t yd;
|
||||||
|
int x_resolution;
|
||||||
|
int y_resolution;
|
||||||
|
|
||||||
|
/*! \brief Error and flow logging control */
|
||||||
|
logging_state_t logging;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* State of a working instance of the T.43 JBIG for gray and colour FAX decoder */
|
||||||
|
struct t43_decode_state_s
|
||||||
|
{
|
||||||
|
/*! A callback routine to handle decoded pixel rows */
|
||||||
|
t4_row_write_handler_t row_write_handler;
|
||||||
|
/*! An opaque pointer passed to row_write_handler() */
|
||||||
|
void *row_write_user_data;
|
||||||
|
|
||||||
|
struct lab_params_s lab;
|
||||||
|
struct t85_decode_state_s t85;
|
||||||
|
|
||||||
|
int bit_planes[4];
|
||||||
|
uint8_t bit_plane_mask;
|
||||||
|
int current_bit_plane;
|
||||||
|
int plane_ptr;
|
||||||
|
|
||||||
|
int colour_map_entries;
|
||||||
|
uint8_t colour_map[3*256];
|
||||||
|
|
||||||
|
int x_resolution;
|
||||||
|
int y_resolution;
|
||||||
|
|
||||||
|
uint8_t *buf;
|
||||||
|
int ptr;
|
||||||
|
int row;
|
||||||
|
|
||||||
|
/*! \brief Error and flow logging control */
|
||||||
|
logging_state_t logging;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/*- End of file ------------------------------------------------------------*/
|
|
@ -94,6 +94,10 @@ struct t4_rx_state_s
|
||||||
/*! \brief Opaque pointer passed to row_write_handler. */
|
/*! \brief Opaque pointer passed to row_write_handler. */
|
||||||
void *row_handler_user_data;
|
void *row_handler_user_data;
|
||||||
|
|
||||||
|
/*! \brief A bit mask of the currently supported image compression modes for writing
|
||||||
|
to the TIFF file. */
|
||||||
|
int supported_tiff_compressions;
|
||||||
|
|
||||||
/*! \brief The number of pages transferred to date. */
|
/*! \brief The number of pages transferred to date. */
|
||||||
int current_page;
|
int current_page;
|
||||||
|
|
||||||
|
@ -111,12 +115,24 @@ struct t4_rx_state_s
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
t4_t6_decode_state_t t4_t6;
|
t4_t6_decode_state_t t4_t6;
|
||||||
|
t85_decode_state_t t85;
|
||||||
|
#if defined(SPANDSP_SUPPORT_T88)
|
||||||
|
t88_decode_state_t t88;
|
||||||
|
#endif
|
||||||
t42_decode_state_t t42;
|
t42_decode_state_t t42;
|
||||||
#if defined(SPANDSP_SUPPORT_T43)
|
#if defined(SPANDSP_SUPPORT_T43)
|
||||||
t43_decode_state_t t43;
|
t43_decode_state_t t43;
|
||||||
#endif
|
#endif
|
||||||
t85_decode_state_t t85;
|
#if defined(SPANDSP_SUPPORT_T45)
|
||||||
|
t45_decode_state_t t45;
|
||||||
|
#endif
|
||||||
} decoder;
|
} decoder;
|
||||||
|
int current_decoder;
|
||||||
|
|
||||||
|
uint8_t *pre_encoded_buf;
|
||||||
|
int pre_encoded_len;
|
||||||
|
int pre_encoded_ptr;
|
||||||
|
int pre_encoded_bit;
|
||||||
|
|
||||||
/* Supporting information, like resolutions, which the backend may want. */
|
/* Supporting information, like resolutions, which the backend may want. */
|
||||||
t4_rx_metadata_t metadata;
|
t4_rx_metadata_t metadata;
|
||||||
|
|
|
@ -146,11 +146,17 @@ struct t4_tx_state_s
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
t4_t6_encode_state_t t4_t6;
|
t4_t6_encode_state_t t4_t6;
|
||||||
|
t85_encode_state_t t85;
|
||||||
|
#if defined(SPANDSP_SUPPORT_T88)
|
||||||
|
t88_encode_state_t t88;
|
||||||
|
#endif
|
||||||
t42_encode_state_t t42;
|
t42_encode_state_t t42;
|
||||||
#if defined(SPANDSP_SUPPORT_T43)
|
#if defined(SPANDSP_SUPPORT_T43)
|
||||||
t43_encode_state_t t43;
|
t43_encode_state_t t43;
|
||||||
#endif
|
#endif
|
||||||
t85_encode_state_t t85;
|
#if defined(SPANDSP_SUPPORT_T45)
|
||||||
|
t45_encode_state_t t45;
|
||||||
|
#endif
|
||||||
} encoder;
|
} encoder;
|
||||||
|
|
||||||
image_translate_state_t translator;
|
image_translate_state_t translator;
|
||||||
|
@ -160,6 +166,11 @@ struct t4_tx_state_s
|
||||||
uint8_t *colour_map;
|
uint8_t *colour_map;
|
||||||
int colour_map_entries;
|
int colour_map_entries;
|
||||||
|
|
||||||
|
uint8_t *pre_encoded_buf;
|
||||||
|
int pre_encoded_len;
|
||||||
|
int pre_encoded_ptr;
|
||||||
|
int pre_encoded_bit;
|
||||||
|
|
||||||
/* Supporting information, like resolutions, which the backend may want. */
|
/* Supporting information, like resolutions, which the backend may want. */
|
||||||
t4_tx_metadata_t metadata;
|
t4_tx_metadata_t metadata;
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,6 @@ struct v18_state_s
|
||||||
int baudot_tx_shift;
|
int baudot_tx_shift;
|
||||||
int tx_signal_on;
|
int tx_signal_on;
|
||||||
uint8_t next_byte;
|
uint8_t next_byte;
|
||||||
int byte_no;
|
|
||||||
|
|
||||||
fsk_rx_state_t fskrx;
|
fsk_rx_state_t fskrx;
|
||||||
dtmf_rx_state_t dtmfrx;
|
dtmf_rx_state_t dtmfrx;
|
||||||
|
|
|
@ -439,12 +439,10 @@ SPAN_DECLARE(int) t30_set_ecm_capability(t30_state_t *s, int enabled);
|
||||||
/*! Specify the output encoding for TIFF files created during FAX reception.
|
/*! Specify the output encoding for TIFF files created during FAX reception.
|
||||||
\brief Specify the output encoding for TIFF files created during FAX reception.
|
\brief Specify the output encoding for TIFF files created during FAX reception.
|
||||||
\param s The T.30 context.
|
\param s The T.30 context.
|
||||||
\param encoding The coding required. The options are T4_COMPRESSION_T4_1D,
|
\param supported_compressions Bit field list of the supported compression types, for
|
||||||
T4_COMPRESSION_T4_2D, T4_COMPRESSION_T6. T6 is usually the
|
output of received page images.
|
||||||
densest option, but support for it is broken in a number of software
|
|
||||||
packages.
|
|
||||||
\return 0 if OK, else -1. */
|
\return 0 if OK, else -1. */
|
||||||
SPAN_DECLARE(int) t30_set_rx_encoding(t30_state_t *s, int encoding);
|
SPAN_DECLARE(int) t30_set_supported_output_compressions(t30_state_t *s, int supported_compressions);
|
||||||
|
|
||||||
/*! Specify the minimum scan line time supported by a T.30 context.
|
/*! Specify the minimum scan line time supported by a T.30 context.
|
||||||
\brief Specify minimum scan line time.
|
\brief Specify minimum scan line time.
|
||||||
|
|
|
@ -0,0 +1,196 @@
|
||||||
|
/*
|
||||||
|
* SpanDSP - a series of DSP components for telephony
|
||||||
|
*
|
||||||
|
* t43.h - ITU T.43 JBIG for grey and colour FAX image processing
|
||||||
|
*
|
||||||
|
* Written by Steve Underwood <steveu@coppice.org>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Steve Underwood
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License version 2.1,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file */
|
||||||
|
|
||||||
|
#if !defined(_SPANDSP_T43_H_)
|
||||||
|
#define _SPANDSP_T43_H_
|
||||||
|
|
||||||
|
/*! \page t43_page T.43 (JBIG for gray and colour FAX) image compression and decompression
|
||||||
|
|
||||||
|
\section t43_page_sec_1 What does it do?
|
||||||
|
|
||||||
|
\section t43_page_sec_1 How does it work?
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! State of a working instance of the T.43 encoder */
|
||||||
|
typedef struct t43_encode_state_s t43_encode_state_t;
|
||||||
|
|
||||||
|
/*! State of a working instance of the T.43 decoder */
|
||||||
|
typedef struct t43_decode_state_s t43_decode_state_t;
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SPAN_DECLARE(const char *) t43_image_type_to_str(int type);
|
||||||
|
|
||||||
|
SPAN_DECLARE(void) t43_encode_set_options(t43_encode_state_t *s,
|
||||||
|
uint32_t l0,
|
||||||
|
int mx,
|
||||||
|
int options);
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_set_image_width(t43_encode_state_t *s, uint32_t image_width);
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_set_image_length(t43_encode_state_t *s, uint32_t length);
|
||||||
|
|
||||||
|
SPAN_DECLARE(void) t43_encode_abort(t43_encode_state_t *s);
|
||||||
|
|
||||||
|
SPAN_DECLARE(void) t43_encode_comment(t43_encode_state_t *s, const uint8_t comment[], size_t len);
|
||||||
|
|
||||||
|
/*! \brief Check if we are at the end of the current document page.
|
||||||
|
\param s The T.43 context.
|
||||||
|
\return 0 for more data to come. SIG_STATUS_END_OF_DATA for no more data. */
|
||||||
|
SPAN_DECLARE(int) t43_encode_image_complete(t43_encode_state_t *s);
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_get(t43_encode_state_t *s, uint8_t buf[], size_t max_len);
|
||||||
|
|
||||||
|
SPAN_DECLARE(uint32_t) t43_encode_get_image_width(t43_encode_state_t *s);
|
||||||
|
|
||||||
|
SPAN_DECLARE(uint32_t) t43_encode_get_image_length(t43_encode_state_t *s);
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_get_compressed_image_size(t43_encode_state_t *s);
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_set_row_read_handler(t43_encode_state_t *s,
|
||||||
|
t4_row_read_handler_t handler,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
/*! Get the logging context associated with a T.43 encode context.
|
||||||
|
\brief Get the logging context associated with a T.43 encode context.
|
||||||
|
\param s The T.43 encode context.
|
||||||
|
\return A pointer to the logging context */
|
||||||
|
SPAN_DECLARE(logging_state_t *) t43_encode_get_logging_state(t43_encode_state_t *s);
|
||||||
|
|
||||||
|
/*! \brief Restart a T.43 encode context.
|
||||||
|
\param s The T.43 context.
|
||||||
|
\param image image_width The image width, in pixels.
|
||||||
|
\param image image_width The image length, in pixels.
|
||||||
|
\return 0 for success, otherwise -1. */
|
||||||
|
SPAN_DECLARE(int) t43_encode_restart(t43_encode_state_t *s, uint32_t image_width, uint32_t image_length);
|
||||||
|
|
||||||
|
/*! \brief Prepare to encode an image in T.43 format.
|
||||||
|
\param s The T.43 context.
|
||||||
|
\param image_width Image width, in pixels.
|
||||||
|
\param image_length Image length, in pixels.
|
||||||
|
\param handler A callback routine to handle encoded image rows.
|
||||||
|
\param user_data An opaque pointer passed to handler.
|
||||||
|
\return A pointer to the context, or NULL if there was a problem. */
|
||||||
|
SPAN_DECLARE(t43_encode_state_t *) t43_encode_init(t43_encode_state_t *s,
|
||||||
|
uint32_t image_width,
|
||||||
|
uint32_t image_length,
|
||||||
|
t4_row_read_handler_t handler,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
/*! \brief Release a T.43 encode context.
|
||||||
|
\param s The T.43 encode context.
|
||||||
|
\return 0 for OK, else -1. */
|
||||||
|
SPAN_DECLARE(int) t43_encode_release(t43_encode_state_t *s);
|
||||||
|
|
||||||
|
/*! \brief Free a T.43 encode context.
|
||||||
|
\param s The T.43 encode context.
|
||||||
|
\return 0 for OK, else -1. */
|
||||||
|
SPAN_DECLARE(int) t43_encode_free(t43_encode_state_t *s);
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_create_header(t43_decode_state_t *s, uint8_t data[], size_t len);
|
||||||
|
|
||||||
|
SPAN_DECLARE(void) t43_decode_rx_status(t43_decode_state_t *s, int status);
|
||||||
|
|
||||||
|
/*! \brief Decode a chunk of T.43 data.
|
||||||
|
\param s The T.43 context.
|
||||||
|
\param data The data to be decoded.
|
||||||
|
\param len The length of the data to be decoded.
|
||||||
|
\return 0 for OK. */
|
||||||
|
SPAN_DECLARE(int) t43_decode_put(t43_decode_state_t *s, const uint8_t data[], size_t len);
|
||||||
|
|
||||||
|
/*! \brief Set the row handler routine.
|
||||||
|
\param s The T.43 context.
|
||||||
|
\param handler A callback routine to handle decoded image rows.
|
||||||
|
\param user_data An opaque pointer passed to handler.
|
||||||
|
\return 0 for OK. */
|
||||||
|
SPAN_DECLARE(int) t43_decode_set_row_write_handler(t43_decode_state_t *s,
|
||||||
|
t4_row_write_handler_t handler,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
/*! \brief Set the comment handler routine.
|
||||||
|
\param s The T.43 context.
|
||||||
|
\param max_comment_len The maximum length of comment to be passed to the handler.
|
||||||
|
\param handler A callback routine to handle decoded comment.
|
||||||
|
\param user_data An opaque pointer passed to handler.
|
||||||
|
\return 0 for OK. */
|
||||||
|
SPAN_DECLARE(int) t43_decode_set_comment_handler(t43_decode_state_t *s,
|
||||||
|
uint32_t max_comment_len,
|
||||||
|
t4_row_write_handler_t handler,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_decode_set_image_size_constraints(t43_decode_state_t *s,
|
||||||
|
uint32_t max_xd,
|
||||||
|
uint32_t max_yd);
|
||||||
|
|
||||||
|
/*! \brief Get the width of the image.
|
||||||
|
\param s The T.43 context.
|
||||||
|
\return The width of the image, in pixels. */
|
||||||
|
SPAN_DECLARE(uint32_t) t43_decode_get_image_width(t43_decode_state_t *s);
|
||||||
|
|
||||||
|
/*! \brief Get the length of the image.
|
||||||
|
\param s The T.43 context.
|
||||||
|
\return The length of the image, in pixels. */
|
||||||
|
SPAN_DECLARE(uint32_t) t43_decode_get_image_length(t43_decode_state_t *s);
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_decode_get_compressed_image_size(t43_decode_state_t *s);
|
||||||
|
|
||||||
|
/*! Get the logging context associated with a T.43 decode context.
|
||||||
|
\brief Get the logging context associated with a T.43 decode context.
|
||||||
|
\param s The T.43 decode context.
|
||||||
|
\return A pointer to the logging context */
|
||||||
|
SPAN_DECLARE(logging_state_t *) t43_decode_get_logging_state(t43_decode_state_t *s);
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_decode_restart(t43_decode_state_t *s);
|
||||||
|
|
||||||
|
/*! \brief Prepare to decode an image in T.43 format.
|
||||||
|
\param s The T.43 context.
|
||||||
|
\param handler A callback routine to handle decoded image rows.
|
||||||
|
\param user_data An opaque pointer passed to handler.
|
||||||
|
\return A pointer to the context, or NULL if there was a problem. */
|
||||||
|
SPAN_DECLARE(t43_decode_state_t *) t43_decode_init(t43_decode_state_t *s,
|
||||||
|
t4_row_write_handler_t handler,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
/*! \brief Release a T.43 decode context.
|
||||||
|
\param s The T.43 decode context.
|
||||||
|
\return 0 for OK, else -1. */
|
||||||
|
SPAN_DECLARE(int) t43_decode_release(t43_decode_state_t *s);
|
||||||
|
|
||||||
|
/*! \brief Free a T.43 decode context.
|
||||||
|
\param s The T.43 decode context.
|
||||||
|
\return 0 for OK, else -1. */
|
||||||
|
SPAN_DECLARE(int) t43_decode_free(t43_decode_state_t *s);
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/*- End of file ------------------------------------------------------------*/
|
|
@ -67,47 +67,49 @@ typedef enum
|
||||||
/*! T.42 + T.81 + T.30 Annex E colour JPEG coding */
|
/*! T.42 + T.81 + T.30 Annex E colour JPEG coding */
|
||||||
T4_COMPRESSION_T42_T81 = 8,
|
T4_COMPRESSION_T42_T81 = 8,
|
||||||
/*! T.42 + T.81 + T.30 Annex K colour sYCC-JPEG coding */
|
/*! T.42 + T.81 + T.30 Annex K colour sYCC-JPEG coding */
|
||||||
T4_COMPRESSION_SYCC_T81 = 9
|
T4_COMPRESSION_SYCC_T81 = 9,
|
||||||
|
/*! T.88 monochrome JBIG2 compression */
|
||||||
|
T4_COMPRESSION_T88 = 10
|
||||||
} t4_image_compression_t;
|
} t4_image_compression_t;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
/*! No compression */
|
/*! No compression */
|
||||||
T30_SUPPORT_COMPRESSION_NONE = 0x01,
|
T4_SUPPORT_COMPRESSION_NONE = 0x01,
|
||||||
/*! T.1 1D compression */
|
/*! T.1 1D compression */
|
||||||
T30_SUPPORT_COMPRESSION_T4_1D = 0x02,
|
T4_SUPPORT_COMPRESSION_T4_1D = 0x02,
|
||||||
/*! T.4 2D compression */
|
/*! T.4 2D compression */
|
||||||
T30_SUPPORT_COMPRESSION_T4_2D = 0x04,
|
T4_SUPPORT_COMPRESSION_T4_2D = 0x04,
|
||||||
/*! T.6 2D compression */
|
/*! T.6 2D compression */
|
||||||
T30_SUPPORT_COMPRESSION_T6 = 0x08,
|
T4_SUPPORT_COMPRESSION_T6 = 0x08,
|
||||||
/*! T.85 monochrome JBIG compression, with fixed L0 */
|
/*! T.85 monochrome JBIG compression, with fixed L0 */
|
||||||
T30_SUPPORT_COMPRESSION_T85 = 0x10,
|
T4_SUPPORT_COMPRESSION_T85 = 0x10,
|
||||||
/*! T.85 monochrome JBIG compression, with variable L0 */
|
/*! T.85 monochrome JBIG compression, with variable L0 */
|
||||||
T30_SUPPORT_COMPRESSION_T85_L0 = 0x20,
|
T4_SUPPORT_COMPRESSION_T85_L0 = 0x20,
|
||||||
/*! T.43 colour JBIG compression */
|
/*! T.43 colour JBIG compression */
|
||||||
T30_SUPPORT_COMPRESSION_T43 = 0x40,
|
T4_SUPPORT_COMPRESSION_T43 = 0x40,
|
||||||
/*! T.45 run length colour compression */
|
/*! T.45 run length colour compression */
|
||||||
T30_SUPPORT_COMPRESSION_T45 = 0x80,
|
T4_SUPPORT_COMPRESSION_T45 = 0x80,
|
||||||
/*! T.81 + T.30 Annex E colour JPEG compression */
|
/*! T.81 + T.30 Annex E colour JPEG compression */
|
||||||
T30_SUPPORT_COMPRESSION_T42_T81 = 0x100,
|
T4_SUPPORT_COMPRESSION_T42_T81 = 0x100,
|
||||||
/*! T.81 + T.30 Annex K colour sYCC-JPEG compression */
|
/*! T.81 + T.30 Annex K colour sYCC-JPEG compression */
|
||||||
T30_SUPPORT_COMPRESSION_SYCC_T81 = 0x200,
|
T4_SUPPORT_COMPRESSION_SYCC_T81 = 0x200,
|
||||||
/*! T.88 monochrome JBIG2 compression */
|
/*! T.88 monochrome JBIG2 compression */
|
||||||
T30_SUPPORT_COMPRESSION_T88 = 0x400,
|
T4_SUPPORT_COMPRESSION_T88 = 0x400,
|
||||||
/*! Gray-scale support by multi-level codecs */
|
/*! Gray-scale support by multi-level codecs */
|
||||||
T30_SUPPORT_COMPRESSION_GRAYSCALE = 0x1000000,
|
T4_SUPPORT_COMPRESSION_GRAYSCALE = 0x1000000,
|
||||||
/*! Colour support by multi-level codecs */
|
/*! Colour support by multi-level codecs */
|
||||||
T30_SUPPORT_COMPRESSION_COLOUR = 0x2000000,
|
T4_SUPPORT_COMPRESSION_COLOUR = 0x2000000,
|
||||||
/*! 12 bit mode for gray-scale and colour */
|
/*! 12 bit mode for gray-scale and colour */
|
||||||
T30_SUPPORT_COMPRESSION_12BIT = 0x4000000,
|
T4_SUPPORT_COMPRESSION_12BIT = 0x4000000,
|
||||||
/*! Convert a colour image to a gray-scale one */
|
/*! Convert a colour image to a gray-scale one */
|
||||||
T30_SUPPORT_COMPRESSION_COLOUR_TO_GRAY = 0x8000000,
|
T4_SUPPORT_COMPRESSION_COLOUR_TO_GRAY = 0x8000000,
|
||||||
/*! Dither a gray-scale image down a simple bilevel image, with rescaling to fit a FAX page */
|
/*! Dither a gray-scale image down a simple bilevel image, with rescaling to fit a FAX page */
|
||||||
T30_SUPPORT_GRAY_TO_BILEVEL = 0x10000000,
|
T30_SUPPORT_GRAY_TO_BILEVEL = 0x10000000,
|
||||||
/*! Dither a colour image down a simple bilevel image, with rescaling to fit a FAX page */
|
/*! Dither a colour image down a simple bilevel image, with rescaling to fit a FAX page */
|
||||||
T30_SUPPORT_COLOUR_TO_BILEVEL = 0x20000000,
|
T30_SUPPORT_COLOUR_TO_BILEVEL = 0x20000000,
|
||||||
/*! Rescale an image (except a bi-level image) to fit a permitted FAX width when necessary */
|
/*! Rescale an image (except a bi-level image) to fit a permitted FAX width when necessary */
|
||||||
T30_SUPPORT_COMPRESSION_RESCALING = 0x40000000
|
T4_SUPPORT_COMPRESSION_RESCALING = 0x40000000
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! Image type */
|
/*! Image type */
|
||||||
|
@ -561,9 +563,9 @@ SPAN_DECLARE(logging_state_t *) t4_rx_get_logging_state(t4_rx_state_t *s);
|
||||||
/*! \brief Prepare for reception of a document.
|
/*! \brief Prepare for reception of a document.
|
||||||
\param s The T.4 context.
|
\param s The T.4 context.
|
||||||
\param file The name of the file to be received.
|
\param file The name of the file to be received.
|
||||||
\param output_encoding The output encoding.
|
\param supported_compressions The compression schemes supported for output to a TIFF file.
|
||||||
\return A pointer to the context, or NULL if there was a problem. */
|
\return A pointer to the context, or NULL if there was a problem. */
|
||||||
SPAN_DECLARE(t4_rx_state_t *) t4_rx_init(t4_rx_state_t *s, const char *file, int output_encoding);
|
SPAN_DECLARE(t4_rx_state_t *) t4_rx_init(t4_rx_state_t *s, const char *file, int supported_compressions);
|
||||||
|
|
||||||
/*! \brief End reception of a document. Tidy up and close the file.
|
/*! \brief End reception of a document. Tidy up and close the file.
|
||||||
This should be used to end T.4 reception started with t4_rx_init.
|
This should be used to end T.4 reception started with t4_rx_init.
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -1195,9 +1195,9 @@ int t30_build_dis_or_dtc(t30_state_t *s)
|
||||||
/* No scan-line padding required, but some may be specified by the application. */
|
/* 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, T30_DIS_BIT_MIN_SCAN_LINE_TIME_CAPABILITY_1);
|
set_ctrl_bits(s->local_dis_dtc_frame, s->local_min_scan_time_code, T30_DIS_BIT_MIN_SCAN_LINE_TIME_CAPABILITY_1);
|
||||||
|
|
||||||
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T4_2D))
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T4_2D))
|
||||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE);
|
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE);
|
||||||
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_NONE))
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_NONE))
|
||||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_UNCOMPRESSED_CAPABLE);
|
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_UNCOMPRESSED_CAPABLE);
|
||||||
if (s->ecm_allowed)
|
if (s->ecm_allowed)
|
||||||
{
|
{
|
||||||
|
@ -1206,46 +1206,46 @@ int t30_build_dis_or_dtc(t30_state_t *s)
|
||||||
|
|
||||||
/* Only offer the option of fancy compression schemes, if we are
|
/* Only offer the option of fancy compression schemes, if we are
|
||||||
also offering the ECM option needed to support them. */
|
also offering the ECM option needed to support them. */
|
||||||
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T6))
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T6))
|
||||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE);
|
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE);
|
||||||
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T85))
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T85))
|
||||||
{
|
{
|
||||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T85_CAPABLE);
|
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
|
/* Bit 79 set with bit 78 clear is invalid, so only check for L0
|
||||||
support here. */
|
support here. */
|
||||||
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T85_L0))
|
if ((s->supported_compressions & T4_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_L0_CAPABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_COLOUR))
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_COLOUR))
|
||||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_FULL_COLOUR_CAPABLE);
|
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_FULL_COLOUR_CAPABLE);
|
||||||
|
|
||||||
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T42_T81))
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T42_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_T81_CAPABLE);
|
||||||
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T43))
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T43))
|
||||||
{
|
{
|
||||||
/* Note 25 of table 2/T.30 */
|
/* 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_T43_CAPABLE);
|
||||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE);
|
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE);
|
||||||
}
|
}
|
||||||
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T45))
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T45))
|
||||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T45_CAPABLE);
|
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T45_CAPABLE);
|
||||||
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_SYCC_T81))
|
if ((s->supported_compressions & T4_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_T81_CAPABLE);
|
||||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_SYCC_T81_CAPABLE);
|
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_SYCC_T81_CAPABLE);
|
||||||
}
|
}
|
||||||
//if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_T88))
|
//if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T88))
|
||||||
//{
|
//{
|
||||||
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T88_CAPABILITY_1);
|
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T88_CAPABILITY_1);
|
||||||
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T88_CAPABILITY_2);
|
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T88_CAPABILITY_2);
|
||||||
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T88_CAPABILITY_3);
|
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_T88_CAPABILITY_3);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_12BIT))
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_12BIT))
|
||||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE);
|
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE);
|
||||||
|
|
||||||
//if ((s->supported_compressions & T30_SUPPORT_COMPRESSION_NO_SUBSAMPLING))
|
//if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_NO_SUBSAMPLING))
|
||||||
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING);
|
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING);
|
||||||
|
|
||||||
/* No custom illuminant */
|
/* No custom illuminant */
|
||||||
|
@ -1345,8 +1345,8 @@ int t30_build_dis_or_dtc(t30_state_t *s)
|
||||||
if ((s->supported_bilevel_resolutions & T4_SUPPORT_RESOLUTION_200_200))
|
if ((s->supported_bilevel_resolutions & T4_SUPPORT_RESOLUTION_200_200))
|
||||||
{
|
{
|
||||||
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE);
|
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE);
|
||||||
//if ((s->supported_colour_resolutions & T4_SUPPORT_RESOLUTION_200_200))
|
if ((s->supported_colour_resolutions & T4_SUPPORT_RESOLUTION_200_200))
|
||||||
// set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_???_CAPABLE);
|
set_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_FULL_COLOUR_CAPABLE);
|
||||||
}
|
}
|
||||||
/* Standard FAX resolution bi-level image support goes without saying */
|
/* Standard FAX resolution bi-level image support goes without saying */
|
||||||
if ((s->supported_colour_resolutions & T4_SUPPORT_RESOLUTION_100_100))
|
if ((s->supported_colour_resolutions & T4_SUPPORT_RESOLUTION_100_100))
|
||||||
|
@ -1421,14 +1421,14 @@ static int build_dcs(t30_state_t *s)
|
||||||
int bad;
|
int bad;
|
||||||
int row_squashing_ratio;
|
int row_squashing_ratio;
|
||||||
int use_bilevel;
|
int use_bilevel;
|
||||||
//int image_type;
|
int image_type;
|
||||||
|
|
||||||
/* Reacquire page information, in case the image was resized, flattened, etc. */
|
/* Reacquire page information, in case the image was resized, flattened, etc. */
|
||||||
s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx);
|
s->x_resolution = t4_tx_get_x_resolution(&s->t4.tx);
|
||||||
s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx);
|
s->y_resolution = t4_tx_get_y_resolution(&s->t4.tx);
|
||||||
//s->current_page_resolution = t4_tx_get_resolution(&s->t4.tx);
|
s->current_page_resolution = t4_tx_get_resolution(&s->t4.tx);
|
||||||
s->image_width = t4_tx_get_image_width(&s->t4.tx);
|
s->image_width = t4_tx_get_image_width(&s->t4.tx);
|
||||||
//image_type = t4_tx_get_image_type(&s->t4.tx);
|
image_type = t4_tx_get_image_type(&s->t4.tx);
|
||||||
|
|
||||||
/* Make a DCS frame based on local issues and the latest received DIS/DTC frame.
|
/* Make a DCS frame based on local issues and the latest received DIS/DTC frame.
|
||||||
Negotiate the result based on what both parties can do. */
|
Negotiate the result based on what both parties can do. */
|
||||||
|
@ -1483,22 +1483,24 @@ static int build_dcs(t30_state_t *s)
|
||||||
#endif
|
#endif
|
||||||
case T4_COMPRESSION_T42_T81:
|
case T4_COMPRESSION_T42_T81:
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T81_MODE);
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T81_MODE);
|
||||||
//if (image_type == T4_IMAGE_TYPE_COLOUR_8BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
|
if (image_type == T4_IMAGE_TYPE_COLOUR_8BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
|
||||||
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
|
||||||
//if (image_type == T4_IMAGE_TYPE_GRAY_12BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
|
if (image_type == T4_IMAGE_TYPE_GRAY_12BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
|
||||||
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
|
||||||
//if (???????? & T4_COMPRESSION_?????))
|
//if (???????? & T4_COMPRESSION_?????))
|
||||||
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING);
|
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING);
|
||||||
|
//if (???????? & T4_COMPRESSION_?????))
|
||||||
|
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_PREFERRED_HUFFMAN_TABLES);
|
||||||
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
|
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
|
||||||
use_bilevel = FALSE;
|
use_bilevel = FALSE;
|
||||||
break;
|
break;
|
||||||
#if defined(SPANDSP_SUPPORT_T43)
|
#if defined(SPANDSP_SUPPORT_T43)
|
||||||
case T4_COMPRESSION_T43:
|
case T4_COMPRESSION_T43:
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T43_MODE);
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_T43_MODE);
|
||||||
//if (image_type == T4_IMAGE_TYPE_COLOUR_8BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
|
if (image_type == T4_IMAGE_TYPE_COLOUR_8BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
|
||||||
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
|
||||||
//if (image_type == T4_IMAGE_TYPE_GRAY_12BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
|
if (image_type == T4_IMAGE_TYPE_GRAY_12BIT || image_type == T4_IMAGE_TYPE_COLOUR_12BIT)
|
||||||
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_12BIT_COMPONENT);
|
||||||
//if (???????? & T4_COMPRESSION_?????))
|
//if (???????? & T4_COMPRESSION_?????))
|
||||||
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING);
|
// set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING);
|
||||||
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
|
set_ctrl_bits(s->dcs_frame, T30_MIN_SCAN_0MS, T30_DCS_BIT_MIN_SCAN_LINE_TIME_1);
|
||||||
|
@ -1523,159 +1525,139 @@ static int build_dcs(t30_state_t *s)
|
||||||
/* Set the Y resolution bits */
|
/* Set the Y resolution bits */
|
||||||
row_squashing_ratio = 1;
|
row_squashing_ratio = 1;
|
||||||
bad = T30_ERR_NORESSUPPORT;
|
bad = T30_ERR_NORESSUPPORT;
|
||||||
if (use_bilevel)
|
if ((use_bilevel && (s->current_page_resolution & s->mutual_bilevel_resolutions))
|
||||||
|
||
|
||||||
|
(!use_bilevel && (s->current_page_resolution & s->mutual_colour_resolutions)))
|
||||||
{
|
{
|
||||||
switch (s->y_resolution)
|
/* The resolution is supported by both parties */
|
||||||
|
switch (s->current_page_resolution)
|
||||||
{
|
{
|
||||||
case T4_Y_RESOLUTION_1200:
|
case T4_RESOLUTION_1200_1200:
|
||||||
switch (s->x_resolution)
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200);
|
||||||
{
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||||
case T4_X_RESOLUTION_1200:
|
if (!use_bilevel)
|
||||||
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_1200_1200))
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_1200_1200);
|
||||||
{
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_1200_1200);
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
|
||||||
bad = T30_ERR_OK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case T4_X_RESOLUTION_600:
|
|
||||||
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_600_1200))
|
|
||||||
{
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200);
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
|
||||||
bad = T30_ERR_OK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case T4_Y_RESOLUTION_800:
|
case T4_RESOLUTION_600_1200:
|
||||||
switch (s->x_resolution)
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_1200);
|
||||||
{
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||||
case T4_X_RESOLUTION_R16:
|
|
||||||
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_400_800))
|
|
||||||
{
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800);
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
|
||||||
bad = T30_ERR_OK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case T4_Y_RESOLUTION_600:
|
case T4_RESOLUTION_600_600:
|
||||||
switch (s->x_resolution)
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600);
|
||||||
{
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||||
case T4_X_RESOLUTION_600:
|
if (!use_bilevel)
|
||||||
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_600_600))
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_600_600);
|
||||||
{
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_600_600);
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
|
||||||
bad = T30_ERR_OK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case T4_X_RESOLUTION_300:
|
|
||||||
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_300_600))
|
|
||||||
{
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600);
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
|
||||||
bad = T30_ERR_OK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case T4_Y_RESOLUTION_300:
|
case T4_RESOLUTION_400_800:
|
||||||
switch (s->x_resolution)
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_800);
|
||||||
{
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||||
case T4_X_RESOLUTION_300:
|
|
||||||
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_300_300))
|
|
||||||
{
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300);
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
|
||||||
bad = T30_ERR_OK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case T4_Y_RESOLUTION_SUPERFINE:
|
case T4_RESOLUTION_400_400:
|
||||||
case T4_Y_RESOLUTION_400:
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
|
||||||
if (s->x_resolution == T4_X_RESOLUTION_400 && s->y_resolution == T4_Y_RESOLUTION_400)
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||||
|
if (!use_bilevel)
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_300_300_400_400);
|
||||||
|
break;
|
||||||
|
case T4_RESOLUTION_300_600:
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_600);
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||||
|
break;
|
||||||
|
case T4_RESOLUTION_300_300:
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_300_300);
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||||
|
if (!use_bilevel)
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_300_300_400_400);
|
||||||
|
break;
|
||||||
|
case T4_RESOLUTION_200_400:
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||||
|
break;
|
||||||
|
case T4_RESOLUTION_200_200:
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||||
|
if (!use_bilevel)
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE);
|
||||||
|
break;
|
||||||
|
case T4_RESOLUTION_200_100:
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||||
|
break;
|
||||||
|
case T4_RESOLUTION_100_100:
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
||||||
|
if (!use_bilevel)
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_COLOUR_GRAY_100_100);
|
||||||
|
break;
|
||||||
|
case T4_RESOLUTION_R16_SUPERFINE:
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
|
||||||
|
break;
|
||||||
|
case T4_RESOLUTION_R8_SUPERFINE:
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
|
||||||
|
break;
|
||||||
|
case T4_RESOLUTION_R8_FINE:
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
|
||||||
|
break;
|
||||||
|
case T4_RESOLUTION_R8_STANDARD:
|
||||||
|
/* Nothing special to set */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bad = T30_ERR_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
/* Deal with resolution fudging */
|
||||||
|
if ((s->current_page_resolution & (T4_RESOLUTION_R16_SUPERFINE | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE | T4_RESOLUTION_R8_STANDARD)))
|
||||||
|
{
|
||||||
|
if ((s->mutual_bilevel_resolutions & (T4_RESOLUTION_400_400 | T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_200_100)))
|
||||||
{
|
{
|
||||||
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_400_400))
|
/* Fudge between imperial and metric */
|
||||||
{
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
|
||||||
bad = T30_ERR_OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (s->x_resolution == T4_X_RESOLUTION_R16 && s->y_resolution == T4_Y_RESOLUTION_SUPERFINE)
|
}
|
||||||
|
else if ((s->current_page_resolution & (T4_RESOLUTION_400_400 | T4_RESOLUTION_200_400 | T4_RESOLUTION_200_200 | T4_RESOLUTION_200_100))
|
||||||
|
{
|
||||||
|
if ((s->mutual_bilevel_resolutions & (T4_RESOLUTION_R16_SUPERFINE | T4_RESOLUTION_R8_SUPERFINE | T4_RESOLUTION_R8_FINE | T4_RESOLUTION_R8_STANDARD)))
|
||||||
{
|
{
|
||||||
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_R16_SUPERFINE))
|
/* Fudge between imperial and metric */
|
||||||
{
|
|
||||||
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)
|
}
|
||||||
|
#endif
|
||||||
|
/* Deal with squashing options */
|
||||||
|
if ((s->current_page_resolution & T4_RESOLUTION_R8_SUPERFINE))
|
||||||
|
{
|
||||||
|
if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_R8_FINE))
|
||||||
{
|
{
|
||||||
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_200_400))
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
|
||||||
{
|
row_squashing_ratio = 2;
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
|
||||||
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 & T4_SUPPORT_RESOLUTION_R8_SUPERFINE))
|
|
||||||
{
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
|
|
||||||
bad = T30_ERR_OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
row_squashing_ratio <<= 1;
|
|
||||||
/* Fall through */
|
|
||||||
case T4_Y_RESOLUTION_FINE:
|
|
||||||
case T4_Y_RESOLUTION_200:
|
|
||||||
if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_200)
|
|
||||||
{
|
|
||||||
if ((s->mutual_bilevel_resolutions & T4_SUPPORT_RESOLUTION_200_200))
|
|
||||||
{
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
|
||||||
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 & T4_SUPPORT_RESOLUTION_R8_FINE))
|
|
||||||
{
|
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
|
|
||||||
bad = T30_ERR_OK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
row_squashing_ratio <<= 1;
|
|
||||||
/* Fall through */
|
|
||||||
default:
|
|
||||||
case T4_Y_RESOLUTION_STANDARD:
|
|
||||||
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;
|
bad = T30_ERR_OK;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
else if (s->x_resolution == T4_X_RESOLUTION_200 && s->y_resolution == T4_Y_RESOLUTION_100)
|
else if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_R8_STANDARD))
|
||||||
{
|
{
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_INCH_RESOLUTION);
|
row_squashing_ratio = 4;
|
||||||
bad = T30_ERR_OK;
|
bad = T30_ERR_OK;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
else if ((s->current_page_resolution & T4_RESOLUTION_R8_FINE) && (s->mutual_bilevel_resolutions & T4_RESOLUTION_R8_STANDARD))
|
||||||
|
{
|
||||||
|
row_squashing_ratio = 2;
|
||||||
|
bad = T30_ERR_OK;
|
||||||
|
}
|
||||||
|
else if ((s->current_page_resolution & T4_RESOLUTION_200_400))
|
||||||
|
{
|
||||||
|
if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_200_200))
|
||||||
|
{
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_200);
|
||||||
|
row_squashing_ratio = 2;
|
||||||
|
bad = T30_ERR_OK;
|
||||||
|
}
|
||||||
|
else if ((s->mutual_bilevel_resolutions & T4_RESOLUTION_200_100))
|
||||||
|
{
|
||||||
|
row_squashing_ratio = 4;
|
||||||
|
bad = T30_ERR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((s->current_page_resolution & T4_RESOLUTION_200_200) && (s->mutual_bilevel_resolutions & T4_RESOLUTION_200_100))
|
||||||
|
{
|
||||||
|
row_squashing_ratio = 2;
|
||||||
|
bad = T30_ERR_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1768,10 +1750,15 @@ static int build_dcs(t30_state_t *s)
|
||||||
/* Deal with the image length */
|
/* Deal with the image length */
|
||||||
/* If the other end supports unlimited length, then use that. Otherwise, if the other end supports
|
/* If the other end supports unlimited length, then use that. Otherwise, if the other end supports
|
||||||
B4 use that, as its longer than the default A4 length. */
|
B4 use that, as its longer than the default A4 length. */
|
||||||
|
printf("Size1 0x%x\n", s->mutual_image_sizes);
|
||||||
if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_UNLIMITED))
|
if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_UNLIMITED))
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_UNLIMITED_LENGTH);
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_UNLIMITED_LENGTH);
|
||||||
else if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_B4))
|
else if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_B4))
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_B4_LENGTH);
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_B4_LENGTH);
|
||||||
|
else if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_US_LETTER))
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NORTH_AMERICAN_LETTER);
|
||||||
|
else if ((s->mutual_image_sizes & T4_SUPPORT_LENGTH_US_LEGAL))
|
||||||
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_NORTH_AMERICAN_LEGAL);
|
||||||
|
|
||||||
if (s->error_correcting_mode)
|
if (s->error_correcting_mode)
|
||||||
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_ECM_MODE);
|
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_ECM_MODE);
|
||||||
|
@ -1845,40 +1832,40 @@ static int analyze_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
|
||||||
if (!s->error_correcting_mode)
|
if (!s->error_correcting_mode)
|
||||||
{
|
{
|
||||||
/* Remove any compression schemes which need error correction to work. */
|
/* 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);
|
s->mutual_compressions &= (0xF0000000 | T4_SUPPORT_COMPRESSION_NONE | T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D);
|
||||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
|
||||||
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T4_2D;
|
s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T4_2D;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Check the bi-level capabilities */
|
/* Check the bi-level capabilities */
|
||||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_2D_CAPABLE))
|
||||||
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T4_2D;
|
s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T4_2D;
|
||||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T6_CAPABLE))
|
||||||
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T6;
|
s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T6;
|
||||||
/* T.85 L0 capable without T.85 capable is an invalid combination, so let
|
/* 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. */
|
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))
|
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);
|
s->mutual_compressions &= ~(T4_SUPPORT_COMPRESSION_T85 | T4_SUPPORT_COMPRESSION_T85_L0);
|
||||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T85_L0_CAPABLE))
|
||||||
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T85_L0;
|
s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T85_L0;
|
||||||
|
|
||||||
/* Check for full colour or only gray-scale from the multi-level codecs */
|
/* Check for full colour or only gray-scale from the multi-level codecs */
|
||||||
//if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_FULL_COLOUR_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_FULL_COLOUR_CAPABLE))
|
||||||
// s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_COLOUR;
|
s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_COLOUR;
|
||||||
|
|
||||||
/* Check the colour capabilities */
|
/* Check the colour capabilities */
|
||||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T81_CAPABLE))
|
||||||
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T42_T81;
|
s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T42_T81;
|
||||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_SYCC_T81_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_SYCC_T81_CAPABLE))
|
||||||
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_SYCC_T81;
|
s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_SYCC_T81;
|
||||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T43_CAPABLE))
|
||||||
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T43;
|
s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T43;
|
||||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T45_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_T45_CAPABLE))
|
||||||
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_T45;
|
s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_T45;
|
||||||
|
|
||||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_12BIT_CAPABLE))
|
||||||
s->mutual_compressions &= ~T30_SUPPORT_COMPRESSION_12BIT;
|
s->mutual_compressions &= ~T4_SUPPORT_COMPRESSION_12BIT;
|
||||||
//if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING))
|
//if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NO_SUBSAMPLING))
|
||||||
// ???? = T4_COMPRESSION_T42_T81_SUBSAMPLING;
|
// ???? = T4_COMPRESSION_T42_T81_SUBSAMPLING;
|
||||||
|
|
||||||
|
@ -1975,9 +1962,9 @@ static int analyze_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
|
||||||
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_A4_B4_LENGTH_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_A4_B4_LENGTH_CAPABLE))
|
||||||
s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_B4;
|
s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_B4;
|
||||||
}
|
}
|
||||||
if (!test_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LETTER_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LETTER_CAPABLE))
|
||||||
s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_US_LETTER;
|
s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_US_LETTER;
|
||||||
if (!test_ctrl_bit(s->local_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LEGAL_CAPABLE))
|
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_NORTH_AMERICAN_LEGAL_CAPABLE))
|
||||||
s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_US_LEGAL;
|
s->mutual_image_sizes &= ~T4_SUPPORT_LENGTH_US_LEGAL;
|
||||||
|
|
||||||
switch (s->far_dis_dtc_frame[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3))
|
switch (s->far_dis_dtc_frame[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3))
|
||||||
|
@ -2067,6 +2054,7 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
|
||||||
s->x_resolution = -1;
|
s->x_resolution = -1;
|
||||||
s->y_resolution = -1;
|
s->y_resolution = -1;
|
||||||
s->current_page_resolution = 0;
|
s->current_page_resolution = 0;
|
||||||
|
s->line_encoding = -1;
|
||||||
x = -1;
|
x = -1;
|
||||||
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T81_MODE)
|
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T81_MODE)
|
||||||
||
|
||
|
||||||
|
@ -2081,17 +2069,28 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
|
||||||
/* Note 35 of Table 2/T.30 */
|
/* Note 35 of Table 2/T.30 */
|
||||||
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE))
|
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_FULL_COLOUR_MODE))
|
||||||
{
|
{
|
||||||
/* We are going to work in full colour mode */
|
if ((s->supported_colour_resolutions & T4_SUPPORT_COMPRESSION_COLOUR))
|
||||||
|
{
|
||||||
|
/* We are going to work in full colour mode */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_12BIT_COMPONENT))
|
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_12BIT_COMPONENT))
|
||||||
{
|
{
|
||||||
/* We are going to work in 12 bit mode */
|
if ((s->supported_colour_resolutions & T4_SUPPORT_COMPRESSION_12BIT))
|
||||||
|
{
|
||||||
|
/* We are going to work in 12 bit mode */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING))
|
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_NO_SUBSAMPLING))
|
||||||
{
|
{
|
||||||
//???? = T30_SUPPORT_COMPRESSION_T42_T81_SUBSAMPLING;
|
//???? = T4_SUPPORT_COMPRESSION_T42_T81_SUBSAMPLING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!test_ctrl_bit(dcs_frame, T30_DCS_BIT_PREFERRED_HUFFMAN_TABLES))
|
||||||
|
{
|
||||||
|
//???? = T4_SUPPORT_COMPRESSION_T42_T81_HUFFMAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_COLOUR_GRAY_1200_1200))
|
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_COLOUR_GRAY_1200_1200))
|
||||||
|
@ -2154,6 +2153,28 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
|
||||||
x = 0;
|
x = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check which compression the far end has decided to use. */
|
||||||
|
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T81_MODE))
|
||||||
|
{
|
||||||
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T42_T81))
|
||||||
|
s->line_encoding = T4_COMPRESSION_T42_T81;
|
||||||
|
}
|
||||||
|
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T43_MODE))
|
||||||
|
{
|
||||||
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T43))
|
||||||
|
s->line_encoding = T4_COMPRESSION_T43;
|
||||||
|
}
|
||||||
|
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T45_MODE))
|
||||||
|
{
|
||||||
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T45))
|
||||||
|
s->line_encoding = T4_COMPRESSION_T45;
|
||||||
|
}
|
||||||
|
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_SYCC_T81_MODE))
|
||||||
|
{
|
||||||
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_SYCC_T81))
|
||||||
|
s->line_encoding = T4_COMPRESSION_SYCC_T81;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2304,8 +2325,51 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
|
||||||
x = 1;
|
x = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check which compression the far end has decided to use. */
|
||||||
|
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T88_MODE_1)
|
||||||
|
||
|
||||||
|
test_ctrl_bit(dcs_frame, T30_DCS_BIT_T88_MODE_2)
|
||||||
|
||
|
||||||
|
test_ctrl_bit(dcs_frame, T30_DCS_BIT_T88_MODE_3))
|
||||||
|
{
|
||||||
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T88))
|
||||||
|
s->line_encoding = T4_COMPRESSION_T88;
|
||||||
|
}
|
||||||
|
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T85_L0_MODE))
|
||||||
|
{
|
||||||
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T85_L0))
|
||||||
|
s->line_encoding = T4_COMPRESSION_T85_L0;
|
||||||
|
}
|
||||||
|
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T85_MODE))
|
||||||
|
{
|
||||||
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T85))
|
||||||
|
s->line_encoding = T4_COMPRESSION_T85;
|
||||||
|
}
|
||||||
|
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T6_MODE))
|
||||||
|
{
|
||||||
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T6))
|
||||||
|
s->line_encoding = T4_COMPRESSION_T6;
|
||||||
|
}
|
||||||
|
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_2D_MODE))
|
||||||
|
{
|
||||||
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T4_2D))
|
||||||
|
s->line_encoding = T4_COMPRESSION_T4_2D;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((s->supported_compressions & T4_SUPPORT_COMPRESSION_T4_1D))
|
||||||
|
s->line_encoding = T4_COMPRESSION_T4_1D;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s->line_encoding == -1)
|
||||||
|
{
|
||||||
|
t30_set_status(s, T30_ERR_INCOMPATIBLE);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Far end selected compression %s (%d)\n", t4_encoding_to_str(s->line_encoding), s->line_encoding);
|
||||||
|
|
||||||
if (x < 0)
|
if (x < 0)
|
||||||
{
|
{
|
||||||
t30_set_status(s, T30_ERR_NORESSUPPORT);
|
t30_set_status(s, T30_ERR_NORESSUPPORT);
|
||||||
|
@ -2313,43 +2377,8 @@ static int analyze_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
s->image_width = widths[x][dcs_frame[5] & (DISBIT2 | DISBIT1)];
|
s->image_width = widths[x][dcs_frame[5] & (DISBIT2 | DISBIT1)];
|
||||||
|
/* We don't care that much about the image length control bits. Just accept what arrives */
|
||||||
|
|
||||||
/* Check which compression the far end has decided to use. */
|
|
||||||
#if defined(SPANDSP_SUPPORT_T42)
|
|
||||||
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T81_MODE))
|
|
||||||
{
|
|
||||||
s->line_encoding = T4_COMPRESSION_T42_T81;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
#if defined(SPANDSP_SUPPORT_T43)
|
|
||||||
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T43_MODE))
|
|
||||||
{
|
|
||||||
s->line_encoding = T4_COMPRESSION_T43;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T85_L0_MODE))
|
|
||||||
{
|
|
||||||
s->line_encoding = T4_COMPRESSION_T85_L0;
|
|
||||||
}
|
|
||||||
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T85_MODE))
|
|
||||||
{
|
|
||||||
s->line_encoding = T4_COMPRESSION_T85;
|
|
||||||
}
|
|
||||||
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_T6_MODE))
|
|
||||||
{
|
|
||||||
s->line_encoding = T4_COMPRESSION_T6;
|
|
||||||
}
|
|
||||||
else if (test_ctrl_bit(dcs_frame, T30_DCS_BIT_2D_MODE))
|
|
||||||
{
|
|
||||||
s->line_encoding = T4_COMPRESSION_T4_2D;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s->line_encoding = T4_COMPRESSION_T4_1D;
|
|
||||||
}
|
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Far end selected compression %s (%d)\n", t4_encoding_to_str(s->line_encoding), s->line_encoding);
|
|
||||||
if (!test_ctrl_bit(dcs_frame, T30_DCS_BIT_RECEIVE_FAX_DOCUMENT))
|
if (!test_ctrl_bit(dcs_frame, T30_DCS_BIT_RECEIVE_FAX_DOCUMENT))
|
||||||
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Remote is not requesting receive in DCS\n");
|
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Remote is not requesting receive in DCS\n");
|
||||||
|
|
||||||
|
@ -2749,13 +2778,13 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Choose a compression scheme from amongst those mutually available */
|
/* Choose a compression scheme from amongst those mutually available */
|
||||||
if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T85_L0))
|
if ((s->mutual_compressions & T4_SUPPORT_COMPRESSION_T85_L0))
|
||||||
s->line_encoding = T4_COMPRESSION_T85_L0;
|
s->line_encoding = T4_COMPRESSION_T85_L0;
|
||||||
else if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T85))
|
else if ((s->mutual_compressions & T4_SUPPORT_COMPRESSION_T85))
|
||||||
s->line_encoding = T4_COMPRESSION_T85;
|
s->line_encoding = T4_COMPRESSION_T85;
|
||||||
else if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T6))
|
else if ((s->mutual_compressions & T4_SUPPORT_COMPRESSION_T6))
|
||||||
s->line_encoding = T4_COMPRESSION_T6;
|
s->line_encoding = T4_COMPRESSION_T6;
|
||||||
else if ((s->mutual_compressions & T30_SUPPORT_COMPRESSION_T4_2D))
|
else if ((s->mutual_compressions & T4_SUPPORT_COMPRESSION_T4_2D))
|
||||||
s->line_encoding = T4_COMPRESSION_T4_2D;
|
s->line_encoding = T4_COMPRESSION_T4_2D;
|
||||||
else
|
else
|
||||||
s->line_encoding = T4_COMPRESSION_T4_1D;
|
s->line_encoding = T4_COMPRESSION_T4_1D;
|
||||||
|
@ -6766,7 +6795,7 @@ SPAN_DECLARE(t30_state_t *) t30_init(t30_state_t *s,
|
||||||
|
|
||||||
/* Default to the basic modems. */
|
/* Default to the basic modems. */
|
||||||
s->supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
|
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_compressions = T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D;
|
||||||
s->supported_bilevel_resolutions = T4_SUPPORT_RESOLUTION_R8_STANDARD
|
s->supported_bilevel_resolutions = T4_SUPPORT_RESOLUTION_R8_STANDARD
|
||||||
| T4_SUPPORT_RESOLUTION_R8_FINE
|
| T4_SUPPORT_RESOLUTION_R8_FINE
|
||||||
| T4_SUPPORT_RESOLUTION_R8_SUPERFINE;
|
| T4_SUPPORT_RESOLUTION_R8_SUPERFINE;
|
||||||
|
|
|
@ -646,19 +646,11 @@ SPAN_DECLARE(int) t30_set_ecm_capability(t30_state_t *s, int enabled)
|
||||||
}
|
}
|
||||||
/*- End of function --------------------------------------------------------*/
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
SPAN_DECLARE(int) t30_set_rx_encoding(t30_state_t *s, int encoding)
|
SPAN_DECLARE(int) t30_set_supported_output_compressions(t30_state_t *s, int supported_compressions)
|
||||||
{
|
{
|
||||||
switch (encoding)
|
s->supported_output_compressions = supported_compressions;
|
||||||
{
|
s->output_encoding = supported_compressions;
|
||||||
case T4_COMPRESSION_T4_1D:
|
return 0;
|
||||||
case T4_COMPRESSION_T4_2D:
|
|
||||||
case T4_COMPRESSION_T6:
|
|
||||||
//case T4_COMPRESSION_T85:
|
|
||||||
//case T4_COMPRESSION_T85_L0:
|
|
||||||
s->output_encoding = encoding;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
/*- End of function --------------------------------------------------------*/
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -694,14 +686,14 @@ 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)
|
SPAN_DECLARE(int) t30_set_supported_compressions(t30_state_t *s, int supported_compressions)
|
||||||
{
|
{
|
||||||
/* Mask out the ones we actually support today. */
|
/* Mask out the ones we actually support today. */
|
||||||
supported_compressions &= T30_SUPPORT_COMPRESSION_T4_1D
|
supported_compressions &= T4_SUPPORT_COMPRESSION_T4_1D
|
||||||
| T30_SUPPORT_COMPRESSION_T4_2D
|
| T4_SUPPORT_COMPRESSION_T4_2D
|
||||||
| T30_SUPPORT_COMPRESSION_T6
|
| T4_SUPPORT_COMPRESSION_T6
|
||||||
| T30_SUPPORT_COMPRESSION_T85
|
| T4_SUPPORT_COMPRESSION_T85
|
||||||
| T30_SUPPORT_COMPRESSION_T85_L0
|
| T4_SUPPORT_COMPRESSION_T85_L0
|
||||||
//| T30_SUPPORT_COMPRESSION_T81
|
//| T4_SUPPORT_COMPRESSION_T81
|
||||||
#if defined(SPANDSP_SUPPORT_T43)
|
#if defined(SPANDSP_SUPPORT_T43)
|
||||||
| T30_SUPPORT_COMPRESSION_T43
|
| T4_SUPPORT_COMPRESSION_T43
|
||||||
#endif
|
#endif
|
||||||
| 0;
|
| 0;
|
||||||
s->supported_compressions = supported_compressions;
|
s->supported_compressions = supported_compressions;
|
||||||
|
|
|
@ -0,0 +1,845 @@
|
||||||
|
/*
|
||||||
|
* SpanDSP - a series of DSP components for telephony
|
||||||
|
*
|
||||||
|
* t43.c - ITU T.43 JBIG for grey and colour FAX image processing
|
||||||
|
*
|
||||||
|
* Written by Steve Underwood <steveu@coppice.org>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011, 2013 Steve Underwood
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License version 2.1,
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file */
|
||||||
|
|
||||||
|
#if defined(HAVE_CONFIG_H)
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <tiffio.h>
|
||||||
|
#if defined(HAVE_TGMATH_H)
|
||||||
|
#include <tgmath.h>
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE_MATH_H)
|
||||||
|
#include <math.h>
|
||||||
|
#endif
|
||||||
|
#include <time.h>
|
||||||
|
#include "floating_fudge.h"
|
||||||
|
#include <jpeglib.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
#include "spandsp/telephony.h"
|
||||||
|
#include "spandsp/logging.h"
|
||||||
|
#include "spandsp/async.h"
|
||||||
|
#include "spandsp/timezone.h"
|
||||||
|
#include "spandsp/t4_rx.h"
|
||||||
|
#include "spandsp/t4_tx.h"
|
||||||
|
#include "spandsp/t81_t82_arith_coding.h"
|
||||||
|
#include "spandsp/t85.h"
|
||||||
|
#include "spandsp/t42.h"
|
||||||
|
#include "spandsp/t43.h"
|
||||||
|
|
||||||
|
#include "spandsp/private/logging.h"
|
||||||
|
#include "spandsp/private/t81_t82_arith_coding.h"
|
||||||
|
#include "spandsp/private/t85.h"
|
||||||
|
#include "spandsp/private/t42.h"
|
||||||
|
#include "spandsp/private/t43.h"
|
||||||
|
|
||||||
|
#include "t42_t43_local.h"
|
||||||
|
|
||||||
|
#if !defined(FALSE)
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
#if !defined(TRUE)
|
||||||
|
#define TRUE (!FALSE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SPAN_DECLARE(const char *) t43_image_type_to_str(int type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return "1 bit/colour image (RGB primaries)";
|
||||||
|
case 1:
|
||||||
|
return "1 bit/colour image (CMY primaries)";
|
||||||
|
case 2:
|
||||||
|
return "1 bit/colour image (CMYK primaries)";
|
||||||
|
case 16:
|
||||||
|
return "Palettized colour image (CIELAB 8 bits/component precision table)";
|
||||||
|
case 17:
|
||||||
|
return "Palettized colour image (CIELAB 12 bits/component precision table)";
|
||||||
|
case 32:
|
||||||
|
return "Gray-scale image (using L*)";
|
||||||
|
case 48:
|
||||||
|
return "Continuous-tone colour image (CIELAB)";
|
||||||
|
}
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
static __inline__ uint16_t pack_16(const uint8_t *s)
|
||||||
|
{
|
||||||
|
uint16_t value;
|
||||||
|
|
||||||
|
value = ((uint16_t) s[0] << 8) | (uint16_t) s[1];
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
static __inline__ uint32_t pack_32(const uint8_t *s)
|
||||||
|
{
|
||||||
|
uint32_t value;
|
||||||
|
|
||||||
|
value = ((uint32_t) s[0] << 24) | ((uint32_t) s[1] << 16) | ((uint32_t) s[2] << 8) | (uint32_t) s[3];
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
static __inline__ int unpack_16(uint8_t *s, uint16_t value)
|
||||||
|
{
|
||||||
|
s[0] = (value >> 8) & 0xFF;
|
||||||
|
s[1] = value & 0xFF;
|
||||||
|
return sizeof(uint16_t);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
static __inline__ int unpack_32(uint8_t *s, uint32_t value)
|
||||||
|
{
|
||||||
|
s[0] = (value >> 24) & 0xFF;
|
||||||
|
s[1] = (value >> 16) & 0xFF;
|
||||||
|
s[2] = (value >> 8) & 0xFF;
|
||||||
|
s[3] = value & 0xFF;
|
||||||
|
return sizeof(uint16_t);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_create_header(t43_decode_state_t *s, uint8_t data[], size_t len)
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
pos = 0;
|
||||||
|
unpack_16(data, 0xFFA8);
|
||||||
|
pos += 2;
|
||||||
|
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX0\n");
|
||||||
|
unpack_16(&data[pos], 0xFFE1);
|
||||||
|
pos += 2;
|
||||||
|
unpack_16(&data[pos], 2 + 6 + 10);
|
||||||
|
pos += 2;
|
||||||
|
memcpy(&data[pos], "G3FAX\0", 6);
|
||||||
|
pos += 6;
|
||||||
|
unpack_16(&data[pos], 1997);
|
||||||
|
pos += 2;
|
||||||
|
unpack_16(&data[pos], s->x_resolution);
|
||||||
|
pos += 2;
|
||||||
|
/* JBIG coding method (0) is the only possible value here */
|
||||||
|
data[pos] = 0;
|
||||||
|
pos += 1;
|
||||||
|
data[pos] = 42; //image_type;
|
||||||
|
pos += 1;
|
||||||
|
data[pos] = s->bit_planes[0];
|
||||||
|
pos += 1;
|
||||||
|
data[pos] = s->bit_planes[1];
|
||||||
|
pos += 1;
|
||||||
|
data[pos] = s->bit_planes[2];
|
||||||
|
pos += 1;
|
||||||
|
data[pos] = s->bit_planes[3];
|
||||||
|
pos += 1;
|
||||||
|
|
||||||
|
if (s->lab.offset_L != 0
|
||||||
|
||
|
||||||
|
s->lab.range_L != 100
|
||||||
|
||
|
||||||
|
s->lab.offset_a != 128
|
||||||
|
||
|
||||||
|
s->lab.range_a != 170
|
||||||
|
||
|
||||||
|
s->lab.offset_b != 96
|
||||||
|
||
|
||||||
|
s->lab.range_b != 200)
|
||||||
|
{
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX1\n");
|
||||||
|
unpack_16(&data[pos], 0xFFE1);
|
||||||
|
pos += 2;
|
||||||
|
unpack_16(&data[pos], 2 + 6 + 12);
|
||||||
|
pos += 2;
|
||||||
|
memcpy(&data[pos], "G3FAX\1", 6);
|
||||||
|
pos += 6;
|
||||||
|
unpack_16(&data[pos + 0], s->lab.offset_L);
|
||||||
|
unpack_16(&data[pos + 2], s->lab.range_L);
|
||||||
|
unpack_16(&data[pos + 4], s->lab.offset_a);
|
||||||
|
unpack_16(&data[pos + 6], s->lab.range_a);
|
||||||
|
unpack_16(&data[pos + 8], s->lab.offset_b);
|
||||||
|
unpack_16(&data[pos + 10], s->lab.range_b);
|
||||||
|
pos += 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->lab.x_n != 0.9638f || s->lab.y_n != 1.0f || s->lab.z_n != 0.8245f)
|
||||||
|
{
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX2\n");
|
||||||
|
unpack_16(&data[pos], 0xFFE1);
|
||||||
|
pos += 2;
|
||||||
|
unpack_16(&data[pos], 2 + 6 + 6);
|
||||||
|
pos += 2;
|
||||||
|
memcpy(&data[pos], "G3FAX\2", 6);
|
||||||
|
pos += 6;
|
||||||
|
unpack_16(&data[pos], 0);
|
||||||
|
unpack_16(&data[pos + 2], 0);
|
||||||
|
unpack_16(&data[pos + 4], 0);
|
||||||
|
set_illuminant_from_code(&s->logging, &s->lab, &data[pos]);
|
||||||
|
pos += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (s->colour_map)
|
||||||
|
{
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX3\n");
|
||||||
|
unpack_16(&data[pos], 0xFFE3);
|
||||||
|
pos += 2;
|
||||||
|
unpack_32(&data[pos], ???);
|
||||||
|
pos += 4;
|
||||||
|
memcpy(&data[pos], "G3FAX\3", 6);
|
||||||
|
pos += 6;
|
||||||
|
unpack_16(&data[pos], table_id);
|
||||||
|
pos += 2;
|
||||||
|
unpack_32(&data[pos], s->colour_map_entries);
|
||||||
|
pos += 4;
|
||||||
|
srgb_to_lab(&s->lab, &data[pos], s->colour_map, s->colour_map_entries);
|
||||||
|
pos += 3*s->colour_map_entries;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Putting G3FAX-FF\n");
|
||||||
|
unpack_16(&data[pos], 0xFFE1);
|
||||||
|
pos += 2;
|
||||||
|
unpack_16(&data[pos], 2 + 6);
|
||||||
|
pos += 2;
|
||||||
|
memcpy(&data[pos], "G3FAX\xFF", 6);
|
||||||
|
pos += 6;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(void) t43_encode_set_options(t43_encode_state_t *s,
|
||||||
|
uint32_t l0,
|
||||||
|
int mx,
|
||||||
|
int options)
|
||||||
|
{
|
||||||
|
t85_encode_set_options(&s->t85, l0, mx, options);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_set_image_width(t43_encode_state_t *s, uint32_t image_width)
|
||||||
|
{
|
||||||
|
return t85_encode_set_image_width(&s->t85, image_width);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_set_image_length(t43_encode_state_t *s, uint32_t image_length)
|
||||||
|
{
|
||||||
|
return t85_encode_set_image_length(&s->t85, image_length);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(void) t43_encode_abort(t43_encode_state_t *s)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(void) t43_encode_comment(t43_encode_state_t *s, const uint8_t comment[], size_t len)
|
||||||
|
{
|
||||||
|
t85_encode_comment(&s->t85, comment, len);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_image_complete(t43_encode_state_t *s)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_get(t43_encode_state_t *s, uint8_t buf[], size_t max_len)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(uint32_t) t43_encode_get_image_width(t43_encode_state_t *s)
|
||||||
|
{
|
||||||
|
return t85_encode_get_image_width(&s->t85);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(uint32_t) t43_encode_get_image_length(t43_encode_state_t *s)
|
||||||
|
{
|
||||||
|
return t85_encode_get_image_length(&s->t85);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_get_compressed_image_size(t43_encode_state_t *s)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_set_row_read_handler(t43_encode_state_t *s,
|
||||||
|
t4_row_read_handler_t handler,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
s->row_read_handler = handler;
|
||||||
|
s->row_read_user_data = user_data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(logging_state_t *) t43_encode_get_logging_state(t43_encode_state_t *s)
|
||||||
|
{
|
||||||
|
return &s->logging;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_restart(t43_encode_state_t *s, uint32_t image_width, uint32_t image_length)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(t43_encode_state_t *) t43_encode_init(t43_encode_state_t *s,
|
||||||
|
uint32_t image_width,
|
||||||
|
uint32_t image_length,
|
||||||
|
t4_row_read_handler_t handler,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
if (s == NULL)
|
||||||
|
{
|
||||||
|
if ((s = (t43_encode_state_t *) malloc(sizeof(*s))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(s, 0, sizeof(*s));
|
||||||
|
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
|
||||||
|
span_log_set_protocol(&s->logging, "T.43");
|
||||||
|
|
||||||
|
s->row_read_handler = handler;
|
||||||
|
s->row_read_user_data = user_data;
|
||||||
|
|
||||||
|
t85_encode_init(&s->t85,
|
||||||
|
image_width,
|
||||||
|
image_length,
|
||||||
|
handler,
|
||||||
|
user_data);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_release(t43_encode_state_t *s)
|
||||||
|
{
|
||||||
|
t85_encode_release(&s->t85);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_encode_free(t43_encode_state_t *s)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
t85_encode_free(&s->t85);
|
||||||
|
ret = t43_encode_release(s);
|
||||||
|
free(s);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(void) t43_decode_rx_status(t43_decode_state_t *s, int status)
|
||||||
|
{
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Signal status is %s (%d)\n", signal_status_to_str(status), status);
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case SIG_STATUS_TRAINING_IN_PROGRESS:
|
||||||
|
case SIG_STATUS_TRAINING_FAILED:
|
||||||
|
case SIG_STATUS_TRAINING_SUCCEEDED:
|
||||||
|
case SIG_STATUS_CARRIER_UP:
|
||||||
|
/* Ignore these */
|
||||||
|
break;
|
||||||
|
case SIG_STATUS_CARRIER_DOWN:
|
||||||
|
case SIG_STATUS_END_OF_DATA:
|
||||||
|
/* Finalise the image */
|
||||||
|
t85_decode_put(&s->t85, NULL, 0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected rx status - %d!\n", status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void set_simple_colour_map(t43_decode_state_t *s, int code)
|
||||||
|
{
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
/* Table 3/T.43 1 bit/colour image (using RGB primaries) */
|
||||||
|
memset(s->colour_map, 0, sizeof(s->colour_map));
|
||||||
|
/* Black */
|
||||||
|
/* Blue */
|
||||||
|
s->colour_map[3*0x20 + 2] = 0xF0;
|
||||||
|
/* Green */
|
||||||
|
s->colour_map[3*0x40 + 1] = 0xF0;
|
||||||
|
/* Green + Blue */
|
||||||
|
s->colour_map[3*0x60 + 1] = 0xF0;
|
||||||
|
s->colour_map[3*0x60 + 2] = 0xF0;
|
||||||
|
/* Red */
|
||||||
|
s->colour_map[3*0x80 + 0] = 0xF0;
|
||||||
|
/* Red + Blue */
|
||||||
|
s->colour_map[3*0xA0 + 0] = 0xF0;
|
||||||
|
s->colour_map[3*0xA0 + 2] = 0xF0;
|
||||||
|
/* Red + Green */
|
||||||
|
s->colour_map[3*0xC0 + 0] = 0xF0;
|
||||||
|
s->colour_map[3*0xC0 + 1] = 0xF0;
|
||||||
|
/* White */
|
||||||
|
s->colour_map[3*0xE0 + 0] = 0xF0;
|
||||||
|
s->colour_map[3*0xE0 + 1] = 0xF0;
|
||||||
|
s->colour_map[3*0xE0 + 2] = 0xF0;
|
||||||
|
s->colour_map_entries = 256;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* Table 2/T.43 1 bit/colour image (using CMY primaries) */
|
||||||
|
memset(s->colour_map, 0, sizeof(s->colour_map));
|
||||||
|
/* White */
|
||||||
|
s->colour_map[3*0x00 + 0] = 0xF0;
|
||||||
|
s->colour_map[3*0x00 + 1] = 0xF0;
|
||||||
|
s->colour_map[3*0x00 + 2] = 0xF0;
|
||||||
|
/* Yellow */
|
||||||
|
s->colour_map[3*0x20 + 0] = 0xF0;
|
||||||
|
s->colour_map[3*0x20 + 1] = 0xF0;
|
||||||
|
/* Magenta */
|
||||||
|
s->colour_map[3*0x40 + 0] = 0xF0;
|
||||||
|
s->colour_map[3*0x40 + 2] = 0xF0;
|
||||||
|
/* Magenta + Yellow */
|
||||||
|
s->colour_map[3*0x60 + 0] = 0xF0;
|
||||||
|
/* Cyan */
|
||||||
|
s->colour_map[3*0x80 + 1] = 0xF0;
|
||||||
|
/* Cyan + Yellow */
|
||||||
|
s->colour_map[3*0xA0 + 1] = 0xF0;
|
||||||
|
/* Cyan + Magenta */
|
||||||
|
s->colour_map[3*0xC0 + 2] = 0xF0;
|
||||||
|
/* Black */
|
||||||
|
s->colour_map_entries = 256;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
/* Table 1/T.43 1 bit/colour image (using CMYK primaries) */
|
||||||
|
memset(s->colour_map, 0, sizeof(s->colour_map));
|
||||||
|
/* White */
|
||||||
|
s->colour_map[3*0x00 + 0] = 0xF0;
|
||||||
|
s->colour_map[3*0x00 + 1] = 0xF0;
|
||||||
|
s->colour_map[3*0x00 + 2] = 0xF0;
|
||||||
|
/* Yellow */
|
||||||
|
s->colour_map[3*0x20 + 0] = 0xF0;
|
||||||
|
s->colour_map[3*0x20 + 1] = 0xF0;
|
||||||
|
/* Magenta */
|
||||||
|
s->colour_map[3*0x40 + 0] = 0xF0;
|
||||||
|
s->colour_map[3*0x40 + 2] = 0xF0;
|
||||||
|
/* Magenta + Yellow */
|
||||||
|
s->colour_map[3*0x60 + 0] = 0xF0;
|
||||||
|
/* Cyan */
|
||||||
|
s->colour_map[3*0x80 + 1] = 0xF0;
|
||||||
|
/* Cyan + Yellow */
|
||||||
|
s->colour_map[3*0xA0 + 1] = 0xF0;
|
||||||
|
/* Cyan + Magenta */
|
||||||
|
s->colour_map[3*0xC0 + 2] = 0xF0;
|
||||||
|
/* Black */
|
||||||
|
s->colour_map_entries = 256;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
/* Palettized colour image (using CIELAB 8 bits/component precision table) */
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
/* Palettized colour image (using CIELAB 12 bits/component precision table) */
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
/* Gray-scale image (using L*) */
|
||||||
|
break;
|
||||||
|
case 48:
|
||||||
|
/* Continuous-tone colour image (using CIELAB) */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
static int t43_analyse_header(t43_decode_state_t *s, const uint8_t data[], size_t len)
|
||||||
|
{
|
||||||
|
int seg;
|
||||||
|
int pos;
|
||||||
|
int table_id;
|
||||||
|
int val[6];
|
||||||
|
uint8_t col[3];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Set defaults */
|
||||||
|
set_lab_illuminant(&s->lab, 0.9638f, 1.0f, 0.8245f);
|
||||||
|
set_lab_gamut(&s->lab, 0, 100, -85, 85, -75, 125, FALSE);
|
||||||
|
pos = 0;
|
||||||
|
if (pack_16(&data[pos]) != 0xFFA8)
|
||||||
|
return 0;
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Got BCIH (bit-plane colour image header)\n");
|
||||||
|
pos += 2;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (pack_16(&data[pos]) == 0xFFE1)
|
||||||
|
{
|
||||||
|
pos += 2;
|
||||||
|
seg = pack_16(&data[pos]);
|
||||||
|
pos += 2;
|
||||||
|
seg -= 2;
|
||||||
|
if (seg >= 6 && strncmp((char *) &data[pos], "G3FAX", 5) == 0)
|
||||||
|
{
|
||||||
|
if (data[pos + 5] == 0xFF)
|
||||||
|
{
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Got ECIH (end of colour image header)\n");
|
||||||
|
if (seg != 6)
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Got bad ECIH length - %d\n", seg);
|
||||||
|
pos += seg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (data[pos + 5])
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Got G3FAX0\n");
|
||||||
|
if (seg >= 6 + 10)
|
||||||
|
{
|
||||||
|
val[0] = pack_16(&data[pos + 6 + 0]);
|
||||||
|
s->x_resolution = pack_16(&data[pos + 6 + 2]);
|
||||||
|
val[2] = data[pos + 6 + 4];
|
||||||
|
val[3] = data[pos + 6 + 5];
|
||||||
|
s->bit_planes[0] = data[pos + 6 + 6];
|
||||||
|
s->bit_planes[1] = data[pos + 6 + 7];
|
||||||
|
s->bit_planes[2] = data[pos + 6 + 8];
|
||||||
|
s->bit_planes[3] = data[pos + 6 + 9];
|
||||||
|
span_log(&s->logging,
|
||||||
|
SPAN_LOG_FLOW,
|
||||||
|
"Version %d, resolution %.2fdpi, coding method %d, type %s (%d), bit planes %d,%d,%d,%d\n",
|
||||||
|
val[0],
|
||||||
|
s->x_resolution/100.0f,
|
||||||
|
val[2],
|
||||||
|
t43_image_type_to_str(val[3]),
|
||||||
|
val[3],
|
||||||
|
s->bit_planes[0],
|
||||||
|
s->bit_planes[1],
|
||||||
|
s->bit_planes[2],
|
||||||
|
s->bit_planes[3]);
|
||||||
|
set_simple_colour_map(s, val[3]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX0 length - %d\n", seg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Set gamut\n");
|
||||||
|
if (seg >= 6 + 12)
|
||||||
|
set_gamut_from_code(&s->logging, &s->lab, &data[pos + 6]);
|
||||||
|
else
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX1 length - %d\n", seg);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Set illuminant\n");
|
||||||
|
if (seg >= 6 + 4)
|
||||||
|
set_illuminant_from_code(&s->logging, &s->lab, &data[pos + 6]);
|
||||||
|
else
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX2 length - %d\n", seg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Got unexpected G3FAX%d length - %d\n", data[pos + 5], seg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos += seg;
|
||||||
|
}
|
||||||
|
else if (pack_16(&data[pos]) == 0xFFE3)
|
||||||
|
{
|
||||||
|
pos += 2;
|
||||||
|
seg = pack_32(&data[pos]);
|
||||||
|
pos += 4;
|
||||||
|
seg -= 4;
|
||||||
|
if (seg >= 6)
|
||||||
|
{
|
||||||
|
if (strncmp((char *) &data[pos], "G3FAX\3", 6) == 0)
|
||||||
|
{
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Got G3FAX3\n");
|
||||||
|
table_id = pack_16(&data[pos + 6]);
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, " Table ID %3d\n", table_id);
|
||||||
|
switch (table_id)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
/* 8 bit CIELAB */
|
||||||
|
s->colour_map_entries = pack_32(&data[pos + 8]);
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, " Entries %6d\n", s->colour_map_entries);
|
||||||
|
if (seg >= 12 + s->colour_map_entries*3)
|
||||||
|
{
|
||||||
|
lab_to_srgb(&s->lab, s->colour_map, &data[pos + 12], s->colour_map_entries);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX3 length - %d\n", seg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
/* 12 bit CIELAB */
|
||||||
|
s->colour_map_entries = pack_32(&data[pos + 8]);
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, " Entries %6d\n", s->colour_map_entries);
|
||||||
|
/* TODO: implement 12bit stuff */
|
||||||
|
if (seg >= 12 + s->colour_map_entries*3*2)
|
||||||
|
{
|
||||||
|
for (i = 0; i < s->colour_map_entries; i++)
|
||||||
|
{
|
||||||
|
col[0] = pack_16(&data[pos + 12 + 6*i]) >> 4;
|
||||||
|
col[1] = pack_16(&data[pos + 12 + 6*i + 2]) >> 4;
|
||||||
|
col[2] = pack_16(&data[pos + 12 + 6*i + 4]) >> 4;
|
||||||
|
lab_to_srgb(&s->lab, &s->colour_map[3*i], col, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX3 length - %d\n", seg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
span_log(&s->logging, SPAN_LOG_FLOW, "Got bad G3FAX3 table ID - %d\n", table_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos += seg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
static int t85_row_write_handler(void *user_data, const uint8_t buf[], size_t len)
|
||||||
|
{
|
||||||
|
t43_decode_state_t *s;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
int image_size;
|
||||||
|
uint8_t mask;
|
||||||
|
|
||||||
|
/* Repack the bit packed T.85 image plane to a 3 x 8 bits per pixel colour image.
|
||||||
|
We use the red entry now. This will be remapped to RGB later, as we apply the
|
||||||
|
colour map. */
|
||||||
|
s = (t43_decode_state_t *) user_data;
|
||||||
|
|
||||||
|
if (s->buf == NULL)
|
||||||
|
{
|
||||||
|
image_size = 3*s->t85.xd*s->t85.yd;
|
||||||
|
if ((s->buf = malloc(image_size)) == NULL)
|
||||||
|
return -1;
|
||||||
|
memset(s->buf, 0, image_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
mask = 0x80;
|
||||||
|
for (j = 0; j < 24; j += 3)
|
||||||
|
{
|
||||||
|
if ((buf[i] & mask))
|
||||||
|
s->buf[s->ptr + j] |= s->bit_plane_mask;
|
||||||
|
mask >>= 1;
|
||||||
|
}
|
||||||
|
s->ptr += 3*8;
|
||||||
|
}
|
||||||
|
s->row++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_decode_put(t43_decode_state_t *s, const uint8_t data[], size_t len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
int plane_len;
|
||||||
|
int total_len;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
/* TODO: this isn't allowing for the header arriving in chunks */
|
||||||
|
if (s->current_bit_plane < 0)
|
||||||
|
{
|
||||||
|
i = t43_analyse_header(s, data, len);
|
||||||
|
data += i;
|
||||||
|
len -= i;
|
||||||
|
s->bit_plane_mask = 0x80;
|
||||||
|
s->current_bit_plane++;
|
||||||
|
|
||||||
|
/* There must be at least one bit plane. The real value for this will
|
||||||
|
be filled in as the first plane is processed */
|
||||||
|
s->t85.bit_planes = 1;
|
||||||
|
s->ptr = 0;
|
||||||
|
s->row = 0;
|
||||||
|
s->buf = NULL;
|
||||||
|
s->plane_ptr = 0;
|
||||||
|
t85_decode_new_plane(&s->t85);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now deal the bit-planes, one after another. */
|
||||||
|
while (s->current_bit_plane < s->t85.bit_planes)
|
||||||
|
{
|
||||||
|
j = s->current_bit_plane;
|
||||||
|
|
||||||
|
result = t85_decode_put(&s->t85, data, len);
|
||||||
|
if (result != T4_DECODE_OK)
|
||||||
|
{
|
||||||
|
s->plane_ptr += len;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
plane_len = t85_decode_get_compressed_image_size(&s->t85);
|
||||||
|
data += (plane_len/8 - s->plane_ptr);
|
||||||
|
len -= (plane_len/8 - s->plane_ptr);
|
||||||
|
total_len = s->ptr;
|
||||||
|
|
||||||
|
/* Start the next plane */
|
||||||
|
s->bit_plane_mask >>= 1;
|
||||||
|
s->current_bit_plane++;
|
||||||
|
s->ptr = 0;
|
||||||
|
s->row = 0;
|
||||||
|
s->plane_ptr = 0;
|
||||||
|
t85_decode_new_plane(&s->t85);
|
||||||
|
}
|
||||||
|
/* Apply the colour map, and produce the RGB data from the collected bit-planes */
|
||||||
|
for (j = 0; j < total_len; j += 3)
|
||||||
|
{
|
||||||
|
i = s->buf[j];
|
||||||
|
s->buf[j] = s->colour_map[3*i];
|
||||||
|
s->buf[j + 1] = s->colour_map[3*i + 1];
|
||||||
|
s->buf[j + 2] = s->colour_map[3*i + 2];
|
||||||
|
}
|
||||||
|
for (j = 0; j < s->t85.yd; j++)
|
||||||
|
{
|
||||||
|
s->row_write_handler(s->row_write_user_data, &s->buf[j*3*s->t85.xd], 3*s->t85.xd);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_decode_set_row_write_handler(t43_decode_state_t *s,
|
||||||
|
t4_row_write_handler_t handler,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
s->row_write_handler = handler;
|
||||||
|
s->row_write_user_data = user_data;
|
||||||
|
s->t85.row_write_handler = handler;
|
||||||
|
s->t85.row_write_user_data = user_data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_decode_set_comment_handler(t43_decode_state_t *s,
|
||||||
|
uint32_t max_comment_len,
|
||||||
|
t4_row_write_handler_t handler,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
return t85_decode_set_comment_handler(&s->t85, max_comment_len, handler, user_data);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_decode_set_image_size_constraints(t43_decode_state_t *s,
|
||||||
|
uint32_t max_xd,
|
||||||
|
uint32_t max_yd)
|
||||||
|
{
|
||||||
|
return t85_decode_set_image_size_constraints(&s->t85, max_xd, max_yd);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(uint32_t) t43_decode_get_image_width(t43_decode_state_t *s)
|
||||||
|
{
|
||||||
|
return t85_decode_get_image_width(&s->t85);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(uint32_t) t43_decode_get_image_length(t43_decode_state_t *s)
|
||||||
|
{
|
||||||
|
return t85_decode_get_image_length(&s->t85);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_decode_get_compressed_image_size(t43_decode_state_t *s)
|
||||||
|
{
|
||||||
|
return t85_decode_get_compressed_image_size(&s->t85);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(logging_state_t *) t43_decode_get_logging_state(t43_decode_state_t *s)
|
||||||
|
{
|
||||||
|
return &s->logging;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_decode_restart(t43_decode_state_t *s)
|
||||||
|
{
|
||||||
|
return t85_decode_restart(&s->t85);
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(t43_decode_state_t *) t43_decode_init(t43_decode_state_t *s,
|
||||||
|
t4_row_write_handler_t handler,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
if (s == NULL)
|
||||||
|
{
|
||||||
|
if ((s = (t43_decode_state_t *) malloc(sizeof(*s))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(s, 0, sizeof(*s));
|
||||||
|
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
|
||||||
|
span_log_set_protocol(&s->logging, "T.43");
|
||||||
|
|
||||||
|
s->row_write_handler = handler;
|
||||||
|
s->row_write_user_data = user_data;
|
||||||
|
|
||||||
|
t85_decode_init(&s->t85, t85_row_write_handler, s);
|
||||||
|
|
||||||
|
s->t85.min_bit_planes = 1;
|
||||||
|
s->t85.max_bit_planes = 8;
|
||||||
|
s->bit_plane_mask = 0x80;
|
||||||
|
s->current_bit_plane = -1;
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_decode_release(t43_decode_state_t *s)
|
||||||
|
{
|
||||||
|
t85_decode_release(&s->t85);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
SPAN_DECLARE(int) t43_decode_free(t43_decode_state_t *s)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = t43_decode_release(s);
|
||||||
|
t85_decode_free(&s->t85);
|
||||||
|
free(s);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
/*- End of file ------------------------------------------------------------*/
|
|
@ -107,6 +107,8 @@ SPAN_DECLARE(const char *) t4_encoding_to_str(int encoding)
|
||||||
return "T.85";
|
return "T.85";
|
||||||
case T4_COMPRESSION_T85_L0:
|
case T4_COMPRESSION_T85_L0:
|
||||||
return "T.85(L0)";
|
return "T.85(L0)";
|
||||||
|
case T4_COMPRESSION_T88:
|
||||||
|
return "T.88";
|
||||||
case T4_COMPRESSION_T42_T81:
|
case T4_COMPRESSION_T42_T81:
|
||||||
return "T.81";
|
return "T.81";
|
||||||
case T4_COMPRESSION_SYCC_T81:
|
case T4_COMPRESSION_SYCC_T81:
|
||||||
|
|
|
@ -104,12 +104,12 @@ static void t4_tx_set_image_length(t4_tx_state_t *s, int image_length);
|
||||||
|
|
||||||
static const res_table_t x_res_table[] =
|
static const res_table_t x_res_table[] =
|
||||||
{
|
{
|
||||||
//{ 100.0f/CM_PER_INCH, T4_X_RESOLUTION_100},
|
{ 100.0f/CM_PER_INCH, T4_X_RESOLUTION_100},
|
||||||
{ 102.0f/CM_PER_INCH, T4_X_RESOLUTION_R4},
|
{ 102.0f/CM_PER_INCH, T4_X_RESOLUTION_R4},
|
||||||
//{ 200.0f/CM_PER_INCH, T4_X_RESOLUTION_200},
|
{ 200.0f/CM_PER_INCH, T4_X_RESOLUTION_200},
|
||||||
{ 204.0f/CM_PER_INCH, T4_X_RESOLUTION_R8},
|
{ 204.0f/CM_PER_INCH, T4_X_RESOLUTION_R8},
|
||||||
{ 300.0f/CM_PER_INCH, T4_X_RESOLUTION_300},
|
{ 300.0f/CM_PER_INCH, T4_X_RESOLUTION_300},
|
||||||
//{ 400.0f/CM_PER_INCH, T4_X_RESOLUTION_400},
|
{ 400.0f/CM_PER_INCH, T4_X_RESOLUTION_400},
|
||||||
{ 408.0f/CM_PER_INCH, T4_X_RESOLUTION_R16},
|
{ 408.0f/CM_PER_INCH, T4_X_RESOLUTION_R16},
|
||||||
{ 600.0f/CM_PER_INCH, T4_X_RESOLUTION_600},
|
{ 600.0f/CM_PER_INCH, T4_X_RESOLUTION_600},
|
||||||
{ 800.0f/CM_PER_INCH, T4_X_RESOLUTION_800},
|
{ 800.0f/CM_PER_INCH, T4_X_RESOLUTION_800},
|
||||||
|
@ -120,12 +120,12 @@ static const res_table_t x_res_table[] =
|
||||||
static const res_table_t y_res_table[] =
|
static const res_table_t y_res_table[] =
|
||||||
{
|
{
|
||||||
{ 38.50f, T4_Y_RESOLUTION_STANDARD},
|
{ 38.50f, T4_Y_RESOLUTION_STANDARD},
|
||||||
//{ 100.0f/CM_PER_INCH, T4_Y_RESOLUTION_100},
|
{ 100.0f/CM_PER_INCH, T4_Y_RESOLUTION_100},
|
||||||
{ 77.00f, T4_Y_RESOLUTION_FINE},
|
{ 77.00f, T4_Y_RESOLUTION_FINE},
|
||||||
//{ 200.0f/CM_PER_INCH, T4_Y_RESOLUTION_200},
|
{ 200.0f/CM_PER_INCH, T4_Y_RESOLUTION_200},
|
||||||
{ 300.0f/CM_PER_INCH, T4_Y_RESOLUTION_300},
|
{ 300.0f/CM_PER_INCH, T4_Y_RESOLUTION_300},
|
||||||
{ 154.00f, T4_Y_RESOLUTION_SUPERFINE},
|
{ 154.00f, T4_Y_RESOLUTION_SUPERFINE},
|
||||||
//{ 400.0f/CM_PER_INCH, T4_Y_RESOLUTION_400},
|
{ 400.0f/CM_PER_INCH, T4_Y_RESOLUTION_400},
|
||||||
{ 600.0f/CM_PER_INCH, T4_Y_RESOLUTION_600},
|
{ 600.0f/CM_PER_INCH, T4_Y_RESOLUTION_600},
|
||||||
{ 800.0f/CM_PER_INCH, T4_Y_RESOLUTION_800},
|
{ 800.0f/CM_PER_INCH, T4_Y_RESOLUTION_800},
|
||||||
{1200.0f/CM_PER_INCH, T4_Y_RESOLUTION_1200},
|
{1200.0f/CM_PER_INCH, T4_Y_RESOLUTION_1200},
|
||||||
|
@ -385,7 +385,7 @@ static int get_tiff_directory_info(t4_tx_state_t *s)
|
||||||
best_y_entry = 0;
|
best_y_entry = 0;
|
||||||
s->metadata.y_resolution = y_res_table[best_y_entry].code;
|
s->metadata.y_resolution = y_res_table[best_y_entry].code;
|
||||||
|
|
||||||
//s->metadata.resolution_code = resolution_map[best_y_entry][best_x_entry];
|
s->metadata.resolution_code = resolution_map[best_y_entry][best_x_entry];
|
||||||
|
|
||||||
t4_tx_set_image_width(s, s->image_width);
|
t4_tx_set_image_width(s, s->image_width);
|
||||||
t4_tx_set_image_length(s, s->image_length);
|
t4_tx_set_image_length(s, s->image_length);
|
||||||
|
|
|
@ -73,10 +73,21 @@
|
||||||
#define FP_SCALE(x) (x)
|
#define FP_SCALE(x) (x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "v17_v32bis_rx_rrc.h"
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
|
#define FP_SYNC_SCALE(x) FP_Q_6_10(x)
|
||||||
|
#define FP_SYNC_SCALE_32(x) FP_Q_6_10_32(x)
|
||||||
|
#define FP_SYNC_SHIFT_FACTOR 10
|
||||||
|
#else
|
||||||
|
#define FP_SYNC_SCALE(x) (x)
|
||||||
|
#define FP_SYNC_SCALE_32(x) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FP_CONSTELLATION_SCALE(x) FP_SCALE(x)
|
#define FP_CONSTELLATION_SCALE(x) FP_SCALE(x)
|
||||||
|
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||||
|
#define FP_CONSTELLATION_SHIFT_FACTOR FP_SHIFT_FACTOR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "v17_v32bis_rx_rrc.h"
|
||||||
#include "v17_v32bis_tx_constellation_maps.h"
|
#include "v17_v32bis_tx_constellation_maps.h"
|
||||||
#include "v17_v32bis_rx_constellation_maps.h"
|
#include "v17_v32bis_rx_constellation_maps.h"
|
||||||
|
|
||||||
|
@ -106,6 +117,23 @@
|
||||||
/*! The 16 bit pattern used in the bridge section of the training sequence */
|
/*! The 16 bit pattern used in the bridge section of the training sequence */
|
||||||
#define V17_BRIDGE_WORD 0x8880
|
#define V17_BRIDGE_WORD 0x8880
|
||||||
|
|
||||||
|
/* Coefficients for the band edge symbol timing synchroniser (alpha = 0.99) */
|
||||||
|
/* low_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ - BAUD_RATE/2.0f)/SAMPLE_RATE; */
|
||||||
|
/* high_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ + BAUD_RATE/2.0f)/SAMPLE_RATE; */
|
||||||
|
#define SIN_LOW_BAND_EDGE 0.453990499f
|
||||||
|
#define COS_LOW_BAND_EDGE 0.891006542f
|
||||||
|
#define SIN_HIGH_BAND_EDGE 0.707106781f
|
||||||
|
#define COS_HIGH_BAND_EDGE -0.707106781f
|
||||||
|
#define ALPHA 0.99f
|
||||||
|
|
||||||
|
#define SYNC_LOW_BAND_EDGE_COEFF_0 FP_SYNC_SCALE(2.0f*ALPHA*COS_LOW_BAND_EDGE)
|
||||||
|
#define SYNC_LOW_BAND_EDGE_COEFF_1 FP_SYNC_SCALE(-ALPHA*ALPHA)
|
||||||
|
#define SYNC_LOW_BAND_EDGE_COEFF_2 FP_SYNC_SCALE(-ALPHA*SIN_LOW_BAND_EDGE)
|
||||||
|
#define SYNC_HIGH_BAND_EDGE_COEFF_0 FP_SYNC_SCALE(2.0f*ALPHA*COS_HIGH_BAND_EDGE)
|
||||||
|
#define SYNC_HIGH_BAND_EDGE_COEFF_1 FP_SYNC_SCALE(-ALPHA*ALPHA)
|
||||||
|
#define SYNC_HIGH_BAND_EDGE_COEFF_2 FP_SYNC_SCALE(-ALPHA*SIN_HIGH_BAND_EDGE)
|
||||||
|
#define SYNC_MIXED_EDGES_COEFF_3 FP_SYNC_SCALE(-ALPHA*ALPHA*(SIN_HIGH_BAND_EDGE*COS_LOW_BAND_EDGE - SIN_LOW_BAND_EDGE*COS_HIGH_BAND_EDGE))
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
TRAINING_STAGE_NORMAL_OPERATION = 0,
|
TRAINING_STAGE_NORMAL_OPERATION = 0,
|
||||||
|
@ -123,33 +151,6 @@ enum
|
||||||
TRAINING_STAGE_PARKED
|
TRAINING_STAGE_PARKED
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Coefficients for the band edge symbol timing synchroniser (alpha = 0.99) */
|
|
||||||
/* low_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ - BAUD_RATE/2.0f)/SAMPLE_RATE; */
|
|
||||||
/* high_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ + BAUD_RATE/2.0f)/SAMPLE_RATE; */
|
|
||||||
#define SIN_LOW_BAND_EDGE 0.453990499f
|
|
||||||
#define COS_LOW_BAND_EDGE 0.891006542f
|
|
||||||
#define SIN_HIGH_BAND_EDGE 0.707106781f
|
|
||||||
#define COS_HIGH_BAND_EDGE -0.707106781f
|
|
||||||
#define ALPHA 0.99f
|
|
||||||
|
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
|
||||||
#define SYNC_LOW_BAND_EDGE_COEFF_0 FP_Q_6_10(2.0f*ALPHA*COS_LOW_BAND_EDGE)
|
|
||||||
#define SYNC_LOW_BAND_EDGE_COEFF_1 FP_Q_6_10(-ALPHA*ALPHA)
|
|
||||||
#define SYNC_LOW_BAND_EDGE_COEFF_2 FP_Q_6_10(-ALPHA*SIN_LOW_BAND_EDGE)
|
|
||||||
#define SYNC_HIGH_BAND_EDGE_COEFF_0 FP_Q_6_10(2.0f*ALPHA*COS_HIGH_BAND_EDGE)
|
|
||||||
#define SYNC_HIGH_BAND_EDGE_COEFF_1 FP_Q_6_10(-ALPHA*ALPHA)
|
|
||||||
#define SYNC_HIGH_BAND_EDGE_COEFF_2 FP_Q_6_10(-ALPHA*SIN_HIGH_BAND_EDGE)
|
|
||||||
#define SYNC_MIXED_EDGES_COEFF_3 FP_Q_6_10(-ALPHA*ALPHA*(SIN_HIGH_BAND_EDGE*COS_LOW_BAND_EDGE - SIN_LOW_BAND_EDGE*COS_HIGH_BAND_EDGE))
|
|
||||||
#else
|
|
||||||
#define SYNC_LOW_BAND_EDGE_COEFF_0 (2.0f*ALPHA*COS_LOW_BAND_EDGE)
|
|
||||||
#define SYNC_LOW_BAND_EDGE_COEFF_1 (-ALPHA*ALPHA)
|
|
||||||
#define SYNC_LOW_BAND_EDGE_COEFF_2 (-ALPHA*SIN_LOW_BAND_EDGE)
|
|
||||||
#define SYNC_HIGH_BAND_EDGE_COEFF_0 (2.0f*ALPHA*COS_HIGH_BAND_EDGE)
|
|
||||||
#define SYNC_HIGH_BAND_EDGE_COEFF_1 (-ALPHA*ALPHA)
|
|
||||||
#define SYNC_HIGH_BAND_EDGE_COEFF_2 (-ALPHA*SIN_HIGH_BAND_EDGE)
|
|
||||||
#define SYNC_MIXED_EDGES_COEFF_3 (-ALPHA*ALPHA*(SIN_HIGH_BAND_EDGE*COS_LOW_BAND_EDGE - SIN_LOW_BAND_EDGE*COS_HIGH_BAND_EDGE))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
static const int16_t constellation_spacing[4] =
|
static const int16_t constellation_spacing[4] =
|
||||||
#else
|
#else
|
||||||
|
@ -245,14 +246,14 @@ static void equalizer_reset(v17_rx_state_t *s)
|
||||||
{
|
{
|
||||||
/* Start with an equalizer based on everything being perfect */
|
/* Start with an equalizer based on everything being perfect */
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
static const complexi16_t x = {FP_SCALE(3.0f), FP_SCALE(0.0f)};
|
static const complexi16_t x = {FP_CONSTELLATION_SCALE(3.0f), FP_CONSTELLATION_SCALE(0.0f)};
|
||||||
|
|
||||||
cvec_zeroi16(s->eq_coeff, V17_EQUALIZER_LEN);
|
cvec_zeroi16(s->eq_coeff, V17_EQUALIZER_LEN);
|
||||||
s->eq_coeff[V17_EQUALIZER_PRE_LEN] = x;
|
s->eq_coeff[V17_EQUALIZER_PRE_LEN] = x;
|
||||||
cvec_zeroi16(s->eq_buf, V17_EQUALIZER_LEN);
|
cvec_zeroi16(s->eq_buf, V17_EQUALIZER_LEN);
|
||||||
s->eq_delta = 32768.0f*EQUALIZER_DELTA/V17_EQUALIZER_LEN;
|
s->eq_delta = 32768.0f*EQUALIZER_DELTA/V17_EQUALIZER_LEN;
|
||||||
#else
|
#else
|
||||||
static const complexf_t x = {3.0f, 0.0f};
|
static const complexf_t x = {FP_CONSTELLATION_SCALE(3.0f), FP_CONSTELLATION_SCALE(0.0f)};
|
||||||
|
|
||||||
cvec_zerof(s->eq_coeff, V17_EQUALIZER_LEN);
|
cvec_zerof(s->eq_coeff, V17_EQUALIZER_LEN);
|
||||||
s->eq_coeff[V17_EQUALIZER_PRE_LEN] = x;
|
s->eq_coeff[V17_EQUALIZER_PRE_LEN] = x;
|
||||||
|
@ -313,20 +314,6 @@ static void tune_equalizer(v17_rx_state_t *s, const complexf_t *z, const complex
|
||||||
#endif
|
#endif
|
||||||
/*- End of function --------------------------------------------------------*/
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
static int descramble(v17_rx_state_t *s, int in_bit)
|
|
||||||
{
|
|
||||||
int out_bit;
|
|
||||||
|
|
||||||
out_bit = (in_bit ^ (s->scramble_reg >> s->scrambler_tap) ^ (s->scramble_reg >> (23 - 1))) & 1;
|
|
||||||
s->scramble_reg <<= 1;
|
|
||||||
if (s->training_stage > TRAINING_STAGE_NORMAL_OPERATION && s->training_stage < TRAINING_STAGE_TCM_WINDUP)
|
|
||||||
s->scramble_reg |= out_bit;
|
|
||||||
else
|
|
||||||
s->scramble_reg |= (in_bit & 1);
|
|
||||||
return out_bit;
|
|
||||||
}
|
|
||||||
/*- End of function --------------------------------------------------------*/
|
|
||||||
|
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
static __inline__ void track_carrier(v17_rx_state_t *s, const complexi16_t *z, const complexi16_t *target)
|
static __inline__ void track_carrier(v17_rx_state_t *s, const complexi16_t *z, const complexi16_t *target)
|
||||||
#else
|
#else
|
||||||
|
@ -355,6 +342,21 @@ static __inline__ void track_carrier(v17_rx_state_t *s, const complexf_t *z, con
|
||||||
}
|
}
|
||||||
/*- End of function --------------------------------------------------------*/
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
|
static int descramble(v17_rx_state_t *s, int in_bit)
|
||||||
|
{
|
||||||
|
int out_bit;
|
||||||
|
|
||||||
|
in_bit &= 1;
|
||||||
|
out_bit = (in_bit ^ (s->scramble_reg >> s->scrambler_tap) ^ (s->scramble_reg >> (23 - 1))) & 1;
|
||||||
|
s->scramble_reg <<= 1;
|
||||||
|
if (s->training_stage > TRAINING_STAGE_NORMAL_OPERATION && s->training_stage < TRAINING_STAGE_TCM_WINDUP)
|
||||||
|
s->scramble_reg |= out_bit;
|
||||||
|
else
|
||||||
|
s->scramble_reg |= (in_bit & 1);
|
||||||
|
return out_bit;
|
||||||
|
}
|
||||||
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
static __inline__ void put_bit(v17_rx_state_t *s, int bit)
|
static __inline__ void put_bit(v17_rx_state_t *s, int bit)
|
||||||
{
|
{
|
||||||
int out_bit;
|
int out_bit;
|
||||||
|
@ -675,13 +677,13 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
complexi16_t z;
|
complexi16_t z;
|
||||||
complexi16_t z16;
|
complexi16_t z16;
|
||||||
const complexi16_t *target;
|
const complexi16_t *target;
|
||||||
static const complexi16_t zero = {0, 0};
|
static const complexi16_t zero = {FP_SCALE(0.0f), FP_SCALE(0.0f)};
|
||||||
#else
|
#else
|
||||||
float p;
|
float p;
|
||||||
complexf_t z;
|
complexf_t z;
|
||||||
complexf_t zz;
|
complexf_t zz;
|
||||||
const complexf_t *target;
|
const complexf_t *target;
|
||||||
static const complexf_t zero = {0.0f, 0.0f};
|
static const complexf_t zero = {FP_SCALE(0.0f), FP_SCALE(0.0f)};
|
||||||
#endif
|
#endif
|
||||||
int bit;
|
int bit;
|
||||||
int i;
|
int i;
|
||||||
|
@ -724,13 +726,8 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
s->training_stage = TRAINING_STAGE_LOG_PHASE;
|
s->training_stage = TRAINING_STAGE_LOG_PHASE;
|
||||||
vec_zeroi32(s->diff_angles, 16);
|
vec_zeroi32(s->diff_angles, 16);
|
||||||
s->last_angles[0] = arctan2(z.im, z.re);
|
s->last_angles[0] = arctan2(z.im, z.re);
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
if (s->agc_scaling_save == FP_SCALE(0.0f))
|
||||||
if (s->agc_scaling_save == 0)
|
|
||||||
s->agc_scaling_save = s->agc_scaling;
|
s->agc_scaling_save = s->agc_scaling;
|
||||||
#else
|
|
||||||
if (s->agc_scaling_save == 0.0f)
|
|
||||||
s->agc_scaling_save = s->agc_scaling;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TRAINING_STAGE_LOG_PHASE:
|
case TRAINING_STAGE_LOG_PHASE:
|
||||||
|
@ -816,11 +813,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
{
|
{
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
||||||
/* Park this modem */
|
/* Park this modem */
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
s->agc_scaling_save = FP_SCALE(0.0f);
|
||||||
s->agc_scaling_save = 0;
|
|
||||||
#else
|
|
||||||
s->agc_scaling_save = 0.0f;
|
|
||||||
#endif
|
|
||||||
s->training_stage = TRAINING_STAGE_PARKED;
|
s->training_stage = TRAINING_STAGE_PARKED;
|
||||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||||
break;
|
break;
|
||||||
|
@ -860,11 +853,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
of a real training sequence. Note that this might be TEP. */
|
of a real training sequence. Note that this might be TEP. */
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
||||||
/* Park this modem */
|
/* Park this modem */
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
s->agc_scaling_save = FP_SCALE(0.0f);
|
||||||
s->agc_scaling_save = 0;
|
|
||||||
#else
|
|
||||||
s->agc_scaling_save = 0.0f;
|
|
||||||
#endif
|
|
||||||
s->training_stage = TRAINING_STAGE_PARKED;
|
s->training_stage = TRAINING_STAGE_PARKED;
|
||||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||||
}
|
}
|
||||||
|
@ -880,12 +869,11 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
z16 = complex_subi16(&z, target);
|
z16 = complex_subi16(&z, target);
|
||||||
s->training_error += poweri16(&z16);
|
s->training_error += poweri16(&z16);
|
||||||
if (++s->training_count == V17_TRAINING_SEG_2_LEN - 2000 || s->training_error < 1*FP_FACTOR*FP_FACTOR || s->training_error > 200*FP_FACTOR*FP_FACTOR)
|
|
||||||
#else
|
#else
|
||||||
zz = complex_subf(&z, target);
|
zz = complex_subf(&z, target);
|
||||||
s->training_error = powerf(&zz);
|
s->training_error = powerf(&zz);
|
||||||
if (++s->training_count == V17_TRAINING_SEG_2_LEN - 2000 || s->training_error < 1.0f || s->training_error > 200.0f)
|
|
||||||
#endif
|
#endif
|
||||||
|
if (++s->training_count == V17_TRAINING_SEG_2_LEN - 2000 || s->training_error < FP_SCALE(1.0f)*FP_SCALE(1.0f) || s->training_error > FP_SCALE(200.0f)*FP_SCALE(1.0f))
|
||||||
#else
|
#else
|
||||||
if (++s->training_count == V17_TRAINING_SEG_2_LEN - 2000)
|
if (++s->training_count == V17_TRAINING_SEG_2_LEN - 2000)
|
||||||
#endif
|
#endif
|
||||||
|
@ -948,15 +936,12 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
{
|
{
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Long training error %d\n", s->training_error);
|
span_log(&s->logging, SPAN_LOG_FLOW, "Long training error %d\n", s->training_error);
|
||||||
if (s->training_error < 20.0f*1.414f*FP_FACTOR*FP_FACTOR*constellation_spacing[s->space_map])
|
|
||||||
{
|
|
||||||
s->training_error = 0;
|
|
||||||
#else
|
#else
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Long training error %f\n", s->training_error);
|
span_log(&s->logging, SPAN_LOG_FLOW, "Long training error %f\n", s->training_error);
|
||||||
if (s->training_error < 20.0f*1.414f*constellation_spacing[s->space_map])
|
|
||||||
{
|
|
||||||
s->training_error = 0.0f;
|
|
||||||
#endif
|
#endif
|
||||||
|
if (s->training_error < FP_SCALE(20.0f)*FP_SCALE(1.414f)*constellation_spacing[s->space_map])
|
||||||
|
{
|
||||||
|
s->training_error = FP_SCALE(0.0f);
|
||||||
s->training_count = 0;
|
s->training_count = 0;
|
||||||
s->training_stage = TRAINING_STAGE_BRIDGE;
|
s->training_stage = TRAINING_STAGE_BRIDGE;
|
||||||
}
|
}
|
||||||
|
@ -964,11 +949,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
{
|
{
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (convergence failed)\n");
|
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (convergence failed)\n");
|
||||||
/* Park this modem */
|
/* Park this modem */
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
s->agc_scaling_save = FP_SCALE(0.0f);
|
||||||
s->agc_scaling_save = 0;
|
|
||||||
#else
|
|
||||||
s->agc_scaling_save = 0.0f;
|
|
||||||
#endif
|
|
||||||
s->training_stage = TRAINING_STAGE_PARKED;
|
s->training_stage = TRAINING_STAGE_PARKED;
|
||||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||||
}
|
}
|
||||||
|
@ -980,11 +961,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
target = &z;
|
target = &z;
|
||||||
if (++s->training_count >= V17_TRAINING_SEG_3_LEN)
|
if (++s->training_count >= V17_TRAINING_SEG_3_LEN)
|
||||||
{
|
{
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
s->training_error = FP_SCALE(0.0f);
|
||||||
s->training_error = 0;
|
|
||||||
#else
|
|
||||||
s->training_error = 0.0f;
|
|
||||||
#endif
|
|
||||||
s->training_count = 0;
|
s->training_count = 0;
|
||||||
if (s->bits_per_symbol == 2)
|
if (s->bits_per_symbol == 2)
|
||||||
{
|
{
|
||||||
|
@ -1012,11 +989,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
bit = descramble(s, 1);
|
bit = descramble(s, 1);
|
||||||
bit = (bit << 1) | descramble(s, 1);
|
bit = (bit << 1) | descramble(s, 1);
|
||||||
target = &cdba[bit];
|
target = &cdba[bit];
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
s->training_error = FP_SCALE(0.0f);
|
||||||
s->training_error = 0;
|
|
||||||
#else
|
|
||||||
s->training_error = 0.0f;
|
|
||||||
#endif
|
|
||||||
s->training_count = 1;
|
s->training_count = 1;
|
||||||
s->training_stage = TRAINING_STAGE_SHORT_TRAIN_ON_CDBA_AND_TEST;
|
s->training_stage = TRAINING_STAGE_SHORT_TRAIN_ON_CDBA_AND_TEST;
|
||||||
break;
|
break;
|
||||||
|
@ -1066,11 +1039,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
/* TODO: This was increased by a factor of 10 after studying real world failures.
|
/* TODO: This was increased by a factor of 10 after studying real world failures.
|
||||||
However, it is not clear why this is an improvement, If something gives
|
However, it is not clear why this is an improvement, If something gives
|
||||||
a huge training error, surely it shouldn't decode too well? */
|
a huge training error, surely it shouldn't decode too well? */
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
if (s->training_error < (V17_TRAINING_SHORT_SEG_2_LEN - 8)*FP_SCALE(4.0f)*FP_SCALE(1.0f)*constellation_spacing[s->space_map])
|
||||||
if (s->training_error < (V17_TRAINING_SHORT_SEG_2_LEN - 8)*4.0f*FP_FACTOR*FP_FACTOR*constellation_spacing[s->space_map])
|
|
||||||
#else
|
|
||||||
if (s->training_error < (V17_TRAINING_SHORT_SEG_2_LEN - 8)*4.0f*constellation_spacing[s->space_map])
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
s->training_count = 0;
|
s->training_count = 0;
|
||||||
if (s->bits_per_symbol == 2)
|
if (s->bits_per_symbol == 2)
|
||||||
|
@ -1078,11 +1047,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
/* There is no trellis, so go straight to processing decoded data */
|
/* There is no trellis, so go straight to processing decoded data */
|
||||||
/* Restart the differential decoder */
|
/* Restart the differential decoder */
|
||||||
s->diff = (s->short_train) ? 0 : 1;
|
s->diff = (s->short_train) ? 0 : 1;
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
s->training_error = FP_SCALE(0.0f);
|
||||||
s->training_error = 0;
|
|
||||||
#else
|
|
||||||
s->training_error = 0.0f;
|
|
||||||
#endif
|
|
||||||
s->training_stage = TRAINING_STAGE_TEST_ONES;
|
s->training_stage = TRAINING_STAGE_TEST_ONES;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1116,11 +1081,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
#endif
|
#endif
|
||||||
if (++s->training_count >= V17_TRAINING_SEG_4A_LEN)
|
if (++s->training_count >= V17_TRAINING_SEG_4A_LEN)
|
||||||
{
|
{
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
s->training_error = FP_SCALE(0.0f);
|
||||||
s->training_error = 0;
|
|
||||||
#else
|
|
||||||
s->training_error = 0.0f;
|
|
||||||
#endif
|
|
||||||
s->training_count = 0;
|
s->training_count = 0;
|
||||||
/* Restart the differential decoder */
|
/* Restart the differential decoder */
|
||||||
s->diff = (s->short_train) ? 0 : 1;
|
s->diff = (s->short_train) ? 0 : 1;
|
||||||
|
@ -1143,13 +1104,11 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
#endif
|
#endif
|
||||||
if (++s->training_count >= V17_TRAINING_SEG_4_LEN)
|
if (++s->training_count >= V17_TRAINING_SEG_4_LEN)
|
||||||
{
|
{
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
if (s->training_error < V17_TRAINING_SEG_4_LEN*FP_SCALE(1.0f)*FP_SCALE(1.0f)*constellation_spacing[s->space_map])
|
||||||
if (s->training_error < V17_TRAINING_SEG_4_LEN*FP_FACTOR*FP_FACTOR*constellation_spacing[s->space_map])
|
|
||||||
{
|
{
|
||||||
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training succeeded at %dbps (constellation mismatch %d)\n", s->bit_rate, s->training_error);
|
span_log(&s->logging, SPAN_LOG_FLOW, "Training succeeded at %dbps (constellation mismatch %d)\n", s->bit_rate, s->training_error);
|
||||||
#else
|
#else
|
||||||
if (s->training_error < V17_TRAINING_SEG_4_LEN*constellation_spacing[s->space_map])
|
|
||||||
{
|
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training succeeded at %dbps (constellation mismatch %f)\n", s->bit_rate, s->training_error);
|
span_log(&s->logging, SPAN_LOG_FLOW, "Training succeeded at %dbps (constellation mismatch %f)\n", s->bit_rate, s->training_error);
|
||||||
#endif
|
#endif
|
||||||
/* We are up and running */
|
/* We are up and running */
|
||||||
|
@ -1167,13 +1126,11 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
/* Training has failed. Park this modem. */
|
/* Training has failed. Park this modem. */
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (constellation mismatch %d)\n", s->training_error);
|
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (constellation mismatch %d)\n", s->training_error);
|
||||||
if (!s->short_train)
|
|
||||||
s->agc_scaling_save = 0;
|
|
||||||
#else
|
#else
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (constellation mismatch %f)\n", s->training_error);
|
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (constellation mismatch %f)\n", s->training_error);
|
||||||
if (!s->short_train)
|
|
||||||
s->agc_scaling_save = 0.0f;
|
|
||||||
#endif
|
#endif
|
||||||
|
if (!s->short_train)
|
||||||
|
s->agc_scaling_save = FP_SCALE(0.0f);
|
||||||
s->training_stage = TRAINING_STAGE_PARKED;
|
s->training_stage = TRAINING_STAGE_PARKED;
|
||||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||||
}
|
}
|
||||||
|
@ -1317,11 +1274,15 @@ SPAN_DECLARE_NONSTD(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
||||||
sample.re = (v*s->agc_scaling) >> 10;
|
sample.re = (v*s->agc_scaling) >> 10;
|
||||||
/* Symbol timing synchronisation band edge filters */
|
/* Symbol timing synchronisation band edge filters */
|
||||||
/* Low Nyquist band edge filter */
|
/* Low Nyquist band edge filter */
|
||||||
v = ((s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0) >> 10) + ((s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1) >> 10) + sample.re;
|
v = ((s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0) >> 10)
|
||||||
|
+ ((s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1) >> 10)
|
||||||
|
+ sample.re;
|
||||||
s->symbol_sync_low[1] = s->symbol_sync_low[0];
|
s->symbol_sync_low[1] = s->symbol_sync_low[0];
|
||||||
s->symbol_sync_low[0] = v;
|
s->symbol_sync_low[0] = v;
|
||||||
/* High Nyquist band edge filter */
|
/* High Nyquist band edge filter */
|
||||||
v = ((s->symbol_sync_high[0]*SYNC_HIGH_BAND_EDGE_COEFF_0) >> 10) + ((s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_1) >> 10) + sample.re;
|
v = ((s->symbol_sync_high[0]*SYNC_HIGH_BAND_EDGE_COEFF_0) >> 10)
|
||||||
|
+ ((s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_1) >> 10)
|
||||||
|
+ sample.re;
|
||||||
s->symbol_sync_high[1] = s->symbol_sync_high[0];
|
s->symbol_sync_high[1] = s->symbol_sync_high[0];
|
||||||
s->symbol_sync_high[0] = v;
|
s->symbol_sync_high[0] = v;
|
||||||
#else
|
#else
|
||||||
|
@ -1342,18 +1303,16 @@ SPAN_DECLARE_NONSTD(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
||||||
if (s->eq_put_step <= 0)
|
if (s->eq_put_step <= 0)
|
||||||
{
|
{
|
||||||
/* Only AGC until we have locked down the setting. */
|
/* Only AGC until we have locked down the setting. */
|
||||||
|
if (s->agc_scaling_save == FP_SCALE(0.0f))
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
if (s->agc_scaling_save == 0)
|
s->agc_scaling = saturate16(((int32_t) (FP_SCALE(2.17f)*1024.0f))/fixed_sqrt32(power));
|
||||||
s->agc_scaling = saturate16(((int32_t) (1024.0f*FP_FACTOR*2.17f))/fixed_sqrt32(power));
|
|
||||||
#else
|
#else
|
||||||
if (s->agc_scaling_save == 0.0f)
|
s->agc_scaling = (FP_SCALE(2.17f)/RX_PULSESHAPER_GAIN)/sqrtf(power);
|
||||||
s->agc_scaling = (1.0f/RX_PULSESHAPER_GAIN)*2.17f/sqrtf(power);
|
|
||||||
#endif
|
#endif
|
||||||
/* Pulse shape while still at the carrier frequency, using a quadrature
|
/* Pulse shape while still at the carrier frequency, using a quadrature
|
||||||
pair of filters. This results in a properly bandpass filtered complex
|
pair of filters. This results in a properly bandpass filtered complex
|
||||||
signal, which can be brought directly to baseband by complex mixing.
|
signal, which can be brought directly to baseband by complex mixing.
|
||||||
No further filtering, to remove mixer harmonics, is needed. */
|
No further filtering, to remove mixer harmonics, is needed. */
|
||||||
s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
|
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_im[step], V17_RX_FILTER_STEPS, s->rrc_filter_step) >> 15;
|
v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_im[step], V17_RX_FILTER_STEPS, s->rrc_filter_step) >> 15;
|
||||||
sample.im = (v*s->agc_scaling) >> 10;
|
sample.im = (v*s->agc_scaling) >> 10;
|
||||||
|
@ -1367,6 +1326,7 @@ SPAN_DECLARE_NONSTD(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
||||||
zz.re = sample.re*z.re - sample.im*z.im;
|
zz.re = sample.re*z.re - sample.im*z.im;
|
||||||
zz.im = -sample.re*z.im - sample.im*z.re;
|
zz.im = -sample.re*z.im - sample.im*z.re;
|
||||||
#endif
|
#endif
|
||||||
|
s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
|
||||||
process_half_baud(s, &zz);
|
process_half_baud(s, &zz);
|
||||||
}
|
}
|
||||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||||
|
@ -1467,11 +1427,10 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
||||||
s->bit_rate = bit_rate;
|
s->bit_rate = bit_rate;
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
vec_zeroi16(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
|
vec_zeroi16(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
|
||||||
s->training_error = 0;
|
|
||||||
#else
|
#else
|
||||||
vec_zerof(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
|
vec_zerof(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
|
||||||
s->training_error = 0.0f;
|
|
||||||
#endif
|
#endif
|
||||||
|
s->training_error = FP_SCALE(0.0f);
|
||||||
s->rrc_filter_step = 0;
|
s->rrc_filter_step = 0;
|
||||||
|
|
||||||
s->diff = 1;
|
s->diff = 1;
|
||||||
|
@ -1486,8 +1445,8 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
||||||
#endif
|
#endif
|
||||||
if (short_train != 2)
|
if (short_train != 2)
|
||||||
s->short_train = short_train;
|
s->short_train = short_train;
|
||||||
memset(s->last_angles, 0, sizeof(s->last_angles));
|
vec_zeroi32(s->last_angles, 2);
|
||||||
memset(s->diff_angles, 0, sizeof(s->diff_angles));
|
vec_zeroi32(s->diff_angles, 16);
|
||||||
|
|
||||||
/* Initialise the TCM decoder parameters. */
|
/* Initialise the TCM decoder parameters. */
|
||||||
/* The accumulated distance vectors are set so state zero starts
|
/* The accumulated distance vectors are set so state zero starts
|
||||||
|
@ -1525,17 +1484,13 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
||||||
{
|
{
|
||||||
s->carrier_phase_rate = DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ);
|
s->carrier_phase_rate = DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ);
|
||||||
equalizer_reset(s);
|
equalizer_reset(s);
|
||||||
|
s->agc_scaling_save = FP_SCALE(0.0f);
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
s->agc_scaling_save = 0;
|
s->agc_scaling = (float) (FP_SCALE(2.17f)*1024.0f)/735.0f;
|
||||||
s->agc_scaling = (float) (1024.0f*FP_FACTOR)*2.17f/735.0f;
|
|
||||||
#else
|
|
||||||
s->agc_scaling_save = 0.0f;
|
|
||||||
s->agc_scaling = (1.0f/RX_PULSESHAPER_GAIN)*2.17f/735.0f;
|
|
||||||
#endif
|
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
|
||||||
s->carrier_track_i = 5000;
|
s->carrier_track_i = 5000;
|
||||||
s->carrier_track_p = 40000;
|
s->carrier_track_p = 40000;
|
||||||
#else
|
#else
|
||||||
|
s->agc_scaling = (FP_SCALE(2.17f)/RX_PULSESHAPER_GAIN)/735.0f;
|
||||||
s->carrier_track_i = 5000.0f;
|
s->carrier_track_i = 5000.0f;
|
||||||
s->carrier_track_p = 40000.0f;
|
s->carrier_track_p = 40000.0f;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1545,23 +1500,13 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Phase rates %f %f\n", dds_frequencyf(s->carrier_phase_rate), dds_frequencyf(s->carrier_phase_rate_save));
|
span_log(&s->logging, SPAN_LOG_FLOW, "Phase rates %f %f\n", dds_frequencyf(s->carrier_phase_rate), dds_frequencyf(s->carrier_phase_rate_save));
|
||||||
|
|
||||||
/* Initialise the working data for symbol timing synchronisation */
|
/* Initialise the working data for symbol timing synchronisation */
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
|
||||||
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
s->symbol_sync_low[i] = 0;
|
s->symbol_sync_low[i] = FP_SCALE(0.0f);
|
||||||
s->symbol_sync_high[i] = 0;
|
s->symbol_sync_high[i] = FP_SCALE(0.0f);
|
||||||
s->symbol_sync_dc_filter[i] = 0;
|
s->symbol_sync_dc_filter[i] = FP_SCALE(0.0f);
|
||||||
}
|
}
|
||||||
s->baud_phase = 0;
|
s->baud_phase = FP_SCALE(0.0f);
|
||||||
#else
|
|
||||||
for (i = 0; i < 2; i++)
|
|
||||||
{
|
|
||||||
s->symbol_sync_low[i] = 0.0f;
|
|
||||||
s->symbol_sync_high[i] = 0.0f;
|
|
||||||
s->symbol_sync_dc_filter[i] = 0.0f;
|
|
||||||
}
|
|
||||||
s->baud_phase = 0.0f;
|
|
||||||
#endif
|
|
||||||
s->baud_half = 0;
|
s->baud_half = 0;
|
||||||
|
|
||||||
s->total_baud_timing_correction = 0;
|
s->total_baud_timing_correction = 0;
|
||||||
|
|
|
@ -861,24 +861,15 @@ int main(int argc, char *argv[])
|
||||||
| T4_SUPPORT_RESOLUTION_600_1200
|
| T4_SUPPORT_RESOLUTION_600_1200
|
||||||
| T4_SUPPORT_RESOLUTION_1200_1200);
|
| T4_SUPPORT_RESOLUTION_1200_1200);
|
||||||
t30_set_supported_colour_resolutions(t30_state[i], 0);
|
t30_set_supported_colour_resolutions(t30_state[i], 0);
|
||||||
//t30_set_rx_encoding(t30_state[i], T4_COMPRESSION_T85);
|
//t30_set_rx_encoding(t30_state[i], T4_COMPRESSION_T6);
|
||||||
t30_set_ecm_capability(t30_state[i], use_ecm);
|
t30_set_ecm_capability(t30_state[i], use_ecm);
|
||||||
if (use_ecm)
|
t30_set_supported_compressions(t30_state[i],
|
||||||
{
|
T4_SUPPORT_COMPRESSION_T4_1D
|
||||||
t30_set_supported_compressions(t30_state[i],
|
| T4_SUPPORT_COMPRESSION_T4_2D
|
||||||
T30_SUPPORT_COMPRESSION_T4_1D
|
| T4_SUPPORT_COMPRESSION_T6
|
||||||
| T30_SUPPORT_COMPRESSION_T4_2D
|
//| T4_SUPPORT_COMPRESSION_t42_T81
|
||||||
| T30_SUPPORT_COMPRESSION_T6
|
| T4_SUPPORT_COMPRESSION_T85
|
||||||
//| T30_SUPPORT_COMPRESSION_T81
|
| T4_SUPPORT_COMPRESSION_T85_L0);
|
||||||
| T30_SUPPORT_COMPRESSION_T85
|
|
||||||
| T30_SUPPORT_COMPRESSION_T85_L0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
t30_set_supported_compressions(t30_state[i],
|
|
||||||
T30_SUPPORT_COMPRESSION_T4_1D
|
|
||||||
| T30_SUPPORT_COMPRESSION_T4_2D);
|
|
||||||
}
|
|
||||||
t30_set_minimum_scan_line_time(t30_state[i], scan_line_time);
|
t30_set_minimum_scan_line_time(t30_state[i], scan_line_time);
|
||||||
|
|
||||||
if (mode[i] == T38_GATEWAY_FAX)
|
if (mode[i] == T38_GATEWAY_FAX)
|
||||||
|
@ -954,6 +945,10 @@ int main(int argc, char *argv[])
|
||||||
logging = fax_get_logging_state(fax_state[i]);
|
logging = fax_get_logging_state(fax_state[i]);
|
||||||
span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
|
span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Mute the signal */
|
||||||
|
vec_zeroi16(fax_rx_buf[i], SAMPLES_PER_CHUNK);
|
||||||
|
#endif
|
||||||
fax_rx(fax_state[i], fax_rx_buf[i], SAMPLES_PER_CHUNK);
|
fax_rx(fax_state[i], fax_rx_buf[i], SAMPLES_PER_CHUNK);
|
||||||
if (!t30_call_active(t30_state[i]))
|
if (!t30_call_active(t30_state[i]))
|
||||||
{
|
{
|
||||||
|
|
|
@ -106,9 +106,9 @@ static const struct command_response_s fax_send_test_seq[] =
|
||||||
EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"),
|
EXCHANGE("AT+FRH=3\r", "\r\nCONNECT\r\n"),
|
||||||
//<DIS frame data>
|
//<DIS frame data>
|
||||||
#if 1
|
#if 1
|
||||||
RESPONSE("\xFF\x13\x80\x00\xEE\xF8\x80\x80\x91\x80\x80\x80\x18\x78\x57\x10\x03"), // For audio FAXing
|
RESPONSE("\xFF\x13\x80\x00\xEE\xF8\x80\x80\x89\x80\x80\x80\x18\x18\xB9\x10\x03"), // For audio FAXing
|
||||||
#else
|
#else
|
||||||
RESPONSE("\xFF\x13\x80\x04\xEE\xF8\x80\x80\x91\x80\x80\x80\x18\xE4\xE7\x10\x03"), // For T.38 FAXing
|
RESPONSE("\xFF\x13\x80\x04\xEE\xF8\x80\x80\x89\x80\x80\x80\x18\x84\x09\x10\x03"), // For T.38 FAXing
|
||||||
#endif
|
#endif
|
||||||
RESPONSE("\r\nOK\r\n"),
|
RESPONSE("\r\nOK\r\n"),
|
||||||
//EXCHANGE("AT+FRH=3\r", "\r\nNO CARRIER\r\n"),
|
//EXCHANGE("AT+FRH=3\r", "\r\nNO CARRIER\r\n"),
|
||||||
|
@ -870,7 +870,7 @@ static int t30_tests(int t38_mode, int use_gui, int log_audio, int test_sending,
|
||||||
if (!done || !sequence_terminated)
|
if (!done || !sequence_terminated)
|
||||||
{
|
{
|
||||||
printf("Tests failed\n");
|
printf("Tests failed\n");
|
||||||
return 2;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -934,7 +934,8 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t30_tests(t38_mode, use_gui, log_audio, test_sending, g1050_model_no, g1050_speed_pattern_no);
|
if (t30_tests(t38_mode, use_gui, log_audio, test_sending, g1050_model_no, g1050_speed_pattern_no) < 0)
|
||||||
|
return 2;
|
||||||
printf("Tests passed\n");
|
printf("Tests passed\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -440,7 +440,7 @@ int main(int argc, char *argv[])
|
||||||
t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A');
|
t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A');
|
||||||
t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A');
|
t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A');
|
||||||
t30_set_ecm_capability(t30, use_ecm);
|
t30_set_ecm_capability(t30, use_ecm);
|
||||||
t30_set_supported_compressions(t30, T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D | T30_SUPPORT_COMPRESSION_T6 | T30_SUPPORT_COMPRESSION_T85);
|
t30_set_supported_compressions(t30, T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D | T4_SUPPORT_COMPRESSION_T6 | T4_SUPPORT_COMPRESSION_T85);
|
||||||
|
|
||||||
if (pcap_scan_pkts(input_file_name, src_addr, src_port, dest_addr, dest_port, t38_terminal_timing_update, process_packet, NULL))
|
if (pcap_scan_pkts(input_file_name, src_addr, src_port, dest_addr, dest_port, t38_terminal_timing_update, process_packet, NULL))
|
||||||
exit(2);
|
exit(2);
|
||||||
|
@ -497,7 +497,7 @@ int main(int argc, char *argv[])
|
||||||
t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'B');
|
t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'B');
|
||||||
t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'B');
|
t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'B');
|
||||||
t30_set_ecm_capability(t30, use_ecm);
|
t30_set_ecm_capability(t30, use_ecm);
|
||||||
t30_set_supported_compressions(t30, T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D | T30_SUPPORT_COMPRESSION_T6);
|
t30_set_supported_compressions(t30, T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D | T4_SUPPORT_COMPRESSION_T6);
|
||||||
|
|
||||||
logging = fax_get_logging_state(fax_state);
|
logging = fax_get_logging_state(fax_state);
|
||||||
span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
|
span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
|
||||||
|
|
|
@ -47,7 +47,6 @@
|
||||||
#include <tif_dir.h>
|
#include <tif_dir.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define IN_FILE_NAME "../test-data/itu/t24/F21_200.TIF"
|
|
||||||
#define IN_FILE_NAME "../test-data/itu/t24/F21B400.TIF"
|
#define IN_FILE_NAME "../test-data/itu/t24/F21B400.TIF"
|
||||||
#define OUT_FILE_NAME "t42_tests_receive.tif"
|
#define OUT_FILE_NAME "t42_tests_receive.tif"
|
||||||
|
|
||||||
|
|
|
@ -409,7 +409,7 @@ static void fax_prepare(void)
|
||||||
| T4_SUPPORT_RESOLUTION_1200_1200);
|
| T4_SUPPORT_RESOLUTION_1200_1200);
|
||||||
t30_set_supported_colour_resolutions(t30, 0);
|
t30_set_supported_colour_resolutions(t30, 0);
|
||||||
t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
|
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_supported_compressions(t30, T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D | T4_SUPPORT_COMPRESSION_T6);
|
||||||
t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A');
|
t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A');
|
||||||
t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A');
|
t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A');
|
||||||
t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A');
|
t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A');
|
||||||
|
@ -882,7 +882,7 @@ static int next_step(faxtester_state_t *s)
|
||||||
t30 = fax_get_t30_state(fax);
|
t30 = fax_get_t30_state(fax);
|
||||||
t30_set_rx_file(t30, output_tiff_file_name, -1);
|
t30_set_rx_file(t30, output_tiff_file_name, -1);
|
||||||
/* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */
|
/* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */
|
||||||
t30_set_rx_encoding(t30, T4_COMPRESSION_T4_1D);
|
t30_set_supported_output_compressions(t30, T4_COMPRESSION_T4_1D);
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
sprintf(path, "%s/%s", image_path, (const char *) value);
|
sprintf(path, "%s/%s", image_path, (const char *) value);
|
||||||
|
@ -897,7 +897,7 @@ static int next_step(faxtester_state_t *s)
|
||||||
next_tx_file[0] = '\0';
|
next_tx_file[0] = '\0';
|
||||||
t30 = fax_get_t30_state(fax);
|
t30 = fax_get_t30_state(fax);
|
||||||
/* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */
|
/* Avoid libtiff 3.8.2 and earlier bug on complex 2D lines. */
|
||||||
t30_set_rx_encoding(t30, T4_COMPRESSION_T4_1D);
|
t30_set_supported_output_compressions(t30, T4_COMPRESSION_T4_1D);
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
sprintf(path, "%s/%s", image_path, (const char *) value);
|
sprintf(path, "%s/%s", image_path, (const char *) value);
|
||||||
|
|
|
@ -890,11 +890,11 @@ static switch_status_t spanfax_init(pvt_t *pvt, transport_mode_t trans_mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pvt->use_ecm) {
|
if (pvt->use_ecm) {
|
||||||
t30_set_supported_compressions(t30, T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D | T30_SUPPORT_COMPRESSION_T6 | T30_SUPPORT_COMPRESSION_T85 | T30_SUPPORT_COMPRESSION_T85_L0);
|
t30_set_supported_compressions(t30, T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D | T4_SUPPORT_COMPRESSION_T6 | T4_SUPPORT_COMPRESSION_T85 | T4_SUPPORT_COMPRESSION_T85_L0);
|
||||||
t30_set_ecm_capability(t30, TRUE);
|
t30_set_ecm_capability(t30, TRUE);
|
||||||
switch_channel_set_variable(channel, "fax_ecm_requested", "1");
|
switch_channel_set_variable(channel, "fax_ecm_requested", "1");
|
||||||
} else {
|
} else {
|
||||||
t30_set_supported_compressions(t30, T30_SUPPORT_COMPRESSION_T4_1D | T30_SUPPORT_COMPRESSION_T4_2D);
|
t30_set_supported_compressions(t30, T4_SUPPORT_COMPRESSION_T4_1D | T4_SUPPORT_COMPRESSION_T4_2D);
|
||||||
switch_channel_set_variable(channel, "fax_ecm_requested", "0");
|
switch_channel_set_variable(channel, "fax_ecm_requested", "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue