]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-8951 #resolve [Video lockup in conference due to race condition]
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 16 Mar 2016 22:38:27 +0000 (17:38 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Wed, 16 Mar 2016 22:38:33 +0000 (17:38 -0500)
src/mod/applications/mod_conference/conference_api.c
src/mod/applications/mod_conference/conference_video.c
src/mod/applications/mod_conference/mod_conference.h

index c1a3ce81b7327963b21f8a1f4d1a5fa83ac7d1d4..0b685d3c3a8ce52dc82597407c382f91304c964a 100644 (file)
@@ -490,11 +490,9 @@ switch_status_t conference_api_sub_unvmute(conference_member_t *member, switch_s
        if (switch_core_session_media_flow(member->session, SWITCH_MEDIA_TYPE_VIDEO) == SWITCH_MEDIA_FLOW_SENDONLY) {
                return SWITCH_STATUS_SUCCESS;
        }
-
-       layer = conference_video_get_layer_locked(member);
-
-       if (layer) {
-               conference_video_clear_layer(layer);
+       
+       if ((layer = conference_video_get_layer_locked(member))) {
+               layer->clear = 1;
                conference_video_release_layer(&layer);
        }
 
index 042bebfc2b157a62b23aa12145a03c0e7799d508..c6fbc4474b68630dff451ecfe619eb914a3aaed3 100644 (file)
@@ -375,6 +375,11 @@ void conference_video_scale_and_patch(mcu_layer_t *layer, switch_image_t *ximg,
                return;
        }
 
+       if (layer->clear) {
+               conference_video_clear_layer(layer);
+               layer->clear = 0;
+       }
+
        if (layer->refresh) {
                switch_img_fill(layer->canvas->img, layer->x_pos, layer->y_pos, layer->screen_w, layer->screen_h, &layer->canvas->letterbox_bgcolor);
                layer->refresh = 0;
@@ -551,14 +556,16 @@ mcu_layer_t *conference_video_get_layer_locked(conference_member_t *member)
        mcu_layer_t *layer = NULL;
        mcu_canvas_t *canvas = NULL;
 
-       if (!member || member->canvas_id < 0 || member->video_layer_id < 0) return NULL;
-
        if ((canvas = conference_video_get_canvas_locked(member))) {
                switch_mutex_lock(canvas->mutex);
-               layer = &canvas->layers[member->video_layer_id];
+
+               if (member->video_layer_id > -1) {
+                       layer = &canvas->layers[member->video_layer_id];
+               }
 
                if (!layer) {
                        switch_mutex_unlock(canvas->mutex);
+                       conference_video_release_canvas(&canvas);
                }
        }
        
@@ -585,10 +592,11 @@ mcu_canvas_t *conference_video_get_canvas_locked(conference_member_t *member)
 {
        mcu_canvas_t *canvas = NULL;
 
-       if (!member || member->canvas_id < 0 || member->video_layer_id < 0) return NULL;
-
        switch_mutex_lock(member->conference->canvas_mutex);
-       canvas = member->conference->canvases[member->canvas_id];
+
+       if (member->canvas_id > -1 && member->video_layer_id > -1) {
+               canvas = member->conference->canvases[member->canvas_id];
+       }
 
        if (!canvas) {
                switch_mutex_unlock(member->conference->canvas_mutex);
@@ -1356,21 +1364,22 @@ void conference_video_vmute_snap(conference_member_t *member, switch_bool_t clea
        if (member->canvas_id > -1 && member->video_layer_id > -1) {
                mcu_layer_t *layer = NULL;
                mcu_canvas_t *canvas = NULL;
-
-               canvas = conference_video_get_canvas_locked(member);
                
-               switch_mutex_lock(canvas->mutex);
-               layer = &canvas->layers[member->video_layer_id];
-               switch_img_free(&layer->mute_img);
-               switch_img_free(&member->video_mute_img);
+               if ((canvas = conference_video_get_canvas_locked(member))) {
+                       
+                       switch_mutex_lock(canvas->mutex);
+                       layer = &canvas->layers[member->video_layer_id];
+                       switch_img_free(&layer->mute_img);
+                       switch_img_free(&member->video_mute_img);
 
-               if (!clear && layer->cur_img) {
-                       switch_img_copy(layer->cur_img, &member->video_mute_img);
-                       switch_img_copy(layer->cur_img, &layer->mute_img);
-               }
+                       if (!clear && layer->cur_img) {
+                               switch_img_copy(layer->cur_img, &member->video_mute_img);
+                               switch_img_copy(layer->cur_img, &layer->mute_img);
+                       }
 
-               switch_mutex_unlock(canvas->mutex);
-               conference_video_release_canvas(&canvas);
+                       switch_mutex_unlock(canvas->mutex);
+                       conference_video_release_canvas(&canvas);
+               }
        }
 }
 
@@ -1539,18 +1548,17 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_write_thread_run(switch_thread_
                                canvas = member->conference->canvases[member->canvas_id];
                                layer = &canvas->layers[member->video_layer_id];
 
-                               if (!layer->need_patch || switch_thread_rwlock_tryrdlock(canvas->video_rwlock) != SWITCH_STATUS_SUCCESS) {
-                                       canvas = NULL;
-                                       layer = NULL;
+                               if (layer->need_patch && switch_thread_rwlock_tryrdlock(canvas->video_rwlock) == SWITCH_STATUS_SUCCESS) {
+                                       if (layer->need_patch) {
+                                               conference_video_scale_and_patch(layer, NULL, SWITCH_FALSE);
+                                               layer->need_patch = 0;
+                                       }
+                                       switch_thread_rwlock_unlock(canvas->video_rwlock);
                                }
                        }
                        switch_mutex_unlock(member->conference->canvas_mutex);
-
-                       if (canvas && layer && layer->need_patch) {
-                               conference_video_scale_and_patch(layer, NULL, SWITCH_FALSE);
-                               layer->need_patch = 0;
-                               switch_thread_rwlock_unlock(canvas->video_rwlock);
-                       }
+                       
+                       
                }
        }
 
@@ -2144,13 +2152,10 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
                int j = 0, personal = conference_utils_test_flag(conference, CFLAG_PERSONAL_CANVAS) ? 1 : 0;
                
                if (!personal) {
-                       switch_mutex_lock(conference->canvas_mutex);
-                       switch_mutex_lock(canvas->mutex);
-                       if (canvas->new_vlayout) {
+                       if (canvas->new_vlayout && switch_mutex_trylock(conference->canvas_mutex) == SWITCH_STATUS_SUCCESS) {
                                conference_video_init_canvas_layers(conference, canvas, NULL);
+                               switch_mutex_unlock(conference->canvas_mutex);
                        }
-                       switch_mutex_unlock(canvas->mutex);
-                       switch_mutex_unlock(conference->canvas_mutex);
                }
 
                if (canvas->video_timer_reset) {
index d4a03cfb2e71bd6ee9d280125560f6316999d453..a32510254a3e1ed89aadbe7d3a511f5f2c14c054 100644 (file)
@@ -439,6 +439,7 @@ typedef struct mcu_layer_s {
        int mute_patched;
        int avatar_patched;
        int refresh;
+       int clear;
        int is_avatar;
        switch_size_t last_img_addr;
        switch_img_position_t logo_pos;