diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index d77014dd3f..ff2ddd269d 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -2555,6 +2555,7 @@ SWITCH_DECLARE(int) switch_core_gen_certs(const char *prefix);
 SWITCH_DECLARE(int) switch_core_cert_gen_fingerprint(const char *prefix, dtls_fingerprint_t *fp);
 SWITCH_DECLARE(int) switch_core_cert_expand_fingerprint(dtls_fingerprint_t *fp, const char *str);
 SWITCH_DECLARE(int) switch_core_cert_verify(dtls_fingerprint_t *fp);
+SWITCH_DECLARE(switch_status_t) switch_core_session_refresh_video(switch_core_session_t *session);
 
 SWITCH_END_EXTERN_C
 #endif
diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h
index 9f15ecd50a..6379a88e6f 100644
--- a/src/include/switch_core_media.h
+++ b/src/include/switch_core_media.h
@@ -255,6 +255,7 @@ SWITCH_DECLARE(void) switch_core_session_set_ice(switch_core_session_t *session)
 SWITCH_DECLARE(void) switch_core_media_init(void);
 SWITCH_DECLARE(void) switch_core_media_deinit(void);
 SWITCH_DECLARE(void) switch_core_media_set_stats(switch_core_session_t *session);
+SWITCH_DECLARE(void) switch_core_session_wake_video_thread(switch_core_session_t *session);
 
 SWITCH_END_EXTERN_C
 #endif
diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h
index 16c7eef86b..38ac6ed2a4 100644
--- a/src/include/switch_rtp.h
+++ b/src/include/switch_rtp.h
@@ -500,9 +500,6 @@ SWITCH_DECLARE(void) switch_rtp_set_cng_pt(switch_rtp_t *rtp_session, switch_pay
 */
 SWITCH_DECLARE(void *) switch_rtp_get_private(switch_rtp_t *rtp_session);
 
-SWITCH_DECLARE(switch_status_t) switch_rtp_activate_stun_ping(switch_rtp_t *rtp_session, const char *stun_ip, switch_port_t stun_port,
-															  uint32_t packet_count, switch_bool_t funny);
-
 SWITCH_DECLARE(void) switch_rtp_intentional_bugs(switch_rtp_t *rtp_session, switch_rtp_bug_flag_t bugs);
 
 SWITCH_DECLARE(switch_rtp_stats_t *) switch_rtp_get_stats(switch_rtp_t *rtp_session, switch_memory_pool_t *pool);
@@ -512,6 +509,7 @@ SWITCH_DECLARE(void) switch_rtp_set_interdigit_delay(switch_rtp_t *rtp_session,
 SWITCH_DECLARE(switch_status_t) switch_rtp_add_dtls(switch_rtp_t *rtp_session, dtls_fingerprint_t *local_fp, dtls_fingerprint_t *remote_fp, dtls_type_t type);
 
 SWITCH_DECLARE(int) switch_rtp_has_dtls(void);
+SWITCH_DECLARE(void) switch_rtp_video_refresh(switch_rtp_t *rtp_session);
 
 /*!
   \}
diff --git a/src/include/switch_types.h b/src/include/switch_types.h
index aced028682..7c24a81378 100644
--- a/src/include/switch_types.h
+++ b/src/include/switch_types.h
@@ -1324,6 +1324,7 @@ typedef enum {
 	CF_DTLS,
 	CF_VERBOSE_SDP,
 	CF_DTLS_OK,
+	CF_VIDEO_PASSIVE,
 	/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
 	/* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */
 	CF_FLAG_MAX
diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c
index ce5dec977c..f282a8b266 100644
--- a/src/mod/applications/mod_conference/mod_conference.c
+++ b/src/mod/applications/mod_conference/mod_conference.c
@@ -1443,7 +1443,10 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
 
 		conference_send_presence(conference);
 
+
+
 		channel = switch_core_session_get_channel(member->session);
+		switch_channel_set_flag(channel, CF_VIDEO_PASSIVE);
 		switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id);
 		switch_channel_set_variable_printf(channel, "conference_moderator", "%s", switch_test_flag(member, MFLAG_MOD) ? "true" : "false");
 		switch_channel_set_variable(channel, "conference_recording", conference->record_filename);
@@ -1670,6 +1673,7 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
 			}
 		}
 
+		switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
 
 		conference_send_presence(conference);
 		switch_channel_set_variable(channel, "conference_call_key", NULL);
diff --git a/src/mod/applications/mod_fsv/mod_fsv.c b/src/mod/applications/mod_fsv/mod_fsv.c
index 8eecd58e1e..20f09a4851 100644
--- a/src/mod/applications/mod_fsv/mod_fsv.c
+++ b/src/mod/applications/mod_fsv/mod_fsv.c
@@ -116,6 +116,8 @@ SWITCH_STANDARD_APP(record_fsv_function)
 	int count = 0, sanity = 30;
 	switch_core_session_message_t msg = { 0 };
 
+	switch_channel_set_flag(channel, CF_VIDEO_PASSIVE);
+
 	/* Tell the channel to request a fresh vid frame */
 	msg.from = __FILE__;
 	msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
@@ -138,7 +140,7 @@ SWITCH_STANDARD_APP(record_fsv_function)
 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s timeout waiting for video.\n", 
 								  switch_channel_get_name(channel));
 				switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Got timeout while waiting for video");
-				return;
+				goto done;
 			}
 		}
 	}
@@ -146,13 +148,13 @@ SWITCH_STANDARD_APP(record_fsv_function)
 	if (!switch_channel_ready(channel)) {
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s not ready.\n", switch_channel_get_name(channel));
 		switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Channel not ready");
-		return;
+		goto done;
 	}
 
 	if ((fd = open((char *) data, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR)) < 0) {
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error opening file %s\n", (char *) data);
 		switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Got error while opening file");
-		return;
+		goto done;
 	}
 
 	if (switch_core_codec_init(&codec,
@@ -284,6 +286,10 @@ SWITCH_STANDARD_APP(record_fsv_function)
 	switch_core_session_set_read_codec(session, NULL);
 	switch_core_codec_destroy(&codec);
 
+ done:
+
+	switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
+
 }
 
 SWITCH_STANDARD_APP(play_fsv_function)
@@ -306,6 +312,8 @@ SWITCH_STANDARD_APP(play_fsv_function)
 	switch_codec_implementation_t read_impl = { 0 };
 	switch_core_session_message_t msg = { 0 };
 
+	switch_channel_set_flag(channel, CF_VIDEO_PASSIVE);
+
 	/* Tell the channel to request a fresh vid frame */
 	msg.from = __FILE__;
 	msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
@@ -322,7 +330,7 @@ SWITCH_STANDARD_APP(play_fsv_function)
 	if ((fd = open((char *) data, O_RDONLY | O_BINARY)) < 0) {
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Error opening file %s\n", (char *) data);
 		switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "Got error while opening file");
-		return;
+		goto done;
 	}
 
 	if (read(fd, &h, sizeof(h)) != sizeof(h)) {
@@ -504,6 +512,9 @@ SWITCH_STANDARD_APP(play_fsv_function)
 	if (fd > -1) {
 		close(fd);
 	}
+
+ done:
+	switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
 }
 
 struct fsv_file_context {
diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c
index 0e21566aef..761d4ea5c0 100644
--- a/src/mod/endpoints/mod_sofia/mod_sofia.c
+++ b/src/mod/endpoints/mod_sofia/mod_sofia.c
@@ -1279,7 +1279,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
 			}
 
 			nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("application/media_control+xml"), SIPTAG_PAYLOAD_STR(pl), TAG_END());
-
+			
 		}
 		break;
 	case SWITCH_MESSAGE_INDICATE_BROADCAST:
diff --git a/src/switch_channel.c b/src/switch_channel.c
index 8d98caa635..c4812f47a3 100644
--- a/src/switch_channel.c
+++ b/src/switch_channel.c
@@ -1922,6 +1922,11 @@ SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch
 	if (flag == CF_RECOVERED) {
 		switch_channel_set_variable(channel, "recovered", NULL);
 	}
+
+	if (flag == CF_VIDEO_PASSIVE) {
+		switch_core_session_wake_video_thread(channel->session);
+	}
+
 }
 
 
diff --git a/src/switch_core_media.c b/src/switch_core_media.c
index 6da434a82f..d456d58585 100644
--- a/src/switch_core_media.c
+++ b/src/switch_core_media.c
@@ -98,6 +98,13 @@ typedef struct codec_params_s {
 
 } codec_params_t;
 
+struct media_helper {
+	switch_core_session_t *session;
+	switch_thread_cond_t *cond;
+	switch_mutex_t *cond_mutex;
+	int up;
+};
+
 typedef struct switch_rtp_engine_s {
 	switch_secure_settings_t ssec;
 	switch_media_type_t type;
@@ -147,7 +154,8 @@ typedef struct switch_rtp_engine_s {
 	char *remote_rtcp_ice_addr;
 	switch_port_t remote_rtcp_ice_port;
 
-
+	struct media_helper mh;
+	switch_thread_t *media_thread;
 
 } switch_rtp_engine_t;
 
@@ -508,7 +516,6 @@ SWITCH_DECLARE(const char *) switch_core_session_local_crypto_key(switch_core_se
 	}
 
 	return session->media_handle->engines[type].ssec.local_crypto_key;
-
 }
 
 
@@ -2133,6 +2140,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, 
 						  "setting remote %s ice addr to %s:%d based on candidate\n", type2str(type),
 						  engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port);
+		engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
 
 		engine->remote_rtp_ice_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
 		engine->remote_rtp_ice_addr = switch_core_session_strdup(smh->session, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
@@ -2157,7 +2165,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
 	}
 
 
-	if (!got_rtcp_mux) {
+	if (m && !got_rtcp_mux) {
 		engine->rtcp_mux = -1;
 	}
 
@@ -2179,8 +2187,8 @@ SWITCH_DECLARE(void) switch_core_session_set_ice(switch_core_session_t *session)
 	switch_channel_set_flag(session->channel, CF_VERBOSE_SDP);
 	switch_channel_set_flag(session->channel, CF_WEBRTC);
 	switch_channel_set_flag(session->channel, CF_ICE);
-	smh->mparams->rtcp_audio_interval_msec = "5000";
-	smh->mparams->rtcp_video_interval_msec = "5000";
+	smh->mparams->rtcp_audio_interval_msec = "10000";
+	smh->mparams->rtcp_video_interval_msec = "10000";
 }
 
 //?
@@ -2376,6 +2384,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
 	switch_core_media_pass_zrtp_hash(session);
 
 	check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, sdp, NULL);
+	check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, NULL);
 
 	for (m = sdp->sdp_media; m; m = m->m_next) {
 		sdp_connection_t *connection;
@@ -2945,7 +2954,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
 					if (!strcasecmp(attr->a_name, "framerate") && attr->a_value) {
 						//framerate = atoi(attr->a_value);
 					}
-					if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
+					if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value && !strcmp(attr->a_value, "1")) {
 						switch_channel_set_variable(session->channel, "rtp_remote_video_rtcp_port", attr->a_value);
 						v_engine->remote_rtcp_port = (switch_port_t)atoi(attr->a_value);
 					} else if (!got_video_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
@@ -3038,7 +3047,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
 						if (!match && vmatch) match = 1;
 
 						check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, m);
