Merge branch 'master' of git.freeswitch.org:freeswitch

This commit is contained in:
Moises Silva
2010-10-01 07:07:12 -04:00
325 changed files with 24933 additions and 4354 deletions

View File

@@ -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 */

View 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)

View 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:
*/

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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--) {

View File

@@ -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 */