diff --git a/plugins/obs-filters/mask-filter.c b/plugins/obs-filters/mask-filter.c index fc930796f..636eb3518 100644 --- a/plugins/obs-filters/mask-filter.c +++ b/plugins/obs-filters/mask-filter.c @@ -2,7 +2,9 @@ #include #include #include +#include #include +#include /* clang-format off */ @@ -28,18 +30,56 @@ struct mask_filter_data { obs_source_t *context; gs_effect_t *effect; + char *image_file; + time_t image_file_timestamp; + float update_time_elapsed; + gs_texture_t *target; gs_image_file_t image; struct vec4 color; bool lock_aspect; }; +static time_t get_modified_timestamp(const char *filename) +{ + struct stat stats; + if (os_stat(filename, &stats) != 0) + return -1; + return stats.st_mtime; +} + static const char *mask_filter_get_name(void *unused) { UNUSED_PARAMETER(unused); return obs_module_text("MaskFilter"); } +static void mask_filter_image_unload(struct mask_filter_data *filter) +{ + obs_enter_graphics(); + gs_image_file_free(&filter->image); + obs_leave_graphics(); +} + +static void mask_filter_image_load(struct mask_filter_data *filter) +{ + mask_filter_image_unload(filter); + + char *path = filter->image_file; + + if (path && *path) { + filter->image_file_timestamp = get_modified_timestamp(path); + gs_image_file_init(&filter->image, path); + filter->update_time_elapsed = 0; + + obs_enter_graphics(); + gs_image_file_init_texture(&filter->image); + obs_leave_graphics(); + + filter->target = filter->image.texture; + } +} + static void mask_filter_update(void *data, obs_data_t *settings) { struct mask_filter_data *filter = data; @@ -50,24 +90,19 @@ static void mask_filter_update(void *data, obs_data_t *settings) int opacity = (int)obs_data_get_int(settings, SETTING_OPACITY); char *effect_path; + if (filter->image_file) + bfree(filter->image_file); + filter->image_file = bstrdup(path); + color &= 0xFFFFFF; color |= (uint32_t)(((double)opacity) * 2.55) << 24; vec4_from_rgba(&filter->color, color); - - obs_enter_graphics(); - gs_image_file_free(&filter->image); - obs_leave_graphics(); - - gs_image_file_init(&filter->image, path); - - obs_enter_graphics(); - - gs_image_file_init_texture(&filter->image); - - filter->target = filter->image.texture; + mask_filter_image_load(filter); filter->lock_aspect = !obs_data_get_bool(settings, SETTING_STRETCH); + obs_enter_graphics(); + effect_path = obs_module_file(effect_file); gs_effect_destroy(filter->effect); filter->effect = gs_effect_create_from_file(effect_path, NULL); @@ -144,6 +179,9 @@ static void mask_filter_destroy(void *data) { struct mask_filter_data *filter = data; + if (filter->image_file) + bfree(filter->image_file); + obs_enter_graphics(); gs_effect_destroy(filter->effect); gs_image_file_free(&filter->image); @@ -152,10 +190,19 @@ static void mask_filter_destroy(void *data) bfree(filter); } -static void mask_filter_tick(void *data, float t) +static void mask_filter_tick(void *data, float seconds) { struct mask_filter_data *filter = data; - UNUSED_PARAMETER(t); + filter->update_time_elapsed += seconds; + + if (filter->update_time_elapsed >= 1.0f) { + time_t t = get_modified_timestamp(filter->image_file); + filter->update_time_elapsed = 0.0f; + + if (filter->image_file_timestamp != t) { + mask_filter_image_load(filter); + } + } if (filter->image.is_animated_gif) { uint64_t cur_time = obs_get_video_frame_time();