FS-9742 #resolve [Refactor canvas zoom code]

This commit is contained in:
Anthony Minessale 2016-11-15 16:13:23 -06:00
parent 1b268de5e2
commit 2ed50a27ca
4 changed files with 95 additions and 24 deletions

View File

@ -39,6 +39,16 @@
#include <switch.h>
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

View File

@ -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);
}

View File

@ -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 {

View File

@ -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++;