diff --git a/conf/sofia.conf.xml b/conf/sofia.conf.xml
index 66c52fae2a..a4fafabb06 100644
--- a/conf/sofia.conf.xml
+++ b/conf/sofia.conf.xml
@@ -50,6 +50,8 @@
+
+
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h
index 24e52001c0..a9bad614ff 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.h
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.h
@@ -111,7 +111,8 @@ typedef enum {
PFLAG_DISABLE_TRANSCODING = (1 << 6),
PFLAG_REWRITE_TIMESTAMPS = (1 << 7),
PFLAG_RUNNING = (1 << 8),
- PFLAG_RESPAWN = (1 << 9)
+ PFLAG_RESPAWN = (1 << 9),
+ PFLAG_GREEDY = (1 << 10)
} PFLAGS;
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index b10b6e0d2a..f9e7cd6204 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -797,6 +797,10 @@ switch_status_t config_sofia(int reload, char *profile_name)
if (switch_true(val)) {
profile->pflags |= PFLAG_PASS_RFC2833;
}
+ } else if (!strcasecmp(var, "inbound-codec-negotiation")) {
+ if (!strcasecmp(val, "greedy")) {
+ profile->pflags |= PFLAG_GREEDY;
+ }
} else if (!strcasecmp(var, "disable-transcoding")) {
if (switch_true(val)) {
profile->pflags |= PFLAG_DISABLE_TRANSCODING;
diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c
index 898c1c886d..c04595aeb1 100644
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -1042,12 +1042,25 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *
private_object_t *tech_pvt;
sdp_media_t *m;
sdp_attribute_t *a;
-
+ int first = 0, last = 0;
int ptime = 0, dptime = 0;
+ int greedy = 0, x = 0, skip = 0, mine = 0;
+ switch_channel_t *channel = NULL;
+ char *val;
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ greedy = !!(tech_pvt->profile->pflags & PFLAG_GREEDY);
+
+ if (!greedy) {
+ if ((val = switch_channel_get_variable(channel, "sip_codec_negotiation")) && !strcasecmp(val, "greedy")) {
+ greedy = 1;
+ }
+ }
if ((tech_pvt->origin = switch_core_session_strdup(session, (char *) sdp->sdp_origin->o_username))) {
if (strstr(tech_pvt->origin, "CiscoSystemsSIP-GW-UserAgent")) {
@@ -1108,12 +1121,18 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *
match = 0;
break;
}
-
+
+ greed:
+ x = 0;
for (map = m->m_rtpmaps; map; map = map->rm_next) {
int32_t i;
const switch_codec_implementation_t *mimp = NULL, *near_match = NULL;
const char *rm_encoding;
-
+
+ if (x++ < skip) {
+ printf("skip %s\n", map->rm_encoding);
+ continue;
+ }
if (!(rm_encoding = map->rm_encoding)) {
rm_encoding = "";
@@ -1135,15 +1154,22 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *
switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_AUTO_CNG);
}
}
-
+
if (match) {
if (te && cng_pt) {
break;
}
continue;
}
+
+ if (greedy) {
+ first = mine;
+ last = first + 1;
+ } else {
+ first = 0; last = tech_pvt->num_codecs;
+ }
- for (i = 0; i < tech_pvt->num_codecs; i++) {
+ for (i = first; i < last && i < tech_pvt->num_codecs; i++) {
const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
uint32_t codec_rate = imp->samples_per_second;
if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
@@ -1174,6 +1200,11 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *
match = 0;
}
}
+
+ if (!match && greedy) {
+ skip++;
+ continue;
+ }
if (!match && near_match) {
const switch_codec_implementation_t *search[1];
@@ -1182,7 +1213,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *
int num;
snprintf(tmp, sizeof(tmp), "%s@%uk@%ui", near_match->iananame, near_match->samples_per_second, ptime);
-
+
prefs[0] = tmp;
num = switch_loadable_module_get_codecs_sorted(search, 1, prefs, 1);
@@ -1221,6 +1252,13 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, sdp_session_t *
}
}
}
+
+ if (!match && greedy && mine < tech_pvt->num_codecs) {
+ mine++;
+ skip = 0;
+ goto greed;
+ }
+
} else if (m->m_type == sdp_media_video) {
sdp_rtpmap_t *map;
const char *rm_encoding;