]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7515: expand on overlays
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 15 Apr 2015 16:19:30 +0000 (11:19 -0500)
committerMichael Jerris <mike@jerris.com>
Thu, 28 May 2015 17:47:20 +0000 (12:47 -0500)
src/mod/applications/mod_cv/mod_cv.cpp

index f43261182c72caed6ab945741aedcb7de32624d2..729e1fd4fa51f73cce0089b870e944339416b2cd 100644 (file)
@@ -79,6 +79,16 @@ struct shape {
 };
 
 #define MAX_SHAPES 32
+#define MAX_OVERLAY 32
+
+struct overlay {
+    char *png_path;
+    char *nick;
+    switch_image_t *png;
+    float x_off;
+    float y_off;
+    float shape_scale;
+};
 
 typedef struct cv_context_s {
     IplImage *rawImage;
@@ -91,23 +101,85 @@ typedef struct cv_context_s {
     struct detect_stats nestDetected;
     int detect_event;
     int nest_detect_event;
-    switch_image_t *png;
     struct shape shape[MAX_SHAPES];
-    int shapeidx;
-    float x_off;
-    float y_off;
-    float shape_scale;
+    int shape_idx;
     int32_t skip;
     int32_t skip_count;
     uint32_t debug;
+    struct overlay overlay[MAX_OVERLAY];
+    uint32_t overlay_idx;
+    uint32_t overlay_count;
        switch_core_session_t *session;
     char *cascade_path;
     char *nested_cascade_path;
-    char *png_path;
     switch_memory_pool_t *pool;
     switch_mutex_t *mutex;
+    char *png_prefix;
 } cv_context_t;
 
+
+static int clear_overlay(cv_context_t *context, int idx)
+{
+    uint32_t i = context->overlay_count;
+    switch_image_t *png;
+    int r = -1, x;
+
+    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_count--;
+
+    for (x = idx + 1; x < i; x++) {
+        context->overlay[x-1] = context->overlay[x];
+        memset(&context->overlay[x], 0, sizeof(struct overlay));
+    }
+
+    return idx - 1 > 0 ? idx -1 : 0;
+}
+
+static int add_overlay(cv_context_t *context, const char *png_path, const char *nick)
+{
+    uint32_t i = context->overlay_count;
+    switch_image_t *png;
+    int r = -1, x;
+
+    for (x = 0; x < i; x++) {
+        if (context->overlay[x].png_path) {
+            if (!zstr(nick)) {
+                if (!zstr(context->overlay[x].nick) && !strcmp(context->overlay[x].nick, nick)) {
+                    return x;
+                }
+            } else {
+                if (strstr(context->overlay[x].png_path, png_path)) {
+                    return x;
+                }
+            }
+        }
+    }
+
+    if (context->png_prefix) {
+        context->overlay[i].png_path = switch_core_sprintf(context->pool, "%s%s%s", context->png_prefix, SWITCH_PATH_SEPARATOR, png_path);
+    } else {
+        context->overlay[i].png_path = switch_core_strdup(context->pool, png_path);
+    }
+
+    if ((png = switch_img_read_png(context->overlay[i].png_path, SWITCH_IMG_FMT_ARGB))) {
+        context->overlay[i].png = png;
+        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;
+        context->overlay_count++;
+        r = (int) i;
+    } else {
+        context->overlay[i].png_path = NULL;
+    }
+
+    return r;
+}
+
+
 static void uninit_context(cv_context_t *context);
 
 static const float coef1 = 0.3190;
@@ -136,12 +208,21 @@ static void reset_context(cv_context_t *context)
         delete nestedCascade;
     }
 
-    switch_img_free(&context->png);
 }
 
 static void uninit_context(cv_context_t *context)
 {
+    int i = 0;
+
     reset_context(context);
+
+    for (i = 0; i < context->overlay_count; i++) {
+        switch_img_free(&context->overlay[i].png);
+        context->overlay[i].png_path = NULL;
+        context->overlay_count = 0;
+        memset(&context->overlay[i], 0, sizeof(struct overlay));
+    }
+
     switch_core_destroy_memory_pool(&context->pool);
 }
 
@@ -153,6 +234,7 @@ static void init_context(cv_context_t *context)
     if (!context->pool) {
         switch_core_new_memory_pool(&context->pool);
         switch_mutex_init(&context->mutex, SWITCH_MUTEX_NESTED, context->pool);
+        context->png_prefix = switch_core_get_variable_pdup("cv_png_prefix", context->pool);
         create = 1;
     }
 
@@ -172,12 +254,7 @@ static void init_context(cv_context_t *context)
         }
     }
 
