Merge branch 'master' of ssh://git.freeswitch.org:222/freeswitch

This commit is contained in:
David Yat Sin 2012-09-13 12:35:19 -04:00
commit 4c3c4c5a28
8 changed files with 159 additions and 83 deletions

View File

@ -534,7 +534,7 @@ fi
if test "$ac_cv_header_tif_dir_h" = "yes" ; then
AC_DEFINE([SPANDSP_SUPPORT_TIFF_FX], [1], [Support TIFF/FX in TIFF file handling])
SPANDSP_SUPPORT_TIFF_FX="#define SPANDSP_SUPPORT_TIFF_FX"
SPANDSP_SUPPORT_TIFF_FX="#define SPANDSP_SUPPORT_TIFF_FX 1"
else
SPANDSP_SUPPORT_TIFF_FX="#undef SPANDSP_SUPPORT_TIFF_FX"
fi

View File

@ -38,7 +38,7 @@ typedef struct
/*! \brief The compression type used in the TIFF file */
uint16_t compression;
/*! \brief Image type - bilevel, gray, colour */
/*! \brief Image type - bi-level, gray, colour, etc. */
int image_type;
/*! \brief The TIFF photometric setting for the current page. */
uint16_t photo_metric;
@ -96,6 +96,11 @@ struct t4_tx_state_s
int line_encoding_gray;
int line_encoding_colour;
/*! \brief When superfine and fine resolution images need to be squahed vertically
to a lower resolution, this value sets the number of source rows which
must be squashed to form each row on the wire. */
int row_squashing_ratio;
/*! \brief The width of the current page, in pixels. */
uint32_t image_width;
/*! \brief The length of the current page, in pixels. */

View File

@ -342,6 +342,12 @@ SPAN_DECLARE(void) t4_tx_set_header_overlays_image(t4_tx_state_t *s, int header_
\return 0 for success, otherwise -1. */
SPAN_DECLARE(int) t4_tx_set_row_read_handler(t4_tx_state_t *s, t4_row_read_handler_t handler, void *user_data);
/*! \brief Set the row squashing ratio, for adjusting row-to-row (y) resolution of bi-level
images for a T.4 transmit context.
\param s The T.4 transmit context.
\param row_squashing_ratio Vertical squashing ratio. */
SPAN_DECLARE(void) t4_tx_set_row_squashing_ratio(t4_tx_state_t *s, int row_squashing_ratio);
/*! \brief Get the row-to-row (y) resolution of the current page.
\param s The T.4 context.
\return The resolution, in pixels per metre. */

View File

@ -1308,6 +1308,7 @@ static int build_dcs(t30_state_t *s)
{
int i;
int bad;
int row_squashing_ratio;
/* 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. */
@ -1369,6 +1370,7 @@ static int build_dcs(t30_state_t *s)
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_RECEIVE_FAX_DOCUMENT);
/* Set the Y resolution bits */
bad = T30_ERR_OK;
row_squashing_ratio = 1;
switch (s->y_resolution)
{
case T4_Y_RESOLUTION_1200:
@ -1425,27 +1427,6 @@ static int build_dcs(t30_state_t *s)
break;
}
break;
case T4_Y_RESOLUTION_SUPERFINE:
if (!(s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION))
{
bad = T30_ERR_NORESSUPPORT;
}
else
{
switch (s->x_resolution)
{
case T4_X_RESOLUTION_R8:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
break;
case T4_X_RESOLUTION_R16:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
break;
default:
bad = T30_ERR_NORESSUPPORT;
break;
}
}
break;
case T4_Y_RESOLUTION_300:
switch (s->x_resolution)
{
@ -1460,12 +1441,27 @@ static int build_dcs(t30_state_t *s)
break;
}
break;
case T4_Y_RESOLUTION_FINE:
if (!(s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION))
case T4_Y_RESOLUTION_SUPERFINE:
if ((s->supported_resolutions & T30_SUPPORT_SUPERFINE_RESOLUTION))
{
bad = T30_ERR_NORESSUPPORT;
switch (s->x_resolution)
{
case T4_X_RESOLUTION_R8:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_200_400);
break;
case T4_X_RESOLUTION_R16:
set_ctrl_bit(s->dcs_frame, T30_DCS_BIT_400_400);
break;
default:
bad = T30_ERR_NORESSUPPORT;
break;
}
break;
}
else
row_squashing_ratio <<= 1;
/* Fall through */
case T4_Y_RESOLUTION_FINE:
if ((s->supported_resolutions & T30_SUPPORT_FINE_RESOLUTION))
{
switch (s->x_resolution)
{
@ -1476,8 +1472,10 @@ static int build_dcs(t30_state_t *s)
bad = T30_ERR_NORESSUPPORT;
break;
}
break;
}
break;
row_squashing_ratio <<= 1;
/* Fall through */
default:
case T4_Y_RESOLUTION_STANDARD:
switch (s->x_resolution)
@ -1491,6 +1489,7 @@ static int build_dcs(t30_state_t *s)
}
break;
}
t4_tx_set_row_squashing_ratio(&s->t4.tx, row_squashing_ratio);
if (bad != T30_ERR_OK)
{
t30_set_status(s, bad);
@ -1915,23 +1914,21 @@ static int set_min_scan_time_code(t30_state_t *s)
switch (s->y_resolution)
{
case T4_Y_RESOLUTION_SUPERFINE:
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE))
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_400_CAPABLE))
{
t30_set_status(s, T30_ERR_NORESSUPPORT);
span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support super-fine resolution.\n");
return -1;
s->min_scan_time_code = translate_min_scan_time[(test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_MIN_SCAN_TIME_HALVES)) ? 2 : 1][min_bits_field];
break;
}
s->min_scan_time_code = translate_min_scan_time[(test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_MIN_SCAN_TIME_HALVES)) ? 2 : 1][min_bits_field];
break;
span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support super-fine resolution. Squashing image.\n");
/* Fall through */
case T4_Y_RESOLUTION_FINE:
if (!test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE))
if (test_ctrl_bit(s->far_dis_dtc_frame, T30_DIS_BIT_200_200_CAPABLE))
{
t30_set_status(s, T30_ERR_NORESSUPPORT);
span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support fine resolution.\n");
return -1;
s->min_scan_time_code = translate_min_scan_time[1][min_bits_field];
break;
}
s->min_scan_time_code = translate_min_scan_time[1][min_bits_field];
break;
span_log(&s->logging, SPAN_LOG_FLOW, "Remote FAX does not support fine resolution. Squashing image.\n");
/* Fall through */
default:
case T4_Y_RESOLUTION_STANDARD:
s->min_scan_time_code = translate_min_scan_time[0][min_bits_field];
@ -2122,7 +2119,7 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
}
}
}
span_log(&s->logging, SPAN_LOG_FLOW, "Selected compression %s (%d)\n", t4_encoding_to_str(s->line_encoding), s->line_encoding);
span_log(&s->logging, SPAN_LOG_FLOW, "Choose compression %s (%d)\n", t4_encoding_to_str(s->line_encoding), s->line_encoding);
switch (s->far_dis_dtc_frame[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3))
{
case (DISBIT6 | DISBIT4 | DISBIT3):
@ -2410,7 +2407,7 @@ static int process_rx_dcs(t30_state_t *s, const uint8_t *msg, int len)
{
s->line_encoding = T4_COMPRESSION_ITU_T4_1D;
}
span_log(&s->logging, SPAN_LOG_FLOW, "Selected compression %s (%d)\n", t4_encoding_to_str(s->line_encoding), s->line_encoding);
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))
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Remote is not requesting receive in DCS\n");
@ -3389,12 +3386,18 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
send_simple_frame(s, T30_RTP);
break;
case T30_COPY_QUALITY_BAD:
#if 0
/* Some people want to keep even the bad pages */
if (s->keep_bad_pages)
rx_end_page(s);
#endif
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
set_state(s, T30_STATE_III_Q_RTN);
send_simple_frame(s, T30_RTN);
break;
}
break;
case T30_DCN:
t30_set_status(s, T30_ERR_RX_DCNFAX);
@ -6306,9 +6309,13 @@ SPAN_DECLARE(t30_state_t *) t30_init(t30_state_t *s,
/* Default to the basic modems. */
s->supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
s->supported_compressions = T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION;
s->supported_resolutions = T30_SUPPORT_STANDARD_RESOLUTION | T30_SUPPORT_FINE_RESOLUTION | T30_SUPPORT_SUPERFINE_RESOLUTION
s->supported_resolutions = T30_SUPPORT_STANDARD_RESOLUTION
| T30_SUPPORT_FINE_RESOLUTION
| T30_SUPPORT_SUPERFINE_RESOLUTION
| T30_SUPPORT_R8_RESOLUTION;
s->supported_image_sizes = T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH
s->supported_image_sizes = T30_SUPPORT_US_LETTER_LENGTH
| T30_SUPPORT_US_LEGAL_LENGTH
| T30_SUPPORT_UNLIMITED_LENGTH
| T30_SUPPORT_215MM_WIDTH;
/* Set the output encoding to something safe. Most things get 1D and 2D
encoding right. Quite a lot get other things wrong. */

View File

@ -484,12 +484,23 @@ static int open_tiff_input_file(t4_tx_state_t *s, const char *file)
static int tiff_row_read_handler(void *user_data, uint8_t buf[], size_t len)
{
t4_tx_state_t *s;
int i;
int j;
s = (t4_tx_state_t *) user_data;
if (s->tiff.row >= s->image_length)
return 0;
memcpy(buf, &s->tiff.image_buffer[s->tiff.row*len], len);
s->tiff.row++;
/* If this is a bi-level image which has more vertical resolution than the
far end will accept, we need to squash it down to size. */
for (i = 1; i < s->row_squashing_ratio && s->tiff.row < s->image_length; i++)
{
for (j = 0; j < s->image_width/8; j++)
buf[j] |= s->tiff.image_buffer[s->tiff.row*len + j];
s->tiff.row++;
}
return len;
}
/*- End of function --------------------------------------------------------*/
@ -497,7 +508,7 @@ static int tiff_row_read_handler(void *user_data, uint8_t buf[], size_t len)
static int row_read(void *user_data, uint8_t buf[], size_t len)
{
t4_tx_state_t *s;
s = (t4_tx_state_t *) user_data;
if (s->tiff.raw_row >= s->tiff.image_length)
@ -650,7 +661,7 @@ static int make_header(t4_tx_state_t *s)
if ((s->header_text = malloc(132 + 1)) == NULL)
return -1;
}
/* This is very English oriented, but then most FAX machines are, too. Some
/* This is very English oriented, but then most FAX machines are. Some
measure of i18n in the time and date, and even the header_info string, is
entirely possible, although the font area would need some serious work to
properly deal with East Asian script. There is no spec for what the header
@ -711,6 +722,7 @@ static int header_row_read_handler(void *user_data, uint8_t buf[], size_t len)
repeats = 1;
break;
}
repeats /= s->row_squashing_ratio;
if (s->header_overlays_image)
{
/* Read and dump a row of the real image, allowing for the possibility
@ -721,23 +733,37 @@ static int header_row_read_handler(void *user_data, uint8_t buf[], size_t len)
return len;
}
}
row = s->header_row/repeats;
pos = 0;
for (t = s->header_text; *t && pos <= len - 2; t++)
switch (s->tiff.image_type)
{
pattern = header_font[(uint8_t) *t][row];
buf[pos++] = (uint8_t) (pattern >> 8);
buf[pos++] = (uint8_t) (pattern & 0xFF);
case T4_IMAGE_TYPE_BILEVEL:
row = s->header_row/repeats;
pos = 0;
for (t = s->header_text; *t && pos <= len - 2; t++)
{
pattern = header_font[(uint8_t) *t][row];
buf[pos++] = (uint8_t) (pattern >> 8);
buf[pos++] = (uint8_t) (pattern & 0xFF);
}
while (pos < len)
buf[pos++] = 0;
s->header_row++;
if (s->header_row >= 16*repeats)
{
/* End of header. Change to normal image row data. */
set_row_read_handler(s, s->row_handler, s->row_handler_user_data);
}
break;
}
while (pos < len)
buf[pos++] = 0;
s->header_row++;
if (s->header_row >= 16*repeats)
set_row_read_handler(s, s->row_handler, s->row_handler_user_data);
return len;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) t4_tx_set_row_squashing_ratio(t4_tx_state_t *s, int row_squashing_ratio)
{
s->row_squashing_ratio = row_squashing_ratio;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t4_tx_next_page_has_different_format(t4_tx_state_t *s)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Checking for the existence of page %d\n", s->current_page + 1);
@ -1143,6 +1169,8 @@ SPAN_DECLARE(t4_tx_state_t *) t4_tx_init(t4_tx_state_t *s, const char *file, int
s->row_handler = tiff_row_read_handler;
s->row_handler_user_data = (void *) s;
s->row_squashing_ratio = 1;
if (file)
{
if (open_tiff_input_file(s, file) < 0)

View File

@ -575,7 +575,7 @@ int main(int argc, char *argv[])
if (compression < 0 || (block_size == 0 && compression_step >= 3))
break;
}
t4_tx_set_tx_encoding(&send_state, compression, T4_COMPRESSION_NONE);
t4_tx_set_tx_encoding(&send_state, compression);
t4_rx_set_rx_encoding(&receive_state, compression);
rows_read = 0;
@ -716,7 +716,7 @@ int main(int argc, char *argv[])
compression = compression_sequence[compression_step++];
}
}
t4_tx_set_tx_encoding(&send_state, compression, T4_COMPRESSION_NONE);
t4_tx_set_tx_encoding(&send_state, compression);
t4_rx_set_rx_encoding(&receive_state, compression);
if (t4_tx_start_page(&send_state))