-						check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, NULL);
+						//check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, NULL);
 						break;
 					} else {
 						vmatch = 0;
@@ -3562,6 +3571,14 @@ SWITCH_DECLARE(void) switch_core_media_deactivate_rtp(switch_core_session_t *ses
 	a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
 	v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
 
+	if (v_engine->media_thread) {
+		switch_status_t st;
+		switch_channel_clear_flag(session->channel, CF_VIDEO_PASSIVE);
+		
+		v_engine->mh.up = 0;
+		switch_thread_join(&st, v_engine->media_thread);
+		v_engine->media_thread = NULL;
+	}
 
 	if (v_engine->rtp_session) {
 		switch_rtp_destroy(&v_engine->rtp_session);
@@ -3608,7 +3625,7 @@ static void gen_ice(switch_core_session_t *session, switch_media_type_t type, co
 	engine = &smh->engines[type];
 
 #ifdef RTCP_MUX
-	if (!engine->rtcp_mux && type == SWITCH_MEDIA_TYPE_AUDIO) {
+	if (!engine->rtcp_mux) {//  && type == SWITCH_MEDIA_TYPE_AUDIO) {
 		engine->rtcp_mux = SWITCH_TRUE;
 	}
 #endif
@@ -3665,6 +3682,100 @@ static void gen_ice(switch_core_session_t *session, switch_media_type_t type, co
 
 }
 
+SWITCH_DECLARE(void) switch_core_session_wake_video_thread(switch_core_session_t *session)
+{
+	switch_media_handle_t *smh;
+	switch_rtp_engine_t *v_engine; 
+
+	if (!(smh = session->media_handle)) {
+		return;
+	}
+
+	v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
+
+	if (!v_engine->rtp_session) {
+		return;
+	}
+
+	if (switch_mutex_trylock(v_engine->mh.cond_mutex) == SWITCH_STATUS_SUCCESS) {
+		switch_thread_cond_broadcast(v_engine->mh.cond);
+		switch_mutex_unlock(v_engine->mh.cond_mutex);
+	}
+}
+
+static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, void *obj)
+{
+	struct media_helper *mh = obj;
+	switch_core_session_t *session = mh->session;
+	switch_channel_t *channel = switch_core_session_get_channel(session);
+	switch_status_t status;
+	switch_frame_t *read_frame;
+	switch_media_handle_t *smh;
+
+	if (!(smh = session->media_handle)) {
+		return NULL;
+	}
+
+	switch_core_session_read_lock(session);
+
+	mh->up = 1;
+	switch_mutex_lock(mh->cond_mutex);
+
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread started\n", switch_channel_get_name(session->channel));
+	switch_core_session_refresh_video(session);
+	
+	while (switch_channel_up_nosig(channel)) {
+
+		if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE)) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread paused\n", switch_channel_get_name(session->channel));
+			switch_thread_cond_wait(mh->cond, mh->cond_mutex);
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread resumed\n", switch_channel_get_name(session->channel));
+			switch_core_session_refresh_video(session);
+		}
+
+		if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE)) {
+			continue;
+		}
+
+		if (!switch_channel_media_up(session->channel)) {
+			switch_yield(10000);
+			continue;
+		}
+
+		
+		status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
+		
+		
+		if (!SWITCH_READ_ACCEPTABLE(status)) {
+			switch_cond_next();
+			continue;
+		}
+		
+
+		if (switch_channel_test_flag(channel, CF_VIDEO_REFRESH_REQ)) {
+			switch_core_session_refresh_video(session);
+			switch_channel_clear_flag(channel, CF_VIDEO_REFRESH_REQ);
+		}
+
+		if (switch_test_flag(read_frame, SFF_CNG)) {
+			continue;
+		}
+
+		switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
+
+	}
+
+
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread ended\n", switch_channel_get_name(session->channel));
+
+	switch_mutex_unlock(mh->cond_mutex);
+	switch_core_session_rwunlock(session);
+
+	mh->up = 0;
+	return NULL;
+}
+
+
 
 
 //?
@@ -3902,7 +4013,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 		uint8_t vad_in = (smh->mparams->vflags & VAD_IN);
 		uint8_t vad_out = (smh->mparams->vflags & VAD_OUT);
 		uint8_t inb = switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND;
-		uint32_t stun_ping = 0;
 		const char *ssrc;
 
 		//switch_core_media_set_rtp_session(session, SWITCH_MEDIA_TYPE_AUDIO, a_engine->rtp_session);
@@ -3934,17 +4044,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 			vad_out = 0;
 		}
 
-		if ((smh->mparams->stun_flags & STUN_FLAG_SET) && (val = switch_channel_get_variable(session->channel, "rtp_stun_ping"))) {
-			int ival = atoi(val);
-
-			if (ival <= 0) {
-				if (switch_true(val)) {
-					ival = 6;
-				}
-			}
-
-			stun_ping = (ival * a_engine->read_impl.samples_per_second) / a_engine->read_impl.samples_per_packet;
-		}
 
 		a_engine->ssrc = switch_rtp_get_ssrc(a_engine->rtp_session);
 		switch_channel_set_variable_printf(session->channel, "rtp_use_ssrc", "%u", a_engine->ssrc);
@@ -3968,14 +4067,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 							  switch_channel_get_name(switch_core_session_get_channel(session)), vad_in ? "in" : "", vad_out ? "out" : "");
 		}
 
-		if (stun_ping) {
-			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setting stun ping to %s:%d\n", smh->mparams->stun_ip, stun_ping);
-							  
-			switch_rtp_activate_stun_ping(a_engine->rtp_session, smh->mparams->stun_ip, smh->mparams->stun_port, stun_ping,
-										  (smh->mparams->stun_flags & STUN_FLAG_FUNNY) ? 1 : 0);
-		}
-
-
 		
 		if (a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].ready) {
 			
@@ -3991,10 +4082,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 									IPR_RTP,
 #ifdef GOOGLE_ICE
 									ICE_GOOGLE_JINGLE,
-									NULL,
+									NULL
 #else
 									switch_channel_direction(session->channel) == 
-									SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : ICE_VANILLA | ICE_CONTROLLED,
+									SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : (ICE_VANILLA | ICE_CONTROLLED),
 									&a_engine->ice_in
 #endif
 									);
@@ -4018,36 +4109,42 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 				switch_rtp_activate_rtcp(a_engine->rtp_session, -1, remote_rtcp_port, a_engine->rtcp_mux > 0);
 			} else {
 				int interval = atoi(val);
-				if (interval < 100 || interval > 5000) {
+				if (interval < 100 || interval > 500000) {
 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
-									  "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval);
-				} else {
-					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP PORT %d\n", remote_rtcp_port);
-					switch_rtp_activate_rtcp(a_engine->rtp_session, interval, remote_rtcp_port, a_engine->rtcp_mux > 0);
+									  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
+					interval = 10000;
 				}
-			}
 
+				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP PORT %d\n", remote_rtcp_port);
+				switch_rtp_activate_rtcp(a_engine->rtp_session, interval, remote_rtcp_port, a_engine->rtcp_mux > 0);
+				
+			}
 
 			if (a_engine->ice_in.cands[a_engine->ice_in.chosen[1]][1].ready) {
-				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP ICE\n");
+				if (!strcmp(a_engine->ice_in.cands[a_engine->ice_in.chosen[1]][1].con_addr, a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].con_addr)
+					&& a_engine->ice_in.cands[a_engine->ice_in.chosen[1]][1].con_port == a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].con_port) {
+					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Skipping RTCP ICE (Same as RTP)\n");
+				} else {
+					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP ICE\n");
 				
-				switch_rtp_activate_ice(a_engine->rtp_session, 
-										a_engine->ice_in.ufrag,
-										a_engine->ice_out.ufrag,
-										a_engine->ice_out.pwd,
-										a_engine->ice_in.pwd,
-										IPR_RTCP,
+					switch_rtp_activate_ice(a_engine->rtp_session, 
+											a_engine->ice_in.ufrag,
+											a_engine->ice_out.ufrag,
+											a_engine->ice_out.pwd,
+											a_engine->ice_in.pwd,
+											IPR_RTCP,
 #ifdef GOOGLE_ICE
-										ICE_GOOGLE_JINGLE,
-										NULL
+											ICE_GOOGLE_JINGLE,
+											NULL
 #else
-										switch_channel_direction(session->channel) == 
-										SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : ICE_VANILLA | ICE_CONTROLLED,
-										&a_engine->ice_in
+											switch_channel_direction(session->channel) == 
+											SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : (ICE_VANILLA | ICE_CONTROLLED),
+											&a_engine->ice_in
 #endif
 										);
+				}
+				
 			}
-
 		}
 
 		if (!zstr(a_engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(smh->session)) {
@@ -4364,8 +4461,17 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 
 
 			if (switch_rtp_ready(v_engine->rtp_session)) {
+				switch_threadattr_t *thd_attr = NULL;
+				switch_memory_pool_t *pool = switch_core_session_get_pool(session);
+
 				switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->codec_params.agreed_pt);
-				//switch_core_media_set_rtp_session(session, SWITCH_MEDIA_TYPE_VIDEO, v_engine->rtp_session);
+				v_engine->mh.session = session;
+				switch_threadattr_create(&thd_attr, pool);
+				switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+
+				switch_thread_cond_create(&v_engine->mh.cond, pool);
+				switch_mutex_init(&v_engine->mh.cond_mutex, SWITCH_MUTEX_NESTED, pool);
+				switch_thread_create(&v_engine->media_thread, thd_attr, video_helper_thread, &v_engine->mh, switch_core_session_get_pool(session));
 			}
 
 			if (switch_rtp_ready(v_engine->rtp_session)) {
@@ -4378,14 +4484,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 				} else {
 					switch_rtp_set_ssrc(v_engine->rtp_session, v_engine->ssrc);
 				}
-
-
+				
 				if (v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].ready) {
 					
 					gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0);
-					
-					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating Video ICE\n");
 
+					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating Video ICE\n");
+						
 					switch_rtp_activate_ice(v_engine->rtp_session, 
 											v_engine->ice_in.ufrag,
 											v_engine->ice_out.ufrag,
@@ -4396,17 +4501,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 											ICE_GOOGLE_JINGLE,
 											NULL
 #else
-											ICE_VANILLA | ICE_CONTROLLED,
+											switch_channel_direction(session->channel) == 
+											SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : (ICE_VANILLA | ICE_CONTROLLED),
 											&v_engine->ice_in
 #endif
 											);
+						
 					
 				}
 
