diff --git a/plugins/obs-filters/nvidia-greenscreen-filter.c b/plugins/obs-filters/nvidia-greenscreen-filter.c index 84a21546d..70c1e4584 100644 --- a/plugins/obs-filters/nvidia-greenscreen-filter.c +++ b/plugins/obs-filters/nvidia-greenscreen-filter.c @@ -39,10 +39,11 @@ struct nv_greenscreen_data { obs_source_t *context; bool images_allocated; bool initial_render; - bool processing_stop; + volatile bool processing_stop; bool processed_frame; bool target_valid; volatile bool got_new_frame; + signal_handler_t *handler; /* RTX SDK vars */ NvVFX_Handle handle; @@ -97,7 +98,7 @@ static void nv_greenscreen_filter_actual_destroy(void *data) return; } - filter->processing_stop = true; + os_atomic_set_bool(&filter->processing_stop, true); if (filter->images_allocated) { obs_enter_graphics(); @@ -131,6 +132,62 @@ static void nv_greenscreen_filter_destroy(void *data) data, false); } +static void nv_greenscreen_filter_reset(void *data, calldata_t *calldata) +{ + struct nv_greenscreen_data *filter = (struct nv_greenscreen_data *)data; + NvCV_Status vfxErr; + + os_atomic_set_bool(&filter->processing_stop, true); + // first destroy + if (filter->stream) { + NvVFX_CudaStreamDestroy(filter->stream); + } + if (filter->handle) { + NvVFX_DestroyEffect(filter->handle); + } + // recreate + /* 1. Create FX */ + vfxErr = NvVFX_CreateEffect(NVVFX_FX_GREEN_SCREEN, &filter->handle); + if (NVCV_SUCCESS != vfxErr) { + const char *errString = NvCV_GetErrorStringFromCode(vfxErr); + error("Error recreating AI Greenscreen FX; error %i: %s", + vfxErr, errString); + nv_greenscreen_filter_destroy(filter); + } + + /* 2. Set models path & initialize CudaStream */ + char buffer[MAX_PATH]; + char modelDir[MAX_PATH]; + nvvfx_get_sdk_path(buffer, MAX_PATH); + size_t max_len = sizeof(buffer) / sizeof(char); + snprintf(modelDir, max_len, "%s\\models", buffer); + vfxErr = NvVFX_SetString(filter->handle, NVVFX_MODEL_DIRECTORY, + modelDir); + vfxErr = NvVFX_CudaStreamCreate(&filter->stream); + if (NVCV_SUCCESS != vfxErr) { + const char *errString = NvCV_GetErrorStringFromCode(vfxErr); + error("Error creating CUDA Stream; error %i: %s", vfxErr, + errString); + nv_greenscreen_filter_destroy(filter); + } + vfxErr = NvVFX_SetCudaStream(filter->handle, NVVFX_CUDA_STREAM, + filter->stream); + if (NVCV_SUCCESS != vfxErr) { + const char *errString = NvCV_GetErrorStringFromCode(vfxErr); + error("Error setting CUDA Stream %i", vfxErr); + nv_greenscreen_filter_destroy(filter); + } + + /* 3. load FX */ + vfxErr = NvVFX_SetU32(filter->handle, NVVFX_MODE, filter->mode); + vfxErr = NvVFX_Load(filter->handle); + if (NVCV_SUCCESS != vfxErr) + error("Error loading AI Greenscreen FX %i", vfxErr); + + filter->images_allocated = false; + os_atomic_set_bool(&filter->processing_stop, false); +} + static void init_images_greenscreen(struct nv_greenscreen_data *filter) { NvCV_Status vfxErr; @@ -224,7 +281,7 @@ static void init_images_greenscreen(struct nv_greenscreen_data *filter) return; fail: error("Error during allocation of images"); - filter->processing_stop = true; + os_atomic_set_bool(&filter->processing_stop, true); return; } @@ -264,7 +321,6 @@ static bool process_texture_greenscreen(struct nv_greenscreen_data *filter) if (vfxErr != NVCV_SUCCESS) { const char *errString = NvCV_GetErrorStringFromCode(vfxErr); error("Error running the FX; error %i: %s", vfxErr, errString); - goto fail; } /* 4. Map dst texture before transfer from dst img provided by FX */ @@ -295,7 +351,7 @@ static bool process_texture_greenscreen(struct nv_greenscreen_data *filter) return true; fail: - filter->processing_stop = true; + os_atomic_set_bool(&filter->processing_stop, true); return false; } @@ -317,7 +373,8 @@ static void *nv_greenscreen_filter_create(obs_data_t *settings, filter->width = 0; filter->height = 0; filter->initial_render = false; - filter->processing_stop = false; + os_atomic_set_bool(&filter->processing_stop, false); + filter->handler = NULL; /* 1. Create FX */ vfxErr = NvVFX_CreateEffect(NVVFX_FX_GREEN_SCREEN, &filter->handle); @@ -518,7 +575,11 @@ static void nv_greenscreen_filter_render(void *data, gs_effect_t *effect) obs_source_skip_video_filter(filter->context); return; } - + if (parent && !filter->handler) { + filter->handler = obs_source_get_signal_handler(parent); + signal_handler_connect(filter->handler, "update_properties", + nv_greenscreen_filter_reset, filter); + } /* 1. Render to retrieve texture. */ render = filter->render; if (!render) { @@ -573,7 +634,7 @@ static void nv_greenscreen_filter_render(void *data, gs_effect_t *effect) NvCV_GetErrorStringFromCode(vfxErr); error("Error creating src img; error %i: %s", vfxErr, errString); - filter->processing_stop = true; + os_atomic_set_bool(&filter->processing_stop, true); return; } vfxErr = NvCVImage_InitFromD3D11Texture(filter->src_img, @@ -583,7 +644,7 @@ static void nv_greenscreen_filter_render(void *data, gs_effect_t *effect) NvCV_GetErrorStringFromCode(vfxErr); error("Error passing src ID3D11Texture to img; error %i: %s", vfxErr, errString); - filter->processing_stop = true; + os_atomic_set_bool(&filter->processing_stop, true); return; } filter->initial_render = true;