1
0
mirror of https://github.com/signalwire/freeswitch.git synced 2025-03-05 18:13:27 +00:00

FS-7515: add more features to mod_cv

This commit is contained in:
Anthony Minessale 2015-04-16 15:38:49 -05:00 committed by Michael Jerris
parent 40d0e1fdd7
commit 93c841d9e8
2 changed files with 282 additions and 135 deletions
src
mod/applications/mod_cv
switch_core_video.c

@ -88,13 +88,14 @@ struct overlay {
float xo;
float yo;
float shape_scale;
int scale_w;
int scale_h;
int zidx;
switch_img_position_t abs;
};
typedef struct cv_context_s {
IplImage *rawImage;
IplImage *yuvImage;
CascadeClassifier *cascade;
CascadeClassifier *nestedCascade;
int w;
@ -130,20 +131,93 @@ static int clear_overlay(cv_context_t *context, int idx)
return 0;
}
context->overlay[idx]->png_path = NULL;
context->overlay[idx]->nick = NULL;
switch_img_free(&context->overlay[idx]->png);
memset(context->overlay[idx], 0, sizeof(struct overlay));
context->overlay[idx]->shape_scale = 1;
context->overlay_count--;
for (x = idx + 1; x < i; x++) {
context->overlay[x-1] = context->overlay[x];
memset(context->overlay[x], 0, sizeof(struct overlay));
context->overlay[x]->shape_scale = 1;
}
return idx - 1 > 0 ? idx -1 : 0;
}
static int add_text(cv_context_t *context, const char *nick, const char *fg, const char *bg, const char *font_face, int font_size, const char *text)
{
uint32_t i = context->overlay_count;
switch_rgb_color_t fgcolor, bgcolor;
int x = 0, width = 0, is_new = 1;
switch_img_txt_handle_t *txthandle = NULL;
for (x = 0; x < i; x++) {
if (context->overlay[x] && context->overlay[x]->png) {
if (!zstr(nick)) {
if (!zstr(context->overlay[x]->nick) && !strcmp(context->overlay[x]->nick, nick)) {
i = x;
is_new = 0;
break;
}
} else {
if (strstr(context->overlay[x]->png_path, text)) {
if (!zstr(nick) && (zstr(context->overlay[x]->nick) || strcmp(nick, context->overlay[x]->nick))) {
context->overlay[x]->nick = switch_core_strdup(context->pool, nick);
}
i = x;
is_new = 0;
break;
}
}
}
}
if (is_new) {
context->overlay_count++;
if (!zstr(nick)) {
context->overlay[i]->nick = switch_core_strdup(context->pool, nick);
}
}
if (!font_size) {
font_size = 24;
}
if (!font_face) {
font_face = "FreeMono.ttf";
}
if (!fg) {
fg = "#cccccc";
}
if (!bg) {
bg = "#142e55";
}
width = (int) (float)(font_size * 0.75f * strlen(text));
switch_color_set_rgb(&fgcolor, fg);
switch_color_set_rgb(&bgcolor, bg);
switch_img_free(&context->overlay[i]->png);
context->overlay[i]->png = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, width, font_size * 2, 1);
switch_img_fill(context->overlay[i]->png, 0, 0, context->overlay[i]->png->d_w, context->overlay[i]->png->d_h, &bgcolor);
switch_img_txt_handle_create(&txthandle, font_face, fg, bg, font_size, 0, NULL);
switch_img_txt_handle_render(txthandle, context->overlay[i]->png, font_size / 2, font_size / 2, text, NULL, fg, bg, 0, 0);
switch_img_txt_handle_destroy(&txthandle);
return i;
}
static int add_overlay(cv_context_t *context, const char *png_path, const char *nick)
{
uint32_t i = context->overlay_count;
@ -159,6 +233,9 @@ static int add_overlay(cv_context_t *context, const char *png_path, const char *
}
} else {
if (strstr(context->overlay[x]->png_path, png_path)) {
if (!zstr(nick) && (zstr(context->overlay[x]->nick) || strcmp(nick, context->overlay[x]->nick))) {
context->overlay[x]->nick = switch_core_strdup(context->pool, nick);
}
return x;
}
}
@ -182,8 +259,6 @@ static int add_overlay(cv_context_t *context, const char *png_path, const char *
if (!zstr(nick)) {
context->overlay[i]->nick = switch_core_strdup(context->pool, nick);
}
if (!context->overlay[i]->shape_scale) context->overlay[i]->shape_scale = 1;
r = (int) i;
} else {
context->overlay[i]->png_path = NULL;
@ -236,6 +311,7 @@ static void uninit_context(cv_context_t *context)
context->overlay[i]->png_path = NULL;
context->overlay_count = 0;
memset(context->overlay[i], 0, sizeof(struct overlay));
context->overlay[i]->shape_scale = 1;
}
switch_core_destroy_memory_pool(&context->pool);
@ -256,6 +332,7 @@ static void init_context(cv_context_t *context)
for (int i = 0; i < MAX_OVERLAY; i++) {
context->overlay[i] = (struct overlay *) switch_core_alloc(context->pool, sizeof(struct overlay));
context->overlay[i]->abs = POS_NONE;
context->overlay[i]->shape_scale = 1;
}
create = 1;
@ -461,36 +538,36 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
{
cv_context_t *context = (cv_context_t *) user_data;
switch_channel_t *channel = switch_core_session_get_channel(session);
int i;
if (!switch_channel_ready(channel)) {
return SWITCH_STATUS_FALSE;
}
if (frame->img) {
if (!frame->img) {
return SWITCH_STATUS_SUCCESS;
}
if (context->cascade) {
switch_event_t *event;
if ((frame->img->d_w != context->w || frame->img->d_h != context->h) && context->rawImage) {
cvReleaseImage(&context->rawImage);
cvReleaseImage(&context->yuvImage);
}
if (!context->rawImage) {
context->rawImage = cvCreateImage(cvSize(frame->img->d_w, frame->img->d_h), IPL_DEPTH_8U, 3);
context->yuvImage = cvCreateImage(cvSize(frame->img->d_w, frame->img->d_h), IPL_DEPTH_8U, 3);
switch_assert(context->rawImage);
switch_assert(context->rawImage->width * 3 == context->rawImage->widthStep);
}
//printf("context->rawImage: %dx%d stride: %d size: %d color:%s\n", context->rawImage->width, context->rawImage->height, context->rawImage->widthStep, context->rawImage->imageSize, context->rawImage->colorModel);
libyuv::I420ToRGB24(frame->img->planes[0], frame->img->stride[0],
frame->img->planes[1], frame->img->stride[1],
frame->img->planes[2], frame->img->stride[2],
(uint8_t *)context->rawImage->imageData, context->rawImage->widthStep,
context->rawImage->width, context->rawImage->height);
if (context->cascade) {
switch_event_t *event;
detectAndDraw(context);
if (context->detected.simo_count > 20) {
@ -595,9 +672,15 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
context->rawImage->width, context->rawImage->height);
}
if (context->overlay_count && context->detect_event && context->shape[0].cx) {
int i;
int abs = 0;
for (i = 0; i < context->overlay_count; i++) {
if (context->overlay[i]->abs != POS_NONE) {
abs++;
}
}
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];
int x = 0, y = 0;
@ -607,6 +690,10 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
int shape_w, shape_h;
int cx, cy;
if (context->overlay[i]->abs == POS_NONE && !context->detect_event && !context->shape[0].cx) {
continue;
}
shape_w = context->shape[0].w;
shape_h = context->shape[0].h;
@ -615,11 +702,24 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
if (overlay->abs != POS_NONE) {
if (overlay->shape_scale != 1) {
if (overlay->scale_w || overlay->scale_h) {
if (overlay->scale_w && !overlay->scale_h) {
scale_w = frame->img->d_w;
scale_h = ((overlay->png->d_h * scale_w) / overlay->png->d_w);
} else if (overlay->scale_h && !overlay->scale_w) {
scale_h = frame->img->d_h;
scale_w = ((overlay->png->d_w * scale_h) / overlay->png->d_h);
} else {
scale_w = frame->img->d_w;
scale_h = frame->img->d_h;
}
} else if (overlay->shape_scale != 1) {
scale_w = overlay->png->d_w * overlay->shape_scale;
if (scale_w > frame->img->d_w) {
scale_w = frame->img->d_w;
}
scale_h = ((overlay->png->d_h * scale_w) / overlay->png->d_w);
} else {
scale_w = overlay->png->d_w;
@ -656,8 +756,6 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
}
}
}
return SWITCH_STATUS_SUCCESS;
}
@ -701,7 +799,6 @@ static void parse_params(cv_context_t *context, int start, int argc, char **argv
}
if (name && val) {
if (!strcasecmp(name, "xo")) {
context->overlay[png_idx]->xo = atof(val);
} else if (!strcasecmp(name, "nick")) {
@ -714,6 +811,25 @@ static void parse_params(cv_context_t *context, int start, int argc, char **argv
sort++;
} else if (!strcasecmp(name, "abs")) {
context->overlay[png_idx]->abs = parse_img_position(val);
if (context->overlay[png_idx]->abs == POS_NONE) {
context->overlay[png_idx]->scale_w = context->overlay[png_idx]->scale_h = 0;
}
} else if (!strcasecmp(name, "scaleto") && context->overlay[png_idx]->abs != POS_NONE) {
if (strchr(val, 'W')) {
context->overlay[png_idx]->scale_w = 1;
}
if (strchr(val, 'H')) {
context->overlay[png_idx]->scale_h = 1;
}
if (strchr(val, 'w')) {
context->overlay[png_idx]->scale_w = 0;
}
if (strchr(val, 'h')) {
context->overlay[png_idx]->scale_h = 0;
}
} else if (!strcasecmp(name, "scale")) {
context->overlay[png_idx]->shape_scale = atof(val);
} else if (!strcasecmp(name, "skip")) {
@ -728,10 +844,26 @@ static void parse_params(cv_context_t *context, int start, int argc, char **argv
changed++;
} else if (!strcasecmp(name, "png")) {
png_idx = add_overlay(context, val, nick);
} else if (!strcasecmp(name, "txt")) {
int iargc = 0;
char *iargv[10] = { 0 };
iargc = switch_split(val, ':', iargv);
if (iargc >= 5) {
png_idx = add_text(context, nick, iargv[0], iargv[1], iargv[2], atoi(iargv[3]), iargv[4]);
}
}
} else if (name) {
if (!strcasecmp(name, "clear")) {
png_idx = clear_overlay(context, png_idx);
} else if (!strcasecmp(name, "allclear")) {
for (int x = context->overlay_count - 1; x >= 0; x--) {
png_idx = clear_overlay(context, x);
context->overlay[x]->xo = context->overlay[x]->yo = context->overlay[x]->shape_scale = 0.0f;
context->overlay[x]->zidx = 0;
context->overlay[x]->scale_w = context->overlay[x]->scale_h = 0;
context->overlay[x]->shape_scale = 1;
}
} else if (!strcasecmp(name, "home")) {
context->overlay[png_idx]->xo = context->overlay[png_idx]->yo = context->overlay[png_idx]->shape_scale = 0.0f;
context->overlay[png_idx]->zidx = 0;

@ -507,7 +507,22 @@ SWITCH_DECLARE(switch_status_t) switch_img_txt_handle_create(switch_img_txt_hand
new_handle->pool = pool;
new_handle->free_pool = free_pool;
if (!switch_is_file_path(font_family)) {
new_handle->font_family = switch_core_sprintf(new_handle->pool, "%s%s%s",SWITCH_GLOBAL_dirs.fonts_dir, SWITCH_PATH_SEPARATOR, font_family);
} else {
new_handle->font_family = switch_core_strdup(new_handle->pool, font_family);
}
if (switch_file_exists(new_handle->font_family, new_handle->pool) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Font %s does not exist\n", new_handle->font_family);
if (free_pool) {
switch_core_destroy_memory_pool(&pool);
}
*handleP = NULL;
return SWITCH_STATUS_FALSE;
}
new_handle->font_size = font_size;
new_handle->angle = angle;