-
 				if ((val = switch_channel_get_variable(session->channel, "rtcp_video_interval_msec")) || (val = smh->mparams->rtcp_video_interval_msec)) {
 					const char *rport = switch_channel_get_variable(session->channel, "rtp_remote_video_rtcp_port");
 					switch_port_t remote_port = v_engine->remote_rtcp_port;
+
 					if (rport) {
 						remote_port = (switch_port_t)atoi(rport);
 					}
@@ -4415,40 +4522,49 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
 						switch_rtp_activate_rtcp(v_engine->rtp_session, -1, remote_port, v_engine->rtcp_mux > 0);
 					} else {
 						int interval = atoi(val);
-						if (interval < 100 || interval > 5000) {
+						if (interval < 100 || interval > 500000) {
 							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
-											  "Invalid rtcp interval spec [%d] must be between 100 and 5000\n", interval);
-						} else {
-							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP PORT %d\n", remote_port);
-							switch_rtp_activate_rtcp(v_engine->rtp_session, interval, remote_port, v_engine->rtcp_mux > 0);
+											  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
 						}
+						interval = 10000;
+						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP PORT %d mux %d\n", remote_port, v_engine->rtcp_mux);
+						switch_rtp_activate_rtcp(v_engine->rtp_session, interval, remote_port, v_engine->rtcp_mux > 0);
+							
 					}
 					
 
 					if (v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].ready) {
-						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP ICE\n");
-						switch_rtp_activate_ice(v_engine->rtp_session, 
-												v_engine->ice_in.ufrag,
-												v_engine->ice_out.ufrag,
-												v_engine->ice_out.pwd,
-												v_engine->ice_in.pwd,
-												IPR_RTCP,
-#ifdef GOOGLE_ICE
-												ICE_GOOGLE_JINGLE,
-												NULL
-#else
-												switch_channel_direction(session->channel) == 
-												SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : ICE_VANILLA | ICE_CONTROLLED,
-												
-												&v_engine->ice_in
-#endif
-												);
-					}
-					
-				
-				}
-					
 
+						if (!strcmp(v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].con_addr, v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].con_addr)
+							&& v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].con_port == v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].con_port) {
+							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Skipping VIDEO RTCP ICE (Same as VIDEO RTP)\n");
+						} else {
+
+							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP ICE\n");
+							switch_rtp_activate_ice(v_engine->rtp_session, 
+													v_engine->ice_in.ufrag,
+													v_engine->ice_out.ufrag,
+													v_engine->ice_out.pwd,
+													v_engine->ice_in.pwd,
+													IPR_RTCP,
+#ifdef GOOGLE_ICE
+													ICE_GOOGLE_JINGLE,
+													NULL
+#else
+													switch_channel_direction(session->channel) == 
+													SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : (ICE_VANILLA | ICE_CONTROLLED),
+													
+													&v_engine->ice_in
+#endif
+													);
+						
+						
+						
+						}
+				
+					}
+				}
+				
 				if (!zstr(v_engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(smh->session)) {
 					dtls_type_t xtype, 
 						dtype = switch_channel_direction(smh->session->channel) == SWITCH_CALL_DIRECTION_INBOUND ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
@@ -4711,8 +4827,8 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
 		char tmp2[11] = "";
 		uint32_t c1 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 1);
 		uint32_t c2 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 2);
-		uint32_t c3 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 1);
-		uint32_t c4 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 2);
+		//uint32_t c3 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 1);
+		//uint32_t c4 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 2);
 		ice_t *ice_out;
 
 		tmp1[10] = '\0';
@@ -4744,7 +4860,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
 			&& a_engine->codec_params.local_sdp_port != ice_out->cands[0][0].con_port) {
 
 			switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
-							tmp2, ice_out->cands[0][0].transport, c3,
+							tmp2, ice_out->cands[0][0].transport, c2,
 							ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
 							a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port
 							);
@@ -4754,7 +4870,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
 			
 
 			switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\n", 
-							tmp1, ice_out->cands[0][0].transport, c2,
+							tmp1, ice_out->cands[0][0].transport, c1,
 							ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
 							);
 			
@@ -4763,7 +4879,7 @@ static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
 				&& a_engine->codec_params.local_sdp_port != ice_out->cands[0][1].con_port) {
 				
 				switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx raddr %s rport %d generation 0\n", 
-								tmp2, ice_out->cands[0][0].transport, c4,
+								tmp2, ice_out->cands[0][0].transport, c2,
 								ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
 								a_engine->codec_params.local_sdp_ip, a_engine->codec_params.local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
 								);
@@ -4927,6 +5043,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
 	const char *pass_fmtp = switch_channel_get_variable(session->channel, "rtp_video_fmtp");
 	const char *ov_fmtp = switch_channel_get_variable(session->channel, "rtp_force_video_fmtp");
 	const char *append_audio = switch_channel_get_variable(session->channel, "rtp_append_audio_sdp");
+	const char *append_video = switch_channel_get_variable(session->channel, "rtp_append_video_sdp");
 	char srbuf[128] = "";
 	const char *var_val;
 	const char *username;
@@ -4942,6 +5059,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
 	switch_media_handle_t *smh;
 	ice_t *ice_out;
 
+
 	switch_assert(session);
 
 	if (!(smh = session->media_handle)) {
@@ -5468,6 +5586,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
 					switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\n", v_engine->codec_params.pt, pass_fmtp);
 				}
 
