]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7513: add code to track media direction to avoid assigning floor or video layers...
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 19 Feb 2015 23:08:05 +0000 (17:08 -0600)
committerMichael Jerris <mike@jerris.com>
Thu, 28 May 2015 17:47:03 +0000 (12:47 -0500)
src/include/switch_core_media.h
src/include/switch_types.h
src/mod/applications/mod_conference/mod_conference.c
src/switch_core_media.c

index 7f8e8868493c94d45c4239f27e74862e68ffa085..d4adedf9429f6fae5ae2beb6e0f9089bc54055b1 100644 (file)
@@ -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
index 148e24fdc8e4f52ce621ad4bfd3eddf9e99695c8..83ae8b168b16b021c0463b22adb3ef9cc18f5a1b 100644 (file)
@@ -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),
index cf4bf13befb81c58c4f5024dd0c067363819b771..f4179f2615c860569211b8c7843f9d4de15ff83d 100644 (file)
@@ -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;
index 91d342178a9753cdb64e80e10c4b93f0cafa5dcb..9072cb7aa33d4506d0fdc60464fed9abf9d1354e 100644 (file)
@@ -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;