]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
wip
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 19 Dec 2012 20:47:04 +0000 (14:47 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Mon, 1 Apr 2013 02:27:14 +0000 (21:27 -0500)
src/mod/endpoints/mod_sofia/sofia_glue.c
src/mod/endpoints/mod_sofia/sofia_media.c

index b15a4ce15c8339f9dc5929c96a29cd86216f004c..c3707f5ae3f5fe1494d79849da8b94b63b5d39a7 100644 (file)
@@ -178,187 +178,6 @@ void sofia_glue_set_udptl_image_sdp(private_object_t *tech_pvt, switch_t38_optio
 
 }
 
-static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, 
-                                          switch_port_t port,
-                                          int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map, int verbose_sdp, int secure)
-{
-       int i = 0;
-       int rate;
-       int already_did[128] = { 0 };
-       int ptime = 0, noptime = 0;
-       const char *local_audio_crypto_key = switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
-
-
-       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP", 
-                                       port, secure ? "S" : "");
-                               
-       
-
-       for (i = 0; i < tech_pvt->num_codecs; i++) {
-               const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
-               int this_ptime = (imp->microseconds_per_packet / 1000);
-
-               if (!strcasecmp(imp->iananame, "ilbc")) {
-                       this_ptime = 20;
-               }
-
-               if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
-                       continue;
-               }
-
-               if (!noptime) {
-                       if (!cur_ptime) {
-#if 0
-                               if (ptime) {
-                                       if (ptime != this_ptime) {
-                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
-                                                                                 "Codec %s payload %d added to sdp wanting ptime %d but it's already %d (%s:%d:%d), disabling ptime.\n", 
-                                                                                 imp->iananame,
-                                                                                 tech_pvt->ianacodes[i],
-                                                                                 this_ptime,
-                                                                                 ptime,
-                                                                                 tech_pvt->codecs[0]->iananame,
-                                                                                 tech_pvt->codecs[0]->ianacode,
-                                                                                 ptime);
-                                               ptime = 0;
-                                               noptime = 1;
-                                       }
-                               } else {
-                                       ptime = this_ptime;
-                               }
-#else
-                               if (!ptime) {
-                                       ptime = this_ptime;
-                               }
-#endif
-                       } else {
-                               if (this_ptime != cur_ptime) {
-                                       continue;
-                               }
-                       }
-               }
-
-               if (tech_pvt->ianacodes[i] < 128) {
-                       if (already_did[tech_pvt->ianacodes[i]]) {
-                               continue;
-                       }
-
-                       already_did[tech_pvt->ianacodes[i]] = 1;
-               }
-
-               
-               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", tech_pvt->ianacodes[i]);
-       }
-
-       if (tech_pvt->dtmf_type == DTMF_2833 && tech_pvt->te > 95) {
-               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", tech_pvt->te);
-       }
-               
-       if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && cng_type && use_cng) {
-               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", cng_type);
-       }
-               
-       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "\n");
-
-
-       memset(already_did, 0, sizeof(already_did));
-               
-       for (i = 0; i < tech_pvt->num_codecs; i++) {
-               const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
-               char *fmtp = imp->fmtp;
-               int this_ptime = imp->microseconds_per_packet / 1000;
-
-               if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
-                       continue;
-               }
-
-               if (!strcasecmp(imp->iananame, "ilbc")) {
-                       this_ptime = 20;
-               }
-
-               if (!noptime) {
-                       if (!cur_ptime) {
-                               if (!ptime) {
-                                       ptime = this_ptime;
-                               }
-                       } else {
-                               if (this_ptime != cur_ptime) {
-                                       continue;
-                               }
-                       }
-               }
-               
-               if (tech_pvt->ianacodes[i] < 128) {
-                       if (already_did[tech_pvt->ianacodes[i]]) {
-                               continue;
-                       }
-                       
-                       already_did[tech_pvt->ianacodes[i]] = 1;
-               }
-
-               
-               rate = imp->samples_per_second;
-
-               if (map) {
-                       char key[128] = "";
-                       char *check = NULL;
-                       switch_snprintf(key, sizeof(key), "%s:%u", imp->iananame, imp->bits_per_second);
-
-                       if ((check = switch_event_get_header(map, key)) || (check = switch_event_get_header(map, imp->iananame))) {
-                               fmtp = check;
-                       }
-               }
-               
-               if (tech_pvt->ianacodes[i] > 95 || verbose_sdp) {
-                       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->ianacodes[i], imp->iananame, rate);
-               }
-
-               if (fmtp) {
-                       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->ianacodes[i], fmtp);
-               }
-       }
-
-
-       if ((tech_pvt->dtmf_type == DTMF_2833 || sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF)) 
-               && tech_pvt->te > 95) {
-               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", tech_pvt->te, tech_pvt->te);
-       }
-
-       if (secure) {
-               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key);
-               //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
-       }
-
-       if (!cng_type) {
-               //switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d CN/8000\n", cng_type);
-               //} else {
-               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=silenceSupp:off - - - -\n");
-       }
-
-       if (append_audio) {
-               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\n");
-       }
-
-       if (!cur_ptime) {
-               cur_ptime = ptime;
-       }
-       
-       if (!noptime && cur_ptime) {
-               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ptime:%d\n", cur_ptime);
-       }
-
-       if (tech_pvt->local_sdp_audio_zrtp_hash) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n",
-                                                 tech_pvt->local_sdp_audio_zrtp_hash);
-               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=zrtp-hash:%s\n",
-                                               tech_pvt->local_sdp_audio_zrtp_hash);
-       }
-
-       if (!zstr(sr)) {
-               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=%s\n", sr);
-       }
-}
-
 void sofia_glue_check_dtmf_type(private_object_t *tech_pvt) 
 {
        const char *val;
@@ -376,533 +195,6 @@ void sofia_glue_check_dtmf_type(private_object_t *tech_pvt)
        }
 }
 
