From 2ed50a27ca2b977a613883e12bc42caf0ced221c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 15 Nov 2016 16:13:23 -0600 Subject: [PATCH] FS-9742 #resolve [Refactor canvas zoom code] --- src/include/switch_frame.h | 11 +++ .../mod_conference/conference_video.c | 85 ++++++++++++++----- .../mod_conference/mod_conference.h | 1 + src/mod/applications/mod_cv/mod_cv.cpp | 22 ++++- 4 files changed, 95 insertions(+), 24 deletions(-) diff --git a/src/include/switch_frame.h b/src/include/switch_frame.h index 0307db1ce7..67be1e689f 100644 --- a/src/include/switch_frame.h +++ b/src/include/switch_frame.h @@ -39,6 +39,16 @@ #include SWITCH_BEGIN_EXTERN_C + +struct switch_frame_geometry { + uint32_t w; + uint32_t h; + uint32_t x; + uint32_t y; + uint32_t z; + uint32_t m; +}; + /*! \brief An abstraction of a data frame */ struct switch_frame { /*! a pointer to the codec information */ @@ -75,6 +85,7 @@ SWITCH_BEGIN_EXTERN_C void *user_data; payload_map_t *pmap; switch_image_t *img; + struct switch_frame_geometry geometry; }; SWITCH_END_EXTERN_C diff --git a/src/mod/applications/mod_conference/conference_video.c b/src/mod/applications/mod_conference/conference_video.c index 6db1cbcaf4..8e6baf0247 100644 --- a/src/mod/applications/mod_conference/conference_video.c +++ b/src/mod/applications/mod_conference/conference_video.c @@ -351,6 +351,8 @@ void conference_video_reset_layer(mcu_layer_t *layer) layer->is_avatar = 0; layer->need_patch = 0; + memset(&layer->bug_frame, 0, sizeof(layer->bug_frame)); + if (layer->geometry.overlap) { layer->canvas->refresh = 1; } @@ -379,6 +381,18 @@ void conference_video_scale_and_patch(mcu_layer_t *layer, switch_image_t *ximg, return; } + if (layer->bugged) { + if (layer->member_id > -1 && layer->member && switch_thread_rwlock_tryrdlock(layer->member->rwlock) == SWITCH_STATUS_SUCCESS) { + + layer->bug_frame.img = img; + switch_core_media_bug_patch_video(layer->member->session, &layer->bug_frame); + layer->bug_frame.img = NULL; + switch_thread_rwlock_unlock(layer->member->rwlock); + } + + layer->bugged = 0; + } + if (layer->clear) { conference_video_clear_layer(layer); layer->clear = 0; @@ -406,27 +420,70 @@ void conference_video_scale_and_patch(mcu_layer_t *layer, switch_image_t *ximg, img_addr = (switch_size_t)img; if (layer->last_img_addr != img_addr && layer->geometry.zoom) { + uint32_t new_w = 0, new_h = 0; + unsigned int cropsize = 0; + double scale = 1; + if (screen_aspect < img_aspect) { - unsigned int cropsize = 0; - double scale = 1; + if (img->d_h != layer->screen_h) { scale = (double)layer->screen_h / img->d_h; } - cropsize = (unsigned int)(((img->d_w )-((double)layer->screen_w/scale)) / 2); + new_w = (uint32_t)((double)layer->screen_w / scale); + new_h = (uint32_t)((double)layer->screen_h / scale); + + if (layer->bug_frame.geometry.x) { + if (layer->bug_frame.geometry.x < layer->bug_frame.geometry.w) { + cropsize = 1; + } else { + cropsize = layer->bug_frame.geometry.x - (new_w / 2); + } + } else { + cropsize = (img->d_w - new_w) / 2; + } + + if (cropsize > img->d_w - new_w) { + cropsize = img->d_w - new_w; + } + + if (cropsize < 1) { + cropsize = 1; + } if (cropsize) { - switch_img_set_rect(img, cropsize, 0, (unsigned int)(layer->screen_w/scale), (unsigned int)(layer->screen_h/scale)); + switch_img_set_rect(img, cropsize, 0, new_w, new_h); img_aspect = (double) img->d_w / img->d_h; } } else if (screen_aspect > img_aspect) { - unsigned int cropsize = 0; - double scale = 1; + if (img->d_w != layer->screen_w) { scale = (double)layer->screen_w / img->d_w; } - cropsize = (int)ceil(((img->d_h )-((double)layer->screen_h/scale)) / 2); + + + new_w = (uint32_t)((double)layer->screen_w / scale); + new_h = (uint32_t)((double)layer->screen_h / scale); + + if (layer->bug_frame.geometry.y) { + if (layer->bug_frame.geometry.y < layer->bug_frame.geometry.h) { + cropsize = 1; + } else { + cropsize = layer->bug_frame.geometry.y - (new_h / 2); + } + } else { + cropsize = (img->d_h - new_h) / 2; + } + + if (cropsize > img->d_h - new_h) { + cropsize = img->d_h - new_h; + } + + if (cropsize < 1) { + cropsize = 1; + } + if (cropsize) { switch_img_set_rect(img, 0, cropsize, (unsigned int)(layer->screen_w/scale), (unsigned int)(layer->screen_h/scale)); img_aspect = (double) img->d_w / img->d_h; @@ -479,19 +536,7 @@ void conference_video_scale_and_patch(mcu_layer_t *layer, switch_image_t *ximg, switch_img_scale(img, &layer->img, img_w, img_h); - if (layer->img) { - if (layer->bugged) { - if (layer->member_id > -1 && layer->member && switch_thread_rwlock_tryrdlock(layer->member->rwlock) == SWITCH_STATUS_SUCCESS) { - switch_frame_t write_frame = { 0 }; - write_frame.img = layer->img; - - switch_core_media_bug_patch_video(layer->member->session, &write_frame); - switch_thread_rwlock_unlock(layer->member->rwlock); - } - - layer->bugged = 0; - } - + if (layer->img) { switch_img_patch(IMG, layer->img, x_pos + layer->geometry.border, y_pos + layer->geometry.border); } diff --git a/src/mod/applications/mod_conference/mod_conference.h b/src/mod/applications/mod_conference/mod_conference.h index a042cc551d..cb5c044237 100644 --- a/src/mod/applications/mod_conference/mod_conference.h +++ b/src/mod/applications/mod_conference/mod_conference.h @@ -460,6 +460,7 @@ typedef struct mcu_layer_s { struct mcu_canvas_s *canvas; int need_patch; conference_member_t *member; + switch_frame_t bug_frame; } mcu_layer_t; typedef struct video_layout_s { diff --git a/src/mod/applications/mod_cv/mod_cv.cpp b/src/mod/applications/mod_cv/mod_cv.cpp index dd41719f97..9343030cc2 100644 --- a/src/mod/applications/mod_cv/mod_cv.cpp +++ b/src/mod/applications/mod_cv/mod_cv.cpp @@ -132,6 +132,7 @@ typedef struct cv_context_s { switch_mutex_t *mutex; char *png_prefix; int tick_speed; + int confidence_level; } cv_context_t; @@ -481,6 +482,7 @@ static void init_context(cv_context_t *context) context->png_prefix = switch_core_get_variable_pdup("cv_png_prefix", context->pool); context->cascade_path = switch_core_get_variable_pdup("cv_default_cascade", context->pool); context->nested_cascade_path = switch_core_get_variable_pdup("cv_default_nested_cascade", context->pool); + context->confidence_level = 20; for (int i = 0; i < MAX_OVERLAY; i++) { context->overlay[i] = (struct overlay *) switch_core_alloc(context->pool, sizeof(struct overlay)); @@ -619,7 +621,7 @@ void detectAndDraw(cv_context_t *context) center.y = switch_round_to_step(cvRound((r->y + r->height*0.5)*scale), 20); radius = switch_round_to_step(cvRound((r->width + r->height)*0.25*scale), 20); - if (context->debug || !context->overlay_count) { + if (context->debug) { circle( img, center, radius, color, 3, 8, 0 ); } @@ -641,7 +643,7 @@ void detectAndDraw(cv_context_t *context) context->shape[context->shape_idx].cx = context->shape[context->shape_idx].x + (context->shape[context->shape_idx].w / 2); context->shape[context->shape_idx].cy = context->shape[context->shape_idx].y + (context->shape[context->shape_idx].h / 2); - if (context->debug || !context->overlay_count) { + if (context->debug) { rectangle( img, cvPoint(context->shape[context->shape_idx].x, context->shape[context->shape_idx].y), cvPoint(context->shape[context->shape_idx].x2, context->shape[context->shape_idx].y2), color, 3, 8, 0); @@ -723,7 +725,7 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi switch_img_to_raw(frame->img, context->rawImage->imageData, context->rawImage->widthStep, SWITCH_IMG_FMT_RGB24); detectAndDraw(context); - if (context->detected.simo_count > 20) { + if (context->detected.simo_count > context->confidence_level) { if (!context->detect_event) { context->detect_event = 1; @@ -743,7 +745,7 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi } } else { - if (context->detected.simo_miss_count >= 20) { + if (context->detected.simo_miss_count >= context->confidence_level) { if (context->detect_event) { if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_VIDEO_DETECT) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Detect-Type", "primary"); @@ -826,6 +828,16 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi } } + if (context->detect_event) { + frame->geometry.x = context->shape[0].cx; + frame->geometry.y = context->shape[0].cy; + frame->geometry.w = context->shape[0].w; + frame->geometry.h = context->shape[0].h; + frame->geometry.m = 1; + } else { + frame->geometry.m = 0; + } + if (context->overlay_count && (abs || (context->detect_event && context->shape[0].cx))) { for (i = 0; i < context->overlay_count; i++) { struct overlay *overlay = context->overlay[i]; @@ -989,6 +1001,8 @@ static void parse_params(cv_context_t *context, int start, int argc, char **argv context->skip = atoi(val); } else if (!strcasecmp(name, "debug")) { context->debug = atoi(val); + } else if (!strcasecmp(name, "confidence")) { + context->confidence_level = atoi(val); } else if (!strcasecmp(name, "cascade")) { context->cascade_path = switch_core_strdup(context->pool, val); changed++;