]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
refactor some of the video passthru code
authorAnthony Minessale <anthm@freeswitch.org>
Tue, 18 Jun 2013 00:52:37 +0000 (19:52 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Tue, 18 Jun 2013 00:52:37 +0000 (19:52 -0500)
14 files changed:
src/include/switch_core.h
src/include/switch_core_media.h
src/include/switch_rtp.h
src/include/switch_types.h
src/mod/applications/mod_conference/mod_conference.c
src/mod/applications/mod_fsv/mod_fsv.c
src/mod/endpoints/mod_sofia/mod_sofia.c
src/switch_channel.c
src/switch_core_media.c
src/switch_core_session.c
src/switch_core_state_machine.c
src/switch_ivr_async.c
src/switch_ivr_bridge.c
src/switch_rtp.c

index d77014dd3f007431edbccbae10e405b8d324126b..ff2ddd269dd027c1adafeaa2711bd168828333c8 100644 (file)
@@ -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
index 9f15ecd50ac363f309ef462d6cb5840b76d4a9fd..6379a88e6f4d1ce258169f2449c3ee9a6e39d957 100644 (file)
@@ -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
index 16c7eef86b7f7aaa085168e469e677a25866548b..38ac6ed2a40c6a6d16789449f2a7071a5d3eb6d3 100644 (file)
@@ -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);
 
 /*!
   \}
index aced0286824bcd90190fa77bc416e2c128cec536..7c24a81378af04a774c2a5ac232af8a5bfaa282a 100644 (file)
@@ -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
index ce5dec977c6e6fc99ca4a6c00887db724857e471..f282a8b26646980b024912afe5ec824ca6403b2f 100644 (file)
@@ -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);
index 8eecd58e1e36f24719f20026969565027f731d2e..20f09a48517b33398a430ff3f093a8a70ddac3c8 100644 (file)
@@ -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 {
index 0e21566aef9f8685fd0e22a6753a068ca3cd8d4c..761d4ea5c09479810094b0b35e98b146eaea8b75 100644 (file)
@@ -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:
index 8d98caa635fe8a9bb6ab50539715c490e6a7b945..c4812f47a37a39114f2bc4542fb3cb8da881c95a 100644 (file)
@@ -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);
+       }
+
 }
 
 
index 6da434a82f1c72c2505dae624f6cef6f8a7c8efb..d456d5858586775e8c2cf74f2638b64b14f27187 100644 (file)
@@ -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,
+
+                                               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
+                                                                                                       ICE_GOOGLE_JINGLE,
+                                                                                                       NULL
 #else
-                                                                                               switch_channel_direction(session->channel) == 
-                                                                                               SWITCH_CALL_DIRECTION_OUTBOUND ? ICE_VANILLA : ICE_VANILLA | ICE_CONTROLLED,
-                                                                                               
-                                                                                               &v_engine->ice_in
+                                                                                                       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)) {
index 656f8bd058368befcb8bbb502ece29895496b178..050069168a3b44c3396d9a2239932da92ccd5f3f 100644 (file)
@@ -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
index 44ed10ed80b6c95055ccb082e4093620c1b45131..e9353c15cc4bbde1fdded814393da4b103f71129 100644 (file)
@@ -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) { \
index 462aff32c7abdf9b8e01ede3246fe32256c82d06..b7a6c012880da727667e674b4ecfd73c39de75ea 100644 (file)
@@ -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;
 }
 
index 0df636cac5ab01b3dd759dd9a9cf4de40e36f0d8..b06566fb48a5c68643be341da07d11ca8af6f051 100644 (file)
@@ -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)) {
+                       continue;
                }
 
-               if (!switch_test_flag(read_frame, SFF_CNG)) {
+               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;
 }
index 8f2201924c3e6f31aa3a5a5dad90ccb191086f4d..0e381d082587309889c17e0d229c1add41193a3e 100644 (file)
@@ -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
 
-static int check_srtp_and_ice(switch_rtp_t *rtp_session)
+#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;
+               }
+       }
+
+
+ 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->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->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] &&
-                       ((unsigned) ((switch_micro_time_now() - rtp_session->last_write_timestamp))) > (rtp_session->ms_per_packet * 10)) {
-                       m++;
+               if (m) {
+                       rtp_session->last_write_ts = RTP_TS_RESET;
+                       rtp_session->ts = 0;
                }
-
-               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++;