+				if (append_video) {
+					switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_video, end_of(append_video) == '\n' ? "" : "\n");
+				}
+
 			} else if (smh->mparams->num_codecs) {
 				int i;
 				int already_did[128] = { 0 };
@@ -6211,6 +6333,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se
 
 	switch (msg->message_id) {
 
+	case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ:
+		{
+			if (v_engine->rtp_session) {
+				switch_rtp_video_refresh(v_engine->rtp_session);
+			}
+		}
+
+		break;
+
 	case SWITCH_MESSAGE_INDICATE_PROXY_MEDIA:
 		{
 			if (switch_rtp_ready(a_engine->rtp_session)) {
diff --git a/src/switch_core_session.c b/src/switch_core_session.c
index 656f8bd058..050069168a 100644
--- a/src/switch_core_session.c
+++ b/src/switch_core_session.c
@@ -2867,6 +2867,22 @@ SWITCH_DECLARE(switch_log_level_t) switch_core_session_get_loglevel(switch_core_
 	return session->loglevel;
 }
 
+SWITCH_DECLARE(switch_status_t) switch_core_session_refresh_video(switch_core_session_t *session)
+{
+	switch_channel_t *channel = switch_core_session_get_channel(session);
+
+	if (switch_channel_test_flag(channel, CF_VIDEO)) {
+		switch_core_session_message_t msg = { 0 };
+		msg.from = __FILE__;
+		msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
+		switch_core_session_receive_message(session, &msg);
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	return SWITCH_STATUS_FALSE;
+}
+
+
 /* For Emacs:
  * Local Variables:
  * mode:c
diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c
index 44ed10ed80..e9353c15cc 100644
--- a/src/switch_core_state_machine.c
+++ b/src/switch_core_state_machine.c
@@ -305,6 +305,7 @@ void switch_core_state_machine_init(switch_memory_pool_t *pool)
 #define STATE_MACRO(__STATE, __STATE_STR)						do {	\
 		midstate = state;												\
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "(%s) State %s\n", switch_channel_get_name(session->channel), __STATE_STR);	\
+		switch_core_session_refresh_video(session);\
 		if (!driver_state_handler->on_##__STATE || (driver_state_handler->on_##__STATE(session) == SWITCH_STATUS_SUCCESS \
 													)) {				\
 			while (do_extra_handlers && (application_state_handler = switch_channel_get_state_handler(session->channel, index++)) != 0) { \
diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c
index 462aff32c7..b7a6c01288 100644
--- a/src/switch_ivr_async.c
+++ b/src/switch_ivr_async.c
@@ -625,52 +625,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_clear(switch_ivr_dmachine_t
 }
 
 
-#ifdef SWITCH_VIDEO_IN_THREADS
-struct echo_helper {
-	switch_core_session_t *session;
-	int up;
-};
-
-static void *SWITCH_THREAD_FUNC echo_video_thread(switch_thread_t *thread, void *obj)
-{
-	struct echo_helper *eh = obj;
-	switch_core_session_t *session = eh->session;
-	switch_channel_t *channel = switch_core_session_get_channel(session);
-	switch_status_t status;
-	switch_frame_t *read_frame;
-	switch_core_session_message_t msg = { 0 };
-
-
-	msg.from = __FILE__;
-	msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
-	
-	switch_core_session_receive_message(session, &msg);
-
-	eh->up = 1;
-	while (switch_channel_ready(channel)) {
-		status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
-
-
-		if (switch_channel_test_flag(channel, CF_VIDEO_REFRESH_REQ)) {
-			switch_core_session_receive_message(session, &msg);
-			switch_channel_clear_flag(channel, CF_VIDEO_REFRESH_REQ);
-		}
-
-		if (!SWITCH_READ_ACCEPTABLE(status)) {
-			break;
-		}
-
-		if (switch_test_flag(read_frame, SFF_CNG)) {
-			continue;
-		}
-
-		switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
-
-	}
-	eh->up = 0;
-	return NULL;
-}
-#endif
 
 SWITCH_DECLARE(switch_status_t) switch_ivr_session_echo(switch_core_session_t *session, switch_input_args_t *args)
 {
@@ -679,12 +633,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_echo(switch_core_session_t *s
 	switch_channel_t *channel = switch_core_session_get_channel(session);
 	int orig_vid = switch_channel_test_flag(channel, CF_VIDEO);
 
-#ifdef SWITCH_VIDEO_IN_THREADS
-	struct echo_helper eh = { 0 };
-	switch_thread_t *thread;
-	switch_threadattr_t *thd_attr = NULL;
-#endif
-
 	if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
 		return SWITCH_STATUS_FALSE;
 	}
@@ -693,16 +641,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_echo(switch_core_session_t *s
 
  restart:
 
-#ifdef SWITCH_VIDEO_IN_THREADS
-	if (switch_channel_test_flag(channel, CF_VIDEO)) {
-		eh.session = session;
-		switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session));
-		switch_threadattr_detach_set(thd_attr, 1);
-		switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
-		switch_thread_create(&thread, thd_attr, echo_video_thread, &eh, switch_core_session_get_pool(session));
-	}
-#endif
-
 	while (switch_channel_ready(channel)) {
 		status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
 		if (!SWITCH_READ_ACCEPTABLE(status)) {
@@ -775,14 +713,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_echo(switch_core_session_t *s
 		}
 	}
 
-#ifdef SWITCH_VIDEO_IN_THREADS
-	if (eh.up) {
-		while (eh.up) {
-			switch_cond_next();
-		}
-	}
-#endif
-
 	return SWITCH_STATUS_SUCCESS;
 }
 
diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c
index 0df636cac5..b06566fb48 100644
--- a/src/switch_ivr_bridge.c
+++ b/src/switch_ivr_bridge.c
@@ -53,25 +53,58 @@ static void *SWITCH_THREAD_FUNC video_bridge_thread(switch_thread_t *thread, voi
 	switch_channel_t *b_channel = switch_core_session_get_channel(vh->session_b);
 	switch_status_t status;
 	switch_frame_t *read_frame;
+	const char *source = switch_channel_get_variable(channel, "source");
+	const char *b_source = switch_channel_get_variable(b_channel, "source");
+	switch_core_session_message_t msg = { 0 };
 
 	vh->up = 1;
-	while (switch_channel_ready(channel) && switch_channel_ready(b_channel) && vh->up == 1) {
-		status = switch_core_session_read_video_frame(vh->session_a, &read_frame, SWITCH_IO_FLAG_NONE, 0);
-		if (!SWITCH_READ_ACCEPTABLE(status)) {
-			break;
+
+	switch_core_session_read_lock(vh->session_a);
+	switch_core_session_read_lock(vh->session_b);
+
+	if (!switch_stristr("loopback", source) && !switch_stristr("loopback", b_source)) {
+		switch_channel_set_flag(channel, CF_VIDEO_PASSIVE);
+		switch_channel_set_flag(b_channel, CF_VIDEO_PASSIVE);
+	}
+
+	msg.from = __FILE__;
+	msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
+	switch_core_session_receive_message(vh->session_a, &msg);
+	switch_core_session_receive_message(vh->session_b, &msg);
+
+	while (switch_channel_up_nosig(channel) && switch_channel_up_nosig(b_channel) && vh->up == 1) {
+
+		if (switch_channel_media_up(channel)) {
+			status = switch_core_session_read_video_frame(vh->session_a, &read_frame, SWITCH_IO_FLAG_NONE, 0);
+			
+			if (!SWITCH_READ_ACCEPTABLE(status)) {
+				switch_cond_next();
+				continue;
+			}
 		}
 
-		if (!switch_test_flag(read_frame, SFF_CNG)) {
+		if (switch_test_flag(read_frame, SFF_CNG)) {
+			continue;
+		}
+
+		if (switch_channel_media_up(b_channel)) {
 			if (switch_core_session_write_video_frame(vh->session_b, read_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) {
-				break;
+				switch_cond_next();
+				continue;
 			}
 		}
 
 	}
 
+	switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
+	switch_channel_clear_flag(b_channel, CF_VIDEO_PASSIVE);
+
 	switch_core_session_kill_channel(vh->session_b, SWITCH_SIG_BREAK);
 	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(vh->session_a), SWITCH_LOG_DEBUG, "%s video thread ended.\n", switch_channel_get_name(channel));
 
+	switch_core_session_rwunlock(vh->session_a);
+	switch_core_session_rwunlock(vh->session_b);
+
 	vh->up = 0;
 	return NULL;
 }
diff --git a/src/switch_rtp.c b/src/switch_rtp.c
index 8f2201924c..0e381d0825 100644
--- a/src/switch_rtp.c
+++ b/src/switch_rtp.c
@@ -59,7 +59,7 @@
 #define WRITE_INC(rtp_session)  switch_mutex_lock(rtp_session->write_mutex); rtp_session->writing++
 #define WRITE_DEC(rtp_session) switch_mutex_unlock(rtp_session->write_mutex); rtp_session->writing--
 
-#define RTP_DEFAULT_STUNCOUNT 25;
+#define RTP_STUN_FREQ 2000000
 #define rtp_header_len 12
 #define RTP_START_PORT 16384
 #define RTP_END_PORT 32768
@@ -72,7 +72,7 @@ static switch_port_t START_PORT = RTP_START_PORT;
 static switch_port_t END_PORT = RTP_END_PORT;
 static switch_port_t NEXT_PORT = RTP_START_PORT;
 static switch_mutex_t *port_lock = NULL;
-static void do_flush(switch_rtp_t *rtp_session);
+static void do_flush(switch_rtp_t *rtp_session, int force);
 
 typedef srtp_hdr_t rtp_hdr_t;
 
@@ -108,6 +108,54 @@ typedef struct {
 
 #define RTP_BODY(_s) (char *) (_s->recv_msg.ebody ? _s->recv_msg.ebody : _s->recv_msg.body)
 
+typedef struct {
+	uint32_t ssrc;
+	uint8_t seq;
+	uint8_t r1;
+	uint8_t r2;
+	uint8_t r3;
+} rtcp_fir_t;
+
+
+#ifdef _MSC_VER
+#pragma pack(push, r1, 1)
+#endif
+
+#if SWITCH_BYTE_ORDER == __BIG_ENDIAN
+typedef struct {
+	unsigned version:2;
+	unsigned p:1;
+	unsigned fmt:5;
+	unsigned pt:8;
+	unsigned length:16;
+	uint32_t send_ssrc;
+	uint32_t recv_ssrc;
+} switch_rtcp_ext_hdr_t;
+
+#else /*  BIG_ENDIAN */
+
+typedef struct {
+	unsigned fmt:5;
+	unsigned p:1;
+	unsigned version:2;
+	unsigned pt:8;
+	unsigned length:16;
+	uint32_t send_ssrc;
+	uint32_t recv_ssrc;
+} switch_rtcp_ext_hdr_t;
+
+#endif
+
+#ifdef _MSC_VER
+#pragma pack(pop, r1)
+#endif
+
+
+typedef struct {
+	switch_rtcp_ext_hdr_t header;
+	char body[SWITCH_RTCP_MAX_BUF_LEN];
+} rtcp_ext_msg_t;
+
 typedef struct {
 	switch_rtcp_hdr_t header;
 	char body[SWITCH_RTCP_MAX_BUF_LEN];
@@ -170,9 +218,8 @@ typedef struct {
 	char *pass;
 	char *rpass;
 	switch_sockaddr_t *addr;
-	uint32_t stuncount;
 	uint32_t funny_stun;
-	uint32_t default_stuncount;
+	switch_time_t next_run;
 	switch_core_media_ice_type_t type;
 	ice_t *ice_params;
 	ice_proto_t proto;
@@ -195,6 +242,8 @@ typedef struct switch_dtls_s {
 	dtls_fingerprint_t *local_fp;
 	dtls_fingerprint_t *remote_fp;
 	dtls_state_t state;
+	dtls_state_t last_state;
+	uint8_t new_state;
 	dtls_type_t type;
 	switch_size_t bytes;
 	void *data;
@@ -231,14 +280,13 @@ struct switch_rtp {
 	switch_sockaddr_t *local_addr, *rtcp_local_addr;
 	rtp_msg_t send_msg;
 	rtcp_msg_t rtcp_send_msg;
-
+	rtcp_ext_msg_t rtcp_ext_send_msg;
+	uint8_t fir_seq;
 	switch_sockaddr_t *remote_addr, *rtcp_remote_addr;
 	rtp_msg_t recv_msg;
 	rtcp_msg_t rtcp_recv_msg;
 	rtcp_msg_t *rtcp_recv_msg_p;
 
-	switch_sockaddr_t *remote_stun_addr;
-
 	uint32_t autoadj_window;
 	uint32_t autoadj_tally;
 
@@ -325,6 +373,7 @@ struct switch_rtp {
 	uint32_t hot_hits;
 	uint32_t sync_packets;
 	int rtcp_interval;
+	switch_time_t next_rtcp_send;
 	switch_bool_t rtcp_fresh_frame;
 
 	switch_time_t send_time;
@@ -390,10 +439,10 @@ struct switch_rtcp_senderinfo {
 	unsigned ts:32;
 	unsigned pc:32;
 	unsigned oc:32;
-       struct switch_rtcp_source sr_source;
-       struct switch_rtcp_s_desc_head sr_desc_head;
-       struct switch_rtcp_s_desc_trunk sr_desc_ssrc;
-
+	struct switch_rtcp_source sr_source;
+	struct switch_rtcp_s_desc_head sr_desc_head;
+	struct switch_rtcp_s_desc_trunk sr_desc_ssrc;
+	
 };
 
 typedef enum {
@@ -616,60 +665,6 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
 							rtp_msg_t *send_msg, void *data, uint32_t datalen, switch_payload_t payload, uint32_t timestamp, switch_frame_flag_t *flags);
 
 
-static switch_status_t do_stun_ping(switch_rtp_t *rtp_session)
-{
-	uint8_t buf[256] = { 0 };
-	uint8_t *start = buf;
-	switch_stun_packet_t *packet;
-	//unsigned int elapsed;
-	switch_size_t bytes;
-	switch_status_t status = SWITCH_STATUS_SUCCESS;
-
-	switch_assert(rtp_session != NULL);
-
-	WRITE_INC(rtp_session);
-
-	if (rtp_session->ice.stuncount != 0) {
-		rtp_session->ice.stuncount--;
-		goto end;
-	}
-#if 0
-	if (rtp_session->last_stun) {
-		elapsed = (unsigned int) ((switch_micro_time_now() - rtp_session->last_stun) / 1000);
-
-		if (elapsed > 30000) {
-			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "No stun for a long time (PUNT!)\n");
-			status = SWITCH_STATUS_FALSE;
-			goto end;
-		}
-	}
-#endif
-
-	if (rtp_session->ice.funny_stun) {
-		*start++ = 0;
-		*start++ = 0;
-		*start++ = 0x22;
-		*start++ = 0x22;
-	}
-
-	packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, start);
-	bytes = switch_stun_packet_length(packet);
-
-	if (rtp_session->ice.funny_stun) {
-		packet = (switch_stun_packet_t *) buf;
-		bytes += 4;
-	}
-
-
-	switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_stun_addr, 0, (void *) packet, &bytes);
-	rtp_session->ice.stuncount = rtp_session->ice.default_stuncount;
-
- end:
-	WRITE_DEC(rtp_session);
-
-	return status;
-}
-
 static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
 {
 	uint8_t buf[256] = { 0 };
@@ -679,30 +674,23 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
 	//switch_sockaddr_t *remote_addr = rtp_session->remote_addr;
 	switch_socket_t *sock_output = rtp_session->sock_output;
+	switch_time_t now = switch_micro_time_now();
 
+	if (ice->next_run && ice->next_run > now) {
+		return SWITCH_STATUS_BREAK;
+	}
 
+	ice->next_run = now + RTP_STUN_FREQ;
+		
 	if (ice == &rtp_session->rtcp_ice) {
 		sock_output = rtp_session->rtcp_sock_output;		
 	}
-	
 
 	switch_assert(rtp_session != NULL);
 	switch_assert(ice->ice_user != NULL);
 
 	READ_INC(rtp_session);
 
-	if (ice->stuncount != 0) {
-		ice->stuncount--;
-		goto end;
-	}
-
-#if 0
-	if (ice->sending != 0) {
-		ice->stuncount = ice->default_stuncount;
-		ice->sending--;
-	}
-#endif
-	
 	if (rtp_session->last_stun) {
 		elapsed = (unsigned int) ((switch_micro_time_now() - rtp_session->last_stun) / 1000);
 
@@ -717,7 +705,7 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
 	packet = switch_stun_packet_build_header(SWITCH_STUN_BINDING_REQUEST, NULL, buf);
 	switch_stun_packet_attribute_add_username(packet, ice->ice_user, (uint16_t)strlen(ice->ice_user));
 
-	switch_set_string(ice->last_sent_id, packet->header.id);
+	memcpy(ice->last_sent_id, packet->header.id, 12);
 
 	//if (ice->pass && ice->type == ICE_GOOGLE_JINGLE) {
 	//	switch_stun_packet_attribute_add_password(packet, ice->pass, (uint16_t)strlen(ice->pass));
@@ -745,9 +733,11 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
 
 	bytes = switch_stun_packet_length(packet);
 
+#ifdef DEBUG_EXTRA
+	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "%s send %s stun\n", switch_core_session_get_name(rtp_session->session), rtp_type(rtp_session));
+#endif
 	switch_socket_sendto(sock_output, ice->addr, 0, (void *) packet, &bytes);
 						 
-	ice->stuncount = ice->default_stuncount;
 	ice->sending = 3;
 
  end:
@@ -757,21 +747,12 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
 }
 
 
-static void handle_stun_ping_reply(switch_rtp_t *rtp_session, void *data, switch_size_t len)
-{
-	if (!switch_rtp_ready(rtp_session)) {
-		return;
-	}
-
-	rtp_session->last_stun = switch_micro_time_now();
-}
-
 static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *data, switch_size_t len)
 {
 	switch_stun_packet_t *packet;
 	switch_stun_packet_attribute_t *attr;
 	void *end_buf;
-	char username[33] = { 0 };
+	char username[34] = { 0 };
 	unsigned char buf[512] = { 0 };
 	switch_size_t cpylen = len;
 	int xlen = 0;
@@ -841,7 +822,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
 			break;
 		case SWITCH_STUN_ATTR_USERNAME:
 			if (attr->type) {
-				switch_stun_packet_attribute_get_username(attr, username, 32);
+				switch_stun_packet_attribute_get_username(attr, username, sizeof(username));
 			}
 			break;
 			
@@ -864,14 +845,43 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
 	}
 
 	if ((ice->type & ICE_VANILLA)) {
-		if (!ok) ok = !strcmp(packet->header.id, ice->last_sent_id);
-		
+		char foo1[13] = "", foo2[13] = "";
+		if (!ok) ok = !strncmp(packet->header.id, ice->last_sent_id, 12);
+
+
+
+		if (packet->header.type == SWITCH_STUN_BINDING_RESPONSE) {
+			ok = 1;
+			if (!ice->rready) {
+				if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
+					rtp_session->ice.rready = 1;
+					rtp_session->rtcp_ice.rready = 1;
+				} else {
+					ice->rready = 1;
+				}
+
+				switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH);
+			}
+		}
+
+		strncpy(foo1, packet->header.id, 12);
+		strncpy(foo2, ice->last_sent_id, 12);
+
 		if (!ok && ice == &rtp_session->ice && rtp_session->rtcp_ice.ice_params && pri && 
 			*pri == rtp_session->rtcp_ice.ice_params->cands[rtp_session->rtcp_ice.ice_params->chosen[1]][1].priority) {
 			ice = &rtp_session->rtcp_ice;
 			ok = 1;
 		}
 
+		if (!zstr(username)) {
+			if (!strcmp(username, ice->user_ice)) {
+				ok = 1;
+			} else if(!strcmp(username, rtp_session->rtcp_ice.user_ice)) {
+				ice = &rtp_session->rtcp_ice;
+				ok = 1;
+			}
+		}
+
 		if (ok) {
 			ice->missed_count = 0;
 		} else {
@@ -881,7 +891,8 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
 			char *host = NULL;
 
 			ice->missed_count++;
-			
+			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "missed %d\n", ice->missed_count);
+
 			if (elapsed > 20000 && pri) {
 				int i, j;
 				uint32_t old;
@@ -958,24 +969,12 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
 		}
 	}
 
-	if (ice->missed_count > 3) {
+	if (ice->missed_count > 5) {
 		ice->rready = 0;
 	}
 
-	if (ok || !ice->rready) {
-		if (packet->header.type == SWITCH_STUN_BINDING_RESPONSE) {
-
-			if (!ice->rready) {
-				if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
-					rtp_session->ice.rready = 1;
-					rtp_session->rtcp_ice.rready = 1;
-				} else {
-					ice->rready = 1;
-				}
-
-				switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH);
-			}
-		} else if (packet->header.type == SWITCH_STUN_BINDING_REQUEST) {
+	if (ok) {
+		if (packet->header.type == SWITCH_STUN_BINDING_REQUEST) {
 			uint8_t stunbuf[512];
 			switch_stun_packet_t *rpacket;
 			const char *remote_ip;
@@ -984,7 +983,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
 			switch_sockaddr_t *from_addr = rtp_session->from_addr;
 			switch_socket_t *sock_output = rtp_session->sock_output;
 
-			if (is_rtcp && !rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
+			if (is_rtcp) {
 				from_addr = rtp_session->rtcp_from_addr;
 				sock_output = rtp_session->rtcp_sock_output;
 			}
@@ -1013,23 +1012,29 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
 			bytes = switch_stun_packet_length(rpacket);
 
 			if (!ice->rready && (ice->type & ICE_VANILLA) && ice->ice_params && !switch_cmp_addr(from_addr, ice->addr)) {
-				const char *host;
-				switch_port_t port;
+				const char *host, *host2;
+				switch_port_t port, port2;
 				char buf[80] = "";
+				char buf2[80] = "";
 				const char *err = "";
 
 				ice->missed_count = 0;
 				ice->rready = 1;
 
-				host = switch_get_addr(buf, len, from_addr);
+				host = switch_get_addr(buf, sizeof(buf), from_addr);
 				port = switch_sockaddr_get_port(from_addr);
 
-				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO,
-								  "Auto Changing stun/%s/dtls port to %s:%u\n", is_rtcp ? "rtcp" : "rtp", host, port);
+				host2 = switch_get_addr(buf2, sizeof(buf2), ice->addr);
+				port2 = switch_sockaddr_get_port(ice->addr);
+				
+				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_NOTICE,
+								  "Auto Changing stun/%s/dtls port from %s:%u to %s:%u\n", is_rtcp ? "rtcp" : "rtp", 
+								  host2, port2,
+								  host, port);
 				
 				ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr = switch_core_strdup(rtp_session->pool, host);
 				ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port = port;
-
+				
 				switch_sockaddr_info_get(&ice->addr, host, SWITCH_UNSPEC, port, 0, rtp_session->pool);
 
 				if (!is_rtcp || rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
@@ -1060,9 +1065,6 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d
 		}
 	} else if (packet->header.type == SWITCH_STUN_BINDING_ERROR_RESPONSE) {
 		
-
-		ice_out(rtp_session, ice);
-
 		if (rtp_session->session) {
 			switch_core_session_message_t msg = { 0 };
 			msg.from = __FILE__;
@@ -1313,13 +1315,99 @@ static uint8_t get_next_write_ts(switch_rtp_t *rtp_session, uint32_t timestamp)
 	return m;
 }
 
+static void send_fir(switch_rtp_t *rtp_session)
+{
+
+	if (!rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && rtp_session->ice.ice_user) {
+		return;
+	}
+
+	if (rtp_session->rtcp_sock_output && rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP]) {
+		rtcp_fir_t *fir = (rtcp_fir_t *) rtp_session->rtcp_ext_send_msg.body;
+		switch_size_t rtcp_bytes;
+
+		rtp_session->rtcp_ext_send_msg.header.version = 2;
+		rtp_session->rtcp_ext_send_msg.header.p = 0;
+		rtp_session->rtcp_ext_send_msg.header.fmt = 4;
+		rtp_session->rtcp_ext_send_msg.header.pt = 206;
+		
+		rtp_session->rtcp_ext_send_msg.header.send_ssrc = htonl(rtp_session->ssrc);
+		rtp_session->rtcp_ext_send_msg.header.recv_ssrc = htonl(rtp_session->stats.rtcp.peer_ssrc);
+
+		fir->ssrc = htonl(rtp_session->stats.rtcp.peer_ssrc);
+		fir->seq = htonl(rtp_session->fir_seq++);
+		
+		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1, "Sending RTCP FIR %d\n", rtp_session->fir_seq);
+		
+		rtcp_bytes = sizeof(switch_rtcp_ext_hdr_t) + sizeof(rtcp_fir_t);
+		rtp_session->rtcp_ext_send_msg.header.length = htons((u_short)(rtcp_bytes / 4) - 1); 
+		
+
+#ifdef ENABLE_SRTP
+		if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND]) {
+			int sbytes = (int) rtcp_bytes;
+			int stat = srtp_protect_rtcp(rtp_session->send_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_ext_send_msg.header, &sbytes);
+			
+			if (stat) {
+				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP RTCP protection failed with code %d\n", stat);
+				goto end;
+			} else {
+				rtcp_bytes = sbytes;
+			}
+
+		}
+#endif
+
+#ifdef ENABLE_ZRTP
+		/* ZRTP Send */
+		if (zrtp_on && !rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA]) {
+			unsigned int sbytes = (int) rtcp_bytes;
+			zrtp_status_t stat = zrtp_status_fail;
+
+			stat = zrtp_process_rtcp(rtp_session->zrtp_stream, (void *) &rtp_session->rtcp_ext_send_msg, &sbytes);
+
+			switch (stat) {
+			case zrtp_status_ok:
+				break;
+			case zrtp_status_drop:
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection drop with code %d\n", stat);
+				ret = (int)rtcp_bytes;
+				goto end;
+				break;
+			case zrtp_status_fail:
+				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection fail with code %d\n", stat);
+				break;
+			default:
+				break;
+			}
+
+			rtcp_bytes = sbytes;
+		}
+#endif
+
+#ifdef DEBUG_EXTRA
+		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "%s SEND %s RTCP %ld\n", 
+						  switch_core_session_get_name(rtp_session->session),
+						  rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] ? "video" : "audio", rtcp_bytes);
+#endif
+		if (switch_socket_sendto(rtp_session->rtcp_sock_output, rtp_session->rtcp_remote_addr, 0, (void *)&rtp_session->rtcp_ext_send_msg, &rtcp_bytes ) != SWITCH_STATUS_SUCCESS) {			
+			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG,"RTCP packet not written\n");
+		} else {
+			rtp_session->stats.inbound.period_packet_count = 0;
+		}
+	}
 
 
-static int check_srtp_and_ice(switch_rtp_t *rtp_session)
+ end:
+
+	return;
+}
+
+static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
 {
 	int ret = 0;
 	int rtcp_ok = 1;
-
+	switch_time_t now = switch_micro_time_now();
 
 	if (rtp_session->flags[SWITCH_RTP_FLAG_AUTO_CNG] && rtp_session->send_msg.header.ts &&
 		rtp_session->timer.samplecount >= (rtp_session->last_write_samplecount + (rtp_session->samples_per_interval * 60))) {
@@ -1338,14 +1426,21 @@ static int check_srtp_and_ice(switch_rtp_t *rtp_session)
 		}
 	}
 