-#define SDPBUFLEN 65536
-void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch_port_t port, const char *sr, int force)
-{
-       char *buf;
-       int ptime = 0;
-       uint32_t rate = 0;
-       uint32_t v_port;
-       int use_cng = 1;
-       const char *val;
-       const char *family;
-       const char *pass_fmtp = switch_channel_get_variable(tech_pvt->channel, "sip_video_fmtp");
-       const char *ov_fmtp = switch_channel_get_variable(tech_pvt->channel, "sip_force_video_fmtp");
-       const char *append_audio = switch_channel_get_variable(tech_pvt->channel, "sip_append_audio_sdp");
-       char srbuf[128] = "";
-       const char *var_val;
-       const char *username = tech_pvt->profile->username;
-       const char *fmtp_out = tech_pvt->fmtp_out;
-       const char *fmtp_out_var = switch_channel_get_variable(tech_pvt->channel, "sip_force_audio_fmtp");
-       switch_event_t *map = NULL, *ptmap = NULL;
-       const char *b_sdp = NULL;
-       int verbose_sdp = 0;
-       const char *local_audio_crypto_key = switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
-
-       switch_zmalloc(buf, SDPBUFLEN);
-       
-       sofia_glue_check_dtmf_type(tech_pvt);
-
-       if (sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) ||
-               ((val = switch_channel_get_variable(tech_pvt->channel, "supress_cng")) && switch_true(val)) ||
-               ((val = switch_channel_get_variable(tech_pvt->channel, "suppress_cng")) && switch_true(val))) {
-               use_cng = 0;
-               tech_pvt->cng_pt = 0;
-       }
-
-       if (!tech_pvt->payload_space) {
-               int i;
-
-               tech_pvt->payload_space = 98;
-
-               for (i = 0; i < tech_pvt->num_codecs; i++) {
-                       const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
-
-                       tech_pvt->ianacodes[i] = imp->ianacode;
-                       
-                       if (tech_pvt->ianacodes[i] > 64) {
-                               if (tech_pvt->dtmf_type == DTMF_2833 && tech_pvt->te > 95 && tech_pvt->te == tech_pvt->payload_space) {
-                                       tech_pvt->payload_space++;
-                               }
-                               if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) &&
-                                       tech_pvt->cng_pt && use_cng  && tech_pvt->cng_pt == tech_pvt->payload_space) {
-                                       tech_pvt->payload_space++;
-                               }
-                               tech_pvt->ianacodes[i] = tech_pvt->payload_space++;
-                       }
-               }
-       }
-
-       if (fmtp_out_var) {
-               fmtp_out = fmtp_out_var;
-       }
-
-       if ((val = switch_channel_get_variable(tech_pvt->channel, "verbose_sdp")) && switch_true(val)) {
-               verbose_sdp = 1;
-       }
-
-       if (!force && !ip && zstr(sr)
-               && (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) || switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA))) {
-               switch_safe_free(buf);
-               return;
-       }
-
-       if (!ip) {
-               if (!(ip = tech_pvt->adv_sdp_audio_ip)) {
-                       ip = tech_pvt->proxy_sdp_audio_ip;
-               }
-       }
-
-       if (!ip) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s NO IP!\n", switch_channel_get_name(tech_pvt->channel));
-               switch_safe_free(buf);
-               return;
-       }
-
-       if (!port) {
-               if (!(port = tech_pvt->adv_sdp_audio_port)) {
-                       port = tech_pvt->proxy_sdp_audio_port;
-               }
-       }
-
-       if (!port) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s NO PORT!\n", switch_channel_get_name(tech_pvt->channel));
-               switch_safe_free(buf);
-               return;
-       }
-
-       if (!tech_pvt->rm_encoding && (b_sdp = switch_channel_get_variable(tech_pvt->channel, SWITCH_B_SDP_VARIABLE))) {
-               sofia_glue_sdp_map(b_sdp, &map, &ptmap);
-       }
-
-       if (zstr(sr)) {
-               if ((var_val = switch_channel_get_variable(tech_pvt->channel, "media_audio_mode"))) {
-                       sr = var_val;
-               } else {
-                       sr = "sendrecv";
-               }
-       }
-
-       if (!tech_pvt->owner_id) {
-               tech_pvt->owner_id = (uint32_t) switch_epoch_time_now(NULL) - port;
-       }
-
-       if (!tech_pvt->session_id) {
-               tech_pvt->session_id = tech_pvt->owner_id;
-       }
-
-       if (switch_true(switch_channel_get_variable_dup(tech_pvt->channel, "drop_dtmf", SWITCH_FALSE, -1))) {
-               sofia_set_flag(tech_pvt, TFLAG_DROP_DTMF);
-       }
-
-       tech_pvt->session_id++;
-
-       if ((tech_pvt->profile->ndlb & PFLAG_NDLB_SENDRECV_IN_SESSION) ||
-               ((var_val = switch_channel_get_variable(tech_pvt->channel, "ndlb_sendrecv_in_session")) && switch_true(var_val))) {
-               if (!zstr(sr)) {
-                       switch_snprintf(srbuf, sizeof(srbuf), "a=%s\n", sr);
-               }
-               sr = NULL;
-       }
-
-       family = strchr(ip, ':') ? "IP6" : "IP4";
-       switch_snprintf(buf, SDPBUFLEN,
-                                       "v=0\n"
-                                       "o=%s %010u %010u IN %s %s\n"
-                                       "s=%s\n"
-                                       "c=IN %s %s\n" "t=0 0\n"
-                                       "%s",
-                                       username, tech_pvt->owner_id, tech_pvt->session_id, family, ip, username, family, ip, srbuf);
-
-       if (tech_pvt->rm_encoding) {
-               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio %d RTP/%sAVP", 
-                                               port, (!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) ? "S" : "");
-
-               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->pt);
-
-               if ((tech_pvt->dtmf_type == DTMF_2833 || sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF)) && tech_pvt->te > 95) {
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->te);
-               }
-               
-               if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && tech_pvt->cng_pt && use_cng) {
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->cng_pt);
-               }
-               
-               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n");
-
-               rate = tech_pvt->rm_rate;
-               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->agreed_pt, tech_pvt->rm_encoding, rate);
-               if (fmtp_out) {
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->agreed_pt, fmtp_out);
-               }
-
-               if (tech_pvt->read_codec.implementation && !ptime) {
-                       ptime = tech_pvt->read_codec.implementation->microseconds_per_packet / 1000;
-               }
-
-
-               if ((tech_pvt->dtmf_type == DTMF_2833 || sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF))
-                       && tech_pvt->te > 95) {
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", tech_pvt->te, tech_pvt->te);
-               }
-               if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && tech_pvt->cng_pt && use_cng) {
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d CN/8000\n", tech_pvt->cng_pt);
-                       if (!tech_pvt->rm_encoding) {
-                               tech_pvt->cng_pt = 0;
-                       }
-               } else {
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=silenceSupp:off - - - -\n");
-               }
-
-               if (append_audio) {
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\n");
-               }
-
-               if (ptime) {
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ptime:%d\n", ptime);
-               }
-
-
-               if (tech_pvt->local_sdp_audio_zrtp_hash) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n",
-                                                         tech_pvt->local_sdp_audio_zrtp_hash);
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=zrtp-hash:%s\n",
-                                                       tech_pvt->local_sdp_audio_zrtp_hash);
-               }
-
-               if (!zstr(sr)) {
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=%s\n", sr);
-               }
-       
-               if (!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) {
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key);
-                       //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=encryption:optional\n");
-               }
-
-       } else if (tech_pvt->num_codecs) {
-               int i;
-               int cur_ptime = 0, this_ptime = 0, cng_type = 0;
-               const char *mult;
-
-               if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && tech_pvt->cng_pt && use_cng) {
-                       cng_type = tech_pvt->cng_pt;
-
-                       if (!tech_pvt->rm_encoding) {
-                               tech_pvt->cng_pt = 0;
-                       }
-               }
-               
-               mult = switch_channel_get_variable(tech_pvt->channel, "sdp_m_per_ptime");
-               
-               if (mult && switch_false(mult)) {
-                       char *bp = buf;
-                       int both = 1;
-
-                       if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE))) {
-                               generate_m(tech_pvt, buf, SDPBUFLEN, port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
-                               bp = (buf + strlen(buf));
-
-                               /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/
-                               if (switch_true(switch_channel_get_variable(tech_pvt->channel, "sdp_secure_savp_only"))) {
-                                       both = 0;
-                               }
-
-                       }
-
-                       if (both) {
-                               generate_m(tech_pvt, bp, SDPBUFLEN - strlen(buf), port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0);
-                       }
-
-               } else {
-
-                       for (i = 0; i < tech_pvt->num_codecs; i++) {
-                               const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
-                               
-                               if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
-                                       continue;
-                               }
-                               
-                               this_ptime = imp->microseconds_per_packet / 1000;
-                               
-                               if (!strcasecmp(imp->iananame, "ilbc")) {
-                                       this_ptime = 20;
-                               }
-                               
-                               if (cur_ptime != this_ptime) {
-                                       char *bp = buf;
-                                       int both = 1;
-
-                                       cur_ptime = this_ptime;                 
-                                       
-                                       if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE))) {
-                                               generate_m(tech_pvt, bp, SDPBUFLEN - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
-                                               bp = (buf + strlen(buf));
-
-                                               /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/
-                                               if (switch_true(switch_channel_get_variable(tech_pvt->channel, "sdp_secure_savp_only"))) {
-                                                       both = 0;
-                                               }
-                                       }
-
-                                       if (both) {
-                                               generate_m(tech_pvt, bp, SDPBUFLEN - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0);
-                                       }
-                               }
-                               
-                       }
-               }
-
-       }
-       
-       if (sofia_test_flag(tech_pvt, TFLAG_VIDEO)) {
-               const char *local_video_crypto_key = switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO);
-               
-               if (!tech_pvt->local_sdp_video_port) {
-                       sofia_glue_tech_choose_video_port(tech_pvt, 0);
-               }
-
-               if ((v_port = tech_pvt->adv_sdp_video_port)) {
-
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video %d RTP/%sAVP", 
-                                                       v_port, (!zstr(local_video_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) ? "S" : "");
-
-
-                       /*****************************/
-                       if (tech_pvt->video_rm_encoding) {
-                               sofia_glue_tech_set_video_codec(tech_pvt, 0);
-                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->video_agreed_pt);
-                       } else if (tech_pvt->num_codecs) {
-                               int i;
-                               int already_did[128] = { 0 };
-                               for (i = 0; i < tech_pvt->num_codecs; i++) {
-                                       const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
-
-                                       if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
-                                               continue;
-                                       }
-
-                                       if (tech_pvt->ianacodes[i] < 128) {
-                                               if (already_did[tech_pvt->ianacodes[i]]) {
-                                                       continue;
-                                               }
-                                               already_did[tech_pvt->ianacodes[i]] = 1;
-                                       }
-
-                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->ianacodes[i]);
-                                       if (!ptime) {
-                                               ptime = imp->microseconds_per_packet / 1000;
-                                       }
-                               }
-                       }
-
-                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n");
-
-                       if (tech_pvt->video_rm_encoding) {
-                               const char *of;
-                               rate = tech_pvt->video_rm_rate;
-                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n", tech_pvt->video_pt, tech_pvt->video_rm_encoding,
-                                                               tech_pvt->video_rm_rate);
-
-                               if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) {
-                                       pass_fmtp = tech_pvt->video_rm_fmtp;
-                               } else {
-
-                                       pass_fmtp = NULL;
-
-                                       if (switch_channel_get_partner_uuid(tech_pvt->channel)) {
-                                               if ((of = switch_channel_get_variable_partner(tech_pvt->channel, "sip_video_fmtp"))) {
-                                                       pass_fmtp = of;
-                                               }
-                                       }
-
-                                       if (ov_fmtp) {
-                                               pass_fmtp = ov_fmtp;
-                                       }// else { // seems to break eyebeam at least...
-                                               //pass_fmtp = switch_channel_get_variable(tech_pvt->channel, "sip_video_fmtp");
-                                       //}
-                               }
-
-                               if (pass_fmtp) {
-                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->video_pt, pass_fmtp);
-                               }
-
-                       } else if (tech_pvt->num_codecs) {
-                               int i;
-                               int already_did[128] = { 0 };
-
-                               for (i = 0; i < tech_pvt->num_codecs; i++) {
-                                       const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
-                                       char *fmtp = NULL;
-                                       uint32_t ianacode = tech_pvt->ianacodes[i];
-
-                                       if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
-                                               continue;
-                                       }
-
-                                       if (ianacode < 128) {
-                                               if (already_did[ianacode]) {
-                                                       continue;
-                                               }
-                                               already_did[ianacode] = 1;
-                                       }
-
-                                       if (!rate) {
-                                               rate = imp->samples_per_second;
-                                       }
-                                       
-                                       
-                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", ianacode, imp->iananame,
-                                                                       imp->samples_per_second);
-                                       
-                                       if (!zstr(ov_fmtp)) {
-                                               fmtp = (char *) ov_fmtp;
-                                       } else {
-                                       
-                                               if (map) {
-                                                       fmtp = switch_event_get_header(map, imp->iananame);
-                                               }
-                                               
-                                               if (zstr(fmtp)) fmtp = imp->fmtp;
-
-                                               if (zstr(fmtp)) fmtp = (char *) pass_fmtp;
-                                       }
-                                       
-                                       if (!zstr(fmtp) && strcasecmp(fmtp, "_blank_")) {
-                                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", ianacode, fmtp);
-                                       }
-                               }
-                               
-                       }
-
-                       if (switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) {
-                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_video_crypto_key);
-                               //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
-                       }                       
-
-
-                       if (tech_pvt->local_sdp_video_zrtp_hash) {
-                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding video a=zrtp-hash:%s\n",
-                                                                 tech_pvt->local_sdp_video_zrtp_hash);
-                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=zrtp-hash:%s\n",
-                                                               tech_pvt->local_sdp_video_zrtp_hash);
-                       }
-               }
-       }
-
-
-       if (map) {
-               switch_event_destroy(&map);
-       }
-       
-       if (ptmap) {
-               switch_event_destroy(&ptmap);
-       }
-
-       sofia_glue_tech_set_local_sdp(tech_pvt, buf, SWITCH_TRUE);
-
-       switch_safe_free(buf);
-}
-
-const char *sofia_glue_get_codec_string(private_object_t *tech_pvt)
-{
-       const char *preferred = NULL, *fallback = NULL;
-       
-       if (!(preferred = switch_channel_get_variable(tech_pvt->channel, "absolute_codec_string"))) {
-               preferred = switch_channel_get_variable(tech_pvt->channel, "codec_string");
-       }
-       
-       if (!preferred) {
-               if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
-                       preferred = tech_pvt->profile->outbound_codec_string;
-                       fallback = tech_pvt->profile->inbound_codec_string;
-               } else {
-                       preferred = tech_pvt->profile->inbound_codec_string;
-                       fallback = tech_pvt->profile->outbound_codec_string;
-               }
-       }
-
-       return !zstr(preferred) ? preferred : fallback;
-}
-
-void sofia_glue_tech_prepare_codecs(private_object_t *tech_pvt)
-{
-       const char *abs, *codec_string = NULL;
-       const char *ocodec = NULL;
-
-       if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) || switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
-               return;
-       }
-
-       if (tech_pvt->num_codecs) {
-               return;
-       }
-
-       tech_pvt->payload_space = 0;
-
-       switch_assert(tech_pvt->session != NULL);
-
-       if ((abs = switch_channel_get_variable(tech_pvt->channel, "absolute_codec_string"))) {
-               /* inherit_codec == true will implicitly clear the absolute_codec_string 
-                  variable if used since it was the reason it was set in the first place and is no longer needed */
-               if (switch_true(switch_channel_get_variable(tech_pvt->channel, "inherit_codec"))) {
-                       switch_channel_set_variable(tech_pvt->channel, "absolute_codec_string", NULL);
-               }
-               codec_string = abs;
-               goto ready;
-       }
-
-       if (!(codec_string = switch_channel_get_variable(tech_pvt->channel, "codec_string"))) {
-               codec_string = sofia_glue_get_codec_string(tech_pvt);
-       }
-
-       if (codec_string && *codec_string == '=') {
-               codec_string++;
-               goto ready;
-       }
-
-
-       if ((ocodec = switch_channel_get_variable(tech_pvt->channel, SWITCH_ORIGINATOR_CODEC_VARIABLE))) {
-               if (!codec_string || sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_TRANSCODING)) {
-                       codec_string = ocodec;
-               } else {
-                       if (!(codec_string = switch_core_session_sprintf(tech_pvt->session, "%s,%s", ocodec, codec_string))) {
-                               codec_string = ocodec;
-                       }
-               }
-       }
-
- ready:
-
-       if (codec_string) {
-               char *tmp_codec_string;
-               if ((tmp_codec_string = switch_core_session_strdup(tech_pvt->session, codec_string))) {
-                       tech_pvt->codec_order_last = switch_separate_string(tmp_codec_string, ',', tech_pvt->codec_order, SWITCH_MAX_CODECS);
-                       tech_pvt->num_codecs =
-                               switch_loadable_module_get_codecs_sorted(tech_pvt->codecs, SWITCH_MAX_CODECS, tech_pvt->codec_order, tech_pvt->codec_order_last);
-               }
-       } else {
-               tech_pvt->num_codecs = switch_loadable_module_get_codecs(tech_pvt->codecs, sizeof(tech_pvt->codecs) / sizeof(tech_pvt->codecs[0]));
-       }
-
-
-}
-
-void sofia_glue_check_video_codecs(private_object_t *tech_pvt)
-{
-       if (tech_pvt->num_codecs && !sofia_test_flag(tech_pvt, TFLAG_VIDEO)) {
-               int i;
-               tech_pvt->video_count = 0;
-               for (i = 0; i < tech_pvt->num_codecs; i++) {
-                       
-                       if (tech_pvt->codecs[i]->codec_type == SWITCH_CODEC_TYPE_VIDEO) {
-                               tech_pvt->video_count++;
-                       }
-               }
-               if (tech_pvt->video_count) {
-                       sofia_set_flag_locked(tech_pvt, TFLAG_VIDEO);
-               }
-       }
-}
 
 private_object_t *sofia_glue_new_pvt(switch_core_session_t *session)
 {
@@ -1673,357 +965,27 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt, co
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
                        status = SWITCH_STATUS_GENERR;
                } else {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
-                                                         tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
-                       if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
-                               !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
-                               /* Reactivate the NAT buster flag. */
-                               switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
-                       }
-                       if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTOFIX_TIMING)) {
-                               tech_pvt->check_frames = 0;
-                       }
-                       status = SWITCH_STATUS_SUCCESS;
-               }
-       }
-
- end:
-
-       return status;
-}
-
-
-void sofia_glue_tech_patch_sdp(private_object_t *tech_pvt)
-{
-       switch_size_t len;
-       char *p, *q, *pe, *qe;
-       int has_video = 0, has_audio = 0, has_ip = 0;
-       char port_buf[25] = "";
-       char vport_buf[25] = "";
-       char *new_sdp;
-       int bad = 0;
-
-       if (zstr(tech_pvt->local_sdp_str)) {
-               return;
-       }
-
-       len = strlen(tech_pvt->local_sdp_str) * 2;
-
-       if (switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED) &&
-               (switch_stristr("sendonly", tech_pvt->local_sdp_str) || switch_stristr("0.0.0.0", tech_pvt->local_sdp_str))) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Skip patch on hold SDP\n");
-               return;
-       }
-
-       if (zstr(tech_pvt->adv_sdp_audio_ip) || !tech_pvt->adv_sdp_audio_port) {
-               if (sofia_glue_tech_choose_port(tech_pvt, 1) != SWITCH_STATUS_SUCCESS) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "%s I/O Error\n",
-                                                         switch_channel_get_name(tech_pvt->channel));
-                       return;
-               }
-               tech_pvt->iananame = switch_core_session_strdup(tech_pvt->session, "PROXY");
-               tech_pvt->rm_rate = 8000;
-               tech_pvt->codec_ms = 20;
-       }
-
-       new_sdp = switch_core_session_alloc(tech_pvt->session, len);
-       switch_snprintf(port_buf, sizeof(port_buf), "%u", tech_pvt->adv_sdp_audio_port);
-
-
-       p = tech_pvt->local_sdp_str;
-       q = new_sdp;
-       pe = p + strlen(p);
-       qe = q + len - 1;
-
-
-       while (p && *p) {
-               if (p >= pe) {
-                       bad = 1;
-                       goto end;
-               }
-
-               if (q >= qe) {
-                       bad = 2;
-                       goto end;
-               }
-
-               if (tech_pvt->adv_sdp_audio_ip && !strncmp("c=IN IP", p, 7)) {
-                       strncpy(q, p, 7);
-                       p += 7;
-                       q += 7;
-                       strncpy(q, strchr(tech_pvt->adv_sdp_audio_ip, ':') ? "6 " : "4 ", 2);
-                       p +=2;
-                       q +=2;                  
-                       strncpy(q, tech_pvt->adv_sdp_audio_ip, strlen(tech_pvt->adv_sdp_audio_ip));
-                       q += strlen(tech_pvt->adv_sdp_audio_ip);
-
-                       while (p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f'))) {
-                               if (p >= pe) {
-                                       bad = 3;
-                                       goto end;
-                               }
-                               p++;
-                       }
-
-                       has_ip++;
-
-               } else if (!strncmp("o=", p, 2)) {
-                       char *oe = strchr(p, '\n');
-                       switch_size_t len;
-
-                       if (oe) {
-                               const char *family = "IP4";
-                               char o_line[1024] = "";
-
-                               if (oe >= pe) {
-                                       bad = 5;
-                                       goto end;
-                               }
-
-                               len = (oe - p);
-                               p += len;
-
-
-                               family = strchr(tech_pvt->profile->sipip, ':') ? "IP6" : "IP4";
-
-                               if (!tech_pvt->owner_id) {
-                                       tech_pvt->owner_id = (uint32_t) switch_epoch_time_now(NULL) * 31821U + 13849U;
-                               }
-
-                               if (!tech_pvt->session_id) {
-                                       tech_pvt->session_id = tech_pvt->owner_id;
-                               }
-
-                               tech_pvt->session_id++;
-
-
-                               snprintf(o_line, sizeof(o_line), "o=%s %010u %010u IN %s %s\n",
-                                                tech_pvt->profile->username, tech_pvt->owner_id, tech_pvt->session_id, family, tech_pvt->profile->sipip);
-
-                               strncpy(q, o_line, strlen(o_line));
-                               q += strlen(o_line) - 1;
-
-                       }
-
-               } else if (!strncmp("s=", p, 2)) {
-                       char *se = strchr(p, '\n');
-                       switch_size_t len;
-
-                       if (se) {
-                               char s_line[1024] = "";
-
-                               if (se >= pe) {
-                                       bad = 5;
-                                       goto end;
-                               }
-
-                               len = (se - p);
-                               p += len;
-
-                               snprintf(s_line, sizeof(s_line), "s=%s\n", tech_pvt->profile->username);
-
-                               strncpy(q, s_line, strlen(s_line));
-                               q += strlen(s_line) - 1;
-
-                       }
-
-               } else if ((!strncmp("m=audio ", p, 8) && *(p + 8) != '0') || (!strncmp("m=image ", p, 8) && *(p + 8) != '0')) {
-                       strncpy(q, p, 8);
-                       p += 8;
-
-                       if (p >= pe) {
-                               bad = 4;
-                               goto end;
-                       }
-
-
-                       q += 8;
-
-                       if (q >= qe) {
-                               bad = 5;
-                               goto end;
-                       }
-
-
-                       strncpy(q, port_buf, strlen(port_buf));
-                       q += strlen(port_buf);
-
-                       if (q >= qe) {
-                               bad = 6;
-                               goto end;
-                       }
-
-                       while (p && *p && (*p >= '0' && *p <= '9')) {
-                               if (p >= pe) {
-                                       bad = 7;
-                                       goto end;
-                               }
-                               p++;
-                       }
-
-                       has_audio++;
-
-               } else if (!strncmp("m=video ", p, 8) && *(p + 8) != '0') {
-                       if (!has_video) {
-                               sofia_glue_tech_choose_video_port(tech_pvt, 1);
-                               tech_pvt->video_rm_encoding = "PROXY-VID";
-                               tech_pvt->video_rm_rate = 90000;
-                               tech_pvt->video_codec_ms = 0;
-                               switch_snprintf(vport_buf, sizeof(vport_buf), "%u", tech_pvt->adv_sdp_video_port);
-                               if (switch_channel_media_ready(tech_pvt->channel) && !switch_rtp_ready(tech_pvt->video_rtp_session)) {
-                                       sofia_set_flag(tech_pvt, TFLAG_VIDEO);
-                                       sofia_set_flag(tech_pvt, TFLAG_REINVITE);
-                                       sofia_media_activate_rtp(tech_pvt);
-                               }
-                       }
-
-                       strncpy(q, p, 8);
-                       p += 8;
-
-                       if (p >= pe) {
-                               bad = 8;
-                               goto end;
-                       }
-
-                       q += 8;
-
-                       if (q >= qe) {
-                               bad = 9;
-                               goto end;
-                       }
-
-                       strncpy(q, vport_buf, strlen(vport_buf));
-                       q += strlen(vport_buf);
-
-                       if (q >= qe) {
-                               bad = 10;
-                               goto end;
-                       }
-
-                       while (p && *p && (*p >= '0' && *p <= '9')) {
-
-                               if (p >= pe) {
-                                       bad = 11;
-                                       goto end;
-                               }
-
-                               p++;
-                       }
-
-                       has_video++;
-               }
-
-               while (p && *p && *p != '\n') {
-
-                       if (p >= pe) {
-                               bad = 12;
-                               goto end;
-                       }
-
-                       if (q >= qe) {
-                               bad = 13;
-                               goto end;
-                       }
-
-                       *q++ = *p++;
-               }
-
-               if (p >= pe) {
-                       bad = 14;
-                       goto end;
-               }
-
-               if (q >= qe) {
-                       bad = 15;
-                       goto end;
-               }
-
-               *q++ = *p++;
-
-       }
-
- end:
-
-       if (bad) {
-               return;
-       }
-
-
-       if (switch_channel_down(tech_pvt->channel) || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%s too late.\n", switch_channel_get_name(tech_pvt->channel));
-               return;
-       }
-
-
-       if (!has_ip && !has_audio) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%s SDP has no audio in it.\n%s\n",
-                                                 switch_channel_get_name(tech_pvt->channel), tech_pvt->local_sdp_str);
-               return;
-       }
-
-
-       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%s Patched SDP\n---\n%s\n+++\n%s\n",
-                                         switch_channel_get_name(tech_pvt->channel), tech_pvt->local_sdp_str, new_sdp);
-
-       sofia_glue_tech_set_local_sdp(tech_pvt, new_sdp, SWITCH_FALSE);
-
-}
-
-
-void sofia_glue_tech_set_local_sdp(private_object_t *tech_pvt, const char *sdp_str, switch_bool_t dup)
-{
-       switch_mutex_lock(tech_pvt->sofia_mutex);
-       tech_pvt->local_sdp_str = dup ? switch_core_session_strdup(tech_pvt->session, sdp_str) : (char *) sdp_str;
-       switch_channel_set_variable(tech_pvt->channel, "sip_local_sdp_str", tech_pvt->local_sdp_str);
-       switch_mutex_unlock(tech_pvt->sofia_mutex);
-}
-
-char *sofia_glue_get_multipart(switch_core_session_t *session, const char *prefix, const char *sdp, char **mp_type)
-{
-       char *extra_headers = NULL;
-       switch_stream_handle_t stream = { 0 };
-       switch_event_header_t *hi = NULL;
-       int x = 0;
-       switch_channel_t *channel = switch_core_session_get_channel(session);
-       const char *boundary = switch_core_session_get_uuid(session);
-
-       SWITCH_STANDARD_STREAM(stream);
-       if ((hi = switch_channel_variable_first(channel))) {
-               for (; hi; hi = hi->next) {
-                       const char *name = (char *) hi->name;
-                       char *value = (char *) hi->value;
-
-                       if (!strncasecmp(name, prefix, strlen(prefix))) {
-                               const char *hname = name + strlen(prefix);
-                               if (*value == '~') {
-                                       stream.write_function(&stream, "--%s\nContent-Type: %s\nContent-Length: %d\n%s\n", boundary, hname, strlen(value), value + 1);
-                               } else {
-                                       stream.write_function(&stream, "--%s\nContent-Type: %s\nContent-Length: %d\n\n%s\n", boundary, hname, strlen(value) + 1, value);
-                               }
-                               x++;
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
+                                                         tech_pvt->remote_sdp_audio_ip, tech_pvt->remote_sdp_audio_port);
+                       if (!sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_RTP_AUTOADJ) &&
+                               !((val = switch_channel_get_variable(tech_pvt->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
+                               /* Reactivate the NAT buster flag. */
+                               switch_rtp_set_flag(tech_pvt->rtp_session, SWITCH_RTP_FLAG_AUTOADJ);
                        }
+                       if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTOFIX_TIMING)) {
+                               tech_pvt->check_frames = 0;
+                       }
+                       status = SWITCH_STATUS_SUCCESS;
                }
-               switch_channel_variable_last(channel);
-       }
-
-       if (x) {
-               *mp_type = switch_core_session_sprintf(session, "multipart/mixed; boundary=%s", boundary);
-               if (sdp) {
-                       stream.write_function(&stream, "--%s\nContent-Type: application/sdp\nContent-Length: %d\n\n%s\n", boundary, strlen(sdp) + 1, sdp);
-               }
-               stream.write_function(&stream, "--%s--\n", boundary);
        }
 
-       if (!zstr((char *) stream.data)) {
-               extra_headers = stream.data;
-       } else {
-               switch_safe_free(stream.data);
-       }
+ end:
 
-       return extra_headers;
+       return status;
 }
 
 
