From b6d6cd618add846634600df7967ea41fe6a7c76c Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Wed, 8 Apr 2009 06:05:56 +0000 Subject: [PATCH] MODENDP-206 git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@12946 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/endpoints/mod_sofia/mod_sofia.h | 2 + src/mod/endpoints/mod_sofia/sofia.c | 10 ++ src/mod/endpoints/mod_sofia/sofia_glue.c | 136 +++++++++++++++++++++++ 3 files changed, 148 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 1452c223b0..3f93e60f3e 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -671,6 +671,8 @@ void launch_sofia_profile_thread(sofia_profile_t *profile); switch_status_t sofia_presence_chat_send(const char *proto, const char *from, const char *to, const char *subject, const char *body, const char *type, const char *hint); void sofia_glue_tech_absorb_sdp(private_object_t *tech_pvt); + +void sofia_glue_set_r_sdp_codec_string(switch_channel_t *channel,const char *codec_string, sdp_session_t *sdp); switch_status_t sofia_glue_tech_media(private_object_t *tech_pvt, const char *r_sdp); char *sofia_reg_find_reg_url(sofia_profile_t *profile, const char *user, const char *host, char *val, switch_size_t len); void event_handler(switch_event_t *event); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index ae4eca7d22..40e55f102a 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -2886,9 +2886,19 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, switch_channel_get_name(channel), nua_callstate_name(ss_state), status); if (r_sdp) { + sdp_parser_t *parser; + sdp_session_t *sdp; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Remote SDP:\n%s\n", r_sdp); tech_pvt->remote_sdp_str = switch_core_session_strdup(session, r_sdp); switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp); + + if ( sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && (parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) { + if ((sdp = sdp_session(parser))) { + sofia_glue_set_r_sdp_codec_string(channel, (tech_pvt->profile?tech_pvt->profile->codec_string:NULL), sdp); + } + sdp_parser_free(parser); + } sofia_glue_pass_sdp(tech_pvt, (char *) r_sdp); } } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 1b77e00212..300bccd97d 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -2380,6 +2380,142 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f } +void sofia_glue_set_r_sdp_codec_string(switch_channel_t *channel,const char *codec_string, sdp_session_t *sdp) +{ + char buf[1024] = {0}; + sdp_media_t *m; + sdp_attribute_t *attr; + int ptime = 0, dptime = 0; + sdp_connection_t *connection; + sdp_rtpmap_t *map; + short int match = 0; + int i; + int already_did[128] = { 0 }; + int num_codecs = 0; + char *codec_order[SWITCH_MAX_CODECS]; + const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS] = { 0 }; + + if (codec_string) { + char *tmp_codec_string; + if ((tmp_codec_string = strdup(codec_string))) { + num_codecs = switch_separate_string(tmp_codec_string, ',', codec_order, SWITCH_MAX_CODECS); + num_codecs = switch_loadable_module_get_codecs_sorted(codecs, SWITCH_MAX_CODECS, codec_order, num_codecs); + switch_safe_free(tmp_codec_string); + } + } else { + num_codecs = switch_loadable_module_get_codecs(codecs, SWITCH_MAX_CODECS); + } + + if (!channel || !num_codecs) { + return; + } + + for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) { + if (switch_strlen_zero(attr->a_name)) { + continue; + } + + if (!strcasecmp(attr->a_name, "ptime")) { + dptime = atoi(attr->a_value); + break; + } + } + + for (m = sdp->sdp_media; m; m = m->m_next) { + ptime = dptime; + if ( m->m_type == sdp_media_image && m->m_port) { + switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",t38"); + } else if (m->m_type == sdp_media_audio && m->m_port) { + for (attr = m->m_attributes; attr; attr = attr->a_next) { + if (switch_strlen_zero(attr->a_name)) { + continue; + } + if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) { + ptime = atoi(attr->a_value); + break; + } + } + connection = sdp->sdp_connection; + if (m->m_connections) { + connection = m->m_connections; + } + + if (!connection) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n"); + break; + } + + for (i = 0; i < num_codecs; i++) { + const switch_codec_implementation_t *imp = codecs[i]; + if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO || imp->ianacode > 127 || already_did[imp->ianacode]) { + continue; + } + for (map = m->m_rtpmaps; map; map = map->rm_next) { + if ( map->rm_pt > 127 || already_did[map->rm_pt]) { + continue; + } + + if (map->rm_pt < 96) { + match = (map->rm_pt == imp->ianacode) ? 1 : 0; + } else { + if(map->rm_encoding) { + match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1; + } else { + match = 0; + } + } + + if (match) { + switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh@%di", imp->iananame, (int) map->rm_rate, ptime); + already_did[imp->ianacode] = 1; + break; + } + } + } + } else if (m->m_type == sdp_media_video && m->m_port) { + connection = sdp->sdp_connection; + if (m->m_connections) { + connection = m->m_connections; + } + + if (!connection) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n"); + break; + } + for (i = 0; i < num_codecs; i++) { + const switch_codec_implementation_t *imp = codecs[i]; + if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO || imp->ianacode > 127 || already_did[imp->ianacode]) { + continue; + } + for (map = m->m_rtpmaps; map; map = map->rm_next) { + if ( map->rm_pt > 127 || already_did[map->rm_pt]) { + continue; + } + + if (map->rm_pt < 96) { + match = (map->rm_pt == imp->ianacode) ? 1 : 0; + } else { + if(map->rm_encoding) { + match = strcasecmp(map->rm_encoding, imp->iananame) ? 0 : 1; + } else { + match = 0; + } + } + + if (match) { + switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh@%di", imp->iananame, (int) map->rm_rate, ptime); + already_did[imp->ianacode] = 1; + break; + } + } + } + } + } + if (buf[0] == ',') { + switch_channel_set_variable(channel, "ep_codec_string", buf + 1); + } +} + switch_status_t sofia_glue_tech_media(private_object_t *tech_pvt, const char *r_sdp) { sdp_parser_t *parser = NULL;