-	if (rtp_session->rtcp_ice.ice_user && !rtp_session->rtcp_ice.rready) {
+	if (rtp_session->rtcp_interval && rtp_session->next_rtcp_send > now) {
+		rtcp_ok = 0;
+	} else {
+		rtp_session->next_rtcp_send = now + (rtp_session->rtcp_interval * 1000);
+	}
+
+	if (rtcp_ok && rtp_session->rtcp_ice.ice_user && !rtp_session->rtcp_ice.rready) {
 		rtcp_ok = 0;
 	}
 
+	//if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
+	//	rtcp_ok = 0;
+	//}
 
-	if (rtp_session->rtcp_sock_output && rtcp_ok &&
-		rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP] && !rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU] &&
-		rtp_session->rtcp_interval && (rtp_session->stats.read_count % rtp_session->rtcp_interval) == 0) {
+	if (rtp_session->rtcp_sock_output && rtcp_ok && rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP] && !rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU]) {
 		struct switch_rtcp_senderinfo *sr = (struct switch_rtcp_senderinfo*) rtp_session->rtcp_send_msg.body;
 		const char* str_cname=NULL;
 		//rtp_msg_t *send_msg = &rtp_session->send_msg;
@@ -1461,23 +1556,18 @@ static int check_srtp_and_ice(switch_rtp_t *rtp_session)
 		}
 #endif
 