+
 char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix)
 {
        char *extra_headers = NULL;
@@ -2892,288 +1854,6 @@ void sofia_glue_deactivate_rtp(private_object_t *tech_pvt)
 
 }
 
-switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int force)
-{
-
-       if (!tech_pvt->video_rm_encoding) {
-               return SWITCH_STATUS_FALSE;
-       }
-
-       if (tech_pvt->video_read_codec.implementation && switch_core_codec_ready(&tech_pvt->video_read_codec)) {
-               if (!force) {
-                       return SWITCH_STATUS_SUCCESS;
-               }
-               if (strcasecmp(tech_pvt->video_read_codec.implementation->iananame, tech_pvt->video_rm_encoding) ||
-                       tech_pvt->video_read_codec.implementation->samples_per_second != tech_pvt->video_rm_rate) {
-
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Changing Codec from %s to %s\n",
-                                                         tech_pvt->video_read_codec.implementation->iananame, tech_pvt->video_rm_encoding);
-                       switch_core_codec_destroy(&tech_pvt->video_read_codec);
-                       switch_core_codec_destroy(&tech_pvt->video_write_codec);
-               } else {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Already using %s\n",
-                                                         tech_pvt->video_read_codec.implementation->iananame);
-                       return SWITCH_STATUS_SUCCESS;
-               }
-       }
-
-
-
-       if (switch_core_codec_init(&tech_pvt->video_read_codec,
-                                                          tech_pvt->video_rm_encoding,
-                                                          tech_pvt->video_rm_fmtp,
-                                                          tech_pvt->video_rm_rate,
-                                                          0,
-                                                          1,
-                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
-                                                          NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
-               return SWITCH_STATUS_FALSE;
-       } else {
-               if (switch_core_codec_init(&tech_pvt->video_write_codec,
-                                                                  tech_pvt->video_rm_encoding,
-                                                                  tech_pvt->video_rm_fmtp,
-                                                                  tech_pvt->video_rm_rate,
-                                                                  0,
-                                                                  1,
-                                                                  SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
-                                                                  NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
-                       return SWITCH_STATUS_FALSE;
-               } else {
-                       tech_pvt->video_read_frame.rate = tech_pvt->video_rm_rate;
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set VIDEO Codec %s %s/%ld %d ms\n",
-                                                         switch_channel_get_name(tech_pvt->channel), tech_pvt->video_rm_encoding, tech_pvt->video_rm_rate, tech_pvt->video_codec_ms);
-                       tech_pvt->video_read_frame.codec = &tech_pvt->video_read_codec;
-
-                       tech_pvt->video_fmtp_out = switch_core_session_strdup(tech_pvt->session, tech_pvt->video_write_codec.fmtp_out);
-
-                       tech_pvt->video_write_codec.agreed_pt = tech_pvt->video_agreed_pt;
-                       tech_pvt->video_read_codec.agreed_pt = tech_pvt->video_agreed_pt;
-                       switch_core_session_set_video_read_codec(tech_pvt->session, &tech_pvt->video_read_codec);
-                       switch_core_session_set_video_write_codec(tech_pvt->session, &tech_pvt->video_write_codec);
-
-
-                       if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
-                               switch_core_session_message_t msg = { 0 };
-
-                               msg.from = __FILE__;
-                               msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
-
-                               switch_rtp_set_default_payload(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt);
-                               
-                               if (tech_pvt->video_recv_pt != tech_pvt->video_agreed_pt) {
-                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, 
-                                                                         "%s Set video receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->video_recv_pt);
-                                       
-                                       switch_rtp_set_recv_pt(tech_pvt->video_rtp_session, tech_pvt->video_recv_pt);
-                               } else {
-                                       switch_rtp_set_recv_pt(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt);
-                               }
-
-                               switch_core_session_receive_message(tech_pvt->session, &msg);
-
-
-                       }
-
-                       switch_channel_set_variable(tech_pvt->channel, "sip_use_video_codec_name", tech_pvt->video_rm_encoding);
-                       switch_channel_set_variable(tech_pvt->channel, "sip_use_video_codec_fmtp", tech_pvt->video_rm_fmtp);
-                       switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_video_codec_rate", "%d", tech_pvt->video_rm_rate);
-                       switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_video_codec_ptime", "%d", 0);
-
-               }
-       }
-       return SWITCH_STATUS_SUCCESS;
-}
-
-switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force)
-{
-       switch_status_t status = SWITCH_STATUS_SUCCESS;
-       int resetting = 0;
-
-       if (!tech_pvt->iananame) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "No audio codec available\n");
-               switch_goto_status(SWITCH_STATUS_FALSE, end);
-       }
-
-       if (switch_core_codec_ready(&tech_pvt->read_codec)) {
-               if (!force) {
-                       switch_goto_status(SWITCH_STATUS_SUCCESS, end);
-               }
-               if (strcasecmp(tech_pvt->read_impl.iananame, tech_pvt->iananame) ||
-                       tech_pvt->read_impl.samples_per_second != tech_pvt->rm_rate ||
-                       tech_pvt->codec_ms != (uint32_t) tech_pvt->read_impl.microseconds_per_packet / 1000) {
-
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, 
-                                                         "Changing Codec from %s@%dms@%dhz to %s@%dms@%luhz\n",
-                                                         tech_pvt->read_impl.iananame, tech_pvt->read_impl.microseconds_per_packet / 1000,
-                                                         tech_pvt->read_impl.samples_per_second,
-                                                         tech_pvt->rm_encoding, 
-                                                         tech_pvt->codec_ms,
-                                                         tech_pvt->rm_rate);
-                       
-                       switch_yield(tech_pvt->read_impl.microseconds_per_packet);
-                       switch_core_session_lock_codec_write(tech_pvt->session);
-                       switch_core_session_lock_codec_read(tech_pvt->session);
-                       resetting = 1;
-                       switch_yield(tech_pvt->read_impl.microseconds_per_packet);
-                       switch_core_codec_destroy(&tech_pvt->read_codec);
-                       switch_core_codec_destroy(&tech_pvt->write_codec);
-               } else {
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Already using %s\n", tech_pvt->read_impl.iananame);
-                       switch_goto_status(SWITCH_STATUS_SUCCESS, end);
-               }
-       }
-
-       if (switch_core_codec_init_with_bitrate(&tech_pvt->read_codec,
-                                                          tech_pvt->iananame,
-                                                          tech_pvt->rm_fmtp,
-                                                          tech_pvt->rm_rate,
-                                                          tech_pvt->codec_ms,
-                                                          1,
-                                                          tech_pvt->bitrate,
-                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | tech_pvt->profile->codec_flags,
-                                                          NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
-               switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
-               switch_goto_status(SWITCH_STATUS_FALSE, end);
-       }
-       
-       tech_pvt->read_codec.session = tech_pvt->session;
-
-
-       if (switch_core_codec_init_with_bitrate(&tech_pvt->write_codec,
-                                                          tech_pvt->iananame,
-                                                          tech_pvt->rm_fmtp,
-                                                          tech_pvt->rm_rate,
-                                                          tech_pvt->codec_ms,
-                                                          1,
-                                                          tech_pvt->bitrate,
-                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | tech_pvt->profile->codec_flags,
-                                                          NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
-               switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
-               switch_goto_status(SWITCH_STATUS_FALSE, end);
-       }
-
-       tech_pvt->write_codec.session = tech_pvt->session;
-
-       switch_channel_set_variable(tech_pvt->channel, "sip_use_codec_name", tech_pvt->iananame);
-       switch_channel_set_variable(tech_pvt->channel, "sip_use_codec_fmtp", tech_pvt->rm_fmtp);
-       switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_codec_rate", "%d", tech_pvt->rm_rate);
-       switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_codec_ptime", "%d", tech_pvt->codec_ms);
-
-
-       switch_assert(tech_pvt->read_codec.implementation);
-       switch_assert(tech_pvt->write_codec.implementation);
-
-       tech_pvt->read_impl = *tech_pvt->read_codec.implementation;
-       tech_pvt->write_impl = *tech_pvt->write_codec.implementation;
-
-       switch_core_session_set_read_impl(tech_pvt->session, tech_pvt->read_codec.implementation);
-       switch_core_session_set_write_impl(tech_pvt->session, tech_pvt->write_codec.implementation);
-
-       if (switch_rtp_ready(tech_pvt->rtp_session)) {
-               switch_assert(tech_pvt->read_codec.implementation);
-               
-               if (switch_rtp_change_interval(tech_pvt->rtp_session,
-                                                                          tech_pvt->read_impl.microseconds_per_packet, 
-                                                                          tech_pvt->read_impl.samples_per_packet) != SWITCH_STATUS_SUCCESS) {
-                       switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
-                       switch_goto_status(SWITCH_STATUS_FALSE, end);
-               }
-       }
-
-       tech_pvt->read_frame.rate = tech_pvt->rm_rate;
-
-       if (!switch_core_codec_ready(&tech_pvt->read_codec)) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
-               switch_goto_status(SWITCH_STATUS_FALSE, end);
-       }
-
-       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set Codec %s %s/%ld %d ms %d samples %d bits\n",
-                                         switch_channel_get_name(tech_pvt->channel), tech_pvt->iananame, tech_pvt->rm_rate, tech_pvt->codec_ms,
-                                         tech_pvt->read_impl.samples_per_packet, tech_pvt->read_impl.bits_per_second);
-       tech_pvt->read_frame.codec = &tech_pvt->read_codec;
-
-       tech_pvt->write_codec.agreed_pt = tech_pvt->agreed_pt;
-       tech_pvt->read_codec.agreed_pt = tech_pvt->agreed_pt;
-
-       if (force != 2) {
-               switch_core_session_set_real_read_codec(tech_pvt->session, &tech_pvt->read_codec);
-               switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
-       }
-
-       tech_pvt->fmtp_out = switch_core_session_strdup(tech_pvt->session, tech_pvt->write_codec.fmtp_out);
-
-       if (switch_rtp_ready(tech_pvt->rtp_session)) {
-               switch_rtp_set_default_payload(tech_pvt->rtp_session, tech_pvt->pt);
-               switch_rtp_set_recv_pt(tech_pvt->rtp_session, tech_pvt->agreed_pt);
-       }
-
- end:
-       if (resetting) {
-               switch_core_session_unlock_codec_write(tech_pvt->session);
-               switch_core_session_unlock_codec_read(tech_pvt->session);
-       }
-
-       sofia_glue_tech_set_video_codec(tech_pvt, force);
-
-       return status;
-}
-
-
-static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size_t buflen)
-{
-       int codec_ms = ptime;
-       uint32_t map_bit_rate = 0;
-       char ptstr[20] = "";
-       char ratestr[20] = "";
-       char bitstr[20] = "";
-       switch_codec_fmtp_t codec_fmtp = { 0 };
-                                               
-       if (!codec_ms) {
-               codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt);
-       }
-
-       map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
-                               
-       if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
-               ptime = codec_ms = 30;
-       }
-                               
-       if (zstr(map->rm_fmtp)) {
-               if (!strcasecmp(map->rm_encoding, "ilbc")) {
-                       ptime = codec_ms = 30;
-                       map_bit_rate = 13330;
-               }
-       } else {
-               if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
-                       if (codec_fmtp.bits_per_second) {
-                               map_bit_rate = codec_fmtp.bits_per_second;
-                       }
-                       if (codec_fmtp.microseconds_per_packet) {
-                               codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
-                       }
-               }
-       }
-
-       if (map->rm_rate) {
-               switch_snprintf(ratestr, sizeof(ratestr), "@%uh", (unsigned int) map->rm_rate);
-       }
-
-       if (codec_ms) {
-               switch_snprintf(ptstr, sizeof(ptstr), "@%di", codec_ms);
-       }
-
-       if (map_bit_rate) {
-               switch_snprintf(bitstr, sizeof(bitstr), "@%db", map_bit_rate);
-       }
-
-       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), ",%s%s%s%s", map->rm_encoding, ratestr, ptstr, bitstr);
-
-}
-
 void sofia_glue_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session)
 {
        switch_channel_t *aleg_channel;
@@ -3273,334 +1953,6 @@ void find_zrtp_hash(switch_core_session_t *session, sdp_session_t *sdp)
        }
 }
 
