mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-08-13 09:36:46 +00:00
Merge branch 'master' of git.freeswitch.org:freeswitch
This commit is contained in:
@@ -98,11 +98,8 @@ typedef enum {
|
||||
AMR_DTX_ENABLED
|
||||
} amr_dtx_t;
|
||||
|
||||
struct amr_context {
|
||||
void *encoder_state;
|
||||
void *decoder_state;
|
||||
switch_byte_t enc_modes;
|
||||
switch_byte_t enc_mode;
|
||||
/*! \brief Various codec settings */
|
||||
struct amr_codec_settings {
|
||||
int dtx_mode;
|
||||
uint32_t change_period;
|
||||
switch_byte_t max_ptime;
|
||||
@@ -110,6 +107,24 @@ struct amr_context {
|
||||
switch_byte_t channels;
|
||||
switch_byte_t flags;
|
||||
};
|
||||
typedef struct amr_codec_settings amr_codec_settings_t;
|
||||
|
||||
static amr_codec_settings_t default_codec_settings = {
|
||||
/*.dtx_mode */ AMR_DTX_ENABLED,
|
||||
/*.change_period */ 0,
|
||||
/*.max_ptime */ 0,
|
||||
/*.ptime */ 0,
|
||||
/*.channels */ 0,
|
||||
/*.flags */ 0,
|
||||
};
|
||||
|
||||
|
||||
struct amr_context {
|
||||
void *encoder_state;
|
||||
void *decoder_state;
|
||||
switch_byte_t enc_modes;
|
||||
switch_byte_t enc_mode;
|
||||
};
|
||||
|
||||
#define AMR_DEFAULT_BITRATE AMR_BITRATE_1220
|
||||
|
||||
@@ -117,6 +132,88 @@ static struct {
|
||||
switch_byte_t default_bitrate;
|
||||
} globals;
|
||||
|
||||
static switch_status_t switch_amr_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
|
||||
{
|
||||
if (codec_fmtp) {
|
||||
amr_codec_settings_t *codec_settings = NULL;
|
||||
if (codec_fmtp->private_info) {
|
||||
codec_settings = codec_fmtp->private_info;
|
||||
memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings));
|
||||
}
|
||||
|
||||
if (fmtp) {
|
||||
int x, argc;
|
||||
char *argv[10];
|
||||
char *fmtp_dup = strdup(fmtp);
|
||||
|
||||
switch_assert(fmtp_dup);
|
||||
|
||||
argc = switch_separate_string((char *) fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
for (x = 0; x < argc; x++) {
|
||||
char *data = argv[x];
|
||||
char *arg;
|
||||
switch_assert(data);
|
||||
while (*data == ' ') {
|
||||
data++;
|
||||
}
|
||||
if ((arg = strchr(data, '='))) {
|
||||
*arg++ = '\0';
|
||||
/*
|
||||
if (!strcasecmp(data, "bitrate")) {
|
||||
bit_rate = atoi(arg);
|
||||
}
|
||||
*/
|
||||
if (codec_settings) {
|
||||
if (!strcasecmp(data, "octet-align")) {
|
||||
if (atoi(arg)) {
|
||||
switch_set_flag(codec_settings, AMR_OPT_OCTET_ALIGN);
|
||||
}
|
||||
} else if (!strcasecmp(data, "mode-change-neighbor")) {
|
||||
if (atoi(arg)) {
|
||||
switch_set_flag(codec_settings, AMR_OPT_MODE_CHANGE_NEIGHBOR);
|
||||
}
|
||||
} else if (!strcasecmp(data, "crc")) {
|
||||
if (atoi(arg)) {
|
||||
switch_set_flag(codec_settings, AMR_OPT_CRC);
|
||||
}
|
||||
} else if (!strcasecmp(data, "robust-sorting")) {
|
||||
if (atoi(arg)) {
|
||||
switch_set_flag(codec_settings, AMR_OPT_ROBUST_SORTING);
|
||||
}
|
||||
} else if (!strcasecmp(data, "interveaving")) {
|
||||
if (atoi(arg)) {
|
||||
switch_set_flag(codec_settings, AMR_OPT_INTERLEAVING);
|
||||
}
|
||||
} else if (!strcasecmp(data, "mode-change-period")) {
|
||||
codec_settings->change_period = atoi(arg);
|
||||
} else if (!strcasecmp(data, "ptime")) {
|
||||
codec_settings->ptime = (switch_byte_t) atoi(arg);
|
||||
} else if (!strcasecmp(data, "channels")) {
|
||||
codec_settings->channels = (switch_byte_t) atoi(arg);
|
||||
} else if (!strcasecmp(data, "maxptime")) {
|
||||
codec_settings->max_ptime = (switch_byte_t) atoi(arg);
|
||||
} else if (!strcasecmp(data, "mode-set")) {
|
||||
int y, m_argc;
|
||||
char *m_argv[7];
|
||||
m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0])));
|
||||
for (y = 0; y < m_argc; y++) {
|
||||
codec_settings->enc_modes |= (1 << atoi(m_argv[y]));
|
||||
}
|
||||
} else if (!strcasecmp(data, "dtx")) {
|
||||
codec_settings->dtx_mode = (atoi(arg)) ? AMR_DTX_ENABLED : AMR_DTX_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
free(fmtp_dup);
|
||||
}
|
||||
//codec_fmtp->bits_per_second = bit_rate;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
|
||||
@@ -128,7 +225,10 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
|
||||
}
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
#else
|
||||
|
||||
struct amr_context *context = NULL;
|
||||
switch_codec_fmtp_t codec_fmtp;
|
||||
amr_codec_settings_t amr_codec_settings;
|
||||
int encoding, decoding;
|
||||
int x, i, argc;
|
||||
char *argv[10];
|
||||
@@ -141,58 +241,9 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
|
||||
return SWITCH_STATUS_FALSE;
|
||||
} else {
|
||||
|
||||
context->dtx_mode = AMR_DTX_ENABLED;
|
||||
if (codec->fmtp_in) {
|
||||
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
for (x = 0; x < argc; x++) {
|
||||
char *data = argv[x];
|
||||
char *arg;
|
||||
while (*data && *data == ' ') {
|
||||
data++;
|
||||
}
|
||||
if ((arg = strchr(data, '='))) {
|
||||
*arg++ = '\0';
|
||||
if (!strcasecmp(data, "octet-align")) {
|
||||
if (atoi(arg)) {
|
||||
switch_set_flag(context, AMR_OPT_OCTET_ALIGN);
|
||||
}
|
||||
} else if (!strcasecmp(data, "mode-change-neighbor")) {
|
||||
if (atoi(arg)) {
|
||||
switch_set_flag(context, AMR_OPT_MODE_CHANGE_NEIGHBOR);
|
||||
}
|
||||
} else if (!strcasecmp(data, "crc")) {
|
||||
if (atoi(arg)) {
|
||||
switch_set_flag(context, AMR_OPT_CRC);
|
||||
}
|
||||
} else if (!strcasecmp(data, "robust-sorting")) {
|
||||
if (atoi(arg)) {
|
||||
switch_set_flag(context, AMR_OPT_ROBUST_SORTING);
|
||||
}
|
||||
} else if (!strcasecmp(data, "interveaving")) {
|
||||
if (atoi(arg)) {
|
||||
switch_set_flag(context, AMR_OPT_INTERLEAVING);
|
||||
}
|
||||
} else if (!strcasecmp(data, "mode-change-period")) {
|
||||
context->change_period = atoi(arg);
|
||||
} else if (!strcasecmp(data, "ptime")) {
|
||||
context->ptime = (switch_byte_t) atoi(arg);
|
||||
} else if (!strcasecmp(data, "channels")) {
|
||||
context->channels = (switch_byte_t) atoi(arg);
|
||||
} else if (!strcasecmp(data, "maxptime")) {
|
||||
context->max_ptime = (switch_byte_t) atoi(arg);
|
||||
} else if (!strcasecmp(data, "mode-set")) {
|
||||
int y, m_argc;
|
||||
char *m_argv[7];
|
||||
m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0])));
|
||||
for (y = 0; y < m_argc; y++) {
|
||||
context->enc_modes |= (1 << atoi(m_argv[y]));
|
||||
}
|
||||
} else if (!strcasecmp(data, "dtx")) {
|
||||
context->dtx_mode = (atoi(arg)) ? AMR_DTX_ENABLED : AMR_DTX_DISABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
|
||||
codec_fmtp.private_info = &amr_codec_settings;
|
||||
switch_amr_fmtp_parse(codec->fmtp_in, &codec_fmtp);
|
||||
|
||||
if (context->enc_modes) {
|
||||
for (i = 7; i > -1; i++) {
|
||||
@@ -321,6 +372,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_amr_load)
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
SWITCH_ADD_CODEC(codec_interface, "AMR");
|
||||
#ifndef AMR_PASSTHROUGH
|
||||
codec_interface->parse_fmtp = switch_amr_fmtp_parse;
|
||||
#endif
|
||||
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
|
||||
96, /* the IANA code number */
|
||||
"AMR", /* the IANA code name */
|
||||
|
14
src/mod/codecs/mod_codec2/Makefile
Normal file
14
src/mod/codecs/mod_codec2/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
BASE=../../../..
|
||||
|
||||
CODEC2_DIR=$(switch_srcdir)/libs/libcodec2
|
||||
CODEC2_BUILDDIR=$(switch_builddir)/libs/libcodec2
|
||||
CODEC2LA=$(CODEC2_BUILDDIR)/src/libcodec2.la
|
||||
|
||||
LOCAL_CFLAGS=-I$(CODEC2_DIR)/include -I$(CODEC2_BUILDDIR)/src
|
||||
LOCAL_LIBADD=$(CODEC2LA)
|
||||
include $(BASE)/build/modmake.rules
|
||||
|
||||
$(CODEC2LA): $(CODEC2_DIR) $(CODEC2_DIR)/.update
|
||||
cd $(CODEC2_BUILDDIR) && $(MAKE)
|
||||
$(TOUCH_TARGET)
|
||||
|
264
src/mod/codecs/mod_codec2/mod_codec2.c
Normal file
264
src/mod/codecs/mod_codec2/mod_codec2.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005-2010, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is FreeSWITCH Modular Media Switching Software Library
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Brian West <brian@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mathieu Rene <mrene@avgs.ca>
|
||||
*
|
||||
* mod_codec2 -- FreeSWITCH CODEC2 Module
|
||||
*
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include <codec2.h>
|
||||
|
||||
/* Uncomment to log input/output data for debugging
|
||||
#define LOG_DATA
|
||||
#define CODEC2_DEBUG
|
||||
*/
|
||||
|
||||
#ifdef CODEC2_DEBUG
|
||||
#define codec2_assert(_x) switch_assert(_x)
|
||||
#else
|
||||
#define codec2_assert(_x)
|
||||
#endif
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_codec2_load);
|
||||
|
||||
SWITCH_MODULE_DEFINITION(mod_codec2, mod_codec2_load, NULL, NULL);
|
||||
|
||||
struct codec2_context {
|
||||
void *encoder;
|
||||
void *decoder;
|
||||
#ifdef LOG_DATA
|
||||
FILE *encoder_in;
|
||||
FILE *encoder_out;
|
||||
FILE *encoder_out_unpacked;
|
||||
FILE *decoder_in;
|
||||
FILE *decoder_in_unpacked;
|
||||
FILE *decoder_out;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef LOG_DATA
|
||||
static int c2_count = 0;
|
||||
#endif
|
||||
|
||||
static switch_status_t switch_codec2_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
|
||||
{
|
||||
uint32_t encoding, decoding;
|
||||
struct codec2_context *context = NULL;
|
||||
|
||||
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
|
||||
decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
|
||||
|
||||
if (!(encoding || decoding)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context)))) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (encoding) {
|
||||
context->encoder = codec2_create();
|
||||
}
|
||||
|
||||
if (decoding) {
|
||||
context->decoder = codec2_create();
|
||||
}
|
||||
|
||||
codec->private_info = context;
|
||||
|
||||
#ifdef LOG_DATA
|
||||
{
|
||||
|
||||
int c = c2_count++;
|
||||
char buf[1024];
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Logging as /tmp/c2-%d-*\n", c);
|
||||
|
||||
if (encoding) {
|
||||
snprintf(buf, sizeof(buf), "/tmp/c2-%d-enc-in", c);
|
||||
context->encoder_in = fopen(buf, "w");
|
||||
|
||||
snprintf(buf, sizeof(buf), "/tmp/c2-%d-enc-out", c);
|
||||
context->encoder_out = fopen(buf, "w");
|
||||
|
||||
snprintf(buf, sizeof(buf), "/tmp/c2-%d-enc-out-unpacked", c);
|
||||
context->encoder_out_unpacked = fopen(buf, "w");
|
||||
}
|
||||
if (decoding) {
|
||||
snprintf(buf, sizeof(buf), "/tmp/c2-%d-dec-in", c);
|
||||
context->decoder_in = fopen(buf, "w");
|
||||
|
||||
snprintf(buf, sizeof(buf), "/tmp/c2-%d-dec-out", c);
|
||||
context->decoder_out = fopen(buf, "w");
|
||||
|
||||
snprintf(buf, sizeof(buf), "/tmp/c2-%d-dec-out-unpacked", c);
|
||||
context->decoder_in_unpacked = fopen(buf, "w");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t switch_codec2_encode(switch_codec_t *codec, switch_codec_t *other_codec,
|
||||
void *decoded_data,
|
||||
uint32_t decoded_data_len,
|
||||
uint32_t decoded_rate,
|
||||
void *encoded_data,
|
||||
uint32_t *encoded_data_len,
|
||||
uint32_t *encoded_rate,
|
||||
unsigned int *flag)
|
||||
{
|
||||
struct codec2_context *context = codec->private_info;
|
||||
|
||||
codec2_assert(decoded_data_len == CODEC2_SAMPLES_PER_FRAME * 2);
|
||||
|
||||
#ifdef LOG_DATA
|
||||
fwrite(decoded_data, decoded_data_len, 1, context->encoder_in);
|
||||
fflush(context->encoder_in);
|
||||
#endif
|
||||
|
||||
codec2_encode(context->encoder, encoded_data, decoded_data);
|
||||
|
||||
#ifdef LOG_DATA
|
||||
fwrite(encode_buf, sizeof(encode_buf), 1, context->encoder_out_unpacked);
|
||||
fflush(context->encoder_out_unpacked);
|
||||
fwrite(encoded_data, 8, 1, context->encoder_out);
|
||||
fflush(context->encoder_out);
|
||||
#endif
|
||||
|
||||
*encoded_data_len = 8;
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t switch_codec2_decode(switch_codec_t *codec,
|
||||
switch_codec_t *other_codec,
|
||||
void *encoded_data,
|
||||
uint32_t encoded_data_len,
|
||||
uint32_t encoded_rate,
|
||||
void *decoded_data,
|
||||
uint32_t *decoded_data_len,
|
||||
uint32_t *decoded_rate,
|
||||
unsigned int *flag)
|
||||
{
|
||||
struct codec2_context *context = codec->private_info;
|
||||
|
||||
codec2_assert(encoded_data_len == 8 /* aligned to 8 */);
|
||||
|
||||
#ifdef LOG_DATA
|
||||
fwrite(encoded_data, encoded_data_len, 1, context->decoder_in);
|
||||
fflush(context->decoder_in);
|
||||
fwrite(bits, sizeof(bits), 1, context->decoder_in_unpacked);
|
||||
fflush(context->decoder_in_unpacked);
|
||||
#endif
|
||||
|
||||
codec2_decode(context->decoder, decoded_data, encoded_data);
|
||||
|
||||
#ifdef LOG_DATA
|
||||
fwrite(decoded_data, CODEC2_SAMPLES_PER_FRAME, 2, context->decoder_out);
|
||||
fflush(context->decoder_out);
|
||||
#endif
|
||||
|
||||
*decoded_data_len = CODEC2_SAMPLES_PER_FRAME * 2; /* 160 samples */
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t switch_codec2_destroy(switch_codec_t *codec)
|
||||
{
|
||||
struct codec2_context *context = codec->private_info;
|
||||
|
||||
codec2_destroy(context->encoder);
|
||||
codec2_destroy(context->decoder);
|
||||
|
||||
context->encoder = NULL;
|
||||
context->decoder = NULL;
|
||||
|
||||
#ifdef LOG_DATA
|
||||
if (context->encoder_in) {
|
||||
fclose(context->encoder_in);
|
||||
}
|
||||
if (context->encoder_out) {
|
||||
fclose(context->encoder_out);
|
||||
}
|
||||
if (context->encoder_out_unpacked) {
|
||||
fclose(context->encoder_out_unpacked);
|
||||
}
|
||||
if (context->decoder_in) {
|
||||
fclose(context->decoder_in);
|
||||
}
|
||||
if (context->decoder_in_unpacked) {
|
||||
fclose(context->decoder_in_unpacked);
|
||||
}
|
||||
if (context->decoder_out) {
|
||||
fclose(context->decoder_out);
|
||||
}
|
||||
#endif
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_codec2_load)
|
||||
{
|
||||
switch_codec_interface_t *codec_interface;
|
||||
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
SWITCH_ADD_CODEC(codec_interface, "CODEC2 2550bps");
|
||||
|
||||
switch_core_codec_add_implementation(pool, codec_interface,
|
||||
SWITCH_CODEC_TYPE_AUDIO,
|
||||
111,
|
||||
"CODEC2",
|
||||
NULL,
|
||||
8000, /* samples/sec */
|
||||
8000, /* samples/sec */
|
||||
2550, /* bps */
|
||||
20000, /* ptime */
|
||||
CODEC2_SAMPLES_PER_FRAME, /* samples decoded */
|
||||
CODEC2_SAMPLES_PER_FRAME*2, /* bytes decoded */
|
||||
0, /* bytes encoded */
|
||||
1, /* channels */
|
||||
1, /* frames/packet */
|
||||
switch_codec2_init,
|
||||
switch_codec2_encode,
|
||||
switch_codec2_decode,
|
||||
switch_codec2_destroy);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
@@ -40,6 +40,27 @@ struct ilbc_context {
|
||||
ilbc_decode_state_t decoder_object;
|
||||
};
|
||||
|
||||
static switch_status_t switch_ilbc_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
|
||||
{
|
||||
if (codec_fmtp) {
|
||||
char *mode = NULL;
|
||||
int codec_ms = 0;
|
||||
|
||||
memset(codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
|
||||
|
||||
if (fmtp && (mode = strstr(fmtp, "mode=")) && (mode + 5)) {
|
||||
codec_ms = atoi(mode + 5);
|
||||
}
|
||||
if (!codec_ms) {
|
||||
/* default to 30 when no mode is defined for ilbc ONLY */
|
||||
codec_ms = 30;
|
||||
}
|
||||
codec_fmtp->microseconds_per_packet = (codec_ms * 1000);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
static switch_status_t switch_ilbc_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
|
||||
{
|
||||
struct ilbc_context *context;
|
||||
@@ -51,26 +72,6 @@ static switch_status_t switch_ilbc_init(switch_codec_t *codec, switch_codec_flag
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (codec->fmtp_in) {
|
||||
int x, argc;
|
||||
char *argv[10];
|
||||
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
for (x = 0; x < argc; x++) {
|
||||
char *data = argv[x];
|
||||
char *arg;
|
||||
switch_assert(data);
|
||||
while (*data == ' ') {
|
||||
data++;
|
||||
}
|
||||
if ((arg = strchr(data, '='))) {
|
||||
*arg++ = '\0';
|
||||
if (!strcasecmp(data, "mode")) {
|
||||
mode = atoi(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "mode=%d", mode);
|
||||
|
||||
if (encoding) {
|
||||
@@ -136,6 +137,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_ilbc_load)
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
SWITCH_ADD_CODEC(codec_interface, "iLBC");
|
||||
codec_interface->parse_fmtp = switch_ilbc_fmtp_parse;
|
||||
|
||||
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
|
||||
98, /* the IANA code number */
|
||||
|
@@ -41,6 +41,22 @@ SWITCH_MODULE_DEFINITION(mod_silk, mod_silk_load, NULL, NULL);
|
||||
#define MAX_LBRR_DELAY 2
|
||||
#define MAX_FRAME_LENGTH 480
|
||||
|
||||
/*! \brief Various codec settings */
|
||||
struct silk_codec_settings {
|
||||
SKP_int useinbandfec;
|
||||
SKP_int usedtx;
|
||||
SKP_int maxaveragebitrate;
|
||||
SKP_int plpct;
|
||||
};
|
||||
typedef struct silk_codec_settings silk_codec_settings_t;
|
||||
|
||||
static silk_codec_settings_t default_codec_settings = {
|
||||
/*.useinbandfec */ 0,
|
||||
/*.usedtx */ 0,
|
||||
/*.maxaveragebitrate */ 0,
|
||||
/*.plpct */ 10, // 10% for now
|
||||
};
|
||||
|
||||
struct silk_context {
|
||||
SKP_SILK_SDK_EncControlStruct encoder_object;
|
||||
SKP_SILK_SDK_DecControlStruct decoder_object;
|
||||
@@ -48,12 +64,105 @@ struct silk_context {
|
||||
void *dec_state;
|
||||
};
|
||||
|
||||
static switch_status_t switch_silk_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
|
||||
{
|
||||
if (codec_fmtp) {
|
||||
silk_codec_settings_t *codec_settings = NULL;
|
||||
|
||||
if (codec_fmtp->private_info) {
|
||||
codec_settings = codec_fmtp->private_info;
|
||||
memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings));
|
||||
}
|
||||
|
||||
if (fmtp) {
|
||||
int x, argc;
|
||||
char *argv[10];
|
||||
char *fmtp_dup = strdup(fmtp);
|
||||
|
||||
switch_assert(fmtp_dup);
|
||||
|
||||
argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
for (x = 0; x < argc; x++) {
|
||||
char *data = argv[x];
|
||||
char *arg;
|
||||
switch_assert(data);
|
||||
while (*data == ' ') {
|
||||
data++;
|
||||
}
|
||||
if ((arg = strchr(data, '='))) {
|
||||
*arg++ = '\0';
|
||||
if (codec_settings) {
|
||||
if (!strcasecmp(data, "useinbandfec")) {
|
||||
if (switch_true(arg)) {
|
||||
codec_settings->useinbandfec = 1;
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(data, "usedtx")) {
|
||||
if (switch_true(arg)) {
|
||||
codec_settings->usedtx = 1;
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(data, "maxaveragebitrate")) {
|
||||
codec_settings->maxaveragebitrate = atoi(arg);
|
||||
switch(codec_fmtp->actual_samples_per_second) {
|
||||
case 8000:
|
||||
{
|
||||
if(codec_settings->maxaveragebitrate < 6000 || codec_settings->maxaveragebitrate > 20000) {
|
||||
codec_settings->maxaveragebitrate = 20000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 12000:
|
||||
{
|
||||
if(codec_settings->maxaveragebitrate < 7000 || codec_settings->maxaveragebitrate > 25000) {
|
||||
codec_settings->maxaveragebitrate = 25000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 16000:
|
||||
{
|
||||
if(codec_settings->maxaveragebitrate < 8000 || codec_settings->maxaveragebitrate > 30000) {
|
||||
codec_settings->maxaveragebitrate = 30000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 24000:
|
||||
{
|
||||
if(codec_settings->maxaveragebitrate < 12000 || codec_settings->maxaveragebitrate > 40000) {
|
||||
codec_settings->maxaveragebitrate = 40000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* this should never happen but 20000 is common among all rates */
|
||||
codec_settings->maxaveragebitrate = 20000;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
free(fmtp_dup);
|
||||
}
|
||||
//codec_fmtp->bits_per_second = bit_rate;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static switch_status_t switch_silk_init(switch_codec_t *codec,
|
||||
switch_codec_flag_t freeswitch_flags,
|
||||
const switch_codec_settings_t *codec_settings)
|
||||
{
|
||||
struct silk_context *context = NULL;
|
||||
SKP_int useinbandfec = 0, usedtx = 0, maxaveragebitrate = 0, plpct =0;
|
||||
switch_codec_fmtp_t codec_fmtp;
|
||||
silk_codec_settings_t silk_codec_settings;
|
||||
SKP_int32 encSizeBytes;
|
||||
SKP_int32 decSizeBytes;
|
||||
int encoding = (freeswitch_flags & SWITCH_CODEC_FLAG_ENCODE);
|
||||
@@ -62,78 +171,15 @@ static switch_status_t switch_silk_init(switch_codec_t *codec,
|
||||
if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context))))) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (codec->fmtp_in) {
|
||||
int x, argc;
|
||||
char *argv[10];
|
||||
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
for (x = 0; x < argc; x++) {
|
||||
char *data = argv[x];
|
||||
char *arg;
|
||||
switch_assert(data);
|
||||
while (*data == ' ') {
|
||||
data++;
|
||||
}
|
||||
if ((arg = strchr(data, '='))) {
|
||||
*arg++ = '\0';
|
||||
if (!strcasecmp(data, "useinbandfec")) {
|
||||
if (switch_true(arg)) {
|
||||
useinbandfec = 1;
|
||||
plpct = 10;// 10% for now
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(data, "usedtx")) {
|
||||
if (switch_true(arg)) {
|
||||
usedtx = 1;
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(data, "maxaveragebitrate")) {
|
||||
maxaveragebitrate = atoi(arg);
|
||||
switch(codec->implementation->actual_samples_per_second) {
|
||||
case 8000:
|
||||
{
|
||||
if(maxaveragebitrate < 6000 || maxaveragebitrate > 20000) {
|
||||
maxaveragebitrate = 20000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 12000:
|
||||
{
|
||||
if(maxaveragebitrate < 7000 || maxaveragebitrate > 25000) {
|
||||
maxaveragebitrate = 25000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 16000:
|
||||
{
|
||||
if(maxaveragebitrate < 8000 || maxaveragebitrate > 30000) {
|
||||
maxaveragebitrate = 30000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 24000:
|
||||
{
|
||||
if(maxaveragebitrate < 12000 || maxaveragebitrate > 40000) {
|
||||
maxaveragebitrate = 40000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
/* this should never happen but 20000 is common among all rates */
|
||||
maxaveragebitrate = 20000;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
|
||||
codec_fmtp.private_info = &silk_codec_settings;
|
||||
switch_silk_fmtp_parse(codec->fmtp_in, &codec_fmtp);
|
||||
|
||||
codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "useinbandfec=%s; usedtx=%s; maxaveragebitrate=%d",
|
||||
useinbandfec ? "1" : "0",
|
||||
usedtx ? "1" : "0",
|
||||
maxaveragebitrate ? maxaveragebitrate : codec->implementation->bits_per_second);
|
||||
silk_codec_settings.useinbandfec ? "1" : "0",
|
||||
silk_codec_settings.usedtx ? "1" : "0",
|
||||
silk_codec_settings.maxaveragebitrate ? silk_codec_settings.maxaveragebitrate : codec->implementation->bits_per_second);
|
||||
|
||||
if (encoding) {
|
||||
if (SKP_Silk_SDK_Get_Encoder_Size(&encSizeBytes)) {
|
||||
@@ -148,11 +194,11 @@ static switch_status_t switch_silk_init(switch_codec_t *codec,
|
||||
|
||||
context->encoder_object.sampleRate = codec->implementation->actual_samples_per_second;
|
||||
context->encoder_object.packetSize = codec->implementation->samples_per_packet;
|
||||
context->encoder_object.useInBandFEC = useinbandfec;
|
||||
context->encoder_object.useInBandFEC = silk_codec_settings.useinbandfec;
|
||||
context->encoder_object.complexity = 0;
|
||||
context->encoder_object.bitRate = maxaveragebitrate ? maxaveragebitrate : codec->implementation->bits_per_second;
|
||||
context->encoder_object.useDTX = usedtx;
|
||||
context->encoder_object.packetLossPercentage = plpct;;
|
||||
context->encoder_object.bitRate = silk_codec_settings.maxaveragebitrate ? silk_codec_settings.maxaveragebitrate : codec->implementation->bits_per_second;
|
||||
context->encoder_object.useDTX = silk_codec_settings.usedtx;
|
||||
context->encoder_object.packetLossPercentage = silk_codec_settings.plpct;
|
||||
}
|
||||
|
||||
if (decoding) {
|
||||
@@ -174,7 +220,7 @@ static switch_status_t switch_silk_init(switch_codec_t *codec,
|
||||
|
||||
static switch_status_t switch_silk_destroy(switch_codec_t *codec)
|
||||
{
|
||||
codec->private_info = NULL;
|
||||
codec->private_info = NULL;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -299,6 +345,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_silk_load)
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
SWITCH_ADD_CODEC(codec_interface, "SILK");
|
||||
codec_interface->parse_fmtp = switch_silk_fmtp_parse;
|
||||
switch_core_codec_add_implementation(pool, codec_interface,
|
||||
SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
|
||||
117, /* the IANA code number */
|
||||
|
@@ -47,6 +47,40 @@ struct siren_context {
|
||||
g722_1_encode_state_t encoder_object;
|
||||
};
|
||||
|
||||
static switch_status_t switch_siren_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
|
||||
{
|
||||
if (codec_fmtp) {
|
||||
int bit_rate = 0;
|
||||
memset(codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
|
||||
if (fmtp) {
|
||||
int x, argc;
|
||||
char *argv[10];
|
||||
char *fmtp_dup = strdup(fmtp);
|
||||
|
||||
switch_assert(fmtp_dup);
|
||||
argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
for (x = 0; x < argc; x++) {
|
||||
char *data = argv[x];
|
||||
char *arg;
|
||||
switch_assert(data);
|
||||
while (*data == ' ') {
|
||||
data++;
|
||||
}
|
||||
if ((arg = strchr(data, '='))) {
|
||||
*arg++ = '\0';
|
||||
if (!strcasecmp(data, "bitrate")) {
|
||||
bit_rate = atoi(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(fmtp_dup);
|
||||
}
|
||||
codec_fmtp->bits_per_second = bit_rate;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
static switch_status_t switch_siren_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
|
||||
{
|
||||
struct siren_context *context = NULL;
|
||||
@@ -58,26 +92,6 @@ static switch_status_t switch_siren_init(switch_codec_t *codec, switch_codec_fla
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (codec->fmtp_in) {
|
||||
int x, argc;
|
||||
char *argv[10];
|
||||
argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
for (x = 0; x < argc; x++) {
|
||||
char *data = argv[x];
|
||||
char *arg;
|
||||
switch_assert(data);
|
||||
while (*data == ' ') {
|
||||
data++;
|
||||
}
|
||||
if ((arg = strchr(data, '='))) {
|
||||
*arg++ = '\0';
|
||||
if (!strcasecmp(data, "bitrate")) {
|
||||
bit_rate = atoi(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "bitrate=%d", bit_rate);
|
||||
|
||||
if (encoding) {
|
||||
@@ -145,6 +159,28 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_siren_load)
|
||||
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
||||
|
||||
SWITCH_ADD_CODEC(codec_interface, "Polycom(R) G722.1/G722.1C");
|
||||
codec_interface->parse_fmtp = switch_siren_fmtp_parse;
|
||||
|
||||
spf = 320, bpf = 640;
|
||||
for (count = 3; count > 0; count--) {
|
||||
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
|
||||
107, /* the IANA code number */
|
||||
"G7221", /* the IANA code name */
|
||||
"bitrate=24000", /* default fmtp to send (can be overridden by the init function) */
|
||||
16000, /* samples transferred per second */
|
||||
16000, /* actual samples transferred per second */
|
||||
24000, /* bits transferred per second */
|
||||
mpf * count, /* number of microseconds per frame */
|
||||
spf * count, /* number of samples per frame */
|
||||
bpf * count, /* number of bytes per frame decompressed */
|
||||
0, /* number of bytes per frame compressed */
|
||||
1, /* number of channels represented */
|
||||
1, /* number of frames per network packet */
|
||||
switch_siren_init, /* function to initialize a codec handle using this implementation */
|
||||
switch_siren_encode, /* function to encode raw data into encoded data */
|
||||
switch_siren_decode, /* function to decode encoded data into raw data */
|
||||
switch_siren_destroy); /* deinitalize a codec handle using this implementation */
|
||||
}
|
||||
|
||||
spf = 320, bpf = 640;
|
||||
for (count = 3; count > 0; count--) {
|
||||
|
@@ -37,7 +37,46 @@
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_speex_load);
|
||||
SWITCH_MODULE_DEFINITION(mod_speex, mod_speex_load, NULL, NULL);
|
||||
|
||||
static switch_codec_settings_t default_codec_settings = {
|
||||
/* nobody has more setting than speex so we will let them set the standard */
|
||||
/*! \brief Various codec settings (currently only relevant to speex) */
|
||||
struct speex_codec_settings {
|
||||
/*! desired quality */
|
||||
int quality;
|
||||
/*! desired complexity */
|
||||
int complexity;
|
||||
/*! desired enhancement */
|
||||
int enhancement;
|
||||
/*! desired vad level */
|
||||
int vad;
|
||||
/*! desired vbr level */
|
||||
int vbr;
|
||||
/*! desired vbr quality */
|
||||
float vbr_quality;
|
||||
/*! desired abr level */
|
||||
int abr;
|
||||
/*! desired dtx setting */
|
||||
int dtx;
|
||||
/*! desired preprocessor settings */
|
||||
int preproc;
|
||||
/*! preprocessor vad settings */
|
||||
int pp_vad;
|
||||
/*! preprocessor gain control settings */
|
||||
int pp_agc;
|
||||
/*! preprocessor gain level */
|
||||
float pp_agc_level;
|
||||
/*! preprocessor denoise level */
|
||||
int pp_denoise;
|
||||
/*! preprocessor dereverb settings */
|
||||
int pp_dereverb;
|
||||
/*! preprocessor dereverb decay level */
|
||||
float pp_dereverb_decay;
|
||||
/*! preprocessor dereverb level */
|
||||
float pp_dereverb_level;
|
||||
};
|
||||
|
||||
typedef struct speex_codec_settings speex_codec_settings_t;
|
||||
|
||||
static speex_codec_settings_t default_codec_settings = {
|
||||
/*.quality */ 5,
|
||||
/*.complexity */ 5,
|
||||
/*.enhancement */ 1,
|
||||
@@ -58,6 +97,7 @@ static switch_codec_settings_t default_codec_settings = {
|
||||
|
||||
struct speex_context {
|
||||
switch_codec_t *codec;
|
||||
speex_codec_settings_t codec_settings;
|
||||
unsigned int flags;
|
||||
|
||||
/* Encoder */
|
||||
@@ -74,6 +114,56 @@ struct speex_context {
|
||||
int decoder_mode;
|
||||
};
|
||||
|
||||
static switch_status_t switch_speex_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
|
||||
{
|
||||
if (codec_fmtp) {
|
||||
speex_codec_settings_t *codec_settings = NULL;
|
||||
if (codec_fmtp->private_info) {
|
||||
codec_settings = codec_fmtp->private_info;
|
||||
memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings));
|
||||
}
|
||||
|
||||
if (fmtp) {
|
||||
int x, argc;
|
||||
char *argv[10];
|
||||
char *fmtp_dup = strdup(fmtp);
|
||||
|
||||
switch_assert(fmtp_dup);
|
||||
|
||||
argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
|
||||
|
||||
for (x = 0; x < argc; x++) {
|
||||
char *data = argv[x];
|
||||
char *arg;
|
||||
switch_assert(data);
|
||||
while (*data == ' ') {
|
||||
data++;
|
||||
}
|
||||
if ((arg = strchr(data, '='))) {
|
||||
*arg++ = '\0';
|
||||
/*
|
||||
if (!strcasecmp(data, "bitrate")) {
|
||||
bit_rate = atoi(arg);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
if (codec_settings) {
|
||||
if (!strcasecmp(data, "vad")) {
|
||||
bit_rate = atoi(arg);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
free(fmtp_dup);
|
||||
}
|
||||
/*codec_fmtp->bits_per_second = bit_rate;*/
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
|
||||
{
|
||||
struct speex_context *context = NULL;
|
||||
@@ -82,16 +172,18 @@ static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_fla
|
||||
encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
|
||||
decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
|
||||
|
||||
if (!codec_settings) {
|
||||
codec_settings = &default_codec_settings;
|
||||
}
|
||||
|
||||
memcpy(&codec->codec_settings, codec_settings, sizeof(codec->codec_settings));
|
||||
|
||||
if (!(encoding || decoding) || ((context = switch_core_alloc(codec->memory_pool, sizeof(*context))) == 0)) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
} else {
|
||||
const SpeexMode *mode = NULL;
|
||||
switch_codec_fmtp_t codec_fmtp;
|
||||
speex_codec_settings_t codec_settings;
|
||||
|
||||
memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
|
||||
codec_fmtp.private_info = &codec_settings;
|
||||
switch_speex_fmtp_parse(codec->fmtp_in, &codec_fmtp);
|
||||
|
||||
memcpy(&context->codec_settings, &codec_settings, sizeof(context->codec_settings));
|
||||
|
||||
context->codec = codec;
|
||||
if (codec->implementation->actual_samples_per_second == 8000) {
|
||||
@@ -110,41 +202,41 @@ static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_fla
|
||||
speex_bits_init(&context->encoder_bits);
|
||||
context->encoder_state = speex_encoder_init(mode);
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_GET_FRAME_SIZE, &context->encoder_frame_size);
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_COMPLEXITY, &codec->codec_settings.complexity);
|
||||
if (codec->codec_settings.preproc) {
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_COMPLEXITY, &context->codec_settings.complexity);
|
||||
if (context->codec_settings.preproc) {
|
||||
context->pp = speex_preprocess_state_init(context->encoder_frame_size, codec->implementation->actual_samples_per_second);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_VAD, &codec->codec_settings.pp_vad);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC, &codec->codec_settings.pp_agc);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &codec->codec_settings.pp_agc_level);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DENOISE, &codec->codec_settings.pp_denoise);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB, &codec->codec_settings.pp_dereverb);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &codec->codec_settings.pp_dereverb_decay);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &codec->codec_settings.pp_dereverb_level);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_VAD, &context->codec_settings.pp_vad);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC, &context->codec_settings.pp_agc);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &context->codec_settings.pp_agc_level);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DENOISE, &context->codec_settings.pp_denoise);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB, &context->codec_settings.pp_dereverb);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &context->codec_settings.pp_dereverb_decay);
|
||||
speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &context->codec_settings.pp_dereverb_level);
|
||||
}
|
||||
|
||||
if (!codec->codec_settings.abr && !codec->codec_settings.vbr) {
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_QUALITY, &codec->codec_settings.quality);
|
||||
if (codec->codec_settings.vad) {
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_VAD, &codec->codec_settings.vad);
|
||||
if (!context->codec_settings.abr && !context->codec_settings.vbr) {
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_QUALITY, &context->codec_settings.quality);
|
||||
if (context->codec_settings.vad) {
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_VAD, &context->codec_settings.vad);
|
||||
}
|
||||
}
|
||||
if (codec->codec_settings.vbr) {
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR, &codec->codec_settings.vbr);
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR_QUALITY, &codec->codec_settings.vbr_quality);
|
||||
if (context->codec_settings.vbr) {
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR, &context->codec_settings.vbr);
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR_QUALITY, &context->codec_settings.vbr_quality);
|
||||
}
|
||||
if (codec->codec_settings.abr) {
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_ABR, &codec->codec_settings.abr);
|
||||
if (context->codec_settings.abr) {
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_ABR, &context->codec_settings.abr);
|
||||
}
|
||||
if (codec->codec_settings.dtx) {
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_DTX, &codec->codec_settings.dtx);
|
||||
if (context->codec_settings.dtx) {
|
||||
speex_encoder_ctl(context->encoder_state, SPEEX_SET_DTX, &context->codec_settings.dtx);
|
||||
}
|
||||
}
|
||||
|
||||
if (decoding) {
|
||||
speex_bits_init(&context->decoder_bits);
|
||||
context->decoder_state = speex_decoder_init(mode);
|
||||
if (codec->codec_settings.enhancement) {
|
||||
speex_decoder_ctl(context->decoder_state, SPEEX_SET_ENH, &codec->codec_settings.enhancement);
|
||||
if (context->codec_settings.enhancement) {
|
||||
speex_decoder_ctl(context->decoder_state, SPEEX_SET_ENH, &context->codec_settings.enhancement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +270,7 @@ static switch_status_t switch_speex_encode(switch_codec_t *codec,
|
||||
|
||||
if (is_speech) {
|
||||
is_speech = speex_encode_int(context->encoder_state, buf, &context->encoder_bits)
|
||||
|| !context->codec->codec_settings.dtx;
|
||||
|| !context->codec_settings.dtx;
|
||||
} else {
|
||||
speex_bits_pack(&context->encoder_bits, 0, 5);
|
||||
}
|
||||
@@ -270,6 +362,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_speex_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, "Speex");
|
||||
codec_interface->parse_fmtp = switch_speex_fmtp_parse;
|
||||
for (counta = 1; counta <= 3; counta++) {
|
||||
for (countb = 1; countb > 0; countb--) {
|
||||
switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, /* enumeration defining the type of the codec */
|
||||
|
Reference in New Issue
Block a user