-
+#ifdef DEBUG_EXTRA
+		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "%s SEND %s RTCP %ld\n", 
+						  switch_core_session_get_name(rtp_session->session),
+						  rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] ? "video" : "audio", rtcp_bytes);
+#endif
 		if (switch_socket_sendto(rtp_session->rtcp_sock_output, rtp_session->rtcp_remote_addr, 0, (void *)&rtp_session->rtcp_send_msg, &rtcp_bytes ) != SWITCH_STATUS_SUCCESS) {			
 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG,"RTCP packet not written\n");
 		} else {
 			rtp_session->stats.inbound.period_packet_count = 0;
 		}
-
-		if (rtp_session->rtcp_ice.ice_user) {
-			ice_out(rtp_session, &rtp_session->rtcp_ice);
-		}
 	}
 	
-
-	if (rtp_session->remote_stun_addr) {
-		do_stun_ping(rtp_session);
-	}
-
 	if (rtp_session->ice.ice_user) {
 		if (ice_out(rtp_session, &rtp_session->ice) != SWITCH_STATUS_SUCCESS) {
 			ret = -1;
@@ -1485,11 +1575,12 @@ static int check_srtp_and_ice(switch_rtp_t *rtp_session)
 		}
 	}
 
-
-	if (rtp_session->rtcp_ice.ice_user) {
-		if (ice_out(rtp_session, &rtp_session->rtcp_ice) != SWITCH_STATUS_SUCCESS) {
-			ret = -1;
-			goto end;
+	if (!rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
+		if (rtp_session->rtcp_ice.ice_user) {
+			if (ice_out(rtp_session, &rtp_session->rtcp_ice) != SWITCH_STATUS_SUCCESS) {
+				ret = -1;
+				goto end;
+			}
 		}
 	}
 
@@ -1500,7 +1591,7 @@ static int check_srtp_and_ice(switch_rtp_t *rtp_session)
 
 SWITCH_DECLARE(void) switch_rtp_ping(switch_rtp_t *rtp_session)
 {
-	check_srtp_and_ice(rtp_session);
+	check_rtcp_and_ice(rtp_session);
 }
 
 SWITCH_DECLARE(void) switch_rtp_get_random(void *buf, uint32_t len)
@@ -1836,7 +1927,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_local_address(switch_rtp_t *rtp_s
 	rtp_session->sock_input = new_sock;
 	new_sock = NULL;
 
-	if (rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER] || rtp_session->flags[SWITCH_RTP_FLAG_NOBLOCK]) {
+	if (rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER] || rtp_session->flags[SWITCH_RTP_FLAG_NOBLOCK] || rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
 		switch_socket_opt_set(rtp_session->sock_input, SWITCH_SO_NONBLOCK, TRUE);
 		switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
 	}
@@ -2043,7 +2134,7 @@ static const char *dtls_state_names(dtls_state_t s)
 }
 
 
-#define dtls_set_state(_dtls, _state) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Changing %s DTLS state from %s to %s\n", rtp_type(rtp_session), dtls_state_names(_dtls->state), dtls_state_names(_state)); _dtls->state = _state
+#define dtls_set_state(_dtls, _state) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_INFO, "Changing %s DTLS state from %s to %s\n", rtp_type(rtp_session), dtls_state_names(_dtls->state), dtls_state_names(_state)); _dtls->new_state = 1; _dtls->last_state = _dtls->state; _dtls->state = _state
 
 static int dtls_state_dummy(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
 {
@@ -2123,6 +2214,19 @@ static int dtls_state_setup(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
 
 static int dtls_state_ready(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
 {
+
+	if (dtls->new_state) {
+		if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
+			switch_core_session_t *other_session;
+			send_fir(rtp_session);
+			
+			if (rtp_session->session && switch_core_session_get_partner(rtp_session->session, &other_session) == SWITCH_STATUS_SUCCESS) {
+				switch_core_session_refresh_video(other_session);
+				switch_core_session_rwunlock(other_session);
+			}
+		}
+		dtls->new_state = 0;
+	}
 	return 0;
 }
 
@@ -2840,30 +2944,6 @@ SWITCH_DECLARE(void) switch_rtp_set_cng_pt(switch_rtp_t *rtp_session, switch_pay
 	rtp_session->flags[SWITCH_RTP_FLAG_AUTO_CNG] = 1;
 }
 
-SWITCH_DECLARE(switch_status_t) switch_rtp_activate_stun_ping(switch_rtp_t *rtp_session, const char *stun_ip, switch_port_t stun_port,
-															  uint32_t packet_count, switch_bool_t funny)
-{
-
-	if (switch_sockaddr_info_get(&rtp_session->remote_stun_addr, stun_ip, SWITCH_UNSPEC,
-								 stun_port, 0, rtp_session->pool) != SWITCH_STATUS_SUCCESS || !rtp_session->remote_stun_addr) {
-
-		
-		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error resolving stun ping addr\n");
-		return SWITCH_STATUS_FALSE;
-	}
-
-	if (funny) {
-		rtp_session->ice.funny_stun++;
-	}
-
-	rtp_session->stun_port = stun_port;
-
-	rtp_session->ice.default_stuncount = packet_count;
-
-	rtp_session->stun_ip = switch_core_strdup(rtp_session->pool, stun_ip);
-	return SWITCH_STATUS_SUCCESS;
-}
-
 static void jb_callback(stfu_instance_t *i, void *udata)
 {
 	switch_core_session_t *session = (switch_core_session_t *) udata;
@@ -3018,14 +3098,10 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_sessi
 		rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU] = 1;
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "RTCP passthru enabled. Remote Port: %d\n", rtp_session->remote_rtcp_port);
 	} else {
-		
 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "RTCP send rate is: %d and packet rate is: %d Remote Port: %d\n", 						  send_rate, rtp_session->ms_per_packet, rtp_session->remote_rtcp_port);
 
-		if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
-			rtp_session->rtcp_interval = send_rate / 20;
-		} else {
-			rtp_session->rtcp_interval = send_rate/(rtp_session->ms_per_packet/1000);
-		}
+		rtp_session->rtcp_interval = send_rate;
+		rtp_session->next_rtcp_send = switch_time_now() + (rtp_session->rtcp_interval * 1000);
 	}
 
 	if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
@@ -3088,6 +3164,8 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_sessio
 	ice->pass = "";
 	ice->rpass = "";
 
+	ice->next_run = switch_micro_time_now();
+
 	if (password) {
 		ice->pass = switch_core_strdup(rtp_session->pool, password);
 	}
@@ -3096,9 +3174,6 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_sessio
 		ice->rpass = switch_core_strdup(rtp_session->pool, rpassword);
 	}
 	
-	ice->default_stuncount = RTP_DEFAULT_STUNCOUNT;
-	ice->stuncount = 0;
-
 	if ((ice->type & ICE_VANILLA) && ice->ice_params) {
 		host = ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_addr;
 		port = ice->ice_params->cands[ice->ice_params->chosen[ice->proto]][ice->proto].con_port;
@@ -3124,12 +3199,6 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_ice(switch_rtp_t *rtp_sessio
 
 	rtp_session->rtp_bugs |= RTP_BUG_ACCEPT_ANY_PACKETS;
 
-	if (ice->ice_user) {
-		if (ice_out(rtp_session, &rtp_session->ice) != SWITCH_STATUS_SUCCESS) {
-			return SWITCH_STATUS_FALSE;
-		}
-	}
-
 	return SWITCH_STATUS_SUCCESS;
 }
 
@@ -3143,6 +3212,12 @@ SWITCH_DECLARE(void) switch_rtp_flush(switch_rtp_t *rtp_session)
 	switch_rtp_set_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH);
 }
 
+SWITCH_DECLARE(void) switch_rtp_video_refresh(switch_rtp_t *rtp_session)
+{
+	if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && rtp_session->ice.ice_user) {
+		send_fir(rtp_session);
+	}
+}
 
 SWITCH_DECLARE(void) switch_rtp_break(switch_rtp_t *rtp_session)
 {
@@ -3161,6 +3236,7 @@ SWITCH_DECLARE(void) switch_rtp_break(switch_rtp_t *rtp_session)
 	if (rtp_session->sock_input) {
 		ping_socket(rtp_session);
 	}
+
 	switch_mutex_unlock(rtp_session->flag_mutex);
 }
 
@@ -3654,18 +3730,24 @@ SWITCH_DECLARE(void) rtp_flush_read_buffer(switch_rtp_t *rtp_session, switch_rtp
 	}
 }
 
-static void do_flush(switch_rtp_t *rtp_session)
+static void do_flush(switch_rtp_t *rtp_session, int force)
 {
 	int was_blocking = 0;
 	switch_size_t bytes;
 	uint32_t flushed = 0;
 
-	if (!switch_rtp_ready(rtp_session) || 
-		rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] || 
-		rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] 
-		) {
+	if (!switch_rtp_ready(rtp_session)) {
 		return;
 	}
+
+	if (!force) {
+		if (rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] || 
+			rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] ||
+			rtp_session->flags[SWITCH_RTP_FLAG_UDPTL]
+			) {
+			return;
+		}
+	}
 	
 
 	READ_INC(rtp_session);
@@ -3737,28 +3819,32 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
 	switch_status_t status = SWITCH_STATUS_FALSE;
 	stfu_frame_t *jb_frame;
 	uint32_t ts = 0;
-	char *b = NULL;
+	unsigned char *b = NULL;
 	int sync = 0;
 
 	switch_assert(bytes);
  more:
+
 	*bytes = sizeof(rtp_msg_t);
 	sync = 0;
 
 	status = switch_socket_recvfrom(rtp_session->from_addr, rtp_session->sock_input, 0, (void *) &rtp_session->recv_msg, bytes);
 
+	check_rtcp_and_ice(rtp_session);
+	
 	if (rtp_session->flags[SWITCH_RTP_FLAG_UDPTL]) {
 		goto udptl;
 	}
 