-    if (context->png_path) {
-        context->png = switch_img_read_png(context->png_path, SWITCH_IMG_FMT_ARGB);
-    }
-
     switch_mutex_unlock(context->mutex);
-    
 }
 
 
@@ -267,7 +344,7 @@ void detectAndDraw(cv_context_t *context)
 
     //printf("SCORE: %d %f %d\n", context->detected.simo_count, context->detected.avg, context->detected.last_score);
 
-    context->shapeidx = 0;
+    context->shape_idx = 0;
     //memset(context->shape, 0, sizeof(context->shape[0]) * MAX_SHAPES);
 
     for( vector<Rect>::iterator r = detectedObjs.begin(); r != detectedObjs.end(); r++, i++ ) {
@@ -279,7 +356,7 @@ void detectAndDraw(cv_context_t *context)
         
         double aspect_ratio = (double)r->width/r->height;
 
-        if (context->shapeidx >= MAX_SHAPES) {
+        if (context->shape_idx >= MAX_SHAPES) {
             break;
         }
         
@@ -289,35 +366,35 @@ 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->png) {
+            if (context->debug || !context->overlay_count) {
                 circle( img, center, radius, color, 3, 8, 0 );
             }
 
-            context->shape[context->shapeidx].x = center.x - radius;
-            context->shape[context->shapeidx].y = center.y - radius;
-            context->shape[context->shapeidx].cx = center.x;
-            context->shape[context->shapeidx].cy = center.y;
-            context->shape[context->shapeidx].radius = radius;
-            context->shape[context->shapeidx].w = context->shape[context->shapeidx].h = radius * 2;
-            context->shapeidx++;
+            context->shape[context->shape_idx].x = center.x - radius;
+            context->shape[context->shape_idx].y = center.y - radius;
+            context->shape[context->shape_idx].cx = center.x;
+            context->shape[context->shape_idx].cy = center.y;
+            context->shape[context->shape_idx].radius = radius;
+            context->shape[context->shape_idx].w = context->shape[context->shape_idx].h = radius * 2;
+            context->shape_idx++;
 
         } else {
-            context->shape[context->shapeidx].x = switch_round_to_step(cvRound(r->x*scale), 40);
-            context->shape[context->shapeidx].y = switch_round_to_step(cvRound(r->y*scale), 20);
-            context->shape[context->shapeidx].x2 = switch_round_to_step(cvRound((r->x + r->width-1)*scale), 40);
-            context->shape[context->shapeidx].y2 = switch_round_to_step(cvRound((r->y + r->height-1)*scale), 20);
-            context->shape[context->shapeidx].w = context->shape[context->shapeidx].x2 - context->shape[context->shapeidx].x;
-            context->shape[context->shapeidx].h = context->shape[context->shapeidx].y2 - context->shape[context->shapeidx].y;
-            context->shape[context->shapeidx].cx = context->shape[context->shapeidx].x + (context->shape[context->shapeidx].w / 2);
-            context->shape[context->shapeidx].cy = context->shape[context->shapeidx].y + (context->shape[context->shapeidx].h / 2);
+            context->shape[context->shape_idx].x = switch_round_to_step(cvRound(r->x*scale), 40);
+            context->shape[context->shape_idx].y = switch_round_to_step(cvRound(r->y*scale), 20);
+            context->shape[context->shape_idx].x2 = switch_round_to_step(cvRound((r->x + r->width-1)*scale), 40);
+            context->shape[context->shape_idx].y2 = switch_round_to_step(cvRound((r->y + r->height-1)*scale), 20);
+            context->shape[context->shape_idx].w = context->shape[context->shape_idx].x2 - context->shape[context->shape_idx].x;
+            context->shape[context->shape_idx].h = context->shape[context->shape_idx].y2 - context->shape[context->shape_idx].y;
+            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->png) {
-                rectangle( img, cvPoint(context->shape[context->shapeidx].x, context->shape[context->shapeidx].y),
-                           cvPoint(context->shape[context->shapeidx].x2, context->shape[context->shapeidx].y2),
+            if (context->debug || !context->overlay_count) {
+                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);
             }
 
-            context->shapeidx++;
+            context->shape_idx++;
         }
 
         if(!context->nestedCascade || context->nestedCascade->empty() ) {
@@ -495,46 +572,50 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
                                 context->rawImage->width, context->rawImage->height);
         }
 
