FS-10151: [mod_video_filter] Add filters and fg video to mod_video_filter #resolve
This commit is contained in:
parent
cd5182c27c
commit
e61f6e227c
|
@ -46,6 +46,14 @@ SWITCH_BEGIN_EXTERN_C
|
|||
|
||||
#define CHROMAKEY_MAX_MASK 25
|
||||
|
||||
typedef enum {
|
||||
SCV_FILTER_GRAY_FG = (1 << 0),
|
||||
SCV_FILTER_GRAY_BG = (1 << 1),
|
||||
SCV_FILTER_SEPIA_FG = (1 << 2),
|
||||
SCV_FILTER_SEPIA_BG = (1 << 3)
|
||||
} switch_core_video_filter_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
SWITCH_SHADE_NONE = 0,
|
||||
SWITCH_SHADE_RED,
|
||||
|
@ -476,6 +484,8 @@ SWITCH_DECLARE(void) switch_chromakey_process(switch_chromakey_t *ck, switch_ima
|
|||
SWITCH_DECLARE(switch_image_t *) switch_chromakey_cache_image(switch_chromakey_t *ck);
|
||||
SWITCH_DECLARE(switch_shade_t) switch_chromakey_str2shade(switch_chromakey_t *ck, const char *shade_name);
|
||||
|
||||
SWITCH_DECLARE(void) switch_core_video_parse_filter_string(switch_core_video_filter_t *filters, const char *filter_str);
|
||||
|
||||
SWITCH_END_EXTERN_C
|
||||
#endif
|
||||
/* For Emacs:
|
||||
|
|
|
@ -551,7 +551,7 @@ switch_status_t conference_api_sub_video_filter(conference_member_t *member, swi
|
|||
{
|
||||
char *filter_str = (char *) data;
|
||||
|
||||
conference_video_parse_filter_string(&member->video_filters, filter_str);
|
||||
switch_core_video_parse_filter_string(&member->video_filters, filter_str);
|
||||
|
||||
stream->write_function(stream, "+OK\n");
|
||||
|
||||
|
|
|
@ -294,7 +294,7 @@ switch_status_t conference_file_play(conference_obj_t *conference, char *file, u
|
|||
|
||||
|
||||
if (!zstr(file_filters)) {
|
||||
conference_video_parse_filter_string(&fnode->filters, file_filters);
|
||||
switch_core_video_parse_filter_string(&fnode->filters, file_filters);
|
||||
}
|
||||
|
||||
if (loopsstr) {
|
||||
|
|
|
@ -501,29 +501,6 @@ static void set_bounds(int *x, int *y, int img_w, int img_h, int crop_w, int cro
|
|||
|
||||
}
|
||||
|
||||
void conference_video_parse_filter_string(conference_file_filter_t *filters, const char *filter_str)
|
||||
{
|
||||
*filters = 0;
|
||||
|
||||
if (!filter_str) return;
|
||||
|
||||
if (switch_stristr("fg-gray", filter_str)) {
|
||||
*filters |= FILTER_GRAY_FG;
|
||||
}
|
||||
|
||||
if (switch_stristr("bg-gray", filter_str)) {
|
||||
*filters |= FILTER_GRAY_BG;
|
||||
}
|
||||
|
||||
if (switch_stristr("fg-sepia", filter_str)) {
|
||||
*filters |= FILTER_SEPIA_FG;
|
||||
}
|
||||
|
||||
if (switch_stristr("bg-sepia", filter_str)) {
|
||||
*filters |= FILTER_SEPIA_BG;
|
||||
}
|
||||
}
|
||||
|
||||
void conference_video_scale_and_patch(mcu_layer_t *layer, switch_image_t *ximg, switch_bool_t freeze)
|
||||
{
|
||||
switch_image_t *IMG, *img;
|
||||
|
@ -893,19 +870,19 @@ void conference_video_scale_and_patch(mcu_layer_t *layer, switch_image_t *ximg,
|
|||
if (layer->overlay_img) {
|
||||
switch_img_fit(&layer->overlay_img, layer->img->d_w, layer->img->d_h, SWITCH_FIT_SCALE);
|
||||
|
||||
if (layer->overlay_filters & FILTER_GRAY_FG) {
|
||||
if (layer->overlay_filters & SCV_FILTER_GRAY_FG) {
|
||||
switch_img_gray(layer->img, 0, 0, layer->img->d_w, layer->img->d_h);
|
||||
}
|
||||
|
||||
if (layer->overlay_filters & FILTER_SEPIA_FG) {
|
||||
if (layer->overlay_filters & SCV_FILTER_SEPIA_FG) {
|
||||
switch_img_sepia(layer->img, 0, 0, layer->img->d_w, layer->img->d_h);
|
||||
}
|
||||
|
||||
if (layer->overlay_filters & FILTER_GRAY_BG) {
|
||||
if (layer->overlay_filters & SCV_FILTER_GRAY_BG) {
|
||||
switch_img_gray(layer->overlay_img, 0, 0, layer->overlay_img->d_w, layer->overlay_img->d_h);
|
||||
}
|
||||
|
||||
if (layer->overlay_filters & FILTER_SEPIA_BG) {
|
||||
if (layer->overlay_filters & SCV_FILTER_SEPIA_BG) {
|
||||
switch_img_sepia(layer->overlay_img, 0, 0, layer->overlay_img->d_w, layer->overlay_img->d_h);
|
||||
}
|
||||
|
||||
|
@ -2619,11 +2596,11 @@ void conference_video_pop_next_image(conference_member_t *member, switch_image_t
|
|||
}
|
||||
|
||||
if (img) {
|
||||
if (member->video_filters & FILTER_GRAY_FG) {
|
||||
if (member->video_filters & SCV_FILTER_GRAY_FG) {
|
||||
switch_img_gray(img, 0, 0, img->d_w, img->d_h);
|
||||
}
|
||||
|
||||
if (member->video_filters & FILTER_SEPIA_FG) {
|
||||
if (member->video_filters & SCV_FILTER_SEPIA_FG) {
|
||||
switch_img_sepia(img, 0, 0, img->d_w, img->d_h);
|
||||
}
|
||||
}
|
||||
|
@ -3736,19 +3713,19 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thr
|
|||
switch_image_t *overlay_img = NULL;
|
||||
switch_img_copy(canvas->img, &overlay_img);
|
||||
|
||||
if (conference->fnode->filters & FILTER_GRAY_BG) {
|
||||
if (conference->fnode->filters & SCV_FILTER_GRAY_BG) {
|
||||
switch_img_gray(overlay_img, 0, 0, overlay_img->d_w, overlay_img->d_h);
|
||||
}
|
||||
|
||||
if (conference->fnode->filters & FILTER_SEPIA_BG) {
|
||||
if (conference->fnode->filters & SCV_FILTER_SEPIA_BG) {
|
||||
switch_img_sepia(overlay_img, 0, 0, overlay_img->d_w, overlay_img->d_h);
|
||||
}
|
||||
|
||||
if (conference->fnode->filters & FILTER_GRAY_FG) {
|
||||
if (conference->fnode->filters & SCV_FILTER_GRAY_FG) {
|
||||
switch_img_gray(file_img, 0, 0, file_img->d_w, file_img->d_h);
|
||||
}
|
||||
|
||||
if (conference->fnode->filters & FILTER_SEPIA_FG) {
|
||||
if (conference->fnode->filters & SCV_FILTER_SEPIA_FG) {
|
||||
switch_img_sepia(file_img, 0, 0, file_img->d_w, file_img->d_h);
|
||||
}
|
||||
|
||||
|
|
|
@ -369,13 +369,6 @@ typedef struct al_handle_s {
|
|||
#endif
|
||||
struct conference_obj;
|
||||
|
||||
typedef enum {
|
||||
FILTER_GRAY_FG = (1 << 0),
|
||||
FILTER_GRAY_BG = (1 << 1),
|
||||
FILTER_SEPIA_FG = (1 << 2),
|
||||
FILTER_SEPIA_BG = (1 << 3)
|
||||
} conference_file_filter_t;
|
||||
|
||||
typedef struct conference_file_node {
|
||||
switch_file_handle_t fh;
|
||||
switch_speech_handle_t *sh;
|
||||
|
@ -397,7 +390,7 @@ typedef struct conference_file_node {
|
|||
int loops;
|
||||
int new_fnode;
|
||||
int layer_lock;
|
||||
conference_file_filter_t filters;
|
||||
switch_core_video_filter_t filters;
|
||||
} conference_file_node_t;
|
||||
|
||||
typedef enum {
|
||||
|
@ -504,7 +497,7 @@ typedef struct mcu_layer_s {
|
|||
switch_frame_geometry_t manual_geometry;
|
||||
mcu_layer_cam_opts_t cam_opts;
|
||||
switch_mutex_t *overlay_mutex;
|
||||
conference_file_filter_t overlay_filters;
|
||||
switch_core_video_filter_t overlay_filters;
|
||||
} mcu_layer_t;
|
||||
|
||||
typedef struct video_layout_s {
|
||||
|
@ -882,7 +875,7 @@ struct conference_member {
|
|||
uint32_t text_framesize;
|
||||
|
||||
mcu_layer_cam_opts_t cam_opts;
|
||||
conference_file_filter_t video_filters;
|
||||
switch_core_video_filter_t video_filters;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
@ -1052,7 +1045,6 @@ void conference_video_check_used_layers(mcu_canvas_t *canvas);
|
|||
void conference_video_check_flush(conference_member_t *member, switch_bool_t force);
|
||||
void conference_video_set_canvas_letterbox_bgcolor(mcu_canvas_t *canvas, char *color);
|
||||
void conference_video_set_canvas_bgcolor(mcu_canvas_t *canvas, char *color);
|
||||
void conference_video_parse_filter_string(conference_file_filter_t *filters, const char *filter_str);
|
||||
void conference_video_scale_and_patch(mcu_layer_t *layer, switch_image_t *ximg, switch_bool_t freeze);
|
||||
void conference_video_reset_layer(mcu_layer_t *layer);
|
||||
void conference_video_reset_layer_cam(mcu_layer_t *layer);
|
||||
|
|
|
@ -42,7 +42,9 @@ SWITCH_MODULE_DEFINITION(mod_video_filter, mod_video_filter_load, mod_video_filt
|
|||
typedef struct chromakey_context_s {
|
||||
int threshold;
|
||||
switch_image_t *bgimg;
|
||||
switch_image_t *bgimg_orig;
|
||||
switch_image_t *bgimg_scaled;
|
||||
switch_image_t *fgimg_scaled;
|
||||
switch_image_t *imgfg;
|
||||
switch_image_t *imgbg;
|
||||
void *data;
|
||||
|
@ -50,12 +52,14 @@ typedef struct chromakey_context_s {
|
|||
switch_size_t datalen;
|
||||
switch_size_t patch_datalen;
|
||||
switch_file_handle_t vfh;
|
||||
switch_file_handle_t fg_vfh;
|
||||
switch_rgb_color_t bgcolor;
|
||||
switch_core_session_t *session;
|
||||
switch_mutex_t *command_mutex;
|
||||
int patch;
|
||||
int mod;
|
||||
switch_chromakey_t *ck;
|
||||
switch_core_video_filter_t video_filters;
|
||||
} chromakey_context_t;
|
||||
|
||||
static void init_context(chromakey_context_t *context)
|
||||
|
@ -69,14 +73,22 @@ static void init_context(chromakey_context_t *context)
|
|||
static void uninit_context(chromakey_context_t *context)
|
||||
{
|
||||
switch_img_free(&context->bgimg);
|
||||
switch_img_free(&context->bgimg_orig);
|
||||
switch_img_free(&context->bgimg_scaled);
|
||||
switch_img_free(&context->fgimg_scaled);
|
||||
switch_img_free(&context->imgbg);
|
||||
switch_img_free(&context->imgfg);
|
||||
|
||||
if (switch_test_flag(&context->vfh, SWITCH_FILE_OPEN)) {
|
||||
switch_core_file_close(&context->vfh);
|
||||
memset(&context->vfh, 0, sizeof(context->vfh));
|
||||
}
|
||||
|
||||
if (switch_test_flag(&context->fg_vfh, SWITCH_FILE_OPEN)) {
|
||||
switch_core_file_close(&context->fg_vfh);
|
||||
memset(&context->vfh, 0, sizeof(context->fg_vfh));
|
||||
}
|
||||
|
||||
switch_safe_free(context->data);
|
||||
switch_safe_free(context->patch_data);
|
||||
switch_chromakey_destroy(&context->ck);
|
||||
|
@ -139,6 +151,10 @@ static void parse_params(chromakey_context_t *context, int start, int argc, char
|
|||
memset(&context->vfh, 0, sizeof(context->vfh));
|
||||
}
|
||||
|
||||
if (context->bgimg_orig) {
|
||||
switch_img_free(&context->bgimg_orig);
|
||||
}
|
||||
|
||||
if (context->bgimg) {
|
||||
switch_img_free(&context->bgimg);
|
||||
}
|
||||
|
@ -147,11 +163,15 @@ static void parse_params(chromakey_context_t *context, int start, int argc, char
|
|||
switch_img_free(&context->bgimg_scaled);
|
||||
}
|
||||
|
||||
if (context->fgimg_scaled) {
|
||||
switch_img_free(&context->fgimg_scaled);
|
||||
}
|
||||
|
||||
|
||||
if (argv[i][0] == '#') { // bgcolor
|
||||
switch_color_set_rgb(&context->bgcolor, argv[i]);
|
||||
} else if (switch_stristr(".png", argv[i])) {
|
||||
if (!(context->bgimg = switch_img_read_png(argv[i], SWITCH_IMG_FMT_ARGB))) {
|
||||
if (!(context->bgimg_orig = switch_img_read_png(argv[i], SWITCH_IMG_FMT_ARGB))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening png\n");
|
||||
}
|
||||
} else {
|
||||
|
@ -174,6 +194,50 @@ static void parse_params(chromakey_context_t *context, int start, int argc, char
|
|||
|
||||
|
||||
while (n > 3 && argv[i]) {
|
||||
|
||||
if (!strncasecmp(argv[i], "filter:", 7)) {
|
||||
char *filter = argv[i] + 7;
|
||||
switch_core_video_parse_filter_string(&context->video_filters, filter);
|
||||
|
||||
if (context->bgimg_orig && context->video_filters) {
|
||||
switch_img_free(&context->bgimg);
|
||||
switch_img_copy(context->bgimg_orig, &context->bgimg);
|
||||
|
||||
if (context->video_filters & SCV_FILTER_SEPIA_BG) {
|
||||
switch_img_sepia(context->bgimg, 0, 0, context->bgimg->d_w, context->bgimg->d_h);
|
||||
}
|
||||
|
||||
if (context->video_filters & SCV_FILTER_GRAY_BG) {
|
||||
switch_img_sepia(context->bgimg, 0, 0, context->bgimg->d_w, context->bgimg->d_h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!strncasecmp(argv[i], "fgvid:", 6)) {
|
||||
char *file = argv[i] + 6;
|
||||
|
||||
if (switch_test_flag(&context->fg_vfh, SWITCH_FILE_OPEN)) {
|
||||
switch_core_file_close(&context->fg_vfh);
|
||||
memset(&context->fg_vfh, 0, sizeof(context->fg_vfh));
|
||||
}
|
||||
|
||||
if (!zstr(file)) {
|
||||
if (switch_core_file_open(&context->fg_vfh, file, 1, 8000,
|
||||
SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT | SWITCH_FILE_FLAG_VIDEO,
|
||||
switch_core_session_get_pool(context->session)) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening video file\n");
|
||||
} else {
|
||||
switch_vid_params_t vp = { 0 };
|
||||
|
||||
switch_core_media_get_vid_params(context->session, &vp);
|
||||
context->fg_vfh.mm.scale_w = vp.width;
|
||||
context->fg_vfh.mm.scale_h = vp.height;
|
||||
context->fg_vfh.mm.fps = vp.fps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!strncasecmp(argv[i], "fg:", 3)) {
|
||||
switch_img_free(&context->imgfg);
|
||||
if (!zstr(argv[i]+3)) {
|
||||
|
@ -197,6 +261,10 @@ static void parse_params(chromakey_context_t *context, int start, int argc, char
|
|||
i++;
|
||||
}
|
||||
|
||||
if (context->bgimg_orig && !context->bgimg) {
|
||||
switch_img_copy(context->bgimg_orig, &context->bgimg);
|
||||
}
|
||||
|
||||
switch_core_session_request_video_refresh(context->session);
|
||||
context->mod++;
|
||||
|
||||
|
@ -257,6 +325,14 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
|
|||
switch_assert(img);
|
||||
switch_chromakey_process(context->ck, img);
|
||||
|
||||
if (context->video_filters & SCV_FILTER_GRAY_FG) {
|
||||
switch_img_gray(img, 0, 0, img->d_w, img->d_h);
|
||||
}
|
||||
|
||||
if (context->video_filters & SCV_FILTER_SEPIA_FG) {
|
||||
switch_img_sepia(img, 0, 0, img->d_w, img->d_h);
|
||||
}
|
||||
|
||||
if (context->bgimg) {
|
||||
switch_image_t *tmp = NULL;
|
||||
|
||||
|
@ -304,6 +380,15 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
|
|||
if (file_frame.img) {
|
||||
switch_img_free(&context->bgimg_scaled);
|
||||
use_img = context->bgimg_scaled = file_frame.img;
|
||||
|
||||
if (context->video_filters & SCV_FILTER_SEPIA_BG) {
|
||||
switch_img_sepia(use_img, 0, 0, use_img->d_w, use_img->d_h);
|
||||
}
|
||||
|
||||
if (context->video_filters & SCV_FILTER_GRAY_BG) {
|
||||
switch_img_sepia(use_img, 0, 0, use_img->d_w, use_img->d_h);
|
||||
}
|
||||
|
||||
} else {
|
||||
use_img = context->bgimg_scaled;
|
||||
}
|
||||
|
@ -371,6 +456,49 @@ static switch_status_t video_thread_callback(switch_core_session_t *session, swi
|
|||
switch_img_patch(img, context->imgfg, x, y);
|
||||
}
|
||||
|
||||
if (switch_test_flag(&context->fg_vfh, SWITCH_FILE_OPEN)) {
|
||||
switch_frame_t file_frame = { 0 };
|
||||
switch_status_t status;
|
||||
switch_image_t *use_img = NULL;
|
||||
|
||||
context->fg_vfh.mm.scale_w = frame->img->d_w;
|
||||
context->fg_vfh.mm.scale_h = frame->img->d_h;
|
||||
|
||||
status = switch_core_file_read_video(&context->fg_vfh, &file_frame, SVR_FLUSH);
|
||||
switch_core_file_command(&context->fg_vfh, SCFC_FLUSH_AUDIO);
|
||||
|
||||
|
||||
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
|
||||
int close = 1;
|
||||
|
||||
if (context->fg_vfh.params) {
|
||||
const char *loopstr = switch_event_get_header(context->fg_vfh.params, "loop");
|
||||
if (switch_true(loopstr)) {
|
||||
uint32_t pos = 0;
|
||||
switch_core_file_seek(&context->fg_vfh, &pos, 0, SEEK_SET);
|
||||
close = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (close) {
|
||||
switch_core_file_close(&context->fg_vfh);
|
||||
}
|
||||
}
|
||||
|
||||
if (file_frame.img) {
|
||||
switch_img_free(&context->fgimg_scaled);
|
||||
use_img = context->fgimg_scaled = file_frame.img;
|
||||
} else {
|
||||
use_img = context->fgimg_scaled;
|
||||
}
|
||||
|
||||
if (use_img) {
|
||||
switch_img_patch(img, use_img, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
switch_img_from_raw(frame->img, patch_data, SWITCH_IMG_FMT_ARGB, frame->img->d_w, frame->img->d_h);
|
||||
|
||||
switch_img_free(&img);
|
||||
|
|
|
@ -3301,6 +3301,32 @@ SWITCH_DECLARE(switch_status_t) switch_ARGBToARGB(const uint8_t* src_frame, int
|
|||
}
|
||||
|
||||
|
||||
SWITCH_DECLARE(void) switch_core_video_parse_filter_string(switch_core_video_filter_t *filters, const char *filter_str)
|
||||
{
|
||||
*filters = 0;
|
||||
|
||||
if (!filter_str) return;
|
||||
|
||||
if (switch_stristr("fg-gray", filter_str)) {
|
||||
*filters |= SCV_FILTER_GRAY_FG;
|
||||
}
|
||||
|
||||
if (switch_stristr("bg-gray", filter_str)) {
|
||||
*filters |= SCV_FILTER_GRAY_BG;
|
||||
}
|
||||
|
||||
if (switch_stristr("fg-sepia", filter_str)) {
|
||||
*filters |= SCV_FILTER_SEPIA_FG;
|
||||
}
|
||||
|
||||
if (switch_stristr("bg-sepia", filter_str)) {
|
||||
*filters |= SCV_FILTER_SEPIA_BG;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
|
|
Loading…
Reference in New Issue