+
 	if (*bytes) {
-		b = (char *) &rtp_session->recv_msg;
+		b = (unsigned char *) &rtp_session->recv_msg;
+
+		*flags &= ~SFF_PROXY_PACKET;
 
 		if (*b == 0 || *b == 1) {
 			if (rtp_session->ice.ice_user) {
 				handle_ice(rtp_session, &rtp_session->ice, (void *) &rtp_session->recv_msg, *bytes);
-			} else if (rtp_session->remote_stun_addr) {
-				handle_stun_ping_reply(rtp_session, (void *) &rtp_session->recv_msg, *bytes);
 			}
 			*bytes = 0;
 			sync = 1;
@@ -3777,10 +3863,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
 
 		if (*bytes) {
 			char *b = (char *) &rtp_session->recv_msg;
-		
-			//printf("RECV %d %ld\n", *b, *bytes);
 			
-		
 			if ((*b >= 20) && (*b <= 64)) {
 				rtp_session->dtls->bytes = *bytes;
 				rtp_session->dtls->data = (void *) &rtp_session->recv_msg;
@@ -3812,8 +3895,8 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
 			if (rtp_session->recv_msg.header.pt != rtp_session->rpayload && (!rtp_session->recv_te || 
 																			 rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
 				(!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) &&
-				rtp_session->rtcp_recv_msg_p->header.version == 2 &&
-				rtp_session->rtcp_recv_msg_p->header.type > 199 && rtp_session->rtcp_recv_msg_p->header.type < 205) { //rtcp muxed
+				rtp_session->rtcp_recv_msg_p->header.version == 2 && rtp_session->rtcp_recv_msg_p->header.type > 199 && 
+				rtp_session->rtcp_recv_msg_p->header.type < 208) { //rtcp muxed
 				*flags |= SFF_RTCP;
 				return SWITCH_STATUS_SUCCESS;
 			}
@@ -3821,6 +3904,35 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
 	}
 
 
+	if (*bytes && rtp_session->flags[SWITCH_RTP_FLAG_DEBUG_RTP_READ]) {
+		if (!rtp_session->session) {
+			rtp_session->flags[SWITCH_RTP_FLAG_DEBUG_RTP_READ] = 0;
+			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "RTP HAS NO SESSION!\n");
+		} else {
+			const char *tx_host;
+			const char *old_host;
+			const char *my_host;
+
+			char bufa[30], bufb[30], bufc[30];
+
+
+			tx_host = switch_get_addr(bufa, sizeof(bufa), rtp_session->from_addr);
+			old_host = switch_get_addr(bufb, sizeof(bufb), rtp_session->remote_addr);
+			my_host = switch_get_addr(bufc, sizeof(bufc), rtp_session->local_addr);
+
+			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(rtp_session->session), SWITCH_LOG_CONSOLE,
+							  "R %s b=%4ld %s:%u %s:%u %s:%u pt=%d ts=%u m=%d\n",
+							  switch_channel_get_name(switch_core_session_get_channel(rtp_session->session)),
+							  (long) *bytes,
+							  my_host, switch_sockaddr_get_port(rtp_session->local_addr),
+							  old_host, rtp_session->remote_port,
+							  tx_host, switch_sockaddr_get_port(rtp_session->from_addr),
+							  rtp_session->recv_msg.header.pt, ntohl(rtp_session->recv_msg.header.ts), rtp_session->recv_msg.header.m);
+
+		}
+	}
+	
+
 	if (sync) {
 		if (!rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER] && rtp_session->timer.interval) {
 			switch_core_timer_sync(&rtp_session->timer);
@@ -3896,7 +4008,8 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
 	rtp_session->last_flush_packet_count = rtp_session->stats.inbound.flush_packet_count;
 	rtp_session->last_read_time = switch_micro_time_now();
 
-	if (*bytes && (!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) && 
+	if (!rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] && !rtp_session->flags[SWITCH_RTP_FLAG_UDPTL] && !rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && 
+		*bytes && (!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) && 
 		ts && !rtp_session->jb && !rtp_session->pause_jb && ts == rtp_session->last_cng_ts) {
 		/* we already sent this frame..... */
 		*bytes = 0;
@@ -3945,7 +4058,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
 #endif
 			
 #ifdef ENABLE_SRTP
-			if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV] && rtp_session->recv_msg.header.version == 2) {
+			if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV] && rtp_session->recv_msg.header.version == 2 && rtp_session->recv_msg.header.pt == rtp_session->rpayload) {
 				//if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_RECV] && (!rtp_session->ice.ice_user || rtp_session->recv_msg.header.version == 2)) {
 				int sbytes = (int) *bytes;
 				err_status_t stat = 0;
@@ -3990,7 +4103,6 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
 		}
 	}
 
-
 	if ((rtp_session->recv_te && rtp_session->recv_msg.header.pt == rtp_session->recv_te) || 
 		(*bytes < rtp_header_len && *bytes > 0) ||
 		rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] || rtp_session->flags[SWITCH_RTP_FLAG_UDPTL]) {
@@ -4130,7 +4242,6 @@ static switch_status_t read_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t
 		
 		//printf("RECV2 %d %ld\n", *b, *bytes);
 
-
 		if (*b == 0 || *b == 1) {
 			if (rtp_session->rtcp_ice.ice_user) {
 				handle_ice(rtp_session, &rtp_session->rtcp_ice, (void *) &rtp_session->rtcp_recv_msg, *bytes);
@@ -4328,11 +4439,10 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 			}
 		}
 
-	recvfrom:
-
-
 		rtp_session->stats.read_count++;
 
+	recvfrom:
+
 		if (!read_pretriggered) {
 			bytes = 0;
 		}
@@ -4348,44 +4458,51 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 
 			do_2833(rtp_session);
 
-			if ((rtp_session->ice.ice_user && rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) || rtp_session->dtmf_data.out_digit_dur > 0 || rtp_session->dtmf_data.in_digit_sanity || rtp_session->sending_dtmf || 
+			if (rtp_session->dtmf_data.out_digit_dur > 0 || rtp_session->dtmf_data.in_digit_sanity || rtp_session->sending_dtmf || 
 				switch_queue_size(rtp_session->dtmf_data.dtmf_queue) || switch_queue_size(rtp_session->dtmf_data.dtmf_inqueue)) {
 				pt = 20000;
 			}
 			
+			if ((rtp_session->ice.ice_user && rtp_session->flags[SWITCH_RTP_FLAG_VIDEO])) {
+				pt = 10000;
+			}
+
 			if ((io_flags & SWITCH_IO_FLAG_NOBLOCK)) {
 				pt = 0;
 			}
 
 			poll_status = switch_poll(rtp_session->read_pollfd, 1, &fdr, pt);
-
+			
 			if (rtp_session->dtmf_data.out_digit_dur > 0) {
 				return_cng_frame();
 			}
 		}
-
-
-
+		
 		if (poll_status == SWITCH_STATUS_SUCCESS) {
 			if (read_pretriggered) {
 				read_pretriggered = 0;
 			} else {
 				status = read_rtp_packet(rtp_session, &bytes, flags, SWITCH_TRUE);
+
 				if (status == SWITCH_STATUS_GENERR) {
 					ret = -1;
 					goto end;
 				}
+				if ((*flags & SFF_PROXY_PACKET)) {
+					ret = (int) bytes;
+					goto end;
+				}
+
 				if ((*flags & SFF_RTCP)) {
 					*flags &= ~SFF_RTCP;
 					has_rtcp = 1;
 					goto rtcp;
 				}
+				
 				//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "Read bytes (%i) %ld\n", status, bytes); 
 			}
 			poll_loop = 0;
 		} else {
-			int vid_cng = 1, ice = 0;
-
 			if (!SWITCH_STATUS_IS_BREAK(poll_status) && poll_status != SWITCH_STATUS_TIMEOUT) {
 				char tmp[128] = "";
 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Poll failed with error: %d [%s]\n",
@@ -4394,44 +4511,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 				goto end;
 			}
 
-			if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
-				if (rtp_session->rtcp_ice.ice_user) {
-					if (ice_out(rtp_session, &rtp_session->rtcp_ice) != SWITCH_STATUS_SUCCESS) {
-						ret = -1;
-						goto end;
-					}
-					vid_cng = 0;
-					ice = 1;
-				}
-
-				if (rtp_session->ice.ice_user) {
-					if (ice_out(rtp_session, &rtp_session->ice) != SWITCH_STATUS_SUCCESS) {
-						ret = -1;
-						goto end;
-					}
-					vid_cng = 0;
-					ice = 1;
-				}
-				
-
-				if (ice) {
-
-					if (check_srtp_and_ice(rtp_session)) {
-						ret = -1;
-						goto end;
-					}
-
-					if (poll_loop < 50) {
-						poll_loop++;
-						goto recvfrom;
-					}
-				}
-
-			}
-			
-			poll_loop++;
-
-			if (!rtp_session->flags[SWITCH_RTP_FLAG_UDPTL]) {
+			if (!rtp_session->flags[SWITCH_RTP_FLAG_UDPTL] && !rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
 				rtp_session->missed_count += (poll_sec * 1000) / (rtp_session->ms_per_packet ? rtp_session->ms_per_packet / 1000 : 20);
 				bytes = 0;
 
@@ -4443,8 +4523,11 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 				}
 			}
 
-			if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) && 
-				(rtp_session->dtmf_data.out_digit_dur == 0 || (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && vid_cng))) {
+			if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {				
+				check_rtcp_and_ice(rtp_session);
+
+			} else if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) && 
+					   (rtp_session->dtmf_data.out_digit_dur == 0)) {
 				return_cng_frame();
 			}
 		}
@@ -4476,10 +4559,10 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 				if (rtcp_status == SWITCH_STATUS_SUCCESS) {
 					switch_rtp_reset_media_timer(rtp_session);
 
-					if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU]) {
+					if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU] || rtp_session->rtcp_recv_msg_p->header.type == 206) {
 						switch_channel_t *channel = switch_core_session_get_channel(rtp_session->session);
-
 						const char *uuid = switch_channel_get_partner_uuid(channel);
+
 						if (uuid) {
 							switch_core_session_t *other_session;
 							switch_rtp_t *other_rtp_session = NULL;
@@ -4491,6 +4574,12 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 									switch_rtp_test_flag(other_rtp_session, SWITCH_RTP_FLAG_ENABLE_RTCP)) {
 									*other_rtp_session->rtcp_send_msg.body = *rtp_session->rtcp_recv_msg_p->body;
 
+									if (rtp_session->rtcp_recv_msg_p->header.type == 206) {
+										rtcp_ext_msg_t *extp = (rtcp_ext_msg_t *) rtp_session->rtcp_recv_msg_p;
+										extp->header.recv_ssrc = htonl(other_rtp_session->stats.rtcp.peer_ssrc);
+									}
+
+
 #ifdef ENABLE_SRTP
 									if (switch_rtp_test_flag(other_rtp_session, SWITCH_RTP_FLAG_SECURE_SEND)) {
 										int sbytes = (int) rtcp_bytes;
@@ -4573,7 +4662,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 			goto end;
 		}
 
-		if (rtp_session->max_missed_packets && read_loops == 1) {
+		if (rtp_session->max_missed_packets && read_loops == 1 && !rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
 			if (bytes) {
 				rtp_session->missed_count = 0;
 			} else if (++rtp_session->missed_count >= rtp_session->max_missed_packets) {
@@ -4586,7 +4675,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 
 		if (rtp_session->flags[SWITCH_RTP_FLAG_FLUSH]) {
 			if (!rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
-				do_flush(rtp_session);
+				do_flush(rtp_session, SWITCH_FALSE);
 				bytes = 0;
 			}
 			switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_FLUSH);
@@ -4616,35 +4705,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 			rtp_flush_read_buffer(rtp_session, SWITCH_RTP_FLUSH_ONCE);
 		}
 
-		if (bytes && rtp_session->flags[SWITCH_RTP_FLAG_DEBUG_RTP_READ]) {
-			
-
-			if (!rtp_session->session) {
-				rtp_session->flags[SWITCH_RTP_FLAG_DEBUG_RTP_READ] = 0;
-				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "RTP HAS NO SESSION!\n");
-			} else {
-				const char *tx_host;
-				const char *old_host;
-				const char *my_host;
-
-				char bufa[30], bufb[30], bufc[30];
-
-
-				tx_host = switch_get_addr(bufa, sizeof(bufa), rtp_session->from_addr);
-				old_host = switch_get_addr(bufb, sizeof(bufb), rtp_session->remote_addr);
-				my_host = switch_get_addr(bufc, sizeof(bufc), rtp_session->local_addr);
-
-				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(rtp_session->session), SWITCH_LOG_CONSOLE,
-								  "R %s b=%4ld %s:%u %s:%u %s:%u pt=%d ts=%u m=%d\n",
-								  switch_channel_get_name(switch_core_session_get_channel(rtp_session->session)),
-								  (long) bytes,
-								  my_host, switch_sockaddr_get_port(rtp_session->local_addr),
-								  old_host, rtp_session->remote_port,
-								  tx_host, switch_sockaddr_get_port(rtp_session->from_addr),
-								  rtp_session->recv_msg.header.pt, ntohl(rtp_session->recv_msg.header.ts), rtp_session->recv_msg.header.m);
-
-			}
-		}
 
 		if (((rtp_session->cng_pt && rtp_session->recv_msg.header.pt == rtp_session->cng_pt) || rtp_session->recv_msg.header.pt == 13)) {
 			*flags |= SFF_NOT_AUDIO;
@@ -4722,8 +4782,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 				}
 #endif
 				*flags |= SFF_UDPTL_PACKET;
-			} else {
-				check_srtp_and_ice(rtp_session);
 			}
 
 			ret = (int) bytes;
@@ -4744,13 +4802,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 			}
 		}
 
