diff --git a/src/include/switch_core_video.h b/src/include/switch_core_video.h index 6d96b3b472..8998d0bac5 100644 --- a/src/include/switch_core_video.h +++ b/src/include/switch_core_video.h @@ -406,6 +406,7 @@ SWITCH_DECLARE(void) switch_png_free(switch_png_t **pngP); */ SWITCH_DECLARE(void) switch_img_overlay(switch_image_t *IMG, switch_image_t *img, int x, int y, uint8_t percent); +SWITCH_DECLARE(switch_status_t) switch_img_mirror(switch_image_t *src, switch_image_t **destP); SWITCH_DECLARE(switch_status_t) switch_img_scale(switch_image_t *src, switch_image_t **destP, int width, int height); SWITCH_DECLARE(switch_status_t) switch_img_fit(switch_image_t **srcP, int width, int height, switch_img_fit_t fit); SWITCH_DECLARE(switch_img_position_t) parse_img_position(const char *name); diff --git a/src/mod/applications/mod_conference/conference_api.c b/src/mod/applications/mod_conference/conference_api.c index 0a3aacde3e..2ea16ae9ef 100644 --- a/src/mod/applications/mod_conference/conference_api.c +++ b/src/mod/applications/mod_conference/conference_api.c @@ -747,24 +747,34 @@ switch_status_t conference_api_sub_vid_flip(conference_member_t *member, switch_ return SWITCH_STATUS_GENERR; } - if (conference_utils_member_test_flag(member, MFLAG_FLIP_VIDEO) && !arg) { + if ((conference_utils_member_test_flag(member, MFLAG_FLIP_VIDEO) || conference_utils_member_test_flag(member, MFLAG_MIRROR_VIDEO)) && !arg) { conference_utils_member_clear_flag_locked(member, MFLAG_FLIP_VIDEO); conference_utils_member_clear_flag_locked(member, MFLAG_ROTATE_VIDEO); + conference_utils_member_clear_flag_locked(member, MFLAG_MIRROR_VIDEO); } else { - conference_utils_member_set_flag_locked(member, MFLAG_FLIP_VIDEO); - if (arg) { - if (!strcasecmp(arg, "rotate")) { - conference_utils_member_set_flag_locked(member, MFLAG_ROTATE_VIDEO); - } else if (switch_is_number(arg)) { - int num = atoi(arg); - - if (num == 0 || num == 90 || num == 180 || num == 270) { - member->flip = num; - } + if (arg && !strcasecmp(arg, "mirror")) { + if (conference_utils_member_test_flag(member, MFLAG_MIRROR_VIDEO)) { + conference_utils_member_clear_flag_locked(member, MFLAG_MIRROR_VIDEO); + } else { + conference_utils_member_set_flag_locked(member, MFLAG_MIRROR_VIDEO); } } else { - member->flip = 180; + conference_utils_member_set_flag_locked(member, MFLAG_FLIP_VIDEO); + + if (arg) { + if (!strcasecmp(arg, "rotate")) { + conference_utils_member_set_flag_locked(member, MFLAG_ROTATE_VIDEO); + } else if (switch_is_number(arg)) { + int num = atoi(arg); + + if (num == 0 || num == 90 || num == 180 || num == 270) { + member->flip = num; + } + } + } else { + member->flip = 180; + } } } diff --git a/src/mod/applications/mod_conference/conference_video.c b/src/mod/applications/mod_conference/conference_video.c index c1bd8ff425..494c2c3624 100644 --- a/src/mod/applications/mod_conference/conference_video.c +++ b/src/mod/applications/mod_conference/conference_video.c @@ -4872,7 +4872,8 @@ switch_status_t conference_video_thread_callback(switch_core_session_t *session, switch_queue_size(member->video_queue) < member->conference->video_fps.fps && !member->conference->canvases[canvas_id]->playing_video_file) { - if (conference_utils_member_test_flag(member, MFLAG_FLIP_VIDEO) || conference_utils_member_test_flag(member, MFLAG_ROTATE_VIDEO)) { + if (conference_utils_member_test_flag(member, MFLAG_FLIP_VIDEO) || + conference_utils_member_test_flag(member, MFLAG_ROTATE_VIDEO) || conference_utils_member_test_flag(member, MFLAG_MIRROR_VIDEO)) { if (conference_utils_member_test_flag(member, MFLAG_ROTATE_VIDEO)) { if (member->flip_count++ > (int)(member->conference->video_fps.fps / 2)) { member->flip += 90; @@ -4883,6 +4884,8 @@ switch_status_t conference_video_thread_callback(switch_core_session_t *session, } switch_img_rotate_copy(frame->img, &img_copy, member->flip); + } else if (conference_utils_member_test_flag(member, MFLAG_MIRROR_VIDEO)) { + switch_img_mirror(frame->img, &img_copy); } else { switch_img_rotate_copy(frame->img, &img_copy, member->flip); } diff --git a/src/mod/applications/mod_conference/mod_conference.h b/src/mod/applications/mod_conference/mod_conference.h index 5b174a58ed..a80f47a9a4 100644 --- a/src/mod/applications/mod_conference/mod_conference.h +++ b/src/mod/applications/mod_conference/mod_conference.h @@ -213,6 +213,7 @@ typedef enum { MFLAG_SILENT, MFLAG_FLIP_VIDEO, MFLAG_ROTATE_VIDEO, + MFLAG_MIRROR_VIDEO, MFLAG_INDICATE_DEAF, MFLAG_INDICATE_UNDEAF, MFLAG_TALK_DATA_EVENTS, diff --git a/src/switch_core_video.c b/src/switch_core_video.c index ca9ff3863d..69e8f25032 100644 --- a/src/switch_core_video.c +++ b/src/switch_core_video.c @@ -3191,6 +3191,51 @@ SWITCH_DECLARE(switch_status_t) switch_img_scale(switch_image_t *src, switch_ima #endif } + +SWITCH_DECLARE(switch_status_t) switch_img_mirror(switch_image_t *src, switch_image_t **destP) +{ +#ifdef SWITCH_HAVE_YUV + switch_image_t *dest = NULL; + int ret = 0; + + if (destP) { + dest = *destP; + } + + if (dest && src->fmt != dest->fmt) switch_img_free(&dest); + + if (!dest) dest = switch_img_alloc(NULL, src->fmt, src->d_w, src->d_h, 1); + + if (src->fmt == SWITCH_IMG_FMT_I420) { + ret = I420Mirror(src->planes[0], src->stride[0], + src->planes[1], src->stride[1], + src->planes[2], src->stride[2], + dest->planes[0], dest->stride[0], + dest->planes[1], dest->stride[1], + dest->planes[2], dest->stride[2], + src->d_w, src->d_h); + } else if (src->fmt == SWITCH_IMG_FMT_ARGB) { + ret = ARGBMirror(src->planes[SWITCH_PLANE_PACKED], src->d_w * 4, + dest->planes[SWITCH_PLANE_PACKED], src->d_w * 4, + src->d_w, src->d_h); + + } + + if (ret != 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Mirror Error: ret: %d\n", ret); + return SWITCH_STATUS_FALSE; + } + + if (destP) { + *destP = dest; + } + + return SWITCH_STATUS_SUCCESS; +#else + return SWITCH_STATUS_FALSE; +#endif +} + SWITCH_DECLARE(void) switch_img_find_position(switch_img_position_t pos, int sw, int sh, int iw, int ih, int *xP, int *yP) { switch(pos) {