FS-7824 Add functionality for capturing screenshots from both legs to uuid_write_png

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.
This commit is contained in:
Bradley Jokinen 2015-07-13 09:26:16 -05:00
parent a54e04df00
commit c797e948c8
1 changed files with 93 additions and 10 deletions

View 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;
switch_img_write_png(frame->img, path);
return SWITCH_FALSE;
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;
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 {