-
-		if (check_srtp_and_ice(rtp_session)) {
-			ret = -1;
-			goto end;
-		}
-		
-
 		if (check || bytes) {
 			do_2833(rtp_session);
 		}
@@ -4762,9 +4813,6 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
 				if (rtp_session->ice.ice_user) {
 					handle_ice(rtp_session, &rtp_session->ice, (void *) &rtp_session->recv_msg, bytes);
 					goto recvfrom;
-				} else if (rtp_session->remote_stun_addr) {
-					handle_stun_ping_reply(rtp_session, (void *) &rtp_session->recv_msg, bytes);
-					goto recvfrom;
 				}
 			}
 
@@ -5202,52 +5250,53 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
 		bytes = datalen + rtp_header_len;
 	}
 
+	if (!switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) {
 
-
-	if ((rtp_session->rtp_bugs & RTP_BUG_NEVER_SEND_MARKER)) {
-		m = 0;
-	} else {
-		if ((rtp_session->last_write_ts != RTP_TS_RESET && rtp_session->ts > (rtp_session->last_write_ts + (rtp_session->samples_per_interval * 10)))
-			|| rtp_session->ts == rtp_session->samples_per_interval) {
-			m++;
+		if ((rtp_session->rtp_bugs & RTP_BUG_NEVER_SEND_MARKER)) {
+			m = 0;
+		} else {
+			if ((rtp_session->last_write_ts != RTP_TS_RESET && rtp_session->ts > (rtp_session->last_write_ts + (rtp_session->samples_per_interval * 10)))
+				|| rtp_session->ts == rtp_session->samples_per_interval) {
+				m++;
+			}
+			
+			if (rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER] && 
+				(rtp_session->timer.samplecount - rtp_session->last_write_samplecount) > rtp_session->samples_per_interval * 10) {
+				m++;
+			}
+			
+			if (!rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER] &&
+				((unsigned) ((switch_micro_time_now() - rtp_session->last_write_timestamp))) > (rtp_session->ms_per_packet * 10)) {
+				m++;
+			}
+			
+			if (rtp_session->cn && payload != rtp_session->cng_pt) {
+				rtp_session->cn = 0;
+				m++;
+			}
+			
+			if (rtp_session->need_mark && !rtp_session->sending_dtmf) {
+				m++;
+				rtp_session->need_mark = 0;
+			}
 		}
 
-		if (rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER] && 
-			(rtp_session->timer.samplecount - rtp_session->last_write_samplecount) > rtp_session->samples_per_interval * 10) {
-			m++;
+		if (m) {
+			rtp_session->last_write_ts = RTP_TS_RESET;
+			rtp_session->ts = 0;
 		}
-
-		if (!rtp_session->flags[SWITCH_RTP_FLAG_USE_TIMER] &&
-			((unsigned) ((switch_micro_time_now() - rtp_session->last_write_timestamp))) > (rtp_session->ms_per_packet * 10)) {
-			m++;
-		}
-
-		if (rtp_session->cn && payload != rtp_session->cng_pt) {
-			rtp_session->cn = 0;
-			m++;
+	
+		/* If the marker was set, and the timestamp seems to have started over - set a new SSRC, to indicate this is a new stream */
+		if (m && !switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND) && (rtp_session->rtp_bugs & RTP_BUG_CHANGE_SSRC_ON_MARKER) && 
+			(rtp_session->last_write_ts == RTP_TS_RESET || (rtp_session->ts <= rtp_session->last_write_ts && rtp_session->last_write_ts > 0))) {
+			switch_rtp_set_ssrc(rtp_session, (uint32_t) ((intptr_t) rtp_session + (uint32_t) switch_epoch_time_now(NULL)));
 		}
 		
-		if (rtp_session->need_mark && !rtp_session->sending_dtmf) {
-			m++;
-			rtp_session->need_mark = 0;
+		if (!switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO) && !switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL)) {
+			send_msg->header.m = (m && !(rtp_session->rtp_bugs & RTP_BUG_NEVER_SEND_MARKER)) ? 1 : 0;
 		}
 	}
 
-	if (m) {
-		rtp_session->last_write_ts = RTP_TS_RESET;
-		rtp_session->ts = 0;
-	}
-
-	/* If the marker was set, and the timestamp seems to have started over - set a new SSRC, to indicate this is a new stream */
-	if (m && !switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_SECURE_SEND) && (rtp_session->rtp_bugs & RTP_BUG_CHANGE_SSRC_ON_MARKER) && 
-		(rtp_session->last_write_ts == RTP_TS_RESET || (rtp_session->ts <= rtp_session->last_write_ts && rtp_session->last_write_ts > 0))) {
-		switch_rtp_set_ssrc(rtp_session, (uint32_t) ((intptr_t) rtp_session + (uint32_t) switch_epoch_time_now(NULL)));
-	}
-
-	if (!switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO) && !switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_UDPTL)) {
-		send_msg->header.m = (m && !(rtp_session->rtp_bugs & RTP_BUG_NEVER_SEND_MARKER)) ? 1 : 0;
-	}
-
 	send_msg->header.ssrc = htonl(rtp_session->ssrc);
 
 	if (rtp_session->flags[SWITCH_RTP_FLAG_GOOGLEHACK] && rtp_session->send_msg.header.pt == 97) {
@@ -5361,18 +5410,19 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
 		}
 	}
 
-	this_ts = ntohl(send_msg->header.ts);
+	if (!switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) {
+		this_ts = ntohl(send_msg->header.ts);
 
-	if (abs(rtp_session->last_write_ts - this_ts) > 16000) {
-		rtp_session->last_write_ts = RTP_TS_RESET;
+		if (abs(rtp_session->last_write_ts - this_ts) > 16000) {
+			rtp_session->last_write_ts = RTP_TS_RESET;
+		}
+
+		if (!switch_rtp_ready(rtp_session) || rtp_session->sending_dtmf || !this_ts || 
+			(rtp_session->last_write_ts > RTP_TS_RESET && this_ts < rtp_session->last_write_ts)) {
+			send = 0;
+		}
 	}
 
-	if (!switch_rtp_ready(rtp_session) || rtp_session->sending_dtmf || !this_ts || 
-		(rtp_session->last_write_ts > RTP_TS_RESET && this_ts < rtp_session->last_write_ts)) {
-		send = 0;
-	}
-
-
 	if (rtp_session->ice.ice_user && !(rtp_session->ice.rready)) {
 		send = 0;
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Skip sending %s packet %ld bytes (ice not ready!)\n", rtp_type(rtp_session), (long)bytes);
@@ -5412,8 +5462,8 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
 
 
 			stat = srtp_protect(rtp_session->send_ctx[rtp_session->srtp_idx_rtp], &send_msg->header, &sbytes);
+			
 			if (stat) {
-				
 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP protection failed with code %d\n", stat);
 			}
 
@@ -5458,8 +5508,6 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
 		rtp_session->send_time = now;
 
 		if (rtp_session->flags[SWITCH_RTP_FLAG_DEBUG_RTP_WRITE]) {
-			
-
 			if (!rtp_session->session) {
 				rtp_session->flags[SWITCH_RTP_FLAG_DEBUG_RTP_WRITE] = 0;
 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "RTP HAS NO SESSION!\n");
@@ -5493,6 +5541,7 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
 			ret = -1;
 			goto end;
 		}
+
 		rtp_session->last_write_ts = this_ts;
 
 		if (rtp_session->queue_delay) {
@@ -5500,8 +5549,6 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
 			rtp_session->queue_delay = 0;
 		}
 
-
-
 		rtp_session->stats.outbound.raw_bytes += bytes;
 		rtp_session->stats.outbound.packet_count++;
 
@@ -5520,15 +5567,6 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
 		
 	}
 
-#if 0
-	if (rtp_session->ice.ice_user) {
-		if (ice_out(rtp_session, &rtp_session->ice) != SWITCH_STATUS_SUCCESS) {
-			ret = -1;
-			goto end;
-		}
-	}
-#endif
-
 	ret = (int) bytes;
 
  end:
@@ -5618,10 +5656,16 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra
 		return -1;
 	}
 	
+	//if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
+	//	rtp_session->flags[SWITCH_RTP_FLAG_DEBUG_RTP_READ]++;
+	//	rtp_session->flags[SWITCH_RTP_FLAG_DEBUG_RTP_WRITE]++;
+	//}
+
+
 	if (switch_test_flag(frame, SFF_PROXY_PACKET) || switch_test_flag(frame, SFF_UDPTL_PACKET) ||
 		rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] || rtp_session->flags[SWITCH_RTP_FLAG_UDPTL]) {
 		
-	//if (rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] || rtp_session->flags[SWITCH_RTP_FLAG_UDPTL]) {
+		//if (rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] || rtp_session->flags[SWITCH_RTP_FLAG_UDPTL]) {
 		switch_size_t bytes;
 		//char bufa[30];
 
@@ -5643,7 +5687,6 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra
 			send_msg->header.ssrc = htonl(rtp_session->ssrc);
 		}
 
-
 		if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, frame->packet, &bytes) != SWITCH_STATUS_SUCCESS) {
 			return -1;
 		}
@@ -5724,7 +5767,7 @@ SWITCH_DECLARE(int) switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_fra
 	if (switch_test_flag(frame, SFF_RTP_HEADER)) {
 		switch_size_t wrote = switch_rtp_write_manual(rtp_session, frame->data, frame->datalen,
 													  frame->m, frame->payload, (uint32_t) (frame->timestamp), &frame->flags);
-
+		
 		rtp_session->stats.outbound.raw_bytes += wrote;
 		rtp_session->stats.outbound.media_bytes += wrote;
 		rtp_session->stats.outbound.media_packet_count++;