]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7824 Add functionality for capturing screenshots from both legs to uuid_write_png
authorBradley Jokinen <bradleyjokinen@reliancetelephone.com>
Mon, 13 Jul 2015 14:26:16 +0000 (09:26 -0500)
committerBradley Jokinen <bradleyjokinen@reliancetelephone.com>
Mon, 13 Jul 2015 14:35:38 +0000 (09:35 -0500)
With this patch, uuid_write_png is able to capture screenshots from both
legs of a bridged video call. It still expects a uuid and filename for
the first two arguments. If given a third argument, it must be concat
or split. If concat is specified, screenshots from both ends are taken
and written side by side to the given filename. If one image is shorter
than the other then it is padded with black and vertically centered. If
the third argument is split then the two screenshots are written to
separate files. In this case, a second filename is expected as a fourth
argument.

src/mod/formats/mod_png/mod_png.c

index 63936d1aefad6d29174125d14e2dc169d78350e6..7e1470989b997bca0174ac2a979b4fa999b9a0ba 100644 (file)
@@ -204,11 +204,19 @@ static switch_status_t png_file_read_video(switch_file_handle_t *handle, switch_
        return SWITCH_STATUS_SUCCESS;
 }
 
+typedef struct {
+       switch_image_t *read_img;
+       switch_image_t *write_img;
+       char *path;
+       char *other_path;
+       switch_bool_t both_legs;
+} png_write_data;
+
 static switch_bool_t write_png_bug_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
 {
        switch_core_session_t *session = switch_core_media_bug_get_session(bug);
        switch_channel_t *channel = switch_core_session_get_channel(session);
-       char *path = (char *) user_data;
+       png_write_data *data = (png_write_data *) user_data;
 
        switch (type) {
        case SWITCH_ABC_TYPE_INIT:
@@ -225,25 +233,69 @@ static switch_bool_t write_png_bug_callback(switch_media_bug_t *bug, void *user_
        case SWITCH_ABC_TYPE_READ_VIDEO_PING:
                {
                        switch_frame_t *frame = switch_core_media_bug_get_video_ping_frame(bug);
+
+                       if (!frame || !frame->img) break;
+
+                       if (data->both_legs == SWITCH_FALSE) {
+                               switch_img_write_png(frame->img, data->path);
+                               return SWITCH_FALSE;
+                       }
+
+                       if (!data->read_img) {
+                               switch_img_copy(frame->img, &data->read_img);
+                       }
+               }
+               break;
+       case SWITCH_ABC_TYPE_WRITE_VIDEO_PING:
+               {
+                       switch_frame_t *frame = switch_core_media_bug_get_video_ping_frame(bug);
+
                        if (!frame || !frame->img) break;
-                       switch_img_write_png(frame->img, path);
-                       return SWITCH_FALSE;
+
+                       if (!data->write_img) {
+                               switch_img_copy(frame->img, &data->write_img);
+                       }
                }
                break;
        default:
                break;
        }
 
+       if (data->both_legs == SWITCH_TRUE && data->read_img && data->write_img) {
+               if (data->other_path) {
+                       switch_img_write_png(data->read_img, data->path);
+                       switch_img_write_png(data->write_img, data->other_path);
+               } else {
+                       int width, height;
+                       switch_image_t *img;
+                       switch_rgb_color_t bgcolor;
+
+                       switch_color_set_rgb(&bgcolor, "#000000");
+                       width = data->read_img->d_w + data->write_img->d_w;
+                       height = data->read_img->d_h > data->write_img->d_h ? data->read_img->d_h : data->write_img->d_h;
+                       img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, width, height, 1);
+                       switch_img_fill(img, 0, 0, width, height, &bgcolor);
+                       switch_img_patch(img, data->read_img, 0, (height - data->read_img->d_h) / 2);
+                       switch_img_patch(img, data->write_img, data->read_img->d_w, (height - data->write_img->d_h) / 2);
+                       switch_img_write_png(img, data->path);
+                       switch_img_free(&img);
+               }
+
+               switch_img_free(&data->read_img);
+               switch_img_free(&data->write_img);
+               return SWITCH_FALSE;
+       }
+
        return SWITCH_TRUE;
 }
 
 SWITCH_STANDARD_API(uuid_write_png_function)
 {
        int argc = 0;
-       char *argv[2] = { 0 };
+       char *argv[4] = { 0 };
        char *mydata = NULL;
        char *uuid;
-       char *path;
+       png_write_data *bug_data;
        switch_media_bug_t *bug;
        switch_media_bug_flag_t flags = SMBF_READ_VIDEO_PING;
        switch_core_session_t *session_;
@@ -252,12 +304,13 @@ SWITCH_STANDARD_API(uuid_write_png_function)
                argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
        }
 
