\param arraylen the max size in elements of the array
\return the number of elements added to the array
*/
-SWITCH_DECLARE(int) switch_loadable_module_get_codecs(switch_memory_pool_t *pool,
- switch_codec_interface_t **array,
+SWITCH_DECLARE(int) switch_loadable_module_get_codecs(switch_memory_pool_t *pool, const switch_codec_implementation_t **array,
int arraylen);
+
/*!
\brief Retrieve the list of loaded codecs into an array based on another array showing the sorted order
\param array the array to populate
\return the number of elements added to the array
\note this function only considers codecs that are listed in the "prefs" array and ignores the rest.
*/
-SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(switch_codec_interface_t **array,
- int arraylen,
- char **prefs,
- int preflen);
+SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_implementation_t **array,
+ int arraylen, char **prefs, int preflen);
/*!
\brief Execute a registered API command
/*! \brief A table of settings and callbacks that define a paticular implementation of a codec */
struct switch_codec_implementation {
+ /*! enumeration defining the type of the codec */
+ const switch_codec_type_t codec_type;
/*! the IANA code number */
switch_payload_t ianacode;
/*! the IANA code name */
struct switch_codec_interface {
/*! the name of the interface */
const char *interface_name;
- /*! enumeration defining the type of the codec */
- const switch_codec_type_t codec_type;
/*! a list of codec implementations related to the codec */
const switch_codec_implementation_t *implementations;
const struct switch_codec_interface *next;
#if 0
static const switch_codec_implementation_t g711u_8k_60ms_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 0,
/*.iananame */ "PCMU",
/*.samples_per_second */ 8000,
/*.decode */ switch_g711u_decode,
/*.destroy */ switch_g711u_destroy
};
-
+#endif
static const switch_codec_implementation_t g711u_8k_30ms_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 0,
/*.iananame */ "PCMU",
/*.samples_per_second */ 8000,
/*.encode */ switch_g711u_encode,
/*.decode */ switch_g711u_decode,
/*.destroy */ switch_g711u_destroy,
- /*.next */ &g711u_8k_60ms_implementation
+ /*.next */ NULL
};
-#endif
static const switch_codec_implementation_t g711u_16k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 0,
/*.iananame */ "PCMU",
/*.samples_per_second */ 16000,
/*.encode */ switch_g711u_encode,
/*.decode */ switch_g711u_decode,
/*.destroy */ switch_g711u_destroy,
+ /*.next */ &g711u_8k_30ms_implementation
};
static const switch_codec_implementation_t g711u_8k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 0,
/*.iananame */ "PCMU",
/*.samples_per_second */ 8000,
static const switch_codec_implementation_t g711a_8k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 8,
/*.iananame */ "PCMA",
/*.samples_per_second */ 8000,
static const switch_codec_interface_t g711a_codec_interface = {
/*.interface_name */ "g711 alaw",
- /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.implementations */ &g711a_8k_implementation
};
static const switch_codec_interface_t g711u_codec_interface = {
/*.interface_name */ "g711 ulaw",
- /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.implementations */ &g711u_8k_implementation,
/*.next */ &g711a_codec_interface
};
/* Registration */
static const switch_codec_implementation_t g729_10ms_8k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 18,
/*.iananame */ "G729",
/*.samples_per_second */ 8000,
};
static const switch_codec_implementation_t g729_8k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 18,
/*.iananame */ "G729",
/*.samples_per_second */ 8000,
static const switch_codec_interface_t g729_codec_interface = {
/*.interface_name */ "g729",
- /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.implementations */ &g729_8k_implementation,
};
/* Registration */
static const switch_codec_implementation_t gsm_8k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 3,
/*.iananame */ "gsm",
/*.samples_per_second */ 8000,
};
static const switch_codec_interface_t gsm_codec_interface = {
/*.interface_name */ "gsm",
- /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.implementations */ &gsm_8k_implementation,
};
static switch_loadable_module_interface_t gsm_module_interface = {
/* Registration */
static const switch_codec_implementation_t ilbc_8k_30ms_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 97,
/*.iananame */ "iLBC",
/*.samples_per_second */ 8000,
};
static const switch_codec_implementation_t ilbc_8k_20ms_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 97,
/*.iananame */ "iLBC",
/*.samples_per_second */ 8000,
static const switch_codec_implementation_t ilbc_102_8k_30ms_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 102,
/*.iananame */ "iLBC",
/*.samples_per_second */ 8000,
};
static const switch_codec_implementation_t ilbc_102_8k_20ms_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 102,
/*.iananame */ "iLBC102",
/*.samples_per_second */ 8000,
static const switch_codec_implementation_t ilbc_8k_20ms_nonext_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 97,
/*.iananame */ "iLBC20ms",
/*.samples_per_second */ 8000,
static const switch_codec_interface_t ilbc_20ms_codec_interface = {
/*.interface_name */ "ilbc",
- /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.implementations */ &ilbc_8k_20ms_nonext_implementation
};
static const switch_codec_interface_t ilbc_102_codec_interface = {
/*.interface_name */ "ilbc",
- /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.implementations */ &ilbc_102_8k_20ms_implementation,
/*.next*/ &ilbc_20ms_codec_interface
};
static const switch_codec_interface_t ilbc_codec_interface = {
/*.interface_name */ "ilbc",
- /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.implementations */ &ilbc_8k_20ms_implementation,
/*.next*/ &ilbc_102_codec_interface
};
}
static const switch_codec_implementation_t raw_32k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 10,
/*.iananame */ "L16",
/*.samples_per_second = */ 32000,
};
static const switch_codec_implementation_t raw_22k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 10,
/*.iananame */ "L16",
/*.samples_per_second = */ 22050,
};
static const switch_codec_implementation_t raw_16k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 10,
/*.iananame */ "L16",
/*.samples_per_second = */ 16000,
};
static const switch_codec_implementation_t raw_8k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 10,
/*.iananame */ "L16",
/*.samples_per_second = */ 8000,
static const switch_codec_implementation_t raw_8k_30ms_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 10,
/*.iananame */ "L16",
/*.samples_per_second */ 8000,
static const switch_codec_implementation_t raw_8k_60ms_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 10,
/*.iananame */ "L16",
/*.samples_per_second */ 8000,
};
static const switch_codec_implementation_t raw_8k_120ms_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 10,
/*.iananame */ "L16",
/*.samples_per_second */ 8000,
static const switch_codec_interface_t raw_codec_interface = {
/*.interface_name */ "raw signed linear (16 bit)",
- /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.implementations */ &raw_8k_120ms_implementation
};
/* Registration */
static const switch_codec_implementation_t speex_32k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 98,
/*.iananame */ "speex",
/*.samples_per_second */ 32000,
};
static const switch_codec_implementation_t speex_16k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 98,
/*.iananame */ "speex",
/*.samples_per_second */ 16000,
};
static const switch_codec_implementation_t speex_8k_implementation = {
+ /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.ianacode */ 98,
/*.iananame */ "speex",
/*.samples_per_second */ 8000,
static const switch_codec_interface_t speex_codec_interface = {
/*.interface_name */ "speex",
- /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO,
/*.implementations */ &speex_8k_implementation
};
switch_caller_profile_t *caller_profile;
unsigned short samprate;
switch_mutex_t *mutex;
- switch_codec_interface_t *codecs[SWITCH_MAX_CODECS];
+ const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS];
unsigned int num_codecs;
int codec_index;
switch_rtp_t *rtp_session;
if (force || !switch_test_flag(tech_pvt, TFLAG_CODEC_READY)) {
if (tech_pvt->codec_index < 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Don't have my codec yet here's one\n");
- tech_pvt->codec_name = lame(tech_pvt->codecs[0]->implementations->iananame);
- tech_pvt->codec_num = tech_pvt->codecs[0]->implementations->ianacode;
+ tech_pvt->codec_name = lame(tech_pvt->codecs[0]->iananame);
+ tech_pvt->codec_num = tech_pvt->codecs[0]->ianacode;
tech_pvt->codec_index = 0;
- payloads[0].name = lame(tech_pvt->codecs[0]->implementations->iananame);
- payloads[0].id = tech_pvt->codecs[0]->implementations->ianacode;
+ payloads[0].name = lame(tech_pvt->codecs[0]->iananame);
+ payloads[0].id = tech_pvt->codecs[0]->ianacode;
} else {
- payloads[0].name = lame(tech_pvt->codecs[tech_pvt->codec_index]->implementations->iananame);
- payloads[0].id = tech_pvt->codecs[tech_pvt->codec_index]->implementations->ianacode;
+ payloads[0].name = lame(tech_pvt->codecs[tech_pvt->codec_index]->iananame);
+ payloads[0].id = tech_pvt->codecs[tech_pvt->codec_index]->ianacode;
}
for(x = 0; x < len; x++) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Available Payload %s %u\n", payloads[x].name, payloads[x].id);
for(y = 0; y < tech_pvt->num_codecs; y++) {
- char *name = tech_pvt->codecs[y]->implementations->iananame;
+ char *name = tech_pvt->codecs[y]->iananame;
if (!strncasecmp(name, "ilbc", 4)) {
name = "ilbc";
}
- if (tech_pvt->codecs[y]->implementations->ianacode > 96) {
+ if (tech_pvt->codecs[y]->ianacode > 96) {
match = strcasecmp(name, payloads[x].name) ? 0 : 1;
} else {
- match = (payloads[x].id == tech_pvt->codecs[y]->implementations->ianacode) ? 1 : 0;
+ match = (payloads[x].id == tech_pvt->codecs[y]->ianacode) ? 1 : 0;
}
if (match) {
tech_pvt->codec_index = y;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Choosing Payload index %u %s %u\n", y, payloads[x].name, payloads[x].id);
- tech_pvt->codec_name = tech_pvt->codecs[y]->implementations->iananame;
- tech_pvt->codec_num = tech_pvt->codecs[y]->implementations->ianacode;
+ tech_pvt->codec_name = tech_pvt->codecs[y]->iananame;
+ tech_pvt->codec_num = tech_pvt->codecs[y]->ianacode;
if (!switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
do_describe(tech_pvt, 0);
}
int ssrc;
switch_time_t last_read;
char *realm;
- switch_codec_interface_t *codecs[SWITCH_MAX_CODECS];
+ const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS];
int num_codecs;
switch_payload_t te;
switch_mutex_t *flag_mutex;
static switch_status_t exosip_write_frame(switch_core_session_t *session, switch_frame_t *frame, int timeout,
switch_io_flag_t flags, int stream_id);
static int config_exosip(int reload);
-static switch_status_t parse_sdp_media(struct private_object *tech_pvt, sdp_media_t * media, char **dname, char **drate, char **dpayload);
+static switch_status_t parse_sdp_media(struct private_object *tech_pvt,
+ sdp_media_t * media,
+ char **dname,
+ char **drate,
+ char **dpayload,
+ const switch_codec_implementation_t **impp);
+
static switch_status_t exosip_kill_channel(switch_core_session_t *session, int sig);
static switch_status_t activate_rtp(struct private_object *tech_pvt);
static void deactivate_rtp(struct private_object *tech_pvt);
static const switch_codec_implementation_t *imp;
for (i = 0; i < tech_pvt->num_codecs; i++) {
- imp = tech_pvt->codecs[i]->implementations;
+ imp = tech_pvt->codecs[i];
while(NULL != imp) {
uint32_t sps = imp->samples_per_second;
char *displayname, *username;
osip_header_t *tedious;
char *val;
+ const switch_codec_implementation_t *imp = NULL;
switch_core_session_add_stream(session, NULL);
if ((tech_pvt = (struct private_object *) switch_core_session_alloc(session, sizeof(struct private_object))) != 0) {
if (tech_pvt->num_codecs > 0) {
int i;
- static const switch_codec_implementation_t *imp;
+ static const switch_codec_implementation_t *imp = NULL;
for (i = 0; i < tech_pvt->num_codecs; i++) {
- for (imp = tech_pvt->codecs[i]->implementations; imp; imp = imp->next) {
+ for (imp = tech_pvt->codecs[i]; imp; imp = imp->next) {
sdp_add_codec(tech_pvt->sdp_config, tech_pvt->codecs[i]->codec_type, imp->ianacode, imp->iananame,
imp->samples_per_second, 0);
for (pos = 0; audio_tab[pos] != NULL; pos++) {
osip_rfc3264_complete_answer(tech_pvt->sdp_config, remote_sdp, tech_pvt->local_sdp, audio_tab[pos],
mline);
- if (parse_sdp_media(tech_pvt, audio_tab[pos], &dname, &drate, &dpayload) == SWITCH_STATUS_SUCCESS) {
+ if (parse_sdp_media(tech_pvt, audio_tab[pos], &dname, &drate, &dpayload, &imp) == SWITCH_STATUS_SUCCESS) {
tech_pvt->payload_num = atoi(dpayload);
goto done;
}
{
int rate = atoi(drate);
int ms = globals.codec_ms;
+
+
+ if (imp) {
+ ms = imp->microseconds_per_frame / 1000;
+ }
+
if (!strcasecmp(dname, "ilbc")) {
ms = 30;
}
}
-static switch_status_t parse_sdp_media(struct private_object *tech_pvt, sdp_media_t * media, char **dname, char **drate, char **dpayload)
+static switch_status_t parse_sdp_media(struct private_object *tech_pvt,
+ sdp_media_t * media,
+ char **dname,
+ char **drate,
+ char **dpayload,
+ const switch_codec_implementation_t **impp)
{
int pos = 0;
sdp_attribute_t *attr = NULL;
char *name, *payload, *rate;
switch_status_t status = SWITCH_STATUS_GENERR;
char workspace[512];
+ const switch_codec_implementation_t *imp = NULL;
while (osip_list_eol(media->a_attributes, pos) == 0) {
attr = (sdp_attribute_t *) osip_list_get(media->a_attributes, pos);
}
for(i = 0; !match && i < tech_pvt->num_codecs; i++) {
- const switch_codec_implementation_t *imp;
-
-
- for (imp = tech_pvt->codecs[i]->implementations; imp; imp = imp->next) {
+
+ for (imp = tech_pvt->codecs[i]; imp; imp = imp->next) {
if (pt < 97) {
match = (pt == imp->ianacode) ? 1 : 0;
*dname = strdup(name);
*drate = strdup(rate);
*dpayload = strdup(payload);
+ *impp = imp;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Found negotiated codec Payload: %s Name: %s Rate: %s\n",
*dpayload, *dname, *drate);
return SWITCH_STATUS_SUCCESS;
struct private_object *tech_pvt;
char *dpayload = NULL, *dname = NULL, *drate = NULL;
switch_channel_t *channel;
-
+ const switch_codec_implementation_t *imp = NULL;
if ((tech_pvt = get_pvt_by_call_id(event->cid)) == 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cannot answer nonexistant call [%d]!\n", event->cid);
snprintf(tech_pvt->remote_sdp_audio_ip, 50, conn->c_addr);
/* Grab codec elements */
- if (parse_sdp_media(tech_pvt, remote_med, &dname, &drate, &dpayload) == SWITCH_STATUS_SUCCESS) {
+ if (parse_sdp_media(tech_pvt, remote_med, &dname, &drate, &dpayload, &imp) == SWITCH_STATUS_SUCCESS) {
tech_pvt->payload_num = atoi(dpayload);
}
/* Assign them thar IDs */
tech_pvt->did = event->did;
tech_pvt->tid = event->tid;
-
-
{
int rate = atoi(drate);
int ms = globals.codec_ms;
+
if (!strcasecmp(dname, "ilbc")) {
ms = 30;
}
+ if (imp) {
+ ms = imp->microseconds_per_frame / 1000;
+ }
+
if (switch_core_codec_init(&tech_pvt->read_codec,
dname,
rate,
//int rate = 8000;
//int codec_ms = 20;
switch_channel_t *channel;
- switch_codec_interface_t *codecs[SWITCH_MAX_CODECS];
+ const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS];
int num_codecs = 0;
unsigned int local_cap = 0, mixed_cap = 0, chosen = 0, leading = 0;
int x, srate = 8000;
for (x = 0; x < num_codecs; x++) {
static const switch_codec_implementation_t *imp;
- for (imp = codecs[x]->implementations; imp; imp = imp->next) {
+ for (imp = codecs[x]; imp; imp = imp->next) {
unsigned int codec = iana2ast(imp->ianacode);
if (io == IAX_QUERY) {
mixed_cap = local_cap;
}
- leading = iana2ast(codecs[0]->implementations->ianacode);
+ leading = iana2ast(codecs[0]->ianacode);
if (io == IAX_QUERY) {
chosen = leading;
*format = chosen;
return SWITCH_STATUS_SUCCESS;
} else if (switch_test_flag(&globals, GFLAG_MY_CODEC_PREFS) && (leading & mixed_cap)) {
chosen = leading;
- dname = codecs[0]->implementations->iananame;
+ dname = codecs[0]->iananame;
} else {
unsigned int prefs[32];
int len = 0;
chosen = prefs[x];
for (z = 0; z < num_codecs; z++) {
static const switch_codec_implementation_t *imp;
- for (imp = codecs[z]->implementations; imp; imp = imp->next) {
+ for (imp = codecs[z]; imp; imp = imp->next) {
if (prefs[x] == iana2ast(imp->ianacode)) {
dname = imp->iananame;
break;
chosen = *format;
for (x = 0; x < num_codecs; x++) {
static const switch_codec_implementation_t *imp;
- for (imp = codecs[x]->implementations; imp; imp = imp->next) {
+ for (imp = codecs[x]; imp; imp = imp->next) {
unsigned int cap = iana2ast(imp->ianacode);
if (cap == chosen) {
dname = imp->iananame;
} else { /* c'mon there has to be SOMETHING... */
for (x = 0; x < num_codecs; x++) {
static const switch_codec_implementation_t *imp;
- for (imp = codecs[x]->implementations; imp; imp = imp->next) {
+ for (imp = codecs[x]; imp; imp = imp->next) {
unsigned int cap = iana2ast(imp->ianacode);
if (cap & mixed_cap) {
chosen = cap;
return switch_core_hash_find(loadable_modules.directory_hash, name);
}
-SWITCH_DECLARE(int) switch_loadable_module_get_codecs(switch_memory_pool_t *pool, switch_codec_interface_t **array,
+SWITCH_DECLARE(int) switch_loadable_module_get_codecs(switch_memory_pool_t *pool, const switch_codec_implementation_t **array,
int arraylen)
{
switch_hash_index_t *hi;
void *val;
+ switch_codec_interface_t *codec_interface;
int i = 0;
for (hi = switch_hash_first(pool, loadable_modules.codec_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, NULL, NULL, &val);
- array[i++] = val;
+ codec_interface = (switch_codec_interface_t *) val;
+ array[i++] = codec_interface->implementations;
if (i > arraylen) {
break;
}
}
-SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(switch_codec_interface_t **array,
+SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_implementation_t **array,
int arraylen, char **prefs, int preflen)
{
int x, i = 0;
switch_codec_interface_t *codec_interface;
-
- for (x = 0; x < preflen; x++) {
- if ((codec_interface = switch_loadable_module_get_codec_interface(prefs[x])) != 0 ) {
- array[i++] = codec_interface;
- if (i > arraylen) {
- break;
+ const switch_codec_implementation_t *imp;
+
+ for (x = 0; x < preflen; x++) {
+ char *name, *p, buf[128];
+ uint32_t interval = 0, len = 0;
+
+ name = prefs[x];
+ if ((p = strchr(name, '@'))) {
+ p++;
+ len = p-name;
+
+ if (len > sizeof(buf)) {
+ len = sizeof(buf);
+ }
+ switch_copy_string(buf, name, len);
+ *(buf + len) = '\0';
+ interval = atoi(p);
+ name = buf;
+ }
+
+ if ((codec_interface = switch_loadable_module_get_codec_interface(name)) != 0 ) {
+ for (imp = codec_interface->implementations; imp; imp = imp->next) {
+ if (!interval) {
+ array[i++] = imp;
+ } else if ((imp->microseconds_per_frame / 1000) == interval) {
+ array[i++] = imp;
+ }
}
- }
- }
+ if (i > arraylen) {
+ break;
+ }
+ }
+ }
return i;
}