View File

@ -1,32 +1,28 @@
BASE=../../../..
OPUS=opus-0.9.0
OPUS=opus-1.0.1
OPUS_DIR=$(switch_srcdir)/libs/$(OPUS)
OPUS_BUILDDIR=$(switch_builddir)/libs/$(OPUS)
LOCAL_CFLAGS=-I$(OPUS_DIR)/src -g -O2
LOCAL_CFLAGS=-I$(OPUS_DIR)/include -g -O2
IETF_LA=$(OPUS_BUILDDIR)/src/libietfcodec.la
CELT_LA=$(OPUS_BUILDDIR)/celt/libcelt/libcelt0.la
SILK_LA=$(OPUS_BUILDDIR)/silk/libSKP_SILK_SDK.la
OPUS_LA=$(OPUS_BUILDDIR)/.libs/libopus.la
LOCAL_LIBADD=$(IETF_LA) $(CELT_LA) $(SILK_LA) -lm -lz
LOCAL_LIBADD=$(OPUS_LA) -lm -lz
include $(BASE)/build/modmake.rules
$(OPUS_DIR):
$(GETLIB) $(OPUS).tar.gz
$(OPUS_BUILDDIR)/Makefile: $(OPUS_DIR)
mkdir -p $(OPUS_BUILDDIR)
$(OPUS_DIR)/Makefile: $(OPUS_DIR)
cd $(OPUS_BUILDDIR) && $(DEFAULT_VARS) $(OPUS_DIR)/configure --disable-shared --with-pic --srcdir=$(OPUS_DIR)
$(TOUCH_TARGET)
$(IETF_LA): $(OPUS_BUILDDIR)/Makefile
$(OPUS_LA): $(OPUS_DIR)/Makefile
cd $(OPUS_BUILDDIR) && $(MAKE)
$(TOUCH_TARGET)
$(CELT_LA): $(IETF_LA)
$(SILK_LA): $(IETF_LA)
$(MODNAME).lo: $(IETF_LA) $(CELT_LA) $(SILK_LA)
$(MODNAME).lo: $(OPUS_LA)