-       if (argc < 2) {
-               stream->write_function(stream, "-USAGE: <uuid> <path> \n");     
+       if (argc < 2 || (argc > 2 && strcasecmp(argv[2], "concat") && strcasecmp(argv[2], "split"))) {
+               stream->write_function(stream, "-USAGE: <uuid> <path> [concat | split <other_path>]\n");
                goto end;
        }
        
        uuid = argv[0];
+
        if (!(session_ = switch_core_session_locate(uuid))) {
                stream->write_function(stream, "-ERR Could not locate session.\n");
                goto end;
@@ -269,16 +322,46 @@ SWITCH_STANDARD_API(uuid_write_png_function)
                goto end;
        }
 
+       bug_data = switch_core_session_alloc(session_, sizeof(*bug_data));
+
+       if (argc > 2) {
+               switch_channel_t *channel_ = switch_core_session_get_channel(session_);
+
+               if (!switch_channel_test_flag_partner(channel_, CF_VIDEO)) {
+                       stream->write_function(stream, "-ERR Session must be bridged and other leg must have video.\n");
+                       switch_core_session_rwunlock(session_);
+                       goto end;
+               }
+
+               bug_data->both_legs = SWITCH_TRUE;
+               flags |= SMBF_WRITE_VIDEO_PING;
+
+               if (!strcasecmp(argv[2], "split")) {
+                       if (argc == 3) {
+                               stream->write_function(stream, "-ERR Second filename expected but not given.\n");
+                               switch_core_session_rwunlock(session_);
+                               goto end;
+                       }
+
+                       if (!switch_is_file_path(argv[3])) {
+                               const char *prefix = SWITCH_GLOBAL_dirs.images_dir;
+                               bug_data->other_path = switch_core_session_sprintf(session_, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, argv[3]);
+                       } else {
+                               bug_data->other_path = switch_core_session_strdup(session_, argv[3]);
+                       }
+               }
+       }
+
     if (!switch_is_file_path(argv[1])) {
         const char *prefix = SWITCH_GLOBAL_dirs.images_dir;
-        path = switch_core_session_sprintf(session_, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, argv[1]);
+        bug_data->path = switch_core_session_sprintf(session_, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, argv[1]);
     } else {
-        path = switch_core_session_strdup(session_, argv[1]);
+        bug_data->path = switch_core_session_strdup(session_, argv[1]);
     }
 
        switch_thread_rwlock_rdlock(MODULE_INTERFACE->rwlock);
 
-       if (switch_core_media_bug_add(session_, NULL, NULL, write_png_bug_callback, path, 0, flags, &bug) != SWITCH_STATUS_SUCCESS) {
+       if (switch_core_media_bug_add(session_, NULL, NULL, write_png_bug_callback, bug_data, 0, flags, &bug) != SWITCH_STATUS_SUCCESS) {
                stream->write_function(stream, "-ERR Could not attach bug.\n");
                switch_thread_rwlock_unlock(MODULE_INTERFACE->rwlock);
        } else {