-        if (context->png && context->detect_event && context->shape[0].cx) {
-            int x = 0, y = 0;
-            switch_image_t *img = NULL;
-            int scale_w = 0, scale_h = 0;
-            int x_off = 0, y_off = 0;
-            int shape_w, shape_h;
-            int cx, cy;
+        if (context->overlay_count && context->detect_event && context->shape[0].cx) {
+            int i;
 
-            shape_w = context->shape[0].w;
-            shape_h = context->shape[0].h;
-            
-            cx = context->shape[0].cx;
-            cy = context->shape[0].cy;
-            
-            scale_w = shape_w * context->shape_scale;
-            if (scale_w > frame->img->d_w) {
-                scale_w = frame->img->d_w;
-            }
-            scale_h = ((context->png->d_h * scale_w) / context->png->d_w);
+            for (i = 0; i < context->overlay_count; i++) {
+                struct overlay *overlay = &context->overlay[i];
+                int x = 0, y = 0;
+                switch_image_t *img = NULL;
+                int scale_w = 0, scale_h = 0;
+                int x_off = 0, y_off = 0;
+                int shape_w, shape_h;
+                int cx, cy;
 
-            if (context->x_off) {
-                x_off = context->x_off * shape_w;
-            }
+                shape_w = context->shape[0].w;
+                shape_h = context->shape[0].h;
             
-            if (context->y_off) {
-                y_off = context->y_off * context->shape[0].h;
-            }
+                cx = context->shape[0].cx;
+                cy = context->shape[0].cy;
+            
+                scale_w = shape_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);
+                
+                if (overlay->x_off) {
+                    x_off = overlay->x_off * shape_w;
+                }
+                
+                if (overlay->y_off) {
+                    y_off = overlay->y_off * context->shape[0].h;
+                }
 
-            x = cx - ((scale_w / 2) + x_off);
-            y = cy - ((scale_h / 2) + y_off);
+                x = cx - ((scale_w / 2) + x_off);
+                y = cy - ((scale_h / 2) + y_off);
             
 
-            switch_img_scale(context->png, &img, scale_w, scale_h);
+                switch_img_scale(overlay->png, &img, scale_w, scale_h);
 
-            if (img) {
-                switch_img_patch(frame->img, img, x, y);
-                switch_img_free(&img);
+                if (img) {
+                    switch_img_patch(frame->img, img, x, y);
+                    switch_img_free(&img);
+                }
             }
 
-            // switch_png_patch_img(context->png, frame->img, x, y);
         } else if (!context->debug) {
             libyuv::RGB24ToI420((uint8_t *)context->rawImage->imageData, w * 3,
                                 frame->img->planes[0], frame->img->stride[0],
@@ -550,8 +631,11 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
 
 static void parse_params(cv_context_t *context, int start, int argc, char **argv)
 {
-    int i, changed = 0;
+    int i, changed = 0, png_idx = 0, png_count = 0;
+    char *nick = NULL;
 
+    png_count = context->overlay_count;
+    
     for (i = start; i < argc ; i ++) {
         char *name = strdup(argv[i]);
         char *val = NULL;
@@ -563,11 +647,14 @@ static void parse_params(cv_context_t *context, int start, int argc, char **argv
         if (name && val) {
 
             if (!strcasecmp(name, "x_off")) {
-                context->x_off = atof(val);
+                context->overlay[png_idx].x_off = atof(val);
+            } else if (!strcasecmp(name, "nick")) {
+                switch_safe_free(nick);
+                nick = strdup(val);
             } else if (!strcasecmp(name, "y_off")) {
-                context->y_off = atof(val);
+                context->overlay[png_idx].y_off = atof(val);
             } else if (!strcasecmp(name, "scale")) {
-                context->shape_scale = atof(val);
+                context->overlay[png_idx].shape_scale = atof(val);
             } else if (!strcasecmp(name, "skip")) {
                 context->skip = atoi(val);
             } else if (!strcasecmp(name, "debug")) {
@@ -579,16 +666,24 @@ static void parse_params(cv_context_t *context, int start, int argc, char **argv
                 context->nested_cascade_path = switch_core_strdup(context->pool, val);
                 changed++;
             } else if (!strcasecmp(name, "png")) {
-                context->png_path = switch_core_strdup(context->pool, val);
-                changed++;
+                png_idx = add_overlay(context, val, nick);
+            }
+        } else if (name) {
+            if (!strcasecmp(name, "clear")) {
+                png_idx = clear_overlay(context, png_idx);
             }
         }
 
         free(name);
     }
 
+    switch_safe_free(nick);
+
+    if (context->overlay_count != png_count) {
+        changed++;
+    }
+
     if (!context->skip) context->skip = 1;
-    if (!context->shape_scale) context->shape_scale = 1;
 
     if (changed) {
         init_context(context);