View File

@ -57,27 +57,48 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag
if (encoding) {
/* come up with a way to specify these */
int bitrate_bps = codec->implementation->bits_per_second;
int mode = MODE_HYBRID;
int use_vbr = 1;
int complexity = 10;
int use_inbandfec = 1;
int use_dtx = 1;
int bandwidth = BANDWIDTH_FULLBAND;
int bandwidth = OPUS_BANDWIDTH_FULLBAND;
int err;
context->encoder_object = opus_encoder_create(codec->implementation->actual_samples_per_second, codec->implementation->number_of_channels);
context->encoder_object = opus_encoder_create(codec->implementation->actual_samples_per_second,
codec->implementation->number_of_channels, OPUS_APPLICATION_VOIP, &err);
if (err != OPUS_OK) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create encoder: %s\n", opus_strerror(err));
return SWITCH_STATUS_GENERR;
}
opus_encoder_ctl(context->encoder_object, OPUS_SET_MODE(mode));
opus_encoder_ctl(context->encoder_object, OPUS_SET_BITRATE(bitrate_bps));
opus_encoder_ctl(context->encoder_object, OPUS_SET_BANDWIDTH(bandwidth));
opus_encoder_ctl(context->encoder_object, OPUS_SET_VBR_FLAG(use_vbr));
opus_encoder_ctl(context->encoder_object, OPUS_SET_VBR(use_vbr));
opus_encoder_ctl(context->encoder_object, OPUS_SET_COMPLEXITY(complexity));
opus_encoder_ctl(context->encoder_object, OPUS_SET_INBAND_FEC_FLAG(use_inbandfec));
opus_encoder_ctl(context->encoder_object, OPUS_SET_DTX_FLAG(use_dtx));
opus_encoder_ctl(context->encoder_object, OPUS_SET_INBAND_FEC(use_inbandfec));
opus_encoder_ctl(context->encoder_object, OPUS_SET_DTX(use_dtx));
}
if (decoding) {
context->decoder_object = opus_decoder_create(codec->implementation->actual_samples_per_second, codec->implementation->number_of_channels);
int err;
context->decoder_object = opus_decoder_create(codec->implementation->actual_samples_per_second,
codec->implementation->number_of_channels, &err);
if (err != OPUS_OK) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot create decoder: %s\n", opus_strerror(err));
if (context->encoder_object) {
opus_encoder_destroy(context->encoder_object);
context->encoder_object = NULL;
}
return SWITCH_STATUS_GENERR;
}
}
codec->private_info = context;
@ -87,6 +108,19 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag
static switch_status_t switch_opus_destroy(switch_codec_t *codec)
{
struct opus_context *context = codec->private_info;
if (context) {
if (context->decoder_object) {
opus_decoder_destroy(context->decoder_object);
context->decoder_object = NULL;
}
if (context->encoder_object) {
opus_encoder_destroy(context->encoder_object);
context->encoder_object = NULL;
}
}
codec->private_info = NULL;
return SWITCH_STATUS_SUCCESS;
}
@ -133,7 +167,7 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec,
return SWITCH_STATUS_FALSE;
}
samples = opus_decode(context->decoder_object, encoded_data, encoded_data_len, decoded_data, *decoded_data_len);
samples = opus_decode(context->decoder_object, (*flag & SFF_PLC) ? NULL : encoded_data, encoded_data_len, decoded_data, *decoded_data_len, 0);
if (samples < 0) {
return SWITCH_STATUS_GENERR;
@ -157,12 +191,12 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load)
/* connect my internal structure to the blank pointer passed to me */
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
SWITCH_ADD_CODEC(codec_interface, "OPUS (BETA 0.9.0)");
SWITCH_ADD_CODEC(codec_interface, "OPUS (STANDARD)");
for (x = 0; x < 2; x++) {
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
115, /* the IANA code number */
"Opus-0.9.0",/* the IANA code name */
"opus",/* the IANA code name */
NULL, /* default fmtp to send (can be overridden by the init function) */
rate, /* samples transferred per second */
rate, /* actual samples transferred per second */