diff --git a/plugins/obs-filters/chroma-key-filter.c b/plugins/obs-filters/chroma-key-filter.c index 0fac53041..e58fa84c3 100644 --- a/plugins/obs-filters/chroma-key-filter.c +++ b/plugins/obs-filters/chroma-key-filter.c @@ -33,32 +33,6 @@ struct chroma_key_filter_data { gs_effect_t *effect; gs_eparam_t *color_param; - gs_eparam_t *contrast_param; - gs_eparam_t *brightness_param; - gs_eparam_t *gamma_param; - - gs_eparam_t *pixel_size_param; - gs_eparam_t *chroma_param; - gs_eparam_t *similarity_param; - gs_eparam_t *smoothness_param; - gs_eparam_t *spill_param; - - struct vec4 color; - float contrast; - float brightness; - float gamma; - - struct vec2 chroma; - float similarity; - float smoothness; - float spill; -}; - -struct chroma_key_filter_data_v2 { - obs_source_t *context; - - gs_effect_t *effect; - gs_eparam_t *opacity_param; gs_eparam_t *contrast_param; gs_eparam_t *brightness_param; @@ -70,6 +44,7 @@ struct chroma_key_filter_data_v2 { gs_eparam_t *smoothness_param; gs_eparam_t *spill_param; + struct vec4 color; float opacity; float contrast; float brightness; @@ -90,36 +65,20 @@ static const char *chroma_key_name(void *unused) static const float cb_vec[] = {-0.100644f, -0.338572f, 0.439216f, 0.501961f}; static const float cr_vec[] = {0.439216f, -0.398942f, -0.040274f, 0.501961f}; -static inline void -color_settings_update_v1(struct chroma_key_filter_data *filter, - obs_data_t *settings) +static inline void color_settings_update(struct chroma_key_filter_data *filter, + obs_data_t *settings) { - uint32_t opacity = - (uint32_t)obs_data_get_int(settings, SETTING_OPACITY); - uint32_t color = 0xFFFFFF | (((opacity * 255) / 100) << 24); - double contrast = obs_data_get_double(settings, SETTING_CONTRAST); - double brightness = obs_data_get_double(settings, SETTING_BRIGHTNESS); - double gamma = obs_data_get_double(settings, SETTING_GAMMA); + uint32_t version = obs_source_get_version(filter->context); - contrast = (contrast < 0.0) ? (1.0 / (-contrast + 1.0)) - : (contrast + 1.0); - - brightness *= 0.5; - - gamma = (gamma < 0.0) ? (-gamma + 1.0) : (1.0 / (gamma + 1.0)); - - filter->contrast = (float)contrast; - filter->brightness = (float)brightness; - filter->gamma = (float)gamma; - - vec4_from_rgba(&filter->color, color); -} - -static inline void -color_settings_update_v2(struct chroma_key_filter_data_v2 *filter, - obs_data_t *settings) -{ - filter->opacity = (float)obs_data_get_double(settings, SETTING_OPACITY); + if (version == 1) { + uint32_t opacity = + (uint32_t)obs_data_get_int(settings, SETTING_OPACITY); + uint32_t color = 0xFFFFFF | (((opacity * 255) / 100) << 24); + vec4_from_rgba(&filter->color, color); + } else if (version == 2) { + filter->opacity = + (float)obs_data_get_double(settings, SETTING_OPACITY); + } double contrast = obs_data_get_double(settings, SETTING_CONTRAST); contrast = (contrast < 0.0) ? (1.0 / (-contrast + 1.0)) @@ -129,14 +88,16 @@ color_settings_update_v2(struct chroma_key_filter_data_v2 *filter, filter->brightness = (float)obs_data_get_double(settings, SETTING_BRIGHTNESS); + if (version == 1) + filter->brightness *= 0.5f; + double gamma = obs_data_get_double(settings, SETTING_GAMMA); gamma = (gamma < 0.0) ? (-gamma + 1.0) : (1.0 / (gamma + 1.0)); filter->gamma = (float)gamma; } -static inline void -chroma_settings_update_v1(struct chroma_key_filter_data *filter, - obs_data_t *settings) +static inline void chroma_settings_update(struct chroma_key_filter_data *filter, + obs_data_t *settings) { int64_t similarity = obs_data_get_int(settings, SETTING_SIMILARITY); int64_t smoothness = obs_data_get_int(settings, SETTING_SMOOTHNESS); @@ -168,57 +129,15 @@ chroma_settings_update_v1(struct chroma_key_filter_data *filter, filter->spill = (float)spill / 1000.0f; } -static inline void -chroma_settings_update_v2(struct chroma_key_filter_data_v2 *filter, - obs_data_t *settings) -{ - int64_t similarity = obs_data_get_int(settings, SETTING_SIMILARITY); - int64_t smoothness = obs_data_get_int(settings, SETTING_SMOOTHNESS); - int64_t spill = obs_data_get_int(settings, SETTING_SPILL); - uint32_t key_color = - (uint32_t)obs_data_get_int(settings, SETTING_KEY_COLOR); - const char *key_type = - obs_data_get_string(settings, SETTING_COLOR_TYPE); - struct vec4 key_rgb; - struct vec4 cb_v4; - struct vec4 cr_v4; - - if (strcmp(key_type, "green") == 0) - key_color = 0x00FF00; - else if (strcmp(key_type, "blue") == 0) - key_color = 0xFF9900; - else if (strcmp(key_type, "magenta") == 0) - key_color = 0xFF00FF; - - vec4_from_rgba(&key_rgb, key_color | 0xFF000000); - - memcpy(&cb_v4, cb_vec, sizeof(cb_v4)); - memcpy(&cr_v4, cr_vec, sizeof(cr_v4)); - filter->chroma.x = vec4_dot(&key_rgb, &cb_v4); - filter->chroma.y = vec4_dot(&key_rgb, &cr_v4); - - filter->similarity = (float)similarity / 1000.0f; - filter->smoothness = (float)smoothness / 1000.0f; - filter->spill = (float)spill / 1000.0f; -} - -static void chroma_key_update_v1(void *data, obs_data_t *settings) +static void chroma_key_update(void *data, obs_data_t *settings) { struct chroma_key_filter_data *filter = data; - color_settings_update_v1(filter, settings); - chroma_settings_update_v1(filter, settings); + color_settings_update(filter, settings); + chroma_settings_update(filter, settings); } -static void chroma_key_update_v2(void *data, obs_data_t *settings) -{ - struct chroma_key_filter_data_v2 *filter = data; - - color_settings_update_v2(filter, settings); - chroma_settings_update_v2(filter, settings); -} - -static void chroma_key_destroy_v1(void *data) +static void chroma_key_destroy(void *data) { struct chroma_key_filter_data *filter = data; @@ -231,24 +150,17 @@ static void chroma_key_destroy_v1(void *data) bfree(data); } -static void chroma_key_destroy_v2(void *data) -{ - struct chroma_key_filter_data_v2 *filter = data; - - if (filter->effect) { - obs_enter_graphics(); - gs_effect_destroy(filter->effect); - obs_leave_graphics(); - } - - bfree(data); -} - -static void *chroma_key_create_v1(obs_data_t *settings, obs_source_t *context) +static void *chroma_key_create(obs_data_t *settings, obs_source_t *context) { struct chroma_key_filter_data *filter = bzalloc(sizeof(struct chroma_key_filter_data)); - char *effect_path = obs_module_file("chroma_key_filter.effect"); + char *effect_path = NULL; + uint32_t version = obs_source_get_version(context); + + if (version == 1) + effect_path = obs_module_file("chroma_key_filter.effect"); + else if (version == 2) + effect_path = obs_module_file("chroma_key_filter_v2.effect"); filter->context = context; @@ -256,8 +168,13 @@ static void *chroma_key_create_v1(obs_data_t *settings, obs_source_t *context) filter->effect = gs_effect_create_from_file(effect_path, NULL); if (filter->effect) { - filter->color_param = - gs_effect_get_param_by_name(filter->effect, "color"); + if (version == 1) + filter->color_param = gs_effect_get_param_by_name( + filter->effect, "color"); + else if (version == 2) + filter->opacity_param = gs_effect_get_param_by_name( + filter->effect, "opacity"); + filter->contrast_param = gs_effect_get_param_by_name(filter->effect, "contrast"); filter->brightness_param = gs_effect_get_param_by_name( @@ -281,60 +198,15 @@ static void *chroma_key_create_v1(obs_data_t *settings, obs_source_t *context) bfree(effect_path); if (!filter->effect) { - chroma_key_destroy_v1(filter); + chroma_key_destroy(filter); return NULL; } - chroma_key_update_v1(filter, settings); + chroma_key_update(filter, settings); return filter; } -static void *chroma_key_create_v2(obs_data_t *settings, obs_source_t *context) -{ - struct chroma_key_filter_data_v2 *filter = - bzalloc(sizeof(struct chroma_key_filter_data_v2)); - char *effect_path = obs_module_file("chroma_key_filter_v2.effect"); - - filter->context = context; - - obs_enter_graphics(); - - filter->effect = gs_effect_create_from_file(effect_path, NULL); - if (filter->effect) { - filter->opacity_param = - gs_effect_get_param_by_name(filter->effect, "opacity"); - filter->contrast_param = - gs_effect_get_param_by_name(filter->effect, "contrast"); - filter->brightness_param = gs_effect_get_param_by_name( - filter->effect, "brightness"); - filter->gamma_param = - gs_effect_get_param_by_name(filter->effect, "gamma"); - filter->chroma_param = gs_effect_get_param_by_name( - filter->effect, "chroma_key"); - filter->pixel_size_param = gs_effect_get_param_by_name( - filter->effect, "pixel_size"); - filter->similarity_param = gs_effect_get_param_by_name( - filter->effect, "similarity"); - filter->smoothness_param = gs_effect_get_param_by_name( - filter->effect, "smoothness"); - filter->spill_param = - gs_effect_get_param_by_name(filter->effect, "spill"); - } - - obs_leave_graphics(); - - bfree(effect_path); - - if (!filter->effect) { - chroma_key_destroy_v2(filter); - return NULL; - } - - chroma_key_update_v2(filter, settings); - return filter; -} - -static void chroma_key_render_v1(void *data, gs_effect_t *effect) +static void chroma_key_render(void *data, gs_effect_t *effect) { struct chroma_key_filter_data *filter = data; obs_source_t *target = obs_filter_get_target(filter->context); @@ -348,36 +220,12 @@ static void chroma_key_render_v1(void *data, gs_effect_t *effect) vec2_set(&pixel_size, 1.0f / (float)width, 1.0f / (float)height); - gs_effect_set_vec4(filter->color_param, &filter->color); - gs_effect_set_float(filter->contrast_param, filter->contrast); - gs_effect_set_float(filter->brightness_param, filter->brightness); - gs_effect_set_float(filter->gamma_param, filter->gamma); - gs_effect_set_vec2(filter->chroma_param, &filter->chroma); - gs_effect_set_vec2(filter->pixel_size_param, &pixel_size); - gs_effect_set_float(filter->similarity_param, filter->similarity); - gs_effect_set_float(filter->smoothness_param, filter->smoothness); - gs_effect_set_float(filter->spill_param, filter->spill); + if (filter->color_param) + gs_effect_set_vec4(filter->color_param, &filter->color); - obs_source_process_filter_end(filter->context, filter->effect, 0, 0); + if (filter->opacity_param) + gs_effect_set_float(filter->opacity_param, filter->opacity); - UNUSED_PARAMETER(effect); -} - -static void chroma_key_render_v2(void *data, gs_effect_t *effect) -{ - struct chroma_key_filter_data_v2 *filter = data; - obs_source_t *target = obs_filter_get_target(filter->context); - uint32_t width = obs_source_get_base_width(target); - uint32_t height = obs_source_get_base_height(target); - struct vec2 pixel_size; - - if (!obs_source_process_filter_begin(filter->context, GS_RGBA, - OBS_ALLOW_DIRECT_RENDERING)) - return; - - vec2_set(&pixel_size, 1.0f / (float)width, 1.0f / (float)height); - - gs_effect_set_float(filter->opacity_param, filter->opacity); gs_effect_set_float(filter->contrast_param, filter->contrast); gs_effect_set_float(filter->brightness_param, filter->brightness); gs_effect_set_float(filter->gamma_param, filter->gamma); @@ -410,7 +258,7 @@ static bool key_type_changed(obs_properties_t *props, obs_property_t *p, return true; } -static obs_properties_t *chroma_key_properties_v1(void *data) +static obs_properties_t *chroma_key_properties(uint32_t version) { obs_properties_t *props = obs_properties_create(); @@ -433,79 +281,57 @@ static obs_properties_t *chroma_key_properties_v1(void *data) obs_properties_add_int_slider(props, SETTING_SPILL, TEXT_SPILL, 1, 1000, 1); - obs_properties_add_int_slider(props, SETTING_OPACITY, TEXT_OPACITY, 0, - 100, 1); - obs_properties_add_float_slider(props, SETTING_CONTRAST, TEXT_CONTRAST, - -1.0, 1.0, 0.01); - obs_properties_add_float_slider(props, SETTING_BRIGHTNESS, - TEXT_BRIGHTNESS, -1.0, 1.0, 0.01); - obs_properties_add_float_slider(props, SETTING_GAMMA, TEXT_GAMMA, -1.0, - 1.0, 0.01); + if (version == 1) { + obs_properties_add_int_slider(props, SETTING_OPACITY, + TEXT_OPACITY, 0, 100, 1); + } else if (version == 2) { + obs_properties_add_float_slider(props, SETTING_OPACITY, + TEXT_OPACITY, 0.0, 1.0, 0.0001); + } - UNUSED_PARAMETER(data); - return props; -} - -static obs_properties_t *chroma_key_properties_v2(void *data) -{ - obs_properties_t *props = obs_properties_create(); - - obs_property_t *p = obs_properties_add_list(props, SETTING_COLOR_TYPE, - TEXT_COLOR_TYPE, - OBS_COMBO_TYPE_LIST, - OBS_COMBO_FORMAT_STRING); - obs_property_list_add_string(p, obs_module_text("Green"), "green"); - obs_property_list_add_string(p, obs_module_text("Blue"), "blue"); - obs_property_list_add_string(p, obs_module_text("Magenta"), "magenta"); - obs_property_list_add_string(p, obs_module_text("Custom"), "custom"); - - obs_property_set_modified_callback(p, key_type_changed); - - obs_properties_add_color(props, SETTING_KEY_COLOR, TEXT_KEY_COLOR); - obs_properties_add_int_slider(props, SETTING_SIMILARITY, - TEXT_SIMILARITY, 1, 1000, 1); - obs_properties_add_int_slider(props, SETTING_SMOOTHNESS, - TEXT_SMOOTHNESS, 1, 1000, 1); - obs_properties_add_int_slider(props, SETTING_SPILL, TEXT_SPILL, 1, 1000, - 1); - - obs_properties_add_float_slider(props, SETTING_OPACITY, TEXT_OPACITY, - 0.0, 1.0, 0.0001); obs_properties_add_float_slider(props, SETTING_CONTRAST, TEXT_CONTRAST, -4.0, 4.0, 0.01); obs_properties_add_float_slider(props, SETTING_BRIGHTNESS, TEXT_BRIGHTNESS, -1.0, 1.0, 0.0001); obs_properties_add_float_slider(props, SETTING_GAMMA, TEXT_GAMMA, -1.0, 1.0, 0.01); - - UNUSED_PARAMETER(data); return props; } +static obs_properties_t *chroma_key_properties_v1(void *data) +{ + UNUSED_PARAMETER(data); + return chroma_key_properties(1); +} + +static obs_properties_t *chroma_key_properties_v2(void *data) +{ + UNUSED_PARAMETER(data); + return chroma_key_properties(2); +} + +static void chroma_key_defaults(obs_data_t *settings) +{ + obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0); + obs_data_set_default_double(settings, SETTING_BRIGHTNESS, 0.0); + obs_data_set_default_double(settings, SETTING_GAMMA, 0.0); + obs_data_set_default_int(settings, SETTING_KEY_COLOR, 0x00FF00); + obs_data_set_default_string(settings, SETTING_COLOR_TYPE, "green"); + obs_data_set_default_int(settings, SETTING_SIMILARITY, 400); + obs_data_set_default_int(settings, SETTING_SMOOTHNESS, 80); + obs_data_set_default_int(settings, SETTING_SPILL, 100); +} + static void chroma_key_defaults_v1(obs_data_t *settings) { + chroma_key_defaults(settings); obs_data_set_default_int(settings, SETTING_OPACITY, 100); - obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0); - obs_data_set_default_double(settings, SETTING_BRIGHTNESS, 0.0); - obs_data_set_default_double(settings, SETTING_GAMMA, 0.0); - obs_data_set_default_int(settings, SETTING_KEY_COLOR, 0x00FF00); - obs_data_set_default_string(settings, SETTING_COLOR_TYPE, "green"); - obs_data_set_default_int(settings, SETTING_SIMILARITY, 400); - obs_data_set_default_int(settings, SETTING_SMOOTHNESS, 80); - obs_data_set_default_int(settings, SETTING_SPILL, 100); } static void chroma_key_defaults_v2(obs_data_t *settings) { + chroma_key_defaults(settings); obs_data_set_default_double(settings, SETTING_OPACITY, 1.0); - obs_data_set_default_double(settings, SETTING_CONTRAST, 0.0); - obs_data_set_default_double(settings, SETTING_BRIGHTNESS, 0.0); - obs_data_set_default_double(settings, SETTING_GAMMA, 0.0); - obs_data_set_default_int(settings, SETTING_KEY_COLOR, 0x00FF00); - obs_data_set_default_string(settings, SETTING_COLOR_TYPE, "green"); - obs_data_set_default_int(settings, SETTING_SIMILARITY, 400); - obs_data_set_default_int(settings, SETTING_SMOOTHNESS, 80); - obs_data_set_default_int(settings, SETTING_SPILL, 100); } struct obs_source_info chroma_key_filter = { @@ -513,10 +339,10 @@ struct obs_source_info chroma_key_filter = { .type = OBS_SOURCE_TYPE_FILTER, .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CAP_OBSOLETE, .get_name = chroma_key_name, - .create = chroma_key_create_v1, - .destroy = chroma_key_destroy_v1, - .video_render = chroma_key_render_v1, - .update = chroma_key_update_v1, + .create = chroma_key_create, + .destroy = chroma_key_destroy, + .video_render = chroma_key_render, + .update = chroma_key_update, .get_properties = chroma_key_properties_v1, .get_defaults = chroma_key_defaults_v1, }; @@ -527,10 +353,10 @@ struct obs_source_info chroma_key_filter_v2 = { .type = OBS_SOURCE_TYPE_FILTER, .output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_SRGB, .get_name = chroma_key_name, - .create = chroma_key_create_v2, - .destroy = chroma_key_destroy_v2, - .video_render = chroma_key_render_v2, - .update = chroma_key_update_v2, + .create = chroma_key_create, + .destroy = chroma_key_destroy, + .video_render = chroma_key_render, + .update = chroma_key_update, .get_properties = chroma_key_properties_v2, .get_defaults = chroma_key_defaults_v2, };