From 628edd11832251ee7bc0d23d9a3c74fa56fb468b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 19 Feb 2015 17:08:05 -0600 Subject: [PATCH] FS-7513: add code to track media direction to avoid assigning floor or video layers to those with no signal --- src/include/switch_core_media.h | 1 + src/include/switch_types.h | 7 + .../mod_conference/mod_conference.c | 17 ++- src/switch_core_media.c | 129 ++++++++++++++++-- 4 files changed, 144 insertions(+), 10 deletions(-) diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h index 7f8e886849..d4adedf942 100644 --- a/src/include/switch_core_media.h +++ b/src/include/switch_core_media.h @@ -323,6 +323,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_read_lock_unlock(switch_core_s #define switch_core_media_read_unlock(_s, _t) switch_core_media_read_lock_unlock(_s, _t, SWITCH_FALSE) SWITCH_DECLARE(void) switch_core_session_stop_media(switch_core_session_t *session); +SWITCH_DECLARE(switch_media_flow_t) switch_core_session_media_flow(switch_core_session_t *session, switch_media_type_t type); SWITCH_END_EXTERN_C #endif diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 148e24fdc8..83ae8b168b 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -2475,6 +2475,13 @@ typedef struct payload_map_s { } payload_map_t; +typedef enum { + SWITCH_MEDIA_FLOW_SENDRECV = 0, + SWITCH_MEDIA_FLOW_SENDONLY, + SWITCH_MEDIA_FLOW_RECVONLY, + SWITCH_MEDIA_FLOW_INACTIVE +} switch_media_flow_t; + typedef enum { ICE_GOOGLE_JINGLE = (1 << 0), ICE_VANILLA = (1 << 1), diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index cf4bf13bef..f4179f2615 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -629,6 +629,7 @@ struct conference_member { char *video_logo; char *video_mute_png; char *video_reservation_id; + switch_media_flow_t video_flow; }; typedef enum { @@ -1271,6 +1272,10 @@ static switch_status_t attach_video_layer(conference_member_t *member, int idx) return SWITCH_STATUS_FALSE; } + if (member->video_flow == SWITCH_MEDIA_FLOW_SENDONLY) { + return SWITCH_STATUS_FALSE; + } + switch_mutex_lock(member->conference->canvas->mutex); layer = &member->conference->canvas->layers[idx]; @@ -1677,7 +1682,7 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread } } - if (!layer && conference->canvas->layers_used < conference->canvas->total_layers) { + if (!layer && conference->canvas->layers_used < conference->canvas->total_layers && imember->video_flow != SWITCH_MEDIA_FLOW_SENDONLY) { /* find an empty layer */ for (i = 0; i < conference->canvas->total_layers; i++) { mcu_layer_t *xlayer = &conference->canvas->layers[i]; @@ -3468,6 +3473,10 @@ static void find_video_floor(conference_member_t *member, switch_bool_t entering continue; } + if (imember->video_flow == SWITCH_MEDIA_FLOW_SENDONLY) { + continue; + } + if (!switch_channel_test_flag(imember->channel, CF_VIDEO)) { continue; } @@ -3561,6 +3570,7 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe conference_send_presence(conference); channel = switch_core_session_get_channel(member->session); + member->video_flow = switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO); if (switch_channel_test_flag(channel, CF_VIDEO)) { switch_set_flag_locked(member, MFLAG_ACK_VIDEO); @@ -3753,7 +3763,6 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe switch_mutex_unlock(conference->mutex); status = SWITCH_STATUS_SUCCESS; - find_video_floor(member, SWITCH_TRUE); @@ -3785,6 +3794,10 @@ static void conference_set_video_floor_holder(conference_obj_t *conference, conf return; } + if (member && member->video_flow == SWITCH_MEDIA_FLOW_SENDONLY) { + return; + } + if (conference->video_floor_holder) { if (member && conference->video_floor_holder == member->id) { return; diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 91d342178a..9072cb7aa3 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -155,9 +155,9 @@ typedef struct switch_rtp_engine_s { uint8_t pli; uint8_t nack; uint8_t no_crypto; - switch_codec_settings_t codec_settings; - + switch_media_flow_t rmode; + switch_media_flow_t smode; } switch_rtp_engine_t; struct switch_media_handle_s { @@ -244,6 +244,21 @@ SWITCH_DECLARE(int) switch_core_media_crypto_keylen(switch_rtp_crypto_key_type_t return SUITES[type].keylen; } +static inline switch_media_flow_t sdp_media_flow(unsigned in) +{ + switch(in) { + case sdp_sendonly: + return SWITCH_MEDIA_FLOW_SENDONLY; + case sdp_recvonly: + return SWITCH_MEDIA_FLOW_RECVONLY; + case sdp_sendrecv: + return SWITCH_MEDIA_FLOW_SENDRECV; + case sdp_inactive: + return SWITCH_MEDIA_FLOW_INACTIVE; + } + + return SWITCH_MEDIA_FLOW_SENDRECV; +} static int get_channels(const char *name, int dft) { @@ -1508,6 +1523,13 @@ SWITCH_DECLARE(switch_status_t) switch_media_handle_create(switch_media_handle_t session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].type = SWITCH_MEDIA_TYPE_VIDEO; session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].crypto_type = CRYPTO_INVALID; + + switch_channel_set_variable(session->channel, "video_media_flow", "sendrecv"); + switch_channel_set_variable(session->channel, "audio_media_flow", "sendrecv"); + + session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].smode = SWITCH_MEDIA_FLOW_SENDRECV; + session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].smode = SWITCH_MEDIA_FLOW_SENDRECV; + for (i = 0; i < CRYPTO_INVALID; i++) { session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec[i].crypto_type = i; } @@ -1587,6 +1609,30 @@ SWITCH_DECLARE(int32_t) switch_media_handle_test_media_flag(switch_media_handle_ return smh->media_flags[flag]; } +SWITCH_DECLARE(switch_media_flow_t) switch_core_session_media_flow(switch_core_session_t *session, switch_media_type_t type) +{ + switch_media_flow_t flow = SWITCH_MEDIA_FLOW_SENDRECV; + switch_media_handle_t *smh; + switch_rtp_engine_t *engine = NULL; + + switch_assert(session); + + if (!(smh = session->media_handle)) { + goto end; + } + + if (!smh->media_flags[SCMF_RUNNING]) { + goto end; + } + + engine = &smh->engines[type]; + flow = engine->smode; + + end: + + return flow; +} + SWITCH_DECLARE(switch_status_t) switch_core_session_media_handle_ready(switch_core_session_t *session) { if (session->media_handle && switch_test_flag(session->media_handle, SMF_INIT)) { @@ -2873,7 +2919,6 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ engine->ice_in.pwd = switch_core_session_strdup(smh->session, attr->a_value); } else if (!strcasecmp(attr->a_name, "ice-options")) { engine->ice_in.options = switch_core_session_strdup(smh->session, attr->a_value); - } else if (switch_rtp_has_dtls() && dtls_ok(smh->session) && !strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) { char *p; @@ -3552,6 +3597,25 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s sendonly = 1; } + + a_engine->rmode = sdp_media_flow(m->m_mode); + + if (sdp_type == SDP_TYPE_REQUEST) { + switch(a_engine->rmode) { + case SWITCH_MEDIA_FLOW_RECVONLY: + switch_channel_set_variable(smh->session->channel, "audio_media_flow", "sendonly"); + a_engine->smode = SWITCH_MEDIA_FLOW_SENDONLY; + break; + case SWITCH_MEDIA_FLOW_SENDONLY: + switch_channel_set_variable(smh->session->channel, "audio_media_flow", "recvonly"); + a_engine->smode = SWITCH_MEDIA_FLOW_RECVONLY; + default: + switch_channel_set_variable(smh->session->channel, "audio_media_flow", "sendrecv"); + a_engine->smode = SWITCH_MEDIA_FLOW_SENDRECV; + break; + } + } + for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) { if (zstr(attr->a_name)) { continue; @@ -3596,6 +3660,13 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s switch_channel_set_variable(session->channel, "media_audio_mode", NULL); } + if (sendonly) { + a_engine->smode = sdp_sendonly; + } else if (recvonly) { + a_engine->smode = sdp_recvonly; + } + + if (!(switch_media_handle_test_media_flag(smh, SCMF_DISABLE_HOLD) || ((val = switch_channel_get_variable(session->channel, "rtp_disable_hold")) && switch_true(val))) @@ -4116,6 +4187,26 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s break; } + v_engine->rmode = sdp_media_flow(m->m_mode); + + if (sdp_type == SDP_TYPE_REQUEST) { + switch(v_engine->rmode) { + case SWITCH_MEDIA_FLOW_RECVONLY: + switch_channel_set_variable(smh->session->channel, "video_media_flow", "sendonly"); + v_engine->smode = SWITCH_MEDIA_FLOW_SENDONLY; + break; + case SWITCH_MEDIA_FLOW_SENDONLY: + switch_channel_set_variable(smh->session->channel, "video_media_flow", "recvonly"); + v_engine->smode = SWITCH_MEDIA_FLOW_RECVONLY; + break; + default: + switch_channel_set_variable(smh->session->channel, "video_media_flow", "sendrecv"); + v_engine->smode = SWITCH_MEDIA_FLOW_SENDRECV; + break; + } + } + + for (map = m->m_rtpmaps; map; map = map->rm_next) { if (switch_rtp_has_dtls() && dtls_ok(session)) { @@ -4484,7 +4575,7 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi switch_status_t status; switch_frame_t *read_frame; switch_media_handle_t *smh; - uint32_t loops = 0; + uint32_t loops = 0, xloops = 0; if (!(smh = session->media_handle)) { return NULL; @@ -4500,13 +4591,21 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi switch_core_session_request_video_refresh(session); while (switch_channel_up_nosig(channel)) { + int do_sleep = 0; + if (!switch_channel_test_flag(channel, CF_VIDEO)) { if ((++loops % 100) == 0) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Waiting for video......\n"); switch_yield(20000); continue; } - if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE)) { + if (switch_core_session_media_flow(session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY) { + do_sleep = (++xloops > 20); + } else { + xloops = 0; + } + + if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE) || do_sleep) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread paused. Echo is %s\n", switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off"); switch_thread_cond_wait(mh->cond, mh->cond_mutex); @@ -4515,7 +4614,7 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi switch_core_session_request_video_refresh(session); } - if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE)) { + if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE) || do_sleep) { continue; } @@ -6714,11 +6813,19 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess //} if (zstr(sr)) { - if ((var_val = switch_channel_get_variable(session->channel, "media_audio_mode"))) { - sr = var_val; + if (a_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) { + sr = "sendonly"; + } else if (a_engine->smode == SWITCH_MEDIA_FLOW_RECVONLY) { + sr = "recvonly"; } else { sr = "sendrecv"; } + + //if ((var_val = switch_channel_get_variable(session->channel, "media_audio_mode"))) { + // sr = var_val; + //} else { + // sr = "sendrecv"; + //} } if (!smh->owner_id) { @@ -7185,6 +7292,12 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess if (append_video) { switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_video, end_of(append_video) == '\n' ? "" : "\n"); } + + if (v_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) { + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=sendonly\n"); + } else if (v_engine->smode == SWITCH_MEDIA_FLOW_RECVONLY) { + switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=recvonly\n"); + } } else if (smh->mparams->num_codecs) { int i;