-void sofia_glue_set_r_sdp_codec_string(switch_core_session_t *session, 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 };
-       switch_channel_t *channel = switch_core_session_get_channel(session);
-       private_object_t *tech_pvt = switch_core_session_get_private(session);
-       int prefer_sdp = 0;
-       const char *var;
-
-       if ((var = switch_channel_get_variable(channel, "ep_codec_prefer_sdp")) && switch_true(var)) {
-               prefer_sdp = 1;
-       }
-               
-       if (!zstr(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 (zstr(attr->a_name)) {
-                       continue;
-               }
-               if (!strcasecmp(attr->a_name, "ptime")) {
-                       dptime = atoi(attr->a_value);
-                       break;
-               }
-       }
-
-       find_zrtp_hash(session, sdp);
-       sofia_glue_pass_zrtp_hash(session);
-
-       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 (zstr(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_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
-                               break;
-                       }
-
-                       if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || prefer_sdp) {
-                               for (map = m->m_rtpmaps; map; map = map->rm_next) {
-                                       if (map->rm_pt > 127 || already_did[map->rm_pt]) {
-                                               continue;
-                                       }
-
-                                       for (i = 0; i < num_codecs; i++) {
-                                               const switch_codec_implementation_t *imp = codecs[i];
-
-                                               if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && 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) {
-                                                       add_audio_codec(map, ptime, buf, sizeof(buf));
-                                                       break;
-                                               }
-                                       
-                                       }
-                               }
-
-                       } else {
-                               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 ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && 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) {
-                                                       add_audio_codec(map, ptime, buf, sizeof(buf));
-                                                       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_CHANNEL_LOG(channel), 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 ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && 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) {
-                                               if (ptime > 0) {
-                                                       switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh@%di", imp->iananame, (unsigned int) map->rm_rate,
-                                                                                       ptime);
-                                               } else {
-                                                       switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh", imp->iananame, (unsigned int) map->rm_rate);
-                                               }
-                                               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)
-{
-       uint8_t match = 0;
-
-       switch_assert(tech_pvt != NULL);
-       switch_assert(r_sdp != NULL);
-
-       if (zstr(r_sdp)) {
-               return SWITCH_STATUS_FALSE;
-       }
-
-       if ((match = sofia_glue_negotiate_sdp(tech_pvt->session, r_sdp))) {
-               if (sofia_glue_tech_choose_port(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) {
-                       return SWITCH_STATUS_FALSE;
-               }
-               if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
-                       return SWITCH_STATUS_FALSE;
-               }
-               switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "EARLY MEDIA");
-               sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
-               switch_channel_mark_pre_answered(tech_pvt->channel);
-               return SWITCH_STATUS_SUCCESS;
-       }
-
-
-       return SWITCH_STATUS_FALSE;
-}
-
-int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
-{
-       int changed = 0;
-
-       if (sofia_test_flag(tech_pvt, TFLAG_SLA_BARGE) || sofia_test_flag(tech_pvt, TFLAG_SLA_BARGING)) {
-               switch_channel_mark_hold(tech_pvt->channel, sendonly);
-               return 0;
-       }
-
-       if (sendonly && switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED)) {
-               if (!sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
-                       const char *stream;
-                       const char *msg = "hold";
-
-                       if (sofia_test_pflag(tech_pvt->profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
-                               const char *info = switch_channel_get_variable(tech_pvt->channel, "presence_call_info");
-                               if (info) {
-                                       if (switch_stristr("private", info)) {
-                                               msg = "hold-private";
-                                       }
-                               }
-                       }
-
-                       sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
-                       switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
-                       switch_channel_presence(tech_pvt->channel, "unknown", msg, NULL);
-                       changed = 1;
-
-                       if (tech_pvt->max_missed_hold_packets) {
-                               switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_hold_packets);
-                       }
-
-                       if (!(stream = switch_channel_get_hold_music(tech_pvt->channel))) {
-                               stream = tech_pvt->profile->hold_music;
-                       }
-
-                       if (stream && strcasecmp(stream, "silence")) {
-                               if (!strcasecmp(stream, "indicate_hold")) {
-                                       switch_channel_set_flag(tech_pvt->channel, CF_SUSPEND);
-                                       switch_channel_set_flag(tech_pvt->channel, CF_HOLD);
-                                       switch_ivr_hold_uuid(switch_channel_get_partner_uuid(tech_pvt->channel), NULL, 0);
-                               } else {
-                                       switch_ivr_broadcast(switch_channel_get_partner_uuid(tech_pvt->channel), stream,
-                                                                                SMF_ECHO_ALEG | SMF_LOOP | SMF_PRIORITY);
-                                       switch_yield(250000);
-                               }
-                       }
-               }
-       } else {
-               if (sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
-                       sofia_set_flag(tech_pvt, TFLAG_SIP_HOLD);
-                       switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
-                       changed = 1;
-               }
-
-               sofia_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
-
-               if (sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
-                       const char *uuid;
-                       switch_core_session_t *b_session;
-
-                       switch_yield(250000);
-
-                       if (tech_pvt->max_missed_packets) {
-                               switch_rtp_reset_media_timer(tech_pvt->rtp_session);
-                               switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_packets);
-                       }
-
-                       if ((uuid = switch_channel_get_partner_uuid(tech_pvt->channel)) && (b_session = switch_core_session_locate(uuid))) {
-                               switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
-
-                               if (switch_channel_test_flag(tech_pvt->channel, CF_HOLD)) {
-                                       switch_ivr_unhold(b_session);
-                                       switch_channel_clear_flag(tech_pvt->channel, CF_SUSPEND);
-                                       switch_channel_clear_flag(tech_pvt->channel, CF_HOLD);
-                               } else {
-                                       switch_channel_stop_broadcast(b_channel);
-                                       switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
-                               }
-                               switch_core_session_rwunlock(b_session);
-                       }
-
-                       sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
-                       switch_channel_mark_hold(tech_pvt->channel, SWITCH_FALSE);
-                       switch_channel_presence(tech_pvt->channel, "unknown", "unhold", NULL);
-                       changed = 1;
-               }
-       }
-
-       return changed;
-}
-
-void sofia_glue_copy_t38_options(switch_t38_options_t *t38_options, switch_core_session_t *session)
-{
-       switch_channel_t *channel = switch_core_session_get_channel(session);
-       switch_t38_options_t *local_t38_options = switch_channel_get_private(channel, "t38_options");
-
-       switch_assert(t38_options);
-       
-       if (!local_t38_options) {
-               local_t38_options = switch_core_session_alloc(session, sizeof(switch_t38_options_t));
-       }
-
-       local_t38_options->T38MaxBitRate = t38_options->T38MaxBitRate;
-       local_t38_options->T38FaxFillBitRemoval = t38_options->T38FaxFillBitRemoval;
-       local_t38_options->T38FaxTranscodingMMR = t38_options->T38FaxTranscodingMMR;
-       local_t38_options->T38FaxTranscodingJBIG = t38_options->T38FaxTranscodingJBIG;
-       local_t38_options->T38FaxRateManagement = switch_core_session_strdup(session, t38_options->T38FaxRateManagement);
-       local_t38_options->T38FaxMaxBuffer = t38_options->T38FaxMaxBuffer;
-       local_t38_options->T38FaxMaxDatagram = t38_options->T38FaxMaxDatagram;
-       local_t38_options->T38FaxUdpEC = switch_core_session_strdup(session, t38_options->T38FaxUdpEC);
-       local_t38_options->T38VendorInfo = switch_core_session_strdup(session, t38_options->T38VendorInfo);
-       local_t38_options->remote_ip = switch_core_session_strdup(session, t38_options->remote_ip);
-       local_t38_options->remote_port = t38_options->remote_port;
-
-
-       switch_channel_set_private(channel, "t38_options", local_t38_options);
-
-}
-
 /* map sip responses to QSIG cause codes ala RFC4497 section 8.4.4 */
 switch_call_cause_t sofia_glue_sip_cause_to_freeswitch(int status)
 {
index 738f27cb12035be5dc9cb82737558562a5bc861d..9d0ff64d0d7a10e5e9611f6397bccca8ba0f5a53 100644 (file)
@@ -1776,6 +1776,1662 @@ void sofia_media_set_sdp_codec_string(switch_core_session_t *session, const char
 
 }
 
+switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int force)
+{
+
+       if (!tech_pvt->video_rm_encoding) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (tech_pvt->video_read_codec.implementation && switch_core_codec_ready(&tech_pvt->video_read_codec)) {
+               if (!force) {
+                       return SWITCH_STATUS_SUCCESS;
+               }
+               if (strcasecmp(tech_pvt->video_read_codec.implementation->iananame, tech_pvt->video_rm_encoding) ||
+                       tech_pvt->video_read_codec.implementation->samples_per_second != tech_pvt->video_rm_rate) {
+
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Changing Codec from %s to %s\n",
+                                                         tech_pvt->video_read_codec.implementation->iananame, tech_pvt->video_rm_encoding);
+                       switch_core_codec_destroy(&tech_pvt->video_read_codec);
+                       switch_core_codec_destroy(&tech_pvt->video_write_codec);
+               } else {
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Already using %s\n",
+                                                         tech_pvt->video_read_codec.implementation->iananame);
+                       return SWITCH_STATUS_SUCCESS;
+               }
+       }
+
+
+
+       if (switch_core_codec_init(&tech_pvt->video_read_codec,
+                                                          tech_pvt->video_rm_encoding,
+                                                          tech_pvt->video_rm_fmtp,
+                                                          tech_pvt->video_rm_rate,
+                                                          0,
+                                                          1,
+                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+                                                          NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
+               return SWITCH_STATUS_FALSE;
+       } else {
+               if (switch_core_codec_init(&tech_pvt->video_write_codec,
+                                                                  tech_pvt->video_rm_encoding,
+                                                                  tech_pvt->video_rm_fmtp,
+                                                                  tech_pvt->video_rm_rate,
+                                                                  0,
+                                                                  1,
+                                                                  SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+                                                                  NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
+                       return SWITCH_STATUS_FALSE;
+               } else {
+                       tech_pvt->video_read_frame.rate = tech_pvt->video_rm_rate;
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set VIDEO Codec %s %s/%ld %d ms\n",
+                                                         switch_channel_get_name(tech_pvt->channel), tech_pvt->video_rm_encoding, tech_pvt->video_rm_rate, tech_pvt->video_codec_ms);
+                       tech_pvt->video_read_frame.codec = &tech_pvt->video_read_codec;
+
+                       tech_pvt->video_fmtp_out = switch_core_session_strdup(tech_pvt->session, tech_pvt->video_write_codec.fmtp_out);
+
+                       tech_pvt->video_write_codec.agreed_pt = tech_pvt->video_agreed_pt;
+                       tech_pvt->video_read_codec.agreed_pt = tech_pvt->video_agreed_pt;
+                       switch_core_session_set_video_read_codec(tech_pvt->session, &tech_pvt->video_read_codec);
+                       switch_core_session_set_video_write_codec(tech_pvt->session, &tech_pvt->video_write_codec);
+
+
+                       if (switch_rtp_ready(tech_pvt->video_rtp_session)) {
+                               switch_core_session_message_t msg = { 0 };
+
+                               msg.from = __FILE__;
+                               msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
+
+                               switch_rtp_set_default_payload(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt);
+                               
+                               if (tech_pvt->video_recv_pt != tech_pvt->video_agreed_pt) {
+                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, 
+                                                                         "%s Set video receive payload to %u\n", switch_channel_get_name(tech_pvt->channel), tech_pvt->video_recv_pt);
+                                       
+                                       switch_rtp_set_recv_pt(tech_pvt->video_rtp_session, tech_pvt->video_recv_pt);
+                               } else {
+                                       switch_rtp_set_recv_pt(tech_pvt->video_rtp_session, tech_pvt->video_agreed_pt);
+                               }
+
+                               switch_core_session_receive_message(tech_pvt->session, &msg);
+
+
+                       }
+
+                       switch_channel_set_variable(tech_pvt->channel, "sip_use_video_codec_name", tech_pvt->video_rm_encoding);
+                       switch_channel_set_variable(tech_pvt->channel, "sip_use_video_codec_fmtp", tech_pvt->video_rm_fmtp);
+                       switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_video_codec_rate", "%d", tech_pvt->video_rm_rate);
+                       switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_video_codec_ptime", "%d", 0);
+
+               }
+       }
+       return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force)
+{
+       switch_status_t status = SWITCH_STATUS_SUCCESS;
+       int resetting = 0;
+
+       if (!tech_pvt->iananame) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "No audio codec available\n");
+               switch_goto_status(SWITCH_STATUS_FALSE, end);
+       }
+
+       if (switch_core_codec_ready(&tech_pvt->read_codec)) {
+               if (!force) {
+                       switch_goto_status(SWITCH_STATUS_SUCCESS, end);
+               }
+               if (strcasecmp(tech_pvt->read_impl.iananame, tech_pvt->iananame) ||
+                       tech_pvt->read_impl.samples_per_second != tech_pvt->rm_rate ||
+                       tech_pvt->codec_ms != (uint32_t) tech_pvt->read_impl.microseconds_per_packet / 1000) {
+
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, 
+                                                         "Changing Codec from %s@%dms@%dhz to %s@%dms@%luhz\n",
+                                                         tech_pvt->read_impl.iananame, tech_pvt->read_impl.microseconds_per_packet / 1000,
+                                                         tech_pvt->read_impl.samples_per_second,
+                                                         tech_pvt->rm_encoding, 
+                                                         tech_pvt->codec_ms,
+                                                         tech_pvt->rm_rate);
+                       
+                       switch_yield(tech_pvt->read_impl.microseconds_per_packet);
+                       switch_core_session_lock_codec_write(tech_pvt->session);
+                       switch_core_session_lock_codec_read(tech_pvt->session);
+                       resetting = 1;
+                       switch_yield(tech_pvt->read_impl.microseconds_per_packet);
+                       switch_core_codec_destroy(&tech_pvt->read_codec);
+                       switch_core_codec_destroy(&tech_pvt->write_codec);
+               } else {
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Already using %s\n", tech_pvt->read_impl.iananame);
+                       switch_goto_status(SWITCH_STATUS_SUCCESS, end);
+               }
+       }
+
+       if (switch_core_codec_init_with_bitrate(&tech_pvt->read_codec,
+                                                          tech_pvt->iananame,
+                                                          tech_pvt->rm_fmtp,
+                                                          tech_pvt->rm_rate,
+                                                          tech_pvt->codec_ms,
+                                                          1,
+                                                          tech_pvt->bitrate,
+                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | tech_pvt->profile->codec_flags,
+                                                          NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
+               switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
+               switch_goto_status(SWITCH_STATUS_FALSE, end);
+       }
+       
+       tech_pvt->read_codec.session = tech_pvt->session;
+
+
+       if (switch_core_codec_init_with_bitrate(&tech_pvt->write_codec,
+                                                          tech_pvt->iananame,
+                                                          tech_pvt->rm_fmtp,
+                                                          tech_pvt->rm_rate,
+                                                          tech_pvt->codec_ms,
+                                                          1,
+                                                          tech_pvt->bitrate,
+                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | tech_pvt->profile->codec_flags,
+                                                          NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
+               switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
+               switch_goto_status(SWITCH_STATUS_FALSE, end);
+       }
+
+       tech_pvt->write_codec.session = tech_pvt->session;
+
+       switch_channel_set_variable(tech_pvt->channel, "sip_use_codec_name", tech_pvt->iananame);
+       switch_channel_set_variable(tech_pvt->channel, "sip_use_codec_fmtp", tech_pvt->rm_fmtp);
+       switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_codec_rate", "%d", tech_pvt->rm_rate);
+       switch_channel_set_variable_printf(tech_pvt->channel, "sip_use_codec_ptime", "%d", tech_pvt->codec_ms);
+
+
+       switch_assert(tech_pvt->read_codec.implementation);
+       switch_assert(tech_pvt->write_codec.implementation);
+
+       tech_pvt->read_impl = *tech_pvt->read_codec.implementation;
+       tech_pvt->write_impl = *tech_pvt->write_codec.implementation;
+
+       switch_core_session_set_read_impl(tech_pvt->session, tech_pvt->read_codec.implementation);
+       switch_core_session_set_write_impl(tech_pvt->session, tech_pvt->write_codec.implementation);
+
+       if (switch_rtp_ready(tech_pvt->rtp_session)) {
+               switch_assert(tech_pvt->read_codec.implementation);
+               
+               if (switch_rtp_change_interval(tech_pvt->rtp_session,
+                                                                          tech_pvt->read_impl.microseconds_per_packet, 
+                                                                          tech_pvt->read_impl.samples_per_packet) != SWITCH_STATUS_SUCCESS) {
+                       switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+                       switch_goto_status(SWITCH_STATUS_FALSE, end);
+               }
+       }
+
+       tech_pvt->read_frame.rate = tech_pvt->rm_rate;
+
+       if (!switch_core_codec_ready(&tech_pvt->read_codec)) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
+               switch_goto_status(SWITCH_STATUS_FALSE, end);
+       }
+
+       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set Codec %s %s/%ld %d ms %d samples %d bits\n",
+                                         switch_channel_get_name(tech_pvt->channel), tech_pvt->iananame, tech_pvt->rm_rate, tech_pvt->codec_ms,
+                                         tech_pvt->read_impl.samples_per_packet, tech_pvt->read_impl.bits_per_second);
+       tech_pvt->read_frame.codec = &tech_pvt->read_codec;
+
+       tech_pvt->write_codec.agreed_pt = tech_pvt->agreed_pt;
+       tech_pvt->read_codec.agreed_pt = tech_pvt->agreed_pt;
+
+       if (force != 2) {
+               switch_core_session_set_real_read_codec(tech_pvt->session, &tech_pvt->read_codec);
+               switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
+       }
+
+       tech_pvt->fmtp_out = switch_core_session_strdup(tech_pvt->session, tech_pvt->write_codec.fmtp_out);
+
+       if (switch_rtp_ready(tech_pvt->rtp_session)) {
+               switch_rtp_set_default_payload(tech_pvt->rtp_session, tech_pvt->pt);
+       }
+
+ end:
+       if (resetting) {
+               switch_core_session_unlock_codec_write(tech_pvt->session);
+               switch_core_session_unlock_codec_read(tech_pvt->session);
+       }
+
+       sofia_glue_tech_set_video_codec(tech_pvt, force);
+
+       return status;
+}
+
+
+
+static void add_audio_codec(sdp_rtpmap_t *map, int ptime, char *buf, switch_size_t buflen)
+{
+       int codec_ms = ptime;
+       uint32_t map_bit_rate = 0;
+       char ptstr[20] = "";
+       char ratestr[20] = "";
+       char bitstr[20] = "";
+       switch_codec_fmtp_t codec_fmtp = { 0 };
+                                               
+       if (!codec_ms) {
+               codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt);
+       }
+
+       map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
+                               
+       if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
+               ptime = codec_ms = 30;
+       }
+                               
+       if (zstr(map->rm_fmtp)) {
+               if (!strcasecmp(map->rm_encoding, "ilbc")) {
+                       ptime = codec_ms = 30;
+                       map_bit_rate = 13330;
+               }
+       } else {
+               if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
+                       if (codec_fmtp.bits_per_second) {
+                               map_bit_rate = codec_fmtp.bits_per_second;
+                       }
+                       if (codec_fmtp.microseconds_per_packet) {
+                               codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
+                       }
+               }
+       }
+
+       if (map->rm_rate) {
+               switch_snprintf(ratestr, sizeof(ratestr), "@%uh", (unsigned int) map->rm_rate);
+       }
+
+       if (codec_ms) {
+               switch_snprintf(ptstr, sizeof(ptstr), "@%di", codec_ms);
+       }
+
+       if (map_bit_rate) {
+               switch_snprintf(bitstr, sizeof(bitstr), "@%db", map_bit_rate);
+       }
+
+       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), ",%s%s%s%s", map->rm_encoding, ratestr, ptstr, bitstr);
+
+}
+
+
+void sofia_glue_set_r_sdp_codec_string(switch_core_session_t *session, 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 };
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       private_object_t *tech_pvt = switch_core_session_get_private(session);
+       int prefer_sdp = 0;
+       const char *var;
+
+       if ((var = switch_channel_get_variable(channel, "ep_codec_prefer_sdp")) && switch_true(var)) {
+               prefer_sdp = 1;
+       }
+               
+       if (!zstr(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 (zstr(attr->a_name)) {
+                       continue;
+               }
+               if (!strcasecmp(attr->a_name, "ptime")) {
+                       dptime = atoi(attr->a_value);
+                       break;
+               }
+       }
+
+       find_zrtp_hash(session, sdp);
+       sofia_glue_pass_zrtp_hash(session);
+
+       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 (zstr(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_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
+                               break;
+                       }
+
+                       if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || prefer_sdp) {
+                               for (map = m->m_rtpmaps; map; map = map->rm_next) {
+                                       if (map->rm_pt > 127 || already_did[map->rm_pt]) {
+                                               continue;
+                                       }
+
+                                       for (i = 0; i < num_codecs; i++) {
+                                               const switch_codec_implementation_t *imp = codecs[i];
+
+                                               if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && 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) {
+                                                       add_audio_codec(map, ptime, buf, sizeof(buf));
+                                                       break;
+                                               }
+                                       
+                                       }
+                               }
+
+                       } else {
+                               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 ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && 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) {
+                                                       add_audio_codec(map, ptime, buf, sizeof(buf));
+                                                       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_CHANNEL_LOG(channel), 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 ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && 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) {
+                                               if (ptime > 0) {
+                                                       switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh@%di", imp->iananame, (unsigned int) map->rm_rate,
+                                                                                       ptime);
+                                               } else {
+                                                       switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s@%uh", imp->iananame, (unsigned int) map->rm_rate);
+                                               }
+                                               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)
+{
+       uint8_t match = 0;
+
+       switch_assert(tech_pvt != NULL);
+       switch_assert(r_sdp != NULL);
+
+       if (zstr(r_sdp)) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if ((match = sofia_glue_negotiate_sdp(tech_pvt->session, r_sdp))) {
+               if (sofia_glue_tech_choose_port(tech_pvt, 0) != SWITCH_STATUS_SUCCESS) {
+                       return SWITCH_STATUS_FALSE;
+               }
+               if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
+                       return SWITCH_STATUS_FALSE;
+               }
+               switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "EARLY MEDIA");
+               sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
+               switch_channel_mark_pre_answered(tech_pvt->channel);
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+
+       return SWITCH_STATUS_FALSE;
+}
+
+int sofia_glue_toggle_hold(private_object_t *tech_pvt, int sendonly)
+{
+       int changed = 0;
+
+       if (sofia_test_flag(tech_pvt, TFLAG_SLA_BARGE) || sofia_test_flag(tech_pvt, TFLAG_SLA_BARGING)) {
+               switch_channel_mark_hold(tech_pvt->channel, sendonly);
+               return 0;
+       }
+
+       if (sendonly && switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED)) {
+               if (!sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
+                       const char *stream;
+                       const char *msg = "hold";
+
+                       if (sofia_test_pflag(tech_pvt->profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
+                               const char *info = switch_channel_get_variable(tech_pvt->channel, "presence_call_info");
+                               if (info) {
+                                       if (switch_stristr("private", info)) {
+                                               msg = "hold-private";
+                                       }
+                               }
+                       }
+
+                       sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+                       switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
+                       switch_channel_presence(tech_pvt->channel, "unknown", msg, NULL);
+                       changed = 1;
+
+                       if (tech_pvt->max_missed_hold_packets) {
+                               switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_hold_packets);
+                       }
+
+                       if (!(stream = switch_channel_get_hold_music(tech_pvt->channel))) {
+                               stream = tech_pvt->profile->hold_music;
+                       }
+
+                       if (stream && strcasecmp(stream, "silence")) {
+                               if (!strcasecmp(stream, "indicate_hold")) {
+                                       switch_channel_set_flag(tech_pvt->channel, CF_SUSPEND);
+                                       switch_channel_set_flag(tech_pvt->channel, CF_HOLD);
+                                       switch_ivr_hold_uuid(switch_channel_get_partner_uuid(tech_pvt->channel), NULL, 0);
+                               } else {
+                                       switch_ivr_broadcast(switch_channel_get_partner_uuid(tech_pvt->channel), stream,
+                                                                                SMF_ECHO_ALEG | SMF_LOOP | SMF_PRIORITY);
+                                       switch_yield(250000);
+                               }
+                       }
+               }
+       } else {
+               if (sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)) {
+                       sofia_set_flag(tech_pvt, TFLAG_SIP_HOLD);
+                       switch_channel_mark_hold(tech_pvt->channel, SWITCH_TRUE);
+                       changed = 1;
+               }
+
+               sofia_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
+
+               if (sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
+                       const char *uuid;
+                       switch_core_session_t *b_session;
+
+                       switch_yield(250000);
+
+                       if (tech_pvt->max_missed_packets) {
+                               switch_rtp_reset_media_timer(tech_pvt->rtp_session);
+                               switch_rtp_set_max_missed_packets(tech_pvt->rtp_session, tech_pvt->max_missed_packets);
+                       }
+
+                       if ((uuid = switch_channel_get_partner_uuid(tech_pvt->channel)) && (b_session = switch_core_session_locate(uuid))) {
+                               switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+
+                               if (switch_channel_test_flag(tech_pvt->channel, CF_HOLD)) {
+                                       switch_ivr_unhold(b_session);
+                                       switch_channel_clear_flag(tech_pvt->channel, CF_SUSPEND);
+                                       switch_channel_clear_flag(tech_pvt->channel, CF_HOLD);
+                               } else {
+                                       switch_channel_stop_broadcast(b_channel);
+                                       switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
+                               }
+                               switch_core_session_rwunlock(b_session);
+                       }
+
+                       sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
+                       switch_channel_mark_hold(tech_pvt->channel, SWITCH_FALSE);
+                       switch_channel_presence(tech_pvt->channel, "unknown", "unhold", NULL);
+                       changed = 1;
+               }
+       }
+
+       return changed;
+}
+
+void sofia_glue_copy_t38_options(switch_t38_options_t *t38_options, switch_core_session_t *session)
+{
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       switch_t38_options_t *local_t38_options = switch_channel_get_private(channel, "t38_options");
+
+       switch_assert(t38_options);
+       
+       if (!local_t38_options) {
+               local_t38_options = switch_core_session_alloc(session, sizeof(switch_t38_options_t));
+       }
+
+       local_t38_options->T38MaxBitRate = t38_options->T38MaxBitRate;
+       local_t38_options->T38FaxFillBitRemoval = t38_options->T38FaxFillBitRemoval;
+       local_t38_options->T38FaxTranscodingMMR = t38_options->T38FaxTranscodingMMR;
+       local_t38_options->T38FaxTranscodingJBIG = t38_options->T38FaxTranscodingJBIG;
+       local_t38_options->T38FaxRateManagement = switch_core_session_strdup(session, t38_options->T38FaxRateManagement);
+       local_t38_options->T38FaxMaxBuffer = t38_options->T38FaxMaxBuffer;
+       local_t38_options->T38FaxMaxDatagram = t38_options->T38FaxMaxDatagram;
+       local_t38_options->T38FaxUdpEC = switch_core_session_strdup(session, t38_options->T38FaxUdpEC);
+       local_t38_options->T38VendorInfo = switch_core_session_strdup(session, t38_options->T38VendorInfo);
+       local_t38_options->remote_ip = switch_core_session_strdup(session, t38_options->remote_ip);
+       local_t38_options->remote_port = t38_options->remote_port;
+
+
+       switch_channel_set_private(channel, "t38_options", local_t38_options);
+
+}
+
+static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, 
+                                          switch_port_t port,
+                                          int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map, int verbose_sdp, int secure)
+{
+       int i = 0;
+       int rate;
+       int already_did[128] = { 0 };
+       int ptime = 0, noptime = 0;
+       const char *local_audio_crypto_key = switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
+
+
+       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP", 
+                                       port, secure ? "S" : "");
+                               
+       
+
+       for (i = 0; i < tech_pvt->num_codecs; i++) {
+               const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
+               int this_ptime = (imp->microseconds_per_packet / 1000);
+
+               if (!strcasecmp(imp->iananame, "ilbc")) {
+                       this_ptime = 20;
+               }
+
+               if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
+                       continue;
+               }
+
+               if (!noptime) {
+                       if (!cur_ptime) {
+#if 0
+                               if (ptime) {
+                                       if (ptime != this_ptime) {
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
+                                                                                 "Codec %s payload %d added to sdp wanting ptime %d but it's already %d (%s:%d:%d), disabling ptime.\n", 
+                                                                                 imp->iananame,
+                                                                                 tech_pvt->ianacodes[i],
+                                                                                 this_ptime,
+                                                                                 ptime,
+                                                                                 tech_pvt->codecs[0]->iananame,
+                                                                                 tech_pvt->codecs[0]->ianacode,
+                                                                                 ptime);
+                                               ptime = 0;
+                                               noptime = 1;
+                                       }
+                               } else {
+                                       ptime = this_ptime;
+                               }
+#else
+                               if (!ptime) {
+                                       ptime = this_ptime;
+                               }
+#endif
+                       } else {
+                               if (this_ptime != cur_ptime) {
+                                       continue;
+                               }
+                       }
+               }
+
+               if (tech_pvt->ianacodes[i] < 128) {
+                       if (already_did[tech_pvt->ianacodes[i]]) {
+                               continue;
+                       }
+
+                       already_did[tech_pvt->ianacodes[i]] = 1;
+               }
+
+               
+               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", tech_pvt->ianacodes[i]);
+       }
+
+       if (tech_pvt->dtmf_type == DTMF_2833 && tech_pvt->te > 95) {
+               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", tech_pvt->te);
+       }
+               
+       if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && cng_type && use_cng) {
+               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", cng_type);
+       }
+               
+       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "\n");
+
+
+       memset(already_did, 0, sizeof(already_did));
+               
+       for (i = 0; i < tech_pvt->num_codecs; i++) {
+               const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
+               char *fmtp = imp->fmtp;
+               int this_ptime = imp->microseconds_per_packet / 1000;
+
+               if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
+                       continue;
+               }
+
+               if (!strcasecmp(imp->iananame, "ilbc")) {
+                       this_ptime = 20;
+               }
+
+               if (!noptime) {
+                       if (!cur_ptime) {
+                               if (!ptime) {
+                                       ptime = this_ptime;
+                               }
+                       } else {
+                               if (this_ptime != cur_ptime) {
+                                       continue;
+                               }
+                       }
+               }
+               
+               if (tech_pvt->ianacodes[i] < 128) {
+                       if (already_did[tech_pvt->ianacodes[i]]) {
+                               continue;
+                       }
+                       
+                       already_did[tech_pvt->ianacodes[i]] = 1;
+               }
+
+               
+               rate = imp->samples_per_second;
+
+               if (map) {
+                       char key[128] = "";
+                       char *check = NULL;
+                       switch_snprintf(key, sizeof(key), "%s:%u", imp->iananame, imp->bits_per_second);
+
+                       if ((check = switch_event_get_header(map, key)) || (check = switch_event_get_header(map, imp->iananame))) {
+                               fmtp = check;
+                       }
+               }
+               
+               if (tech_pvt->ianacodes[i] > 95 || verbose_sdp) {
+                       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->ianacodes[i], imp->iananame, rate);
+               }
+
+               if (fmtp) {
+                       switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->ianacodes[i], fmtp);
+               }
+       }
+
+
+       if ((tech_pvt->dtmf_type == DTMF_2833 || sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF)) 
+               && tech_pvt->te > 95) {
+               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", tech_pvt->te, tech_pvt->te);
+       }
+
+       if (secure) {
+               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key);
+               //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
+       }
+
+       if (!cng_type) {
+               //switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d CN/8000\n", cng_type);
+               //} else {
+               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=silenceSupp:off - - - -\n");
+       }
+
+       if (append_audio) {
+               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\n");
+       }
+
+       if (!cur_ptime) {
+               cur_ptime = ptime;
+       }
+       
+       if (!noptime && cur_ptime) {
+               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ptime:%d\n", cur_ptime);
+       }
+
+       if (tech_pvt->local_sdp_audio_zrtp_hash) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n",
+                                                 tech_pvt->local_sdp_audio_zrtp_hash);
+               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=zrtp-hash:%s\n",
+                                               tech_pvt->local_sdp_audio_zrtp_hash);
+       }
+
+       if (!zstr(sr)) {
+               switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=%s\n", sr);
+       }
+}
+
+
+#define SDPBUFLEN 65536
+void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch_port_t port, const char *sr, int force)
+{
+       char *buf;
+       int ptime = 0;
+       uint32_t rate = 0;
+       uint32_t v_port;
+       int use_cng = 1;
+       const char *val;
+       const char *family;
+       const char *pass_fmtp = switch_channel_get_variable(tech_pvt->channel, "sip_video_fmtp");
+       const char *ov_fmtp = switch_channel_get_variable(tech_pvt->channel, "sip_force_video_fmtp");
+       const char *append_audio = switch_channel_get_variable(tech_pvt->channel, "sip_append_audio_sdp");
+       char srbuf[128] = "";
+       const char *var_val;
+       const char *username = tech_pvt->profile->username;
+       const char *fmtp_out = tech_pvt->fmtp_out;
+       const char *fmtp_out_var = switch_channel_get_variable(tech_pvt->channel, "sip_force_audio_fmtp");
+       switch_event_t *map = NULL, *ptmap = NULL;
+       const char *b_sdp = NULL;
+       int verbose_sdp = 0;
+       const char *local_audio_crypto_key = switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
+
+       switch_zmalloc(buf, SDPBUFLEN);
+       
+       sofia_glue_check_dtmf_type(tech_pvt);
+
+       if (sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) ||
+               ((val = switch_channel_get_variable(tech_pvt->channel, "supress_cng")) && switch_true(val)) ||
+               ((val = switch_channel_get_variable(tech_pvt->channel, "suppress_cng")) && switch_true(val))) {
+               use_cng = 0;
+               tech_pvt->cng_pt = 0;
+       }
+
+       if (!tech_pvt->payload_space) {
+               int i;
+
+               tech_pvt->payload_space = 98;
+
+               for (i = 0; i < tech_pvt->num_codecs; i++) {
+                       const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
+
+                       tech_pvt->ianacodes[i] = imp->ianacode;
+                       
+                       if (tech_pvt->ianacodes[i] > 64) {
+                               if (tech_pvt->dtmf_type == DTMF_2833 && tech_pvt->te > 95 && tech_pvt->te == tech_pvt->payload_space) {
+                                       tech_pvt->payload_space++;
+                               }
+                               if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) &&
+                                       tech_pvt->cng_pt && use_cng  && tech_pvt->cng_pt == tech_pvt->payload_space) {
+                                       tech_pvt->payload_space++;
+                               }
+                               tech_pvt->ianacodes[i] = tech_pvt->payload_space++;
+                       }
+               }
+       }
+
+       if (fmtp_out_var) {
+               fmtp_out = fmtp_out_var;
+       }
+
+       if ((val = switch_channel_get_variable(tech_pvt->channel, "verbose_sdp")) && switch_true(val)) {
+               verbose_sdp = 1;
+       }
+
+       if (!force && !ip && zstr(sr)
+               && (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) || switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA))) {
+               switch_safe_free(buf);
+               return;
+       }
+
+       if (!ip) {
+               if (!(ip = tech_pvt->adv_sdp_audio_ip)) {
+                       ip = tech_pvt->proxy_sdp_audio_ip;
+               }
+       }
+
+       if (!ip) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s NO IP!\n", switch_channel_get_name(tech_pvt->channel));
+               switch_safe_free(buf);
+               return;
+       }
+
+       if (!port) {
+               if (!(port = tech_pvt->adv_sdp_audio_port)) {
+                       port = tech_pvt->proxy_sdp_audio_port;
+               }
+       }
+
+       if (!port) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s NO PORT!\n", switch_channel_get_name(tech_pvt->channel));
+               switch_safe_free(buf);
+               return;
+       }
+
+       if (!tech_pvt->rm_encoding && (b_sdp = switch_channel_get_variable(tech_pvt->channel, SWITCH_B_SDP_VARIABLE))) {
+               sofia_glue_sdp_map(b_sdp, &map, &ptmap);
+       }
+
+       if (zstr(sr)) {
+               if ((var_val = switch_channel_get_variable(tech_pvt->channel, "media_audio_mode"))) {
+                       sr = var_val;
+               } else {
+                       sr = "sendrecv";
+               }
+       }
+
+       if (!tech_pvt->owner_id) {
+               tech_pvt->owner_id = (uint32_t) switch_epoch_time_now(NULL) - port;
+       }
+
+       if (!tech_pvt->session_id) {
+               tech_pvt->session_id = tech_pvt->owner_id;
+       }
+
+       if (switch_true(switch_channel_get_variable_dup(tech_pvt->channel, "drop_dtmf", SWITCH_FALSE, -1))) {
+               sofia_set_flag(tech_pvt, TFLAG_DROP_DTMF);
+       }
+
+       tech_pvt->session_id++;
+
+       if ((tech_pvt->profile->ndlb & PFLAG_NDLB_SENDRECV_IN_SESSION) ||
+               ((var_val = switch_channel_get_variable(tech_pvt->channel, "ndlb_sendrecv_in_session")) && switch_true(var_val))) {
+               if (!zstr(sr)) {
+                       switch_snprintf(srbuf, sizeof(srbuf), "a=%s\n", sr);
+               }
+               sr = NULL;
+       }
+
+       family = strchr(ip, ':') ? "IP6" : "IP4";
+       switch_snprintf(buf, SDPBUFLEN,
+                                       "v=0\n"
+                                       "o=%s %010u %010u IN %s %s\n"
+                                       "s=%s\n"
+                                       "c=IN %s %s\n" "t=0 0\n"
+                                       "%s",
+                                       username, tech_pvt->owner_id, tech_pvt->session_id, family, ip, username, family, ip, srbuf);
+
+       if (tech_pvt->rm_encoding) {
+               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio %d RTP/%sAVP", 
+                                               port, (!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) ? "S" : "");
+
+               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->pt);
+
+               if ((tech_pvt->dtmf_type == DTMF_2833 || sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF)) && tech_pvt->te > 95) {
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->te);
+               }
+               
+               if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && tech_pvt->cng_pt && use_cng) {
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->cng_pt);
+               }
+               
+               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n");
+
+               rate = tech_pvt->rm_rate;
+               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", tech_pvt->agreed_pt, tech_pvt->rm_encoding, rate);
+               if (fmtp_out) {
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->agreed_pt, fmtp_out);
+               }
+
+               if (tech_pvt->read_codec.implementation && !ptime) {
+                       ptime = tech_pvt->read_codec.implementation->microseconds_per_packet / 1000;
+               }
+
+
+               if ((tech_pvt->dtmf_type == DTMF_2833 || sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || sofia_test_flag(tech_pvt, TFLAG_LIBERAL_DTMF))
+                       && tech_pvt->te > 95) {
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/8000\na=fmtp:%d 0-16\n", tech_pvt->te, tech_pvt->te);
+               }
+               if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && tech_pvt->cng_pt && use_cng) {
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d CN/8000\n", tech_pvt->cng_pt);
+                       if (!tech_pvt->rm_encoding) {
+                               tech_pvt->cng_pt = 0;
+                       }
+               } else {
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=silenceSupp:off - - - -\n");
+               }
+
+               if (append_audio) {
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\n");
+               }
+
+               if (ptime) {
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ptime:%d\n", ptime);
+               }
+
+
+               if (tech_pvt->local_sdp_audio_zrtp_hash) {
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n",
+                                                         tech_pvt->local_sdp_audio_zrtp_hash);
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=zrtp-hash:%s\n",
+                                                       tech_pvt->local_sdp_audio_zrtp_hash);
+               }
+
+               if (!zstr(sr)) {
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=%s\n", sr);
+               }
+       
+               if (!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) {
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_audio_crypto_key);
+                       //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=encryption:optional\n");
+               }
+
+       } else if (tech_pvt->num_codecs) {
+               int i;
+               int cur_ptime = 0, this_ptime = 0, cng_type = 0;
+               const char *mult;
+
+               if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SUPPRESS_CNG) && tech_pvt->cng_pt && use_cng) {
+                       cng_type = tech_pvt->cng_pt;
+
+                       if (!tech_pvt->rm_encoding) {
+                               tech_pvt->cng_pt = 0;
+                       }
+               }
+               
+               mult = switch_channel_get_variable(tech_pvt->channel, "sdp_m_per_ptime");
+               
+               if (mult && switch_false(mult)) {
+                       char *bp = buf;
+                       int both = 1;
+
+                       if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE))) {
+                               generate_m(tech_pvt, buf, SDPBUFLEN, port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
+                               bp = (buf + strlen(buf));
+
+                               /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/
+                               if (switch_true(switch_channel_get_variable(tech_pvt->channel, "sdp_secure_savp_only"))) {
+                                       both = 0;
+                               }
+
+                       }
+
+                       if (both) {
+                               generate_m(tech_pvt, bp, SDPBUFLEN - strlen(buf), port, 0, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0);
+                       }
+
+               } else {
+
+                       for (i = 0; i < tech_pvt->num_codecs; i++) {
+                               const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
+                               
+                               if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
+                                       continue;
+                               }
+                               
+                               this_ptime = imp->microseconds_per_packet / 1000;
+                               
+                               if (!strcasecmp(imp->iananame, "ilbc")) {
+                                       this_ptime = 20;
+                               }
+                               
+                               if (cur_ptime != this_ptime) {
+                                       char *bp = buf;
+                                       int both = 1;
+
+                                       cur_ptime = this_ptime;                 
+                                       
+                                       if ((!zstr(local_audio_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE))) {
+                                               generate_m(tech_pvt, bp, SDPBUFLEN - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 1);
+                                               bp = (buf + strlen(buf));
+
+                                               /* asterisk can't handle AVP and SAVP in sep streams, way to blow off the spec....*/
+                                               if (switch_true(switch_channel_get_variable(tech_pvt->channel, "sdp_secure_savp_only"))) {
+                                                       both = 0;
+                                               }
+                                       }
+
+                                       if (both) {
+                                               generate_m(tech_pvt, bp, SDPBUFLEN - strlen(buf), port, cur_ptime, append_audio, sr, use_cng, cng_type, map, verbose_sdp, 0);
+                                       }
+                               }
+                               
+                       }
+               }
+
+       }
+       
+       if (sofia_test_flag(tech_pvt, TFLAG_VIDEO)) {
+               const char *local_video_crypto_key = switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO);
+               
+               if (!tech_pvt->local_sdp_video_port) {
+                       sofia_glue_tech_choose_video_port(tech_pvt, 0);
+               }
+
+               if ((v_port = tech_pvt->adv_sdp_video_port)) {
+
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video %d RTP/%sAVP", 
+                                                       v_port, (!zstr(local_video_crypto_key) && switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) ? "S" : "");
+
+
+                       /*****************************/
+                       if (tech_pvt->video_rm_encoding) {
+                               sofia_glue_tech_set_video_codec(tech_pvt, 0);
+                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->video_agreed_pt);
+                       } else if (tech_pvt->num_codecs) {
+                               int i;
+                               int already_did[128] = { 0 };
+                               for (i = 0; i < tech_pvt->num_codecs; i++) {
+                                       const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
+
+                                       if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
+                                               continue;
+                                       }
+
+                                       if (tech_pvt->ianacodes[i] < 128) {
+                                               if (already_did[tech_pvt->ianacodes[i]]) {
+                                                       continue;
+                                               }
+                                               already_did[tech_pvt->ianacodes[i]] = 1;
+                                       }
+
+                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", tech_pvt->ianacodes[i]);
+                                       if (!ptime) {
+                                               ptime = imp->microseconds_per_packet / 1000;
+                                       }
+                               }
+                       }
+
+                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\n");
+
+                       if (tech_pvt->video_rm_encoding) {
+                               const char *of;
+                               rate = tech_pvt->video_rm_rate;
+                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n", tech_pvt->video_pt, tech_pvt->video_rm_encoding,
+                                                               tech_pvt->video_rm_rate);
+
+                               if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) {
+                                       pass_fmtp = tech_pvt->video_rm_fmtp;
+                               } else {
+
+                                       pass_fmtp = NULL;
+
+                                       if (switch_channel_get_partner_uuid(tech_pvt->channel)) {
+                                               if ((of = switch_channel_get_variable_partner(tech_pvt->channel, "sip_video_fmtp"))) {
+                                                       pass_fmtp = of;
+                                               }
+                                       }
+
+                                       if (ov_fmtp) {
+                                               pass_fmtp = ov_fmtp;
+                                       }// else { // seems to break eyebeam at least...
+                                               //pass_fmtp = switch_channel_get_variable(tech_pvt->channel, "sip_video_fmtp");
+                                       //}
+                               }
+
+                               if (pass_fmtp) {
+                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", tech_pvt->video_pt, pass_fmtp);
+                               }
+
+                       } else if (tech_pvt->num_codecs) {
+                               int i;
+                               int already_did[128] = { 0 };
+
+                               for (i = 0; i < tech_pvt->num_codecs; i++) {
+                                       const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
+                                       char *fmtp = NULL;
+                                       uint32_t ianacode = tech_pvt->ianacodes[i];
+
+                                       if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
+                                               continue;
+                                       }
+
+                                       if (ianacode < 128) {
+                                               if (already_did[ianacode]) {
+                                                       continue;
+                                               }
+                                               already_did[ianacode] = 1;
+                                       }
+
+                                       if (!rate) {
+                                               rate = imp->samples_per_second;
+                                       }
+                                       
+                                       
+                                       switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\n", ianacode, imp->iananame,
+                                                                       imp->samples_per_second);
+                                       
+                                       if (!zstr(ov_fmtp)) {
+                                               fmtp = (char *) ov_fmtp;
+                                       } else {
+                                       
+                                               if (map) {
+                                                       fmtp = switch_event_get_header(map, imp->iananame);
+                                               }
+                                               
+                                               if (zstr(fmtp)) fmtp = imp->fmtp;
+
+                                               if (zstr(fmtp)) fmtp = (char *) pass_fmtp;
+                                       }
+                                       
+                                       if (!zstr(fmtp) && strcasecmp(fmtp, "_blank_")) {
+                                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", ianacode, fmtp);
+                                       }
+                               }
+                               
+                       }
+
+                       if (switch_channel_test_flag(tech_pvt->channel, CF_SECURE)) {
+                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\n", local_video_crypto_key);
+                               //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\n");
+                       }                       
+
+
+                       if (tech_pvt->local_sdp_video_zrtp_hash) {
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Adding video a=zrtp-hash:%s\n",
+                                                                 tech_pvt->local_sdp_video_zrtp_hash);
+                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=zrtp-hash:%s\n",
+                                                               tech_pvt->local_sdp_video_zrtp_hash);
+                       }
+               }
+       }
+
+
+       if (map) {
+               switch_event_destroy(&map);
+       }
+       
+       if (ptmap) {
+               switch_event_destroy(&ptmap);
+       }
+
+       sofia_glue_tech_set_local_sdp(tech_pvt, buf, SWITCH_TRUE);
+
+       switch_safe_free(buf);
+}
+
+const char *sofia_glue_get_codec_string(private_object_t *tech_pvt)
+{
+       const char *preferred = NULL, *fallback = NULL;
+       
+       if (!(preferred = switch_channel_get_variable(tech_pvt->channel, "absolute_codec_string"))) {
+               preferred = switch_channel_get_variable(tech_pvt->channel, "codec_string");
+       }
+       
+       if (!preferred) {
+               if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
+                       preferred = tech_pvt->profile->outbound_codec_string;
+                       fallback = tech_pvt->profile->inbound_codec_string;
+               } else {
+                       preferred = tech_pvt->profile->inbound_codec_string;
+                       fallback = tech_pvt->profile->outbound_codec_string;
+               }
+       }
+
+       return !zstr(preferred) ? preferred : fallback;
+}
+
+void sofia_glue_tech_prepare_codecs(private_object_t *tech_pvt)
+{
+       const char *abs, *codec_string = NULL;
+       const char *ocodec = NULL;
+
+       if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) || switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
+               return;
+       }
+
+       if (tech_pvt->num_codecs) {
+               return;
+       }
+
+       tech_pvt->payload_space = 0;
+
+       switch_assert(tech_pvt->session != NULL);
+
+       if ((abs = switch_channel_get_variable(tech_pvt->channel, "absolute_codec_string"))) {
+               /* inherit_codec == true will implicitly clear the absolute_codec_string 
+                  variable if used since it was the reason it was set in the first place and is no longer needed */
+               if (switch_true(switch_channel_get_variable(tech_pvt->channel, "inherit_codec"))) {
+                       switch_channel_set_variable(tech_pvt->channel, "absolute_codec_string", NULL);
+               }
+               codec_string = abs;
+               goto ready;
+       }
+
+       if (!(codec_string = switch_channel_get_variable(tech_pvt->channel, "codec_string"))) {
+               codec_string = sofia_glue_get_codec_string(tech_pvt);
+       }
+
+       if (codec_string && *codec_string == '=') {
+               codec_string++;
+               goto ready;
+       }
+
+
+       if ((ocodec = switch_channel_get_variable(tech_pvt->channel, SWITCH_ORIGINATOR_CODEC_VARIABLE))) {
+               if (!codec_string || sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_TRANSCODING)) {
+                       codec_string = ocodec;
+               } else {
+                       if (!(codec_string = switch_core_session_sprintf(tech_pvt->session, "%s,%s", ocodec, codec_string))) {
+                               codec_string = ocodec;
+                       }
+               }
+       }
+
+ ready:
+
+       if (codec_string) {
+               char *tmp_codec_string;
+               if ((tmp_codec_string = switch_core_session_strdup(tech_pvt->session, codec_string))) {
+                       tech_pvt->codec_order_last = switch_separate_string(tmp_codec_string, ',', tech_pvt->codec_order, SWITCH_MAX_CODECS);
+                       tech_pvt->num_codecs =
+                               switch_loadable_module_get_codecs_sorted(tech_pvt->codecs, SWITCH_MAX_CODECS, tech_pvt->codec_order, tech_pvt->codec_order_last);
+               }
+       } else {
+               tech_pvt->num_codecs = switch_loadable_module_get_codecs(tech_pvt->codecs, sizeof(tech_pvt->codecs) / sizeof(tech_pvt->codecs[0]));
+       }
+
+
+}
+
+void sofia_glue_check_video_codecs(private_object_t *tech_pvt)
+{
+       if (tech_pvt->num_codecs && !sofia_test_flag(tech_pvt, TFLAG_VIDEO)) {
+               int i;
+               tech_pvt->video_count = 0;
+               for (i = 0; i < tech_pvt->num_codecs; i++) {
+                       
+                       if (tech_pvt->codecs[i]->codec_type == SWITCH_CODEC_TYPE_VIDEO) {
+                               tech_pvt->video_count++;
+                       }
+               }
+               if (tech_pvt->video_count) {
+                       sofia_set_flag_locked(tech_pvt, TFLAG_VIDEO);
+               }
+       }
+}
+
+
+void sofia_glue_tech_patch_sdp(private_object_t *tech_pvt)
+{
+       switch_size_t len;
+       char *p, *q, *pe, *qe;
+       int has_video = 0, has_audio = 0, has_ip = 0;
+       char port_buf[25] = "";
+       char vport_buf[25] = "";
+       char *new_sdp;
+       int bad = 0;
+
+       if (zstr(tech_pvt->local_sdp_str)) {
+               return;
+       }
+
+       len = strlen(tech_pvt->local_sdp_str) * 2;
+
+       if (switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED) &&
+               (switch_stristr("sendonly", tech_pvt->local_sdp_str) || switch_stristr("0.0.0.0", tech_pvt->local_sdp_str))) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Skip patch on hold SDP\n");
+               return;
+       }
+
+       if (zstr(tech_pvt->adv_sdp_audio_ip) || !tech_pvt->adv_sdp_audio_port) {
+               if (sofia_glue_tech_choose_port(tech_pvt, 1) != SWITCH_STATUS_SUCCESS) {
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "%s I/O Error\n",
+                                                         switch_channel_get_name(tech_pvt->channel));
+                       return;
+               }
+               tech_pvt->iananame = switch_core_session_strdup(tech_pvt->session, "PROXY");
+               tech_pvt->rm_rate = 8000;
+               tech_pvt->codec_ms = 20;
+       }
+
+       new_sdp = switch_core_session_alloc(tech_pvt->session, len);
+       switch_snprintf(port_buf, sizeof(port_buf), "%u", tech_pvt->adv_sdp_audio_port);
+
+
+       p = tech_pvt->local_sdp_str;
+       q = new_sdp;
+       pe = p + strlen(p);
+       qe = q + len - 1;
+
+
+       while (p && *p) {
+               if (p >= pe) {
+                       bad = 1;
+                       goto end;
+               }
+
+               if (q >= qe) {
+                       bad = 2;
+                       goto end;
+               }
+
+               if (tech_pvt->adv_sdp_audio_ip && !strncmp("c=IN IP", p, 7)) {
+                       strncpy(q, p, 7);
+                       p += 7;
+                       q += 7;
+                       strncpy(q, strchr(tech_pvt->adv_sdp_audio_ip, ':') ? "6 " : "4 ", 2);
+                       p +=2;
+                       q +=2;                  
+                       strncpy(q, tech_pvt->adv_sdp_audio_ip, strlen(tech_pvt->adv_sdp_audio_ip));
+                       q += strlen(tech_pvt->adv_sdp_audio_ip);
+
+                       while (p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f'))) {
+                               if (p >= pe) {
+                                       bad = 3;
+                                       goto end;
+                               }
+                               p++;
+                       }
+
+                       has_ip++;
+
+               } else if (!strncmp("o=", p, 2)) {
+                       char *oe = strchr(p, '\n');
+                       switch_size_t len;
+
+                       if (oe) {
+                               const char *family = "IP4";
+                               char o_line[1024] = "";
+
+                               if (oe >= pe) {
+                                       bad = 5;
+                                       goto end;
+                               }
+
+                               len = (oe - p);
+                               p += len;
+
+
+                               family = strchr(tech_pvt->profile->sipip, ':') ? "IP6" : "IP4";
+
+                               if (!tech_pvt->owner_id) {
+                                       tech_pvt->owner_id = (uint32_t) switch_epoch_time_now(NULL) * 31821U + 13849U;
+                               }
+
+                               if (!tech_pvt->session_id) {
+                                       tech_pvt->session_id = tech_pvt->owner_id;
+                               }
+
+                               tech_pvt->session_id++;
+
+
+                               snprintf(o_line, sizeof(o_line), "o=%s %010u %010u IN %s %s\n",
+                                                tech_pvt->profile->username, tech_pvt->owner_id, tech_pvt->session_id, family, tech_pvt->profile->sipip);
+
+                               strncpy(q, o_line, strlen(o_line));
+                               q += strlen(o_line) - 1;
+
+                       }
+
+               } else if (!strncmp("s=", p, 2)) {
+                       char *se = strchr(p, '\n');
+                       switch_size_t len;
+
+                       if (se) {
+                               char s_line[1024] = "";
+
+                               if (se >= pe) {
+                                       bad = 5;
+                                       goto end;
+                               }
+
+                               len = (se - p);
+                               p += len;
+
+                               snprintf(s_line, sizeof(s_line), "s=%s\n", tech_pvt->profile->username);
+
+                               strncpy(q, s_line, strlen(s_line));
+                               q += strlen(s_line) - 1;
+
+                       }
+
+               } else if ((!strncmp("m=audio ", p, 8) && *(p + 8) != '0') || (!strncmp("m=image ", p, 8) && *(p + 8) != '0')) {
+                       strncpy(q, p, 8);
+                       p += 8;
+
+                       if (p >= pe) {
+                               bad = 4;
+                               goto end;
+                       }
+
+
+                       q += 8;
+
+                       if (q >= qe) {
+                               bad = 5;
+                               goto end;
+                       }
+
+
+                       strncpy(q, port_buf, strlen(port_buf));
+                       q += strlen(port_buf);
+
+                       if (q >= qe) {
+                               bad = 6;
+                               goto end;
+                       }
+
+                       while (p && *p && (*p >= '0' && *p <= '9')) {
+                               if (p >= pe) {
+                                       bad = 7;
+                                       goto end;
+                               }
+                               p++;
+                       }
+
+                       has_audio++;
+
+               } else if (!strncmp("m=video ", p, 8) && *(p + 8) != '0') {
+                       if (!has_video) {
+                               sofia_glue_tech_choose_video_port(tech_pvt, 1);
+                               tech_pvt->video_rm_encoding = "PROXY-VID";
+                               tech_pvt->video_rm_rate = 90000;
+                               tech_pvt->video_codec_ms = 0;
+                               switch_snprintf(vport_buf, sizeof(vport_buf), "%u", tech_pvt->adv_sdp_video_port);
+                               if (switch_channel_media_ready(tech_pvt->channel) && !switch_rtp_ready(tech_pvt->video_rtp_session)) {
+                                       sofia_set_flag(tech_pvt, TFLAG_VIDEO);
+                                       sofia_set_flag(tech_pvt, TFLAG_REINVITE);
+                                       sofia_media_activate_rtp(tech_pvt);
+                               }
+                       }
+
+                       strncpy(q, p, 8);
+                       p += 8;
+
+                       if (p >= pe) {
+                               bad = 8;
+                               goto end;
+                       }
+
+                       q += 8;
+
+                       if (q >= qe) {
+                               bad = 9;
+                               goto end;
+                       }
+
+                       strncpy(q, vport_buf, strlen(vport_buf));
+                       q += strlen(vport_buf);
+
+                       if (q >= qe) {
+                               bad = 10;
+                               goto end;
+                       }
+
+                       while (p && *p && (*p >= '0' && *p <= '9')) {
+
+                               if (p >= pe) {
+                                       bad = 11;
+                                       goto end;
+                               }
+
+                               p++;
+                       }
+
+                       has_video++;
+               }
+
+               while (p && *p && *p != '\n') {
+
+                       if (p >= pe) {
+                               bad = 12;
+                               goto end;
+                       }
+
+                       if (q >= qe) {
+                               bad = 13;
+                               goto end;
+                       }
+
+                       *q++ = *p++;
+               }
+
+               if (p >= pe) {
+                       bad = 14;
+                       goto end;
+               }
+
+               if (q >= qe) {
+                       bad = 15;
+                       goto end;
+               }
+
+               *q++ = *p++;
+
+       }
+
+ end:
+
+       if (bad) {
+               return;
+       }
+
+
+       if (switch_channel_down(tech_pvt->channel) || sofia_test_flag(tech_pvt, TFLAG_BYE)) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%s too late.\n", switch_channel_get_name(tech_pvt->channel));
+               return;
+       }
+
+
+       if (!has_ip && !has_audio) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%s SDP has no audio in it.\n%s\n",
+                                                 switch_channel_get_name(tech_pvt->channel), tech_pvt->local_sdp_str);
+               return;
+       }
+
+
+       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%s Patched SDP\n---\n%s\n+++\n%s\n",
+                                         switch_channel_get_name(tech_pvt->channel), tech_pvt->local_sdp_str, new_sdp);
+
+       sofia_glue_tech_set_local_sdp(tech_pvt, new_sdp, SWITCH_FALSE);
+
+}
+
+
+void sofia_glue_tech_set_local_sdp(private_object_t *tech_pvt, const char *sdp_str, switch_bool_t dup)
+{
+       switch_mutex_lock(tech_pvt->sofia_mutex);
+       tech_pvt->local_sdp_str = dup ? switch_core_session_strdup(tech_pvt->session, sdp_str) : (char *) sdp_str;
+       switch_channel_set_variable(tech_pvt->channel, "sip_local_sdp_str", tech_pvt->local_sdp_str);
+       switch_mutex_unlock(tech_pvt->sofia_mutex);
+}
+
+
+char *sofia_glue_get_multipart(switch_core_session_t *session, const char *prefix, const char *sdp, char **mp_type)
+{
+       char *extra_headers = NULL;
+       switch_stream_handle_t stream = { 0 };
+       switch_event_header_t *hi = NULL;
+       int x = 0;
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       const char *boundary = switch_core_session_get_uuid(session);
+
+       SWITCH_STANDARD_STREAM(stream);
+       if ((hi = switch_channel_variable_first(channel))) {
+               for (; hi; hi = hi->next) {
+                       const char *name = (char *) hi->name;
+                       char *value = (char *) hi->value;
+
+                       if (!strncasecmp(name, prefix, strlen(prefix))) {
+                               const char *hname = name + strlen(prefix);
+                               if (*value == '~') {
+                                       stream.write_function(&stream, "--%s\nContent-Type: %s\nContent-Length: %d\n%s\n", boundary, hname, strlen(value), value + 1);
+                               } else {
+                                       stream.write_function(&stream, "--%s\nContent-Type: %s\nContent-Length: %d\n\n%s\n", boundary, hname, strlen(value) + 1, value);
+                               }
+                               x++;
+                       }
+               }
+               switch_channel_variable_last(channel);
+       }
+
+       if (x) {
+               *mp_type = switch_core_session_sprintf(session, "multipart/mixed; boundary=%s", boundary);
+               if (sdp) {
+                       stream.write_function(&stream, "--%s\nContent-Type: application/sdp\nContent-Length: %d\n\n%s\n", boundary, strlen(sdp) + 1, sdp);
+               }
+               stream.write_function(&stream, "--%s--\n", boundary);
+       }
+
+       if (!zstr((char *) stream.data)) {
+               extra_headers = stream.data;
+       } else {
+               switch_safe_free(stream.data);
+       }
+
+       return extra_headers;
+}
+
+
+
+
 
 /* For Emacs:
  * Local Variables: