diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c
index b15a4ce15c..c3707f5ae3 100644
--- a/src/mod/endpoints/mod_sofia/sofia_glue.c
+++ b/src/mod/endpoints/mod_sofia/sofia_glue.c
@@ -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)
 {
@@ -1693,336 +985,6 @@ switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt, co
 }
 
 
-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;
-}
-
 
 char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix)
 {
@@ -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)
 {
diff --git a/src/mod/endpoints/mod_sofia/sofia_media.c b/src/mod/endpoints/mod_sofia/sofia_media.c
index 738f27cb12..9d0ff64d0d 100644
--- a/src/mod/endpoints/mod_sofia/sofia_media.c
+++ b/src/mod/endpoints/mod_sofia/sofia_media.c
@@ -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: