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