From 37dd362825c51bf0ceb491eab4766e9459632afc Mon Sep 17 00:00:00 2001 From: "kevin.dww" Date: Tue, 10 Jan 2023 15:03:27 +0800 Subject: [PATCH 01/47] rtmp-services: update Mildom servers (cherry picked from commit 321776efa3bc1578fff7bcaa4f7cc18cb7e566b7) --- plugins/rtmp-services/data/package.json | 4 ++-- plugins/rtmp-services/data/services.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/rtmp-services/data/package.json b/plugins/rtmp-services/data/package.json index d4b5cfee4..53ea4db42 100644 --- a/plugins/rtmp-services/data/package.json +++ b/plugins/rtmp-services/data/package.json @@ -1,11 +1,11 @@ { "$schema": "schema/package-schema.json", "url": "https://obsproject.com/obs2_update/rtmp-services/v4", - "version": 216, + "version": 217, "files": [ { "name": "services.json", - "version": 216 + "version": 217 } ] } diff --git a/plugins/rtmp-services/data/services.json b/plugins/rtmp-services/data/services.json index 7022f9cbf..3801c0a10 100644 --- a/plugins/rtmp-services/data/services.json +++ b/plugins/rtmp-services/data/services.json @@ -2381,8 +2381,8 @@ "stream_key_link": "https://www.mildom.com/creator/live", "servers": [ { - "name": "Asia: Tokyo, Japan", - "url": "rtmp://live-tyo-tct.mildom.tv/live" + "name": "Global", + "url": "rtmp://txlvb-push.mildom.tv/live" } ], "recommended": { From ab46d09f17085052605d094710e0890395c855e2 Mon Sep 17 00:00:00 2001 From: "Chris (Flaeri)" Date: Fri, 13 Jan 2023 15:19:32 +0000 Subject: [PATCH 02/47] obs-ffmpeg: Remove forced x264 and aac for RTMP Remove code forcing x264 and ffmpeg aac encoder. People using custom ffmpeg output should be able to use other video and audio encoders when streaming with RTMP, given its h264 or aac. (cherry picked from commit 1166e504bbde35e4574af2cf6fb8104bcf96e088) --- plugins/obs-ffmpeg/obs-ffmpeg-output.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-output.c b/plugins/obs-ffmpeg/obs-ffmpeg-output.c index 10591e3a9..3d5a5498d 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-output.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-output.c @@ -640,9 +640,7 @@ bool ffmpeg_data_init(struct ffmpeg_data *data, struct ffmpeg_cfg *config) } #else if (is_rtmp) { - data->config.audio_encoder = "aac"; data->config.audio_encoder_id = AV_CODEC_ID_AAC; - data->config.video_encoder = "libx264"; data->config.video_encoder_id = AV_CODEC_ID_H264; } #endif From 4e4a803b3b00ee080bb6dd3d8f2a33443bd1299f Mon Sep 17 00:00:00 2001 From: gxalpha Date: Fri, 13 Jan 2023 18:36:22 +0100 Subject: [PATCH 03/47] UI: Reintroduce spacing to YouTube dialog buttons (cherry picked from commit 2133f47658f9c05b317baf83ddb7d08e9cccbd88) --- UI/forms/OBSYoutubeActions.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UI/forms/OBSYoutubeActions.ui b/UI/forms/OBSYoutubeActions.ui index 5825a2314..0594dc942 100644 --- a/UI/forms/OBSYoutubeActions.ui +++ b/UI/forms/OBSYoutubeActions.ui @@ -646,6 +646,9 @@ QLayout::SetNoConstraint + + 10 + From 375da1a0366e619928654a3378aa334414128777 Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sat, 14 Jan 2023 12:54:43 +0900 Subject: [PATCH 04/47] libobs/util: Fix text-lookup not always case-insensitive Convert `lookup` to upper-case before creating the tree so that later code does not need to consider the case-insensitivity. When converting to upper-case, use `toupper` instead of adding 0x20 so that the behavior is consistent with `astrcmpi_n`. (cherry picked from commit 1805712f4695e7ff89ee793f932250283373a9fb) --- libobs/util/text-lookup.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libobs/util/text-lookup.c b/libobs/util/text-lookup.c index 433aebd7f..6fc144f78 100644 --- a/libobs/util/text-lookup.c +++ b/libobs/util/text-lookup.c @@ -14,6 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include "dstr.h" #include "text-lookup.h" #include "lexer.h" @@ -159,11 +160,6 @@ static void lookup_addstring(const char *lookup_val, struct text_leaf *leaf, char val1 = child->str.array[len], val2 = lookup_val[len]; - if (val1 >= 'A' && val1 <= 'Z') - val1 += 0x20; - if (val2 >= 'A' && val2 <= 'Z') - val2 += 0x20; - if (val1 != val2) break; } @@ -323,6 +319,9 @@ static void lookup_addfiledata(struct text_lookup *lookup, leaf->lookup = bstrdup_n(name.array, name.len); leaf->value = convert_string(value.array, value.len); + for (size_t i = 0; i < name.len; i++) + leaf->lookup[i] = toupper(leaf->lookup[i]); + lookup_addstring(leaf->lookup, leaf, lookup->top); if (!lookup_goto_nextline(&lex)) From a166ca6b4fec1a83577c9d60146cb76505cbe4b9 Mon Sep 17 00:00:00 2001 From: derrod Date: Thu, 12 Jan 2023 22:33:55 +0100 Subject: [PATCH 05/47] updater: Fix portable OBS not being relaunched correctly (cherry picked from commit 143877c8ffc69090ea8a32ddae05389c97bb626c) --- UI/win-update/updater/updater.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/UI/win-update/updater/updater.cpp b/UI/win-update/updater/updater.cpp index f65808fa1..0a1cd2ac4 100644 --- a/UI/win-update/updater/updater.cpp +++ b/UI/win-update/updater/updater.cpp @@ -1754,7 +1754,7 @@ static void CancelUpdate(bool quit) } } -static void LaunchOBS() +static void LaunchOBS(bool portable) { wchar_t cwd[MAX_PATH]; wchar_t newCwd[MAX_PATH]; @@ -1794,6 +1794,9 @@ static void LaunchOBS() execInfo.lpDirectory = newCwd; execInfo.nShow = SW_SHOWNORMAL; + if (portable) + execInfo.lpParameters = L"--portable"; + ShellExecuteEx(&execInfo); } @@ -1907,6 +1910,8 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) GetCurrentDirectoryW(_countof(cwd) - 1, cwd); is32bit = wcsstr(cwd, L"bin\\32bit") != nullptr; + bool isPortable = wcsstr(lpCmdLine, L"Portable") != nullptr || + wcsstr(lpCmdLine, L"--portable") != nullptr; if (!IsWindows10OrGreater()) { MessageBox( @@ -1942,7 +1947,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) nullptr); SetCurrentDirectory(newPath); - LaunchOBS(); + LaunchOBS(isPortable); } if (hLowMutex) { @@ -1990,7 +1995,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) WinHandle hMutex = OpenMutex( SYNCHRONIZE, false, L"OBSUpdaterRunningAsNonAdminUser"); if (msg.wParam == 1 && !hMutex) { - LaunchOBS(); + LaunchOBS(isPortable); } return (int)msg.wParam; From 0a7228f1dafbc9fee146a69ec3c490b6e1947b22 Mon Sep 17 00:00:00 2001 From: Kurt Kartaltepe Date: Sun, 8 Jan 2023 19:50:18 -0800 Subject: [PATCH 06/47] libobs-opengl: Drop gl pointers on device_leave_context Mac was already dropping a most of these when leaving contexts, this patch brings the same drops to linux and also drops vertex/index buffers that were noticed as leaking across contexts and resulting in invalid bindings by later draws. Especially with the new spacing labels. (cherry picked from commit 599b017881239c84da7c9bf560ddb47333a5a8f1) --- libobs-opengl/gl-cocoa.m | 2 ++ libobs-opengl/gl-nix.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/libobs-opengl/gl-cocoa.m b/libobs-opengl/gl-cocoa.m index caaf3bf85..599ba9525 100644 --- a/libobs-opengl/gl-cocoa.m +++ b/libobs-opengl/gl-cocoa.m @@ -265,6 +265,8 @@ void device_leave_context(gs_device_t *device) { glFlush(); [NSOpenGLContext clearCurrentContext]; + device->cur_vertex_buffer = NULL; + device->cur_index_buffer = NULL; device->cur_render_target = NULL; device->cur_zstencil_buffer = NULL; device->cur_swap = NULL; diff --git a/libobs-opengl/gl-nix.c b/libobs-opengl/gl-nix.c index 52a300346..c775079fc 100644 --- a/libobs-opengl/gl-nix.c +++ b/libobs-opengl/gl-nix.c @@ -86,6 +86,12 @@ extern void device_enter_context(gs_device_t *device) extern void device_leave_context(gs_device_t *device) { + device->cur_render_target = NULL; + device->cur_zstencil_buffer = NULL; + device->cur_vertex_buffer = NULL; + device->cur_index_buffer = NULL; + device->cur_swap = NULL; + device->cur_fbo = NULL; gl_vtable->device_leave_context(device); } From 7d81905d4bfe5a9caaa8e2b5ff47797b9c6203e8 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Wed, 28 Dec 2022 14:23:40 -0800 Subject: [PATCH 07/47] win-capture: Show Force SDR setting on Windows 10 Was using wrong bool for visibility. (cherry picked from commit fb58f60ae4fdce4fe8b4c5ed1b157330f37b00ed) --- plugins/win-capture/window-capture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/win-capture/window-capture.c b/plugins/win-capture/window-capture.c index 33a2dd06b..f548a6c22 100644 --- a/plugins/win-capture/window-capture.c +++ b/plugins/win-capture/window-capture.c @@ -401,7 +401,7 @@ static void update_settings_visibility(obs_properties_t *props, obs_property_set_visible(p, wgc_options); p = obs_properties_get(props, "force_sdr"); - obs_property_set_visible(p, wgc_cursor_toggle); + obs_property_set_visible(p, wgc_options); pthread_mutex_unlock(&wc->update_mutex); } From a5808c94442472bd0a873de9c6f466e34f14388e Mon Sep 17 00:00:00 2001 From: Exeldro Date: Tue, 3 Jan 2023 14:49:34 +0100 Subject: [PATCH 08/47] libobs: Fix stopping transitions that are not active (cherry picked from commit eb35b07f44bc1cbb01f14960c561ccc255db11f4) --- libobs/obs-source-transition.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libobs/obs-source-transition.c b/libobs/obs-source-transition.c index 45869bc47..9c50f4a99 100644 --- a/libobs/obs-source-transition.c +++ b/libobs/obs-source-transition.c @@ -439,7 +439,7 @@ void obs_transition_set(obs_source_t *transition, obs_source_t *source) obs_source_t *s[2]; bool active[2]; - if (!transition_valid(transition, "obs_transition_clear")) + if (!transition_valid(transition, "obs_transition_set")) return; source = obs_source_get_ref(source); @@ -893,6 +893,9 @@ bool obs_transition_video_render_direct(obs_source_t *transition, transition->transitioning_video = false; video_stopped = true; + if (!obs_source_active(transition)) + transition->transitioning_audio = false; + if (!transition->transitioning_audio) { obs_transition_stop(transition); stopped = true; From d9a5aaafc9f0a1b5d279bebab9874a07db70029e Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sun, 15 Jan 2023 22:09:23 -0800 Subject: [PATCH 09/47] docs: Document a few missing obs_output_t function calls - `obs_weak_output_references_output` - `obs_output_get_id` - `obs_output_output_caption_text[1/2]` (cherry picked from commit 24e9f82f8799078f3960029defbd912a8cfa3da6) --- docs/sphinx/reference-outputs.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/sphinx/reference-outputs.rst b/docs/sphinx/reference-outputs.rst index a0766ef48..730a6bb4b 100644 --- a/docs/sphinx/reference-outputs.rst +++ b/docs/sphinx/reference-outputs.rst @@ -373,12 +373,26 @@ General Output Functions --------------------- +.. function:: bool obs_weak_output_references_output(obs_weak_output_t *weak, obs_output_t *output) + + Compares a weak output reference with an output. + + :return: Whether the weak output reference ties back to the specified output + +--------------------- + .. function:: const char *obs_output_get_name(const obs_output_t *output) :return: The name of the output --------------------- +.. function:: const char *obs_output_get_id(const obs_output_t *output) + + :return: The output's type identifier string + +--------------------- + .. function:: bool obs_output_start(obs_output_t *output) Starts the output. @@ -621,6 +635,18 @@ General Output Functions --------------------- +.. function:: void obs_output_output_caption_text1(obs_output_t *output, const char *text) + void obs_output_output_caption_text2(obs_output_t *output, const char *text, double display_duration) + + Outputs captions from the specified text input. *text1* is the same as + *text2*, except that the *display_duration* is hardcoded to 2.0 seconds. + + *display_duration* represents the minimum quantity of time that a given + caption can be displayed for before moving onto the next caption in the + queue. + +--------------------- + .. function:: float obs_output_get_congestion(obs_output_t *output) :return: The congestion value. This value is used to visualize the From 8aa806adf83a69d4e791524f9a23c7dc58542afc Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sun, 15 Jan 2023 22:59:59 -0800 Subject: [PATCH 10/47] libobs: Remove extra space in output reconnect log message It has been bothering me to no end. (cherry picked from commit 78d31322b2e9fae15f9db4f7a24a81ddfa5392a8) --- libobs/obs-output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libobs/obs-output.c b/libobs/obs-output.c index 3253a3b25..9c096726c 100644 --- a/libobs/obs-output.c +++ b/libobs/obs-output.c @@ -2417,7 +2417,7 @@ static void output_reconnect(struct obs_output *output) blog(LOG_WARNING, "Failed to create reconnect thread"); os_atomic_set_bool(&output->reconnecting, false); } else { - blog(LOG_INFO, "Output '%s': Reconnecting in %.02f seconds..", + blog(LOG_INFO, "Output '%s': Reconnecting in %.02f seconds..", output->context.name, (float)(output->reconnect_retry_cur_msec / 1000.0)); From 00b4c9c88af79645aa078ea25802bd50d26449dd Mon Sep 17 00:00:00 2001 From: PatTheMav Date: Wed, 11 Jan 2023 18:50:04 +0100 Subject: [PATCH 11/47] mac-virtualcam: Fix memory access issues for shared IOSurfaces The DAL plugin-based virtualcamera shares data between OBS and the plugin using an IOSurface. IOSurface locks are necessary to ensure race conditions between data generation (OBS side) and consumption (virtual camera side) and also that an IOSurface is not offloaded to GPU memory when it is indeed needed in CPU memory. Also moves the invalidation of the NSMachPort for the frames to after the IOSurface data has been converted into a pixelbuffer and added to the frame queue of the virtual camera, as an early invalidation will cut off access to the pixel data shared with the DAL plugin. (cherry picked from commit 447adfbe385249ba721dec2ad9d2e4aaa9f0376a) --- .../src/dal-plugin/OBSDALMachClient.mm | 93 ++++++++++--------- .../src/obs-plugin/OBSDALMachServer.mm | 7 ++ 2 files changed, 56 insertions(+), 44 deletions(-) diff --git a/plugins/mac-virtualcam/src/dal-plugin/OBSDALMachClient.mm b/plugins/mac-virtualcam/src/dal-plugin/OBSDALMachClient.mm index 9514eee9f..303a3a4dc 100644 --- a/plugins/mac-virtualcam/src/dal-plugin/OBSDALMachClient.mm +++ b/plugins/mac-virtualcam/src/dal-plugin/OBSDALMachClient.mm @@ -93,6 +93,8 @@ - (void)handlePortMessage:(NSPortMessage *)message { + __strong id strongDelegate = self.delegate; + VLogFunc(@""); NSArray *components = message.components; switch (message.msgid) { @@ -113,57 +115,60 @@ IOSurfaceRef surface = IOSurfaceLookupFromMachPort( [framePort machPort]); + + if (surface) { + /* + * IOSurfaceLocks are only necessary on non Apple Silicon devices, as those have + * unified memory. On Intel machines, the lock ensures that the IOSurface is copied back + * from GPU memory to CPU memory so we can process the pixel buffer. + */ +#ifndef __aarch64__ + IOSurfaceLock(surface, kIOSurfaceLockReadOnly, + NULL); +#endif + CVPixelBufferRef frame; + CVPixelBufferCreateWithIOSurface( + kCFAllocatorDefault, surface, NULL, + &frame); +#ifndef __aarch64__ + IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, + NULL); +#endif + CFRelease(surface); + + uint64_t timestamp; + [components[1] getBytes:×tamp + length:sizeof(timestamp)]; + + VLog(@"Received frame data: %zux%zu (%llu)", + CVPixelBufferGetWidth(frame), + CVPixelBufferGetHeight(frame), timestamp); + + uint32_t fpsNumerator; + [components[2] getBytes:&fpsNumerator + length:sizeof(fpsNumerator)]; + uint32_t fpsDenominator; + [components[3] getBytes:&fpsDenominator + length:sizeof(fpsDenominator)]; + + [strongDelegate + receivedPixelBuffer:frame + timestamp:timestamp + fpsNumerator:fpsNumerator + fpsDenominator:fpsDenominator]; + + CVPixelBufferRelease(frame); + } else { + ELog(@"Failed to obtain IOSurface from Mach port"); + } [framePort invalidate]; mach_port_deallocate(mach_task_self(), [framePort machPort]); - - if (!surface) { - ELog(@"Failed to obtain IOSurface from Mach port"); - return; - } - - /* - * IOSurfaceLocks are only necessary on non Apple Silicon devices, as those have - * unified memory. On Intel machines, the lock ensures that the IOSurface is copied back - * from GPU memory to CPU memory so we can process the pixel buffer. - */ -#ifndef __aarch64__ - IOSurfaceLock(surface, kIOSurfaceLockReadOnly, NULL); -#endif - CVPixelBufferRef frame; - CVPixelBufferCreateWithIOSurface(kCFAllocatorDefault, - surface, NULL, &frame); -#ifndef __aarch64__ - IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, NULL); -#endif - CFRelease(surface); - - uint64_t timestamp; - [components[1] getBytes:×tamp - length:sizeof(timestamp)]; - - VLog(@"Received frame data: %zux%zu (%llu)", - CVPixelBufferGetWidth(frame), - CVPixelBufferGetHeight(frame), timestamp); - - uint32_t fpsNumerator; - [components[2] getBytes:&fpsNumerator - length:sizeof(fpsNumerator)]; - uint32_t fpsDenominator; - [components[3] getBytes:&fpsDenominator - length:sizeof(fpsDenominator)]; - - [self.delegate receivedPixelBuffer:frame - timestamp:timestamp - fpsNumerator:fpsNumerator - fpsDenominator:fpsDenominator]; - - CVPixelBufferRelease(frame); } break; case MachMsgIdStop: DLog(@"Received stop message"); - [self.delegate receivedStop]; + [strongDelegate receivedStop]; break; default: ELog(@"Received unexpected response msgid %u", diff --git a/plugins/mac-virtualcam/src/obs-plugin/OBSDALMachServer.mm b/plugins/mac-virtualcam/src/obs-plugin/OBSDALMachServer.mm index efd33c1b4..450e99466 100644 --- a/plugins/mac-virtualcam/src/obs-plugin/OBSDALMachServer.mm +++ b/plugins/mac-virtualcam/src/obs-plugin/OBSDALMachServer.mm @@ -148,6 +148,9 @@ length:sizeof(fpsDenominator)]; IOSurfaceRef surface = CVPixelBufferGetIOSurface(frame); +#ifndef __aarch64__ + IOSurfaceLock(surface, 0, NULL); +#endif if (!surface) { blog(LOG_ERROR, @@ -174,6 +177,10 @@ ]]; mach_port_deallocate(mach_task_self(), framePort); + +#ifndef __aarch64__ + IOSurfaceUnlock(surface, 0, NULL); +#endif } } From 0ce729ea78d0236192f7e7dd436a631586acf3b6 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sun, 15 Jan 2023 20:12:09 -0800 Subject: [PATCH 12/47] libobs: Protect some encoder functions from being used while active Protect `obs_encoder_set_video()` and `obs_encoder_set_audio()` from being used if the encoder is active. Changing these values while active is undefined behavior. (cherry picked from commit dfc20bbb311b71516f6571584c585a010ea63eb7) --- libobs/obs-encoder.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/libobs/obs-encoder.c b/libobs/obs-encoder.c index dd33e3344..f90817519 100644 --- a/libobs/obs-encoder.c +++ b/libobs/obs-encoder.c @@ -792,6 +792,14 @@ void obs_encoder_set_video(obs_encoder_t *encoder, video_t *video) obs_encoder_get_name(encoder)); return; } + if (encoder_active(encoder)) { + blog(LOG_WARNING, + "encoder '%s': Cannot apply a new video_t " + "object while the encoder is active", + obs_encoder_get_name(encoder)); + return; + } + if (!video) return; @@ -813,6 +821,14 @@ void obs_encoder_set_audio(obs_encoder_t *encoder, audio_t *audio) obs_encoder_get_name(encoder)); return; } + if (encoder_active(encoder)) { + blog(LOG_WARNING, + "encoder '%s': Cannot apply a new audio_t " + "object while the encoder is active", + obs_encoder_get_name(encoder)); + return; + } + if (!audio) return; @@ -1316,7 +1332,7 @@ end: void obs_encoder_add_output(struct obs_encoder *encoder, struct obs_output *output) { - if (!encoder) + if (!encoder || !output) return; pthread_mutex_lock(&encoder->outputs_mutex); @@ -1327,7 +1343,7 @@ void obs_encoder_add_output(struct obs_encoder *encoder, void obs_encoder_remove_output(struct obs_encoder *encoder, struct obs_output *output) { - if (!encoder) + if (!encoder || !output) return; pthread_mutex_lock(&encoder->outputs_mutex); From 9ead5380093abc3a905dc7dcdf9810dcedbaead5 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sun, 15 Jan 2023 20:17:21 -0800 Subject: [PATCH 13/47] libobs: Allow sending NULL to obs_encoder_set_video/audio() There is currently no way to clear a video_t or audio_t object from an encoder once applied. `audio_t`/`video_t` objects can be destructed at any time, and it is dangerous to prevent these object references from even being cleared. This does not fix the issue where destroying an audio/video object does not clear the reference from all subscribed encoders. (cherry picked from commit eb0d9dc5d2492bf3365bf3d6ab596c5447507553) --- libobs/obs-encoder.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/libobs/obs-encoder.c b/libobs/obs-encoder.c index f90817519..4804760cf 100644 --- a/libobs/obs-encoder.c +++ b/libobs/obs-encoder.c @@ -800,14 +800,16 @@ void obs_encoder_set_video(obs_encoder_t *encoder, video_t *video) return; } - if (!video) - return; - - voi = video_output_get_info(video); - - encoder->media = video; - encoder->timebase_num = voi->fps_den; - encoder->timebase_den = voi->fps_num; + if (video) { + voi = video_output_get_info(video); + encoder->media = video; + encoder->timebase_num = voi->fps_den; + encoder->timebase_den = voi->fps_num; + } else { + encoder->media = NULL; + encoder->timebase_num = 0; + encoder->timebase_den = 0; + } } void obs_encoder_set_audio(obs_encoder_t *encoder, audio_t *audio) @@ -829,12 +831,15 @@ void obs_encoder_set_audio(obs_encoder_t *encoder, audio_t *audio) return; } - if (!audio) - return; - - encoder->media = audio; - encoder->timebase_num = 1; - encoder->timebase_den = audio_output_get_sample_rate(audio); + if (audio) { + encoder->media = audio; + encoder->timebase_num = 1; + encoder->timebase_den = audio_output_get_sample_rate(audio); + } else { + encoder->media = NULL; + encoder->timebase_num = 0; + encoder->timebase_den = 0; + } } video_t *obs_encoder_video(const obs_encoder_t *encoder) From 7d579b5a07d1e8623298b823e5e91c00b94cff64 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sun, 15 Jan 2023 20:33:58 -0800 Subject: [PATCH 14/47] libobs: Remove unused internal encoder util function Was previously introduced in a0f679bc40cc9452f84bb7c63143bffb1ac6c348, but has since been made unused. (cherry picked from commit 7e30d3f8a29ccd11710fb9bb438b3b0c84ee31a1) --- libobs/obs-encoder.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/libobs/obs-encoder.c b/libobs/obs-encoder.c index 4804760cf..ea277b524 100644 --- a/libobs/obs-encoder.c +++ b/libobs/obs-encoder.c @@ -175,16 +175,6 @@ static inline void get_video_info(struct obs_encoder *encoder, obs_encoder_set_scaled_size(encoder, info->width, info->height); } -static inline bool has_scaling(const struct obs_encoder *encoder) -{ - uint32_t video_width = video_output_get_width(encoder->media); - uint32_t video_height = video_output_get_height(encoder->media); - - return encoder->scaled_width && encoder->scaled_height && - (video_width != encoder->scaled_width || - video_height != encoder->scaled_height); -} - static inline bool gpu_encode_available(const struct obs_encoder *encoder) { struct obs_core_video_mix *video = get_mix_for_video(encoder->media); From 2fcac0e36355c237677a5990ec9ed7e78ade1737 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sun, 15 Jan 2023 21:24:36 -0800 Subject: [PATCH 15/47] libobs: Prevent encoders from initializing/starting if no media is set This fixes a case of undefined behavior, where encoders can try to init or start without actually having any video_t or audio_t object assigned. (cherry picked from commit c69e40734dcc547c844d14f221adf2f11ff77890) --- libobs/obs-encoder.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libobs/obs-encoder.c b/libobs/obs-encoder.c index ea277b524..cafe2b2b2 100644 --- a/libobs/obs-encoder.c +++ b/libobs/obs-encoder.c @@ -443,6 +443,13 @@ static THREAD_LOCAL bool can_reroute = false; static inline bool obs_encoder_initialize_internal(obs_encoder_t *encoder) { + if (!encoder->media) { + blog(LOG_ERROR, + "obs_encoder_initialize_internal: encoder '%s' has no media set", + encoder->context.name); + return false; + } + if (encoder_active(encoder)) return true; if (encoder->initialized) @@ -552,7 +559,7 @@ static inline void obs_encoder_start_internal( struct encoder_callback cb = {false, new_packet, param}; bool first = false; - if (!encoder->context.data) + if (!encoder->context.data || !encoder->media) return; pthread_mutex_lock(&encoder->callbacks_mutex); From aa1f7b275b6d60b491ec7e549dd5788027d303e1 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sun, 15 Jan 2023 22:53:16 -0800 Subject: [PATCH 16/47] libobs: Fix logging of remaining views OBS has been logging `1 views remain at shutdown` when in reality there are not technically any views remaining. When views are removed, the view itself is destroyed immediately, but the mix remains, to be garbage collected by the graphics thread. In this case, the view has already been removed, but the graphics thread has not run an interation and cleaned up the mix, so this log message appears. Fixes the issue by checking if a mix actually has an assigned view, instead of blindly logging existing mixes. (cherry picked from commit 25df3e183ec2273cf706b9ea9b4ef248153629d1) --- libobs/obs.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libobs/obs.c b/libobs/obs.c index 291e25682..2d284ea30 100644 --- a/libobs/obs.c +++ b/libobs/obs.c @@ -774,13 +774,16 @@ void obs_free_video_mix(struct obs_core_video_mix *video) static void obs_free_video(void) { pthread_mutex_lock(&obs->video.mixes_mutex); - size_t num = obs->video.mixes.num; - if (num) - blog(LOG_WARNING, "%zu views remain at shutdown", num); - for (size_t i = 0; i < num; i++) { - obs_free_video_mix(obs->video.mixes.array[i]); + size_t num_views = 0; + for (size_t i = 0; i < obs->video.mixes.num; i++) { + struct obs_core_video_mix *video = obs->video.mixes.array[i]; + if (video && video->view) + num_views++; + obs_free_video_mix(video); obs->video.mixes.array[i] = NULL; } + if (num_views > 0) + blog(LOG_WARNING, "Number of remaining views: %ld", num_views); pthread_mutex_unlock(&obs->video.mixes_mutex); pthread_mutex_destroy(&obs->video.mixes_mutex); From a25a4c20b47276398353b923220fde2016e0a439 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sun, 15 Jan 2023 21:27:47 -0800 Subject: [PATCH 17/47] UI: Fix logging of output ID when start fails + code cleanup Previously, an output that does not implement `info.get_output_type` would result in these log messages saying `(null)`. This uses the actual ID directly from the output itself instead. Also removes two extra calls to `obs_encoder_set_video()` as they are redundant and unnecessary. (cherry picked from commit 8f0e5a72d6aa1129c02d03016fd1f5eac4ace2f0) --- UI/window-basic-main-outputs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UI/window-basic-main-outputs.cpp b/UI/window-basic-main-outputs.cpp index 6a0985419..cf239b9ee 100644 --- a/UI/window-basic-main-outputs.cpp +++ b/UI/window-basic-main-outputs.cpp @@ -1007,7 +1007,7 @@ bool SimpleOutput::StartStreaming(obs_service_t *service) else lastError = string(); - const char *type = obs_service_get_output_type(service); + const char *type = obs_output_get_id(streamOutput); blog(LOG_WARNING, "Stream output type '%s' failed to start!%s%s", type, hasLastError ? " Last Error: " : "", hasLastError ? error : ""); return false; @@ -1906,7 +1906,7 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service) else lastError = string(); - const char *type = obs_service_get_output_type(service); + const char *type = obs_output_get_id(streamOutput); blog(LOG_WARNING, "Stream output type '%s' failed to start!%s%s", type, hasLastError ? " Last Error: " : "", hasLastError ? error : ""); return false; From 25fba67fe810ca1e9408eb135c923316bd57bac7 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Tue, 17 Jan 2023 20:46:22 -0800 Subject: [PATCH 18/47] UI: Remove extra encoder function calls The audio_t and video_t objects are already applied in the parent functions already. (cherry picked from commit 5a68d3aaf5cb7a34b71699b02c8d89fb153257cb) --- UI/window-basic-main-outputs.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/UI/window-basic-main-outputs.cpp b/UI/window-basic-main-outputs.cpp index cf239b9ee..a46516737 100644 --- a/UI/window-basic-main-outputs.cpp +++ b/UI/window-basic-main-outputs.cpp @@ -1482,7 +1482,6 @@ inline void AdvancedOutput::SetupStreaming() obs_output_set_audio_encoder(streamOutput, streamAudioEnc, 0); obs_encoder_set_scaled_size(videoStreaming, cx, cy); - obs_encoder_set_video(videoStreaming, obs_get_video()); const char *id = obs_service_get_id(main->GetService()); if (strcmp(id, "rtmp_custom") == 0) { @@ -1536,7 +1535,6 @@ inline void AdvancedOutput::SetupRecording() } obs_encoder_set_scaled_size(videoRecording, cx, cy); - obs_encoder_set_video(videoRecording, obs_get_video()); obs_output_set_video_encoder(fileOutput, videoRecording); if (replayBuffer) obs_output_set_video_encoder(replayBuffer, From 58f50a8bbe38d8629f400b67e0022655ae5d08db Mon Sep 17 00:00:00 2001 From: Ryan Foster Date: Thu, 19 Jan 2023 11:35:51 -0500 Subject: [PATCH 19/47] CI: Revert Qt to 6.3.1 on Windows (cherry picked from commit af59a903e19c31a2f64c15c377f488498477538a) --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index daa5b8694..800c2d70a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,11 +22,11 @@ env: QT_HASH_MAC_X86_64: 'c5ed7bc9f6e802910ec539066bcf0a8d64100fafce568071f264c88c22c5859b' QT_HASH_MAC_ARM64: '1ce472fd1e28f947456b72b1d7ab929d6e93cb774c2928e22eca9bb751b12ccf' QT_HASH_MAC_UNIVERSAL: '873f7c9c9f7fcee740a79c075b32a505c932c816d928807fa16f3439c610fbfd' - QT_VERSION_WIN: '6.4.1' + QT_VERSION_WIN: '6.3.1' DEPS_VERSION_MAC: '2022-11-21' DEPS_HASH_MAC_X86_64: 'ed0a145e88496f8975da14a07939dbe5633e60510aada34509a4aef64a66e438' DEPS_HASH_MAC_ARM64: 'f397dc524e5ee7f85684f0b9661c45957446e28d166fcd6dfacf895c9d4d2521' - DEPS_VERSION_WIN: '2022-11-21' + DEPS_VERSION_WIN: '2023-01-06' VLC_VERSION_MAC: '3.0.8' VLC_HASH_MAC: 'e0149ef4a20a19b9ecd87309c2d27787ee3f47dfd47c6639644bc1f6fd95bdf6' VLC_VERSION_WIN: '3.0.0-git' From fb371a340bbb151453a8cf86c54a5aa0e8882da3 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Thu, 19 Jan 2023 02:49:15 -0800 Subject: [PATCH 20/47] libobs: Fix loading of custom_size for empty scenes Previously, `custom_size` was checked at the end of the `scene_load` function. If the scene contained no "items" array, the `custom_scene` loading code would never be run. This moves the `custom_size` code above the return statement. (cherry picked from commit 018ce16703b4dfc384cbca7e6edec8c5ff03b9fb) --- libobs/obs-scene.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libobs/obs-scene.c b/libobs/obs-scene.c index f07e38c97..fd787a720 100644 --- a/libobs/obs-scene.c +++ b/libobs/obs-scene.c @@ -1103,6 +1103,12 @@ static void scene_load(void *data, obs_data_t *settings) remove_all_items(scene); + if (obs_data_get_bool(settings, "custom_size")) { + scene->cx = (uint32_t)obs_data_get_int(settings, "cx"); + scene->cy = (uint32_t)obs_data_get_int(settings, "cy"); + scene->custom_size = true; + } + if (!items) return; @@ -1117,12 +1123,6 @@ static void scene_load(void *data, obs_data_t *settings) if (obs_data_has_user_value(settings, "id_counter")) scene->id_counter = obs_data_get_int(settings, "id_counter"); - if (obs_data_get_bool(settings, "custom_size")) { - scene->cx = (uint32_t)obs_data_get_int(settings, "cx"); - scene->cy = (uint32_t)obs_data_get_int(settings, "cy"); - scene->custom_size = true; - } - obs_data_array_release(items); } From c24c137fa6c575e266c416818b10abc4b54702b9 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Sat, 31 Dec 2022 15:20:09 +0000 Subject: [PATCH 21/47] libobs/graphics: Enable DMABUF on FreeBSD and DragonFly Required under Wayland (wlrobs) on FreeBSD and DragonFly. DMABUF was already partially exposed after c50c62555516. (cherry picked from commit c082c4a74d079d5e0bd6ed7e6338b767c29f69c9) --- docs/sphinx/reference-libobs-graphics-graphics.rst | 6 +++--- libobs/graphics/device-exports.h | 2 +- libobs/graphics/graphics-imports.c | 2 +- libobs/graphics/graphics-internal.h | 2 +- libobs/graphics/graphics.c | 2 +- libobs/graphics/graphics.h | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/sphinx/reference-libobs-graphics-graphics.rst b/docs/sphinx/reference-libobs-graphics-graphics.rst index 16d183fe7..aeba70545 100644 --- a/docs/sphinx/reference-libobs-graphics-graphics.rst +++ b/docs/sphinx/reference-libobs-graphics-graphics.rst @@ -1009,7 +1009,7 @@ Texture Functions .. function:: gs_texture_t *gs_texture_create_from_dmabuf(unsigned int width, unsigned int height, uint32_t drm_format, enum gs_color_format color_format, uint32_t n_planes, const int *fds, const uint32_t *strides, const uint32_t *offsets, const uint64_t *modifiers) - **Linux only:** Creates a texture from DMA-BUF metadata. + **only Linux, FreeBSD, DragonFly:** Creates a texture from DMA-BUF metadata. Exchanging DMA-BUFs is a verbose process because of its multiplanar nature. For example, YUV can have each plane as a color channel, or a monitor buffer @@ -1049,7 +1049,7 @@ Texture Functions .. function:: bool *gs_query_dmabuf_capabilities(enum gs_dmabuf_flags *dmabuf_flags, uint32_t **drm_formats, size_t *n_formats) - **Linux only:** Queries the capabilities for DMA-BUFs. + **only Linux, FreeBSD, DragonFly:** Queries the capabilities for DMA-BUFs. Graphics cards can optimize frame buffers by storing them in custom layouts, depending on their hardware features. These layouts can make these frame @@ -1068,7 +1068,7 @@ Texture Functions .. function:: bool *gs_query_dmabuf_modifiers_for_format(uint32_t drm_format, uint64_t **modifiers, size_t *n_modifiers) - **Linux only:** Queries the supported DMA-BUF modifiers for a given format. + **only Linux, FreeBSD, DragonFly:** Queries the supported DMA-BUF modifiers for a given format. This function queries all supported explicit modifiers for a format, stores them as an array and returns the number of supported modifiers. diff --git a/libobs/graphics/device-exports.h b/libobs/graphics/device-exports.h index 6200796ed..4fcae2e6a 100644 --- a/libobs/graphics/device-exports.h +++ b/libobs/graphics/device-exports.h @@ -178,7 +178,7 @@ EXPORT void device_debug_marker_begin(gs_device_t *device, const float color[4]); EXPORT void device_debug_marker_end(gs_device_t *device); -#if __linux__ +#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) EXPORT gs_texture_t *device_texture_create_from_dmabuf( gs_device_t *device, unsigned int width, unsigned int height, diff --git a/libobs/graphics/graphics-imports.c b/libobs/graphics/graphics-imports.c index b7a32890e..00681680c 100644 --- a/libobs/graphics/graphics-imports.c +++ b/libobs/graphics/graphics-imports.c @@ -234,7 +234,7 @@ bool load_graphics_imports(struct gs_exports *exports, void *module, GRAPHICS_IMPORT_OPTIONAL(device_stagesurface_create_p010); GRAPHICS_IMPORT_OPTIONAL(device_register_loss_callbacks); GRAPHICS_IMPORT_OPTIONAL(device_unregister_loss_callbacks); -#elif __linux__ +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) GRAPHICS_IMPORT(device_texture_create_from_dmabuf); GRAPHICS_IMPORT(device_query_dmabuf_capabilities); GRAPHICS_IMPORT(device_query_dmabuf_modifiers_for_format); diff --git a/libobs/graphics/graphics-internal.h b/libobs/graphics/graphics-internal.h index 434b76187..137a02196 100644 --- a/libobs/graphics/graphics-internal.h +++ b/libobs/graphics/graphics-internal.h @@ -348,7 +348,7 @@ struct gs_exports { gs_device_t *device, const struct gs_device_loss *callbacks); void (*device_unregister_loss_callbacks)(gs_device_t *device, void *data); -#elif __linux__ +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) struct gs_texture *(*device_texture_create_from_dmabuf)( gs_device_t *device, unsigned int width, unsigned int height, uint32_t drm_format, enum gs_color_format color_format, diff --git a/libobs/graphics/graphics.c b/libobs/graphics/graphics.c index c68b26afc..7bc03dff1 100644 --- a/libobs/graphics/graphics.c +++ b/libobs/graphics/graphics.c @@ -1387,7 +1387,7 @@ gs_texture_t *gs_texture_create(uint32_t width, uint32_t height, levels, data, flags); } -#if __linux__ +#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) gs_texture_t *gs_texture_create_from_dmabuf( unsigned int width, unsigned int height, uint32_t drm_format, diff --git a/libobs/graphics/graphics.h b/libobs/graphics/graphics.h index b18f5d9bb..5b309d002 100644 --- a/libobs/graphics/graphics.h +++ b/libobs/graphics/graphics.h @@ -967,7 +967,7 @@ EXPORT gs_stagesurf_t *gs_stagesurface_create_p010(uint32_t width, EXPORT void gs_register_loss_callbacks(const struct gs_device_loss *callbacks); EXPORT void gs_unregister_loss_callbacks(void *data); -#elif defined(__linux__) || defined(__FreeBSD__) +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) EXPORT gs_texture_t *gs_texture_create_from_dmabuf( unsigned int width, unsigned int height, uint32_t drm_format, From 7fb8b7dd75d94ee28656ab9d5fde0366fc9a0efa Mon Sep 17 00:00:00 2001 From: Richard Stanway Date: Thu, 19 Jan 2023 23:12:19 +0100 Subject: [PATCH 22/47] obs-filters: Improve NVIDIA effects SDK version checks - Don't repeatedly query version at runtime in case a user installs the SDK while OBS is running - Restore default DLL search directory - Don't show outdated SDK message if the SDK is not found - Protect minimum version macro with brackets (cherry picked from commit 5a4283816d192d26942f77bc67409d087bf2cd3c) --- plugins/obs-filters/noise-suppress-filter.c | 4 ++-- plugins/obs-filters/nvafx-load.h | 19 +++++++++++++++---- .../obs-filters/nvidia-greenscreen-filter.c | 6 +++--- plugins/obs-filters/nvvfx-load.h | 19 +++++++++++++++---- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/plugins/obs-filters/noise-suppress-filter.c b/plugins/obs-filters/noise-suppress-filter.c index d019a2272..2b042bf2b 100644 --- a/plugins/obs-filters/noise-suppress-filter.c +++ b/plugins/obs-filters/noise-suppress-filter.c @@ -634,7 +634,7 @@ bool load_nvafx(void) blog(LOG_INFO, "[noise suppress]: NVIDIA AUDIO FX version: %i.%i.%i.%i", major, minor, build, revision); - if (version < (MIN_AFX_SDK_VERSION)) { + if (version < MIN_AFX_SDK_VERSION) { blog(LOG_INFO, "[noise suppress]: NVIDIA AUDIO Effects SDK is outdated. Please update both audio & video SDK."); } @@ -1227,7 +1227,7 @@ static obs_properties_t *noise_suppress_properties(void *data) 1.0f, 0.01f); } unsigned int version = get_lib_version(); - if (version < (MIN_AFX_SDK_VERSION)) { + if (version && version < MIN_AFX_SDK_VERSION) { obs_property_t *warning = obs_properties_add_text( ppts, "deprecation", NULL, OBS_TEXT_INFO); obs_property_text_set_info_type(warning, OBS_TEXT_INFO_WARNING); diff --git a/plugins/obs-filters/nvafx-load.h b/plugins/obs-filters/nvafx-load.h index 7fc94c007..0b02c426e 100644 --- a/plugins/obs-filters/nvafx-load.h +++ b/plugins/obs-filters/nvafx-load.h @@ -9,7 +9,7 @@ #define NVAFX_API #ifdef LIBNVAFX_ENABLED -#define MIN_AFX_SDK_VERSION 1 << 24 | 2 << 16 | 13 << 0 +#define MIN_AFX_SDK_VERSION (1 << 24 | 2 << 16 | 13 << 0) static HMODULE nv_audiofx = NULL; static HMODULE nv_cuda = NULL; @@ -312,15 +312,26 @@ static bool load_lib(void) static unsigned int get_lib_version(void) { + static unsigned int version = 0; + static bool version_checked = false; + + if (version_checked) + return version; + + version_checked = true; + char path[MAX_PATH]; if (!nvafx_get_sdk_path(path, sizeof(path))) return 0; SetDllDirectoryA(path); + struct win_version_info nto_ver = {0}; - get_dll_ver(L"NVAudioEffects.dll", &nto_ver); - unsigned int version = nto_ver.major << 24 | nto_ver.minor << 16 | - nto_ver.build << 8 | nto_ver.revis << 0; + if (get_dll_ver(L"NVAudioEffects.dll", &nto_ver)) + version = nto_ver.major << 24 | nto_ver.minor << 16 | + nto_ver.build << 8 | nto_ver.revis << 0; + + SetDllDirectoryA(NULL); return version; } #endif diff --git a/plugins/obs-filters/nvidia-greenscreen-filter.c b/plugins/obs-filters/nvidia-greenscreen-filter.c index dc51d6997..e6f64b389 100644 --- a/plugins/obs-filters/nvidia-greenscreen-filter.c +++ b/plugins/obs-filters/nvidia-greenscreen-filter.c @@ -479,7 +479,7 @@ static void *nv_greenscreen_filter_create(obs_data_t *settings, uint8_t build = (filter->version >> 8) & 0x0000ff; uint8_t revision = (filter->version >> 0) & 0x000000ff; // sanity check - nvvfx_new_sdk = filter->version >= (MIN_VFX_SDK_VERSION) && + nvvfx_new_sdk = filter->version >= MIN_VFX_SDK_VERSION && nvvfx_new_sdk; } @@ -551,7 +551,7 @@ static obs_properties_t *nv_greenscreen_filter_properties(void *data) props, S_PROCESSING, TEXT_PROCESSING, 1, 4, 1); obs_property_set_long_description(partial, TEXT_PROCESSING_HINT); unsigned int version = get_lib_version(); - if (version < (MIN_VFX_SDK_VERSION)) { + if (version && version < MIN_VFX_SDK_VERSION) { obs_property_t *warning = obs_properties_add_text( props, "deprecation", NULL, OBS_TEXT_INFO); obs_property_text_set_info_type(warning, OBS_TEXT_INFO_WARNING); @@ -896,7 +896,7 @@ bool load_nvvfx(void) blog(LOG_INFO, "[NVIDIA VIDEO FX]: NVIDIA VIDEO FX version: %i.%i.%i.%i", major, minor, build, revision); - if (version < (MIN_VFX_SDK_VERSION)) { + if (version < MIN_VFX_SDK_VERSION) { blog(LOG_INFO, "[NVIDIA VIDEO FX]: NVIDIA VIDEO Effects SDK is outdated. Please update both audio & video SDK."); } diff --git a/plugins/obs-filters/nvvfx-load.h b/plugins/obs-filters/nvvfx-load.h index 4feb5afc6..cd1df985b 100644 --- a/plugins/obs-filters/nvvfx-load.h +++ b/plugins/obs-filters/nvvfx-load.h @@ -39,7 +39,7 @@ extern "C" { #define CUDARTAPI #ifdef LIBNVVFX_ENABLED -#define MIN_VFX_SDK_VERSION 0 << 24 | 7 << 16 | 1 << 8 | 0 << 0 +#define MIN_VFX_SDK_VERSION (0 << 24 | 7 << 16 | 1 << 8 | 0 << 0) static HMODULE nv_videofx = NULL; static HMODULE nv_cvimage = NULL; static HMODULE nv_cudart = NULL; @@ -817,14 +817,25 @@ static inline bool load_nv_vfx_libs() static unsigned int get_lib_version(void) { + static unsigned int version = 0; + static bool version_checked = false; + + if (version_checked) + return version; + + version_checked = true; + char path[MAX_PATH]; nvvfx_get_sdk_path(path, sizeof(path)); SetDllDirectoryA(path); + struct win_version_info nto_ver = {0}; - get_dll_ver(L"NVVideoEffects.dll", &nto_ver); - unsigned int version = nto_ver.major << 24 | nto_ver.minor << 16 | - nto_ver.build << 8 | nto_ver.revis << 0; + if (get_dll_ver(L"NVVideoEffects.dll", &nto_ver)) + version = nto_ver.major << 24 | nto_ver.minor << 16 | + nto_ver.build << 8 | nto_ver.revis << 0; + + SetDllDirectoryA(NULL); return version; } #endif From f610bcff38b28e0af7f4560fd64eb5f59faaa77b Mon Sep 17 00:00:00 2001 From: Kurt Kartaltepe Date: Sun, 22 Jan 2023 12:15:32 -0800 Subject: [PATCH 23/47] libobs-opengl: Fixup dmabuf queries on X11 Previously we passed the wrong display and formats/modifiers could not be queried. This prevented pipewire sources from negotiating texture sharing on x11. (cherry picked from commit 4216991413d1df6c4797852378dc1d44ed279aca) --- libobs-opengl/gl-x11-egl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libobs-opengl/gl-x11-egl.c b/libobs-opengl/gl-x11-egl.c index df722f376..908b3d882 100644 --- a/libobs-opengl/gl-x11-egl.c +++ b/libobs-opengl/gl-x11-egl.c @@ -590,7 +590,7 @@ static bool gl_x11_egl_device_query_dmabuf_capabilities( { struct gl_platform *plat = device->plat; - return gl_egl_query_dmabuf_capabilities(plat->xdisplay, dmabuf_flags, + return gl_egl_query_dmabuf_capabilities(plat->edisplay, dmabuf_flags, drm_formats, n_formats); } @@ -601,7 +601,7 @@ static bool gl_x11_egl_device_query_dmabuf_modifiers_for_format( struct gl_platform *plat = device->plat; return gl_egl_query_dmabuf_modifiers_for_format( - plat->xdisplay, drm_format, modifiers, n_modifiers); + plat->edisplay, drm_format, modifiers, n_modifiers); } static const struct gl_winsys_vtable egl_x11_winsys_vtable = { From 80b16e63f5ca8866c085cf881e260ab5e9ba1e66 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 3 Dec 2022 17:59:50 +0100 Subject: [PATCH 24/47] frontend-tools: Fix crash on non X11 windowing systems (cherry picked from commit 7d26721be59d7818721f9f7a2ababb49521e6b15) --- .../auto-scene-switcher-nix.cpp | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/UI/frontend-plugins/frontend-tools/auto-scene-switcher-nix.cpp b/UI/frontend-plugins/frontend-tools/auto-scene-switcher-nix.cpp index 2aa0120a6..e5e5f96af 100644 --- a/UI/frontend-plugins/frontend-tools/auto-scene-switcher-nix.cpp +++ b/UI/frontend-plugins/frontend-tools/auto-scene-switcher-nix.cpp @@ -46,8 +46,14 @@ static bool ewmhIsSupported() unsigned long num = 0, bytes = 0; unsigned char *data = NULL; Window ewmh_window = 0; + Window root_window = 0; - int status = XGetWindowProperty(display, DefaultRootWindow(display), + root_window = DefaultRootWindow(display); + if (!root_window) { + return false; + } + + int status = XGetWindowProperty(display, root_window, netSupportingWmCheck, 0L, 1L, false, XA_WINDOW, &actualType, &format, &num, &bytes, &data); @@ -97,6 +103,9 @@ static std::vector getTopLevelWindows() for (int i = 0; i < ScreenCount(disp()); ++i) { Window rootWin = RootWindow(disp(), i); + if (!rootWin) { + continue; + } int status = XGetWindowProperty(disp(), rootWin, netClList, 0L, ~0L, false, AnyPropertyType, @@ -119,6 +128,9 @@ static std::vector getTopLevelWindows() static std::string GetWindowTitle(size_t i) { Window w = getTopLevelWindows().at(i); + if (!w) { + return ""; + } std::string windowTitle; char *name; @@ -164,11 +176,17 @@ void GetCurrentWindowTitle(string &title) char *name; Window rootWin = RootWindow(disp(), 0); + if (!rootWin) { + return; + } XGetWindowProperty(disp(), rootWin, active, 0L, ~0L, false, AnyPropertyType, &actualType, &format, &num, &bytes, (uint8_t **)&data); + if (!data[0]) { + return; + } int status = XFetchName(disp(), data[0], &name); if (status >= Success && name != nullptr) { From 43086717c446969b3f3c59a32aba3573108bf68f Mon Sep 17 00:00:00 2001 From: jpark37 Date: Tue, 24 Jan 2023 09:12:18 -0800 Subject: [PATCH 25/47] obs-ffmpeg: Tell FFmpeg that BGRA uses alpha Prevents alpha from getting dropped with custom encoders. (cherry picked from commit 3462ea3fdac41b2d544bc9403edac0820d42e911) --- plugins/obs-ffmpeg/obs-ffmpeg-output.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-output.c b/plugins/obs-ffmpeg/obs-ffmpeg-output.c index 3d5a5498d..9f3a807d0 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-output.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-output.c @@ -241,8 +241,10 @@ static bool create_video_stream(struct ffmpeg_data *data) closest_format = data->config.format; if (data->vcodec->pix_fmts) { + const int has_alpha = closest_format == AV_PIX_FMT_BGRA; closest_format = avcodec_find_best_pix_fmt_of_list( - data->vcodec->pix_fmts, data->config.format, 0, NULL); + data->vcodec->pix_fmts, closest_format, has_alpha, + NULL); } #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101) From 063cc0c865a2c8c76c0a0ff617791792a537c934 Mon Sep 17 00:00:00 2001 From: derrod Date: Tue, 24 Jan 2023 13:59:51 +0100 Subject: [PATCH 26/47] UI: Work around Qt dock restore crash (cherry picked from commit 3dcf68f8ed500a23154f502a85caa109afd04d81) --- UI/auth-restream.cpp | 4 +++- UI/auth-twitch.cpp | 8 ++++++-- UI/auth-youtube.cpp | 4 +++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/UI/auth-restream.cpp b/UI/auth-restream.cpp index f242deb9e..689ea14e8 100644 --- a/UI/auth-restream.cpp +++ b/UI/auth-restream.cpp @@ -200,7 +200,9 @@ void RestreamAuth::LoadUI() main->Config(), service(), "DockState"); QByteArray dockState = QByteArray::fromBase64(QByteArray(dockStateStr)); - main->restoreState(dockState); + + if (main->isVisible() || !main->isMaximized()) + main->restoreState(dockState); } uiLoaded = true; diff --git a/UI/auth-twitch.cpp b/UI/auth-twitch.cpp index af942e9e2..c01eb6e4e 100644 --- a/UI/auth-twitch.cpp +++ b/UI/auth-twitch.cpp @@ -276,7 +276,9 @@ void TwitchAuth::LoadUI() main->Config(), service(), "DockState"); QByteArray dockState = QByteArray::fromBase64(QByteArray(dockStateStr)); - main->restoreState(dockState); + + if (main->isVisible() || !main->isMaximized()) + main->restoreState(dockState); } TryLoadSecondaryUIPanes(); @@ -405,7 +407,9 @@ void TwitchAuth::LoadSecondaryUIPanes() main->Config(), service(), "DockState"); QByteArray dockState = QByteArray::fromBase64(QByteArray(dockStateStr)); - main->restoreState(dockState); + + if (main->isVisible() || !main->isMaximized()) + main->restoreState(dockState); } } diff --git a/UI/auth-youtube.cpp b/UI/auth-youtube.cpp index 3a8cc856e..f2ee5e42b 100644 --- a/UI/auth-youtube.cpp +++ b/UI/auth-youtube.cpp @@ -164,7 +164,9 @@ void YoutubeAuth::LoadUI() main->Config(), service(), "DockState"); QByteArray dockState = QByteArray::fromBase64(QByteArray(dockStateStr)); - main->restoreState(dockState); + + if (main->isVisible() || !main->isMaximized()) + main->restoreState(dockState); } #endif From a0b12d87512cc15d5fb53e93734dc566c82e2db9 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Tue, 24 Jan 2023 08:22:40 -0800 Subject: [PATCH 27/47] libobs-d3d11: Log monitor color depth (cherry picked from commit 2e7f7acfebb5de1eb1a10b18a31b369142c702c7) --- libobs-d3d11/d3d11-subsystem.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libobs-d3d11/d3d11-subsystem.cpp b/libobs-d3d11/d3d11-subsystem.cpp index 271d9998e..4028bcc5a 100644 --- a/libobs-d3d11/d3d11-subsystem.cpp +++ b/libobs-d3d11/d3d11-subsystem.cpp @@ -1224,6 +1224,7 @@ static inline void LogAdapterMonitors(IDXGIAdapter1 *adapter) target.monitorFriendlyDeviceName[0] = 0; } + UINT bits_per_color = 8; DXGI_COLOR_SPACE_TYPE type = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; FLOAT min_luminance = 0.f; @@ -1231,6 +1232,7 @@ static inline void LogAdapterMonitors(IDXGIAdapter1 *adapter) FLOAT max_full_frame_luminance = 0.f; DXGI_OUTPUT_DESC1 desc1; if (GetOutputDesc1(output, &desc1)) { + bits_per_color = desc1.BitsPerColor; type = desc1.ColorSpace; min_luminance = desc1.MinLuminance; max_luminance = desc1.MaxLuminance; @@ -1260,13 +1262,14 @@ static inline void LogAdapterMonitors(IDXGIAdapter1 *adapter) "\t size={%d, %d}\n" "\t attached=%s\n" "\t refresh=%u\n" + "\t bits_per_color=%u\n" "\t space=%s\n" "\t sdr_white_nits=%lu\n" "\t nit_range=[min=%f, max=%f, max_full_frame=%f]", i, target.monitorFriendlyDeviceName, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, - desc.AttachedToDesktop ? "true" : "false", refresh, space, - nits, min_luminance, max_luminance, + desc.AttachedToDesktop ? "true" : "false", refresh, + bits_per_color, space, nits, min_luminance, max_luminance, max_full_frame_luminance); } } From 45dd24ecb16c66cbdcf314f440c02cb131cc8994 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Tue, 24 Jan 2023 08:12:47 -0800 Subject: [PATCH 28/47] libobs: Fix SDR async video on non-SDR targets Bug was seen when projecting SDR video capture on WCG displays. (cherry picked from commit 792f8473ee2799bae64b1536d58cd52c855b12d6) --- libobs/obs-source.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libobs/obs-source.c b/libobs/obs-source.c index 3fe724bf8..3657b2349 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -2478,6 +2478,8 @@ static inline void obs_source_render_async_video(obs_source_t *source) bool nonlinear_alpha = false; switch (source_space) { case GS_CS_SRGB: + linear_srgb = linear_srgb || + (current_space != GS_CS_SRGB); nonlinear_alpha = linear_srgb && !source->async_linear_alpha; switch (current_space) { @@ -2492,7 +2494,6 @@ static inline void obs_source_render_async_video(obs_source_t *source) nonlinear_alpha ? "DrawNonlinearAlphaMultiply" : "DrawMultiply"; - linear_srgb = true; multiplier = obs_get_video_sdr_white_level() / 80.0f; } From ab69f5db052f9d020c35a716cc2e29c4ab958385 Mon Sep 17 00:00:00 2001 From: derrod Date: Sun, 22 Jan 2023 00:57:49 +0100 Subject: [PATCH 29/47] updater: Add additional status messages (cherry picked from commit ffd7202168faf5b0d172344b7d6d2a8712ee6322) --- UI/win-update/updater/updater.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UI/win-update/updater/updater.cpp b/UI/win-update/updater/updater.cpp index 0a1cd2ac4..dd4d77674 100644 --- a/UI/win-update/updater/updater.cpp +++ b/UI/win-update/updater/updater.cpp @@ -1648,6 +1648,7 @@ static bool Update(wchar_t *cmdLine) }; if (!bIsPortable) { + Status(L"Installing Virtual Camera..."); wchar_t regsvr[MAX_PATH]; wchar_t src[MAX_PATH]; wchar_t tmp[MAX_PATH]; @@ -1681,11 +1682,13 @@ static bool Update(wchar_t *cmdLine) /* ------------------------------------- * * Update hook files and vulkan registry */ + Status(L"Updating Game Capture hooks..."); UpdateHookFiles(); /* ------------------------------------- * * Finish */ + Status(L"Cleaning up..."); /* If we get here, all updates installed successfully so we can purge * the old versions */ for (update_t &update : updates) { From d66b9bd8e9fd51d4f62f7aee1254faa40970bebd Mon Sep 17 00:00:00 2001 From: jpark37 Date: Tue, 17 Jan 2023 21:39:40 -0800 Subject: [PATCH 30/47] win-capture: Support EnumDisplayDevices failure Seeing EnumDisplayDevices fail in the wild, so use GetMonitorInfo name when the persistent name is unavailable. (cherry picked from commit 0b30ff1debb24149d0d11079e6b92d675a00c51f) --- .../win-capture/duplicator-monitor-capture.c | 106 ++++++++++++------ 1 file changed, 70 insertions(+), 36 deletions(-) diff --git a/plugins/win-capture/duplicator-monitor-capture.c b/plugins/win-capture/duplicator-monitor-capture.c index a1c9ccec8..02e2c9bb0 100644 --- a/plugins/win-capture/duplicator-monitor-capture.c +++ b/plugins/win-capture/duplicator-monitor-capture.c @@ -92,7 +92,7 @@ struct duplicator_capture { struct winrt_capture *capture_winrt; }; -struct wgc_monitor_info { +struct duplicator_monitor_info { char device_id[128]; char name[64]; RECT rect; @@ -187,7 +187,8 @@ static BOOL CALLBACK enum_monitor(HMONITOR handle, HDC hdc, LPRECT rect, { UNUSED_PARAMETER(hdc); - struct wgc_monitor_info *monitor = (struct wgc_monitor_info *)param; + struct duplicator_monitor_info *monitor = + (struct duplicator_monitor_info *)param; bool match = false; @@ -198,8 +199,8 @@ static BOOL CALLBACK enum_monitor(HMONITOR handle, HDC hdc, LPRECT rect, device.cb = sizeof(device); if (EnumDisplayDevicesA(mi.szDevice, 0, &device, EDD_GET_DEVICE_INTERFACE_NAME)) { - const bool match = strcmp(monitor->device_id, - device.DeviceID) == 0; + match = strcmp(monitor->device_id, device.DeviceID) == + 0; if (match) { monitor->rect = *rect; monitor->handle = handle; @@ -212,6 +213,31 @@ static BOOL CALLBACK enum_monitor(HMONITOR handle, HDC hdc, LPRECT rect, return !match; } +static BOOL CALLBACK enum_monitor_fallback(HMONITOR handle, HDC hdc, + LPRECT rect, LPARAM param) +{ + UNUSED_PARAMETER(hdc); + + struct duplicator_monitor_info *monitor = + (struct duplicator_monitor_info *)param; + + bool match = false; + + MONITORINFOEXA mi; + mi.cbSize = sizeof(mi); + if (GetMonitorInfoA(handle, (LPMONITORINFO)&mi)) { + match = strcmp(monitor->device_id, mi.szDevice) == 0; + if (match) { + monitor->rect = *rect; + monitor->handle = handle; + GetMonitorName(handle, monitor->name, + _countof(monitor->name)); + } + } + + return !match; +} + static void log_settings(struct duplicator_capture *capture, const char *monitor, LONG width, LONG height) { @@ -257,15 +283,26 @@ choose_method(enum display_capture_method method, bool wgc_supported, extern bool wgc_supported; +static struct duplicator_monitor_info find_monitor(const char *monitor_id) +{ + struct duplicator_monitor_info monitor = {0}; + strcpy_s(monitor.device_id, _countof(monitor.device_id), monitor_id); + EnumDisplayMonitors(NULL, NULL, &enum_monitor, (LPARAM)&monitor); + if (monitor.handle == NULL) { + EnumDisplayMonitors(NULL, NULL, &enum_monitor_fallback, + (LPARAM)&monitor); + } + + return monitor; +} + static inline void update_settings(struct duplicator_capture *capture, obs_data_t *settings) { pthread_mutex_lock(&capture->update_mutex); - struct wgc_monitor_info monitor = {0}; - strcpy_s(monitor.device_id, _countof(monitor.device_id), - obs_data_get_string(settings, "monitor_id")); - EnumDisplayMonitors(NULL, NULL, enum_monitor, (LPARAM)&monitor); + struct duplicator_monitor_info monitor = + find_monitor(obs_data_get_string(settings, "monitor_id")); capture->method = choose_method((int)obs_data_get_int(settings, "method"), @@ -463,11 +500,7 @@ static void free_capture_data(struct duplicator_capture *capture) static void update_monitor_handle(struct duplicator_capture *capture) { - struct wgc_monitor_info monitor = {0}; - strcpy_s(monitor.device_id, _countof(monitor.device_id), - capture->monitor_id); - EnumDisplayMonitors(NULL, NULL, enum_monitor, (LPARAM)&monitor); - capture->handle = monitor.handle; + capture->handle = find_monitor(capture->monitor_id).handle; } static void duplicator_capture_tick(void *data, float seconds) @@ -727,40 +760,41 @@ static BOOL CALLBACK enum_monitor_props(HMONITOR handle, HDC hdc, LPRECT rect, UNUSED_PARAMETER(hdc); UNUSED_PARAMETER(rect); + char monitor_name[64]; + GetMonitorName(handle, monitor_name, sizeof(monitor_name)); + MONITORINFOEXA mi; mi.cbSize = sizeof(mi); if (GetMonitorInfoA(handle, (LPMONITORINFO)&mi)) { + obs_property_t *monitor_list = (obs_property_t *)param; + struct dstr monitor_desc = {0}; + dstr_printf(&monitor_desc, "%s: %dx%d @ %d,%d", monitor_name, + mi.rcMonitor.right - mi.rcMonitor.left, + mi.rcMonitor.bottom - mi.rcMonitor.top, + mi.rcMonitor.left, mi.rcMonitor.top); + if (mi.dwFlags == MONITORINFOF_PRIMARY) + dstr_catf(&monitor_desc, " (%s)", TEXT_PRIMARY_MONITOR); + DISPLAY_DEVICEA device; device.cb = sizeof(device); if (EnumDisplayDevicesA(mi.szDevice, 0, &device, EDD_GET_DEVICE_INTERFACE_NAME)) { - obs_property_t *monitor_list = (obs_property_t *)param; - struct dstr monitor_desc = {0}; - struct dstr resolution = {0}; - - dstr_catf(&resolution, "%dx%d @ %d,%d", - mi.rcMonitor.right - mi.rcMonitor.left, - mi.rcMonitor.bottom - mi.rcMonitor.top, - mi.rcMonitor.left, mi.rcMonitor.top); - - char monitor_name[64]; - GetMonitorName(handle, monitor_name, - sizeof(monitor_name)); - dstr_catf(&monitor_desc, "%s: %s", monitor_name, - resolution.array); - - if (mi.dwFlags == MONITORINFOF_PRIMARY) { - dstr_catf(&monitor_desc, " (%s)", - TEXT_PRIMARY_MONITOR); - } - obs_property_list_add_string(monitor_list, monitor_desc.array, device.DeviceID); - - dstr_free(&monitor_desc); - dstr_free(&resolution); + } else { + blog(LOG_WARNING, + "[duplicator-monitor-capture] EnumDisplayDevices failed for monitor (%s), falling back to szDevice", + monitor_name); + obs_property_list_add_string( + monitor_list, monitor_desc.array, mi.szDevice); } + + dstr_free(&monitor_desc); + } else { + blog(LOG_WARNING, + "[duplicator-monitor-capture] GetMonitorInfo failed for monitor: %s", + monitor_name); } return TRUE; From c55ce029af15cfa1dbb5d03b2b9469c50b3d7129 Mon Sep 17 00:00:00 2001 From: derrod Date: Mon, 16 Jan 2023 02:29:10 +0100 Subject: [PATCH 31/47] updater: Pass AppData path to elevated process (cherry picked from commit 778cf5a96ab7bb268240af7bc448eee41006da97) --- UI/win-update/updater/updater.cpp | 53 +++++++++++++++++-------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/UI/win-update/updater/updater.cpp b/UI/win-update/updater/updater.cpp index dd4d77674..44e5a12ac 100644 --- a/UI/win-update/updater/updater.cpp +++ b/UI/win-update/updater/updater.cpp @@ -1289,6 +1289,7 @@ static bool Update(wchar_t *cmdLine) bool bIsPortable = false; wstring branch = L"stable"; + wstring appdata; if (cmdLine[0]) { int argc; @@ -1303,6 +1304,9 @@ static bool Update(wchar_t *cmdLine) } else if (wcsncmp(argv[i], L"--branch=", 9) == 0) { branch = argv[i] + 9; + } else if (wcsncmp(argv[i], L"--appdata=", + 10) == 0) { + appdata = argv[i] + 10; } else if (wcscmp(argv[i], L"--portable") == 0) { bIsPortable = true; @@ -1322,18 +1326,16 @@ static bool Update(wchar_t *cmdLine) GetCurrentDirectory(_countof(lpAppDataPath), lpAppDataPath); StringCbCat(lpAppDataPath, sizeof(lpAppDataPath), L"\\config"); } else { - DWORD ret; - ret = GetEnvironmentVariable(L"OBS_USER_APPDATA_PATH", - lpAppDataPath, - _countof(lpAppDataPath)); - - if (ret >= _countof(lpAppDataPath)) { - Status(L"Update failed: Could not determine AppData " - L"location"); - return false; - } - - if (!ret) { + if (!appdata.empty()) { + HRESULT hr = StringCbCopy(lpAppDataPath, + sizeof(lpAppDataPath), + appdata.c_str()); + if (hr != S_OK) { + Status(L"Update failed: Could not determine AppData " + L"location"); + return false; + } + } else { CoTaskMemPtr pOut; HRESULT hr = SHGetKnownFolderPath( FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, @@ -1848,13 +1850,26 @@ static int RestartAsAdmin(LPCWSTR lpCmdLine, LPCWSTR cwd) return 0; } + /* If the admin is a different user, add the path to the user's + * AppData to the command line so we can load the correct manifest. */ + wstring elevatedCmdLine(lpCmdLine); + CoTaskMemPtr pOut; + HRESULT hr = SHGetKnownFolderPath(FOLDERID_RoamingAppData, + KF_FLAG_DEFAULT, nullptr, &pOut); + if (hr == S_OK) { + elevatedCmdLine += L" \"--appdata="; + elevatedCmdLine += pOut; + elevatedCmdLine += L"\""; + } + SHELLEXECUTEINFO shExInfo = {0}; shExInfo.cbSize = sizeof(shExInfo); shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS; shExInfo.hwnd = 0; - shExInfo.lpVerb = L"runas"; /* Operation to perform */ - shExInfo.lpFile = myPath; /* Application to start */ - shExInfo.lpParameters = lpCmdLine; /* Additional parameters */ + shExInfo.lpVerb = L"runas"; /* Operation to perform */ + shExInfo.lpFile = myPath; /* Application to start */ + shExInfo.lpParameters = + elevatedCmdLine.c_str(); /* Additional parameters */ shExInfo.lpDirectory = cwd; shExInfo.nShow = SW_NORMAL; shExInfo.hInstApp = 0; @@ -1863,14 +1878,6 @@ static int RestartAsAdmin(LPCWSTR lpCmdLine, LPCWSTR cwd) * windows :( */ AllowSetForegroundWindow(ASFW_ANY); - /* if the admin is a different user, save the path to the user's - * appdata so we can load the correct manifest */ - CoTaskMemPtr pOut; - HRESULT hr = SHGetKnownFolderPath(FOLDERID_RoamingAppData, - KF_FLAG_DEFAULT, nullptr, &pOut); - if (hr == S_OK) - SetEnvironmentVariable(L"OBS_USER_APPDATA_PATH", pOut); - if (ShellExecuteEx(&shExInfo)) { DWORD exitCode; From 3c6aaeb142340d8dd354652d86b72c54dc972caa Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sun, 15 Jan 2023 17:08:39 +0100 Subject: [PATCH 32/47] cmake,obs-ffmpeg: Refactor Libva finder This refactor adds Libva DRM, required for obs-ffmpeg (cherry picked from commit ee144377dc50b5d9f1fdf0598cea56f7e34eab9b) --- cmake/Modules/FindLibva.cmake | 48 ++++++++++++++++++++++++------- plugins/obs-ffmpeg/CMakeLists.txt | 2 +- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/cmake/Modules/FindLibva.cmake b/cmake/Modules/FindLibva.cmake index afba96b5d..0e49cb42e 100644 --- a/cmake/Modules/FindLibva.cmake +++ b/cmake/Modules/FindLibva.cmake @@ -1,9 +1,10 @@ -# * Try to find Libva, once done this will define # -# * LIBVA_FOUND - system has Libva -# * LIBVA_INCLUDE_DIRS - the Libva include directory -# * LIBVA_LIBRARIES - the libraries needed to use Libva -# * LIBVA_DEFINITIONS - Compiler switches required for using Libva +# This module defines the following variables: +# +# * LIBVA_FOUND - The component was found +# * LIBVA_INCLUDE_DIRS - The component include directory +# * LIBVA_LIBRARIES - The component library Libva +# * LIBVA_DRM_LIBRARIES - The component library Libva DRM # Use pkg-config to get the directories and then use these values in the # find_path() and find_library() calls @@ -11,14 +12,14 @@ find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(_LIBVA libva) + pkg_check_modules(_LIBVA_DRM libva-drm) endif() find_path( LIBVA_INCLUDE_DIR - NAMES va.h + NAMES va/va.h va/va_drm.h HINTS ${_LIBVA_INCLUDE_DIRS} - PATHS /usr/include /usr/local/include /opt/local/include - PATH_SUFFIXES va/) + PATHS /usr/include /usr/local/include /opt/local/include) find_library( LIBVA_LIB @@ -26,14 +27,21 @@ find_library( HINTS ${_LIBVA_LIBRARY_DIRS} PATHS /usr/lib /usr/local/lib /opt/local/lib) +find_library( + LIBVA_DRM_LIB + NAMES ${_LIBVA_DRM_LIBRARIES} libva-drm + HINTS ${_LIBVA_DRM_LIBRARY_DIRS} + PATHS /usr/lib /usr/local/lib /opt/local/lib) + include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Libva REQUIRED_VARS LIBVA_LIB - LIBVA_INCLUDE_DIR) -mark_as_advanced(LIBVA_INCLUDE_DIR LIBVA_LIB) +find_package_handle_standard_args(Libva REQUIRED_VARS LIBVA_INCLUDE_DIR + LIBVA_LIB LIBVA_DRM_LIB) +mark_as_advanced(LIBVA_INCLUDE_DIR LIBVA_LIB LIBVA_DRM_LIB) if(LIBVA_FOUND) set(LIBVA_INCLUDE_DIRS ${LIBVA_INCLUDE_DIR}) set(LIBVA_LIBRARIES ${LIBVA_LIB}) + set(LIBVA_DRM_LIBRARIES ${LIBVA_DRM_LIB}) if(NOT TARGET Libva::va) if(IS_ABSOLUTE "${LIBVA_LIBRARIES}") @@ -45,5 +53,23 @@ if(LIBVA_FOUND) set_target_properties(Libva::va PROPERTIES IMPORTED_LIBNAME "${LIBVA_LIBRARIES}") endif() + + set_target_properties(Libva::va PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${LIBVA_INCLUDE_DIRS}") + endif() + + if(NOT TARGET Libva::drm) + if(IS_ABSOLUTE "${LIBVA_DRM_LIBRARIES}") + add_library(Libva::drm UNKNOWN IMPORTED) + set_target_properties(Libva::drm PROPERTIES IMPORTED_LOCATION + "${LIBVA_DRM_LIBRARIES}") + else() + add_library(Libva::drm INTERFACE IMPORTED) + set_target_properties(Libva::drm PROPERTIES IMPORTED_LIBNAME + "${LIBVA_DRM_LIBRARIES}") + endif() + + set_target_properties(Libva::drm PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${LIBVA_INCLUDE_DIRS}") endif() endif() diff --git a/plugins/obs-ffmpeg/CMakeLists.txt b/plugins/obs-ffmpeg/CMakeLists.txt index 9671ef978..244c6df92 100644 --- a/plugins/obs-ffmpeg/CMakeLists.txt +++ b/plugins/obs-ffmpeg/CMakeLists.txt @@ -123,7 +123,7 @@ elseif(OS_POSIX AND NOT OS_MACOS) find_package(Libpci REQUIRED) target_sources(obs-ffmpeg PRIVATE obs-ffmpeg-vaapi.c vaapi-utils.c vaapi-utils.h) - target_link_libraries(obs-ffmpeg PRIVATE Libva::va LIBPCI::LIBPCI) + target_link_libraries(obs-ffmpeg PRIVATE Libva::va Libva::drm LIBPCI::LIBPCI) endif() setup_plugin_target(obs-ffmpeg) From 53f6c1a215209d183a7f7893c944e4d854366012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= Date: Sat, 21 Jan 2023 05:00:58 +0100 Subject: [PATCH 33/47] libobs: Close display when destroying X11 hotkey platform Currently, the X11 display is leaked when the X11 hotkey platform is destroyed. Fix that by calling XCloseDisplay() to free it. Fixes: bcb04bb80010fb ("libobs: Open a separate X11 connection for hotkeys") (cherry picked from commit 5810571e53238d11aa3beda33a770fe44e98749a) --- libobs/obs-nix-x11.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libobs/obs-nix-x11.c b/libobs/obs-nix-x11.c index ce571b977..a60048a5f 100644 --- a/libobs/obs-nix-x11.c +++ b/libobs/obs-nix-x11.c @@ -878,6 +878,7 @@ static void obs_nix_x11_hotkeys_platform_free(struct obs_core_hotkeys *hotkeys) da_free(context->keycodes[i].list); bfree(context->keysyms); + XCloseDisplay(context->display); bfree(context); hotkeys->platform_context = NULL; From 8c9de5e255b0ce7e4daf72f95408851473ac847c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= Date: Sat, 21 Jan 2023 05:07:16 +0100 Subject: [PATCH 34/47] libobs-opengl: Do not close X11 platform display on error The platform display is not owned by libobs, it should not be closed. Doing so results in heap use-after-frees when Qt components try to use it while trying to show a message box about the failure: info: Initializing OpenGL... error: Failed to initialize EGL: EGL_BAD_ACCESS error: Failed to create context! error: device_create (GL) failed error: Failed to initialize video. Your GPU may not be supported, or your graphics drivers may need to be updated. ================================================================= ==2320345==ERROR: AddressSanitizer: heap-use-after-free on address 0x621000018668 at pc 0x7fcb75e20d6e bp 0x7ffe88d0e910 sp 0x7ffe88d0e900 READ of size 8 at 0x621000018668 thread T0 0 0x7fcb75e20d6d in XInternAtom /.../libx11/src/IntAtom.c:175 1 0x7fcb6bf5edfd in Kvantum::ThemeConfig::getCompositeSpec() 2 0x7fcb6bf0eb19 in Kvantum::Style::setSurfaceFormat(QWidget*) const 3 0x7fcb6bf11bae in Kvantum::Style::styleHint(QStyle::StyleHint, QStyleOption const*, QWidget const*, QStyleHintReturn*) const 4 0x5585cbce70b8 in OBSIgnoreWheelProxyStyle::styleHint(QStyle::StyleHint, QStyleOption const*, QWidget const*, QStyleHintReturn*) const /.../obs-studio/UI/obs-proxy-style.cpp:88 5 0x7fcb85826515 (/usr/lib/libQt6Widgets.so.6+0x226515) 6 0x7fcb859dbf1d (/usr/lib/libQt6Widgets.so.6+0x3dbf1d) 7 0x7fcb859dc5f0 in QMessageBox::QMessageBox(...) 8 0x7fcb859dc6b1 (/usr/lib/libQt6Widgets.so.6+0x3dc6b1) 9 0x5585cbd2fb31 in OBSErrorBoxva /.../obs-studio/UI/qt-wrappers.cpp:48 10 0x5585cbd2fd34 in OBSErrorBox(QWidget*, char const*, ...) /.../obs-studio/UI/qt-wrappers.cpp:55 11 0x5585cbcc3f36 in run_program /.../obs-studio/UI/obs-app.cpp:2475 12 0x5585cbcc52b4 in main /.../obs-studio/UI/obs-app.cpp:3358 13 0x7fcb82e3c28f (/usr/lib/libc.so.6+0x2328f) 14 0x7fcb82e3c349 in __libc_start_main 15 0x5585cbbd2f54 in _start Fixes: 137966e01fffe0 ("libobs-opengl: Try to use the platform display if available") (cherry picked from commit dee7ef85122fe988bfc8059a3fa5305109bc6999) --- libobs-opengl/gl-x11-egl.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/libobs-opengl/gl-x11-egl.c b/libobs-opengl/gl-x11-egl.c index 908b3d882..fd5c1f3f2 100644 --- a/libobs-opengl/gl-x11-egl.c +++ b/libobs-opengl/gl-x11-egl.c @@ -82,6 +82,7 @@ struct gl_platform { EGLConfig config; EGLContext context; EGLSurface pbuffer; + bool close_xdisplay; }; /* The following utility function is copied verbatim from GLX code. */ @@ -269,15 +270,19 @@ static void gl_x11_egl_windowinfo_destroy(struct gl_windowinfo *info) bfree(info); } -static Display *open_windowless_display(Display *platform_display) +static Display *open_windowless_display(bool *should_close) { + Display *platform_display = obs_get_nix_platform_display(); Display *display; xcb_connection_t *xcb_conn; - if (platform_display) + if (platform_display) { display = platform_display; - else + *should_close = false; + } else { display = XOpenDisplay(NULL); + *should_close = true; + } if (!display) { blog(LOG_ERROR, "Unable to open new X connection!"); @@ -298,7 +303,8 @@ static Display *open_windowless_display(Display *platform_display) return display; error: - XCloseDisplay(display); + if (*should_close) + XCloseDisplay(display); return NULL; } @@ -325,8 +331,7 @@ static struct gl_platform *gl_x11_egl_platform_create(gs_device_t *device, For an explanation see here: http://xcb.freedesktop.org/MixingCalls/ Essentially, EGL requires Xlib. Everything else we use xcb. */ struct gl_platform *plat = bmalloc(sizeof(struct gl_platform)); - Display *platform_display = obs_get_nix_platform_display(); - Display *display = open_windowless_display(platform_display); + Display *display = open_windowless_display(&plat->close_xdisplay); if (!display) { goto fail_display_open; @@ -363,7 +368,8 @@ fail_make_current: gl_context_destroy(plat); fail_context_create: fail_load_gl: - XCloseDisplay(display); + if (plat->close_xdisplay) + XCloseDisplay(plat->xdisplay); fail_display_open: bfree(plat); plat = NULL; From 0f4d0eed25a43febd5916bdc3b02138e0443ea1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= Date: Sat, 21 Jan 2023 05:13:47 +0100 Subject: [PATCH 35/47] libobs-opengl: Close display when destroying X11/EGL platform Currently, the X11 display may be leaked when the X11/EGL platform is destroyed. Fix that by calling XCloseDisplay() to free it. Fixes: 2fd8a6df557766 ("libobs-opengl: Introduce the X11/EGL winsys") (cherry picked from commit 8e96d47cd3d94213da52277678d844ef616d08a2) --- libobs-opengl/gl-x11-egl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libobs-opengl/gl-x11-egl.c b/libobs-opengl/gl-x11-egl.c index fd5c1f3f2..56086a997 100644 --- a/libobs-opengl/gl-x11-egl.c +++ b/libobs-opengl/gl-x11-egl.c @@ -385,6 +385,8 @@ static void gl_x11_egl_platform_destroy(struct gl_platform *plat) gl_context_destroy(plat); eglTerminate(plat->edisplay); + if (plat->close_xdisplay) + XCloseDisplay(plat->xdisplay); bfree(plat); } From fbeede9349278b26580a45bccc79a405a8ec8ad6 Mon Sep 17 00:00:00 2001 From: pkv Date: Mon, 23 Jan 2023 14:30:38 +0100 Subject: [PATCH 36/47] obs-filters: Fix expander and upward compressor above threshold Fixes behaviours above threshold for expander and upward compressor. Fixes issues #8052 & #8030 . Signed-off-by: pkv (cherry picked from commit f625bb579f34250a237e0ca9cfdc6f60bb7c5469) --- plugins/obs-filters/expander-filter.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/plugins/obs-filters/expander-filter.c b/plugins/obs-filters/expander-filter.c index 157cf5640..aef9a9972 100644 --- a/plugins/obs-filters/expander-filter.c +++ b/plugins/obs-filters/expander-filter.c @@ -379,14 +379,11 @@ static inline void process_sample(size_t idx, float *samples, float *env_buf, /* --------------------------------- */ /* output */ - float min_val = - is_upwcomp ? fminf(diff, threshold - mul_to_db(samples[idx])) - : 0.0f; - gain = db_to_mul(fminf(min_val, gain_db[idx])); - - // above threshold, don't process expander nor upward compressor - if (threshold - env_db <= 0) - gain = 1.0f; + if (!is_upwcomp) { + gain = db_to_mul(fminf(0, gain_db[idx])); + } else { + gain = db_to_mul(gain_db[idx]); + } samples[idx] *= gain * output_gain; } From 6f96ad48ed3ed04caef9a6bc6ed10fd8b35224bb Mon Sep 17 00:00:00 2001 From: Norihiro Kamae Date: Sun, 22 Jan 2023 19:04:14 +0900 Subject: [PATCH 37/47] obs-filters: Make continuous gain on upward compressor The upward compressor has a -60 dB threshold to stop increasing the gain. At the threshold, the gain was not continuous, which is not ideal. Co-authored-by: pkv Signed-off-by: pkv (cherry picked from commit 50db09760c1a130730da564c8eea505b25ca9810) --- plugins/obs-filters/expander-filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/obs-filters/expander-filter.c b/plugins/obs-filters/expander-filter.c index aef9a9972..d9b7f0687 100644 --- a/plugins/obs-filters/expander-filter.c +++ b/plugins/obs-filters/expander-filter.c @@ -351,8 +351,8 @@ static inline void process_sample(size_t idx, float *samples, float *env_buf, float env_db = mul_to_db(env_buf[idx]); float diff = threshold - env_db; - if (is_upwcomp && env_db <= -60.0f) - diff = 0.0f; + if (is_upwcomp && env_db <= (threshold - 60.0f) / 2) + diff = env_db + 60.0f; float gain = diff > 0.0f ? fmaxf(slope * diff, -60.0f) : 0.0f; float prev_gain = gain_db[idx - 1]; From 6f8ee7abbed2fe4daa3f6c0ac264fef20d357d79 Mon Sep 17 00:00:00 2001 From: pkv Date: Sat, 21 Jan 2023 18:53:05 +0100 Subject: [PATCH 38/47] obs-filters: Improve upward compressor with soft knee This adds a knee setting to the upward compressor. Signed-off-by: pkv (cherry picked from commit 10e6d0fbd0515b7174ef61adc6188c468545724d) --- plugins/obs-filters/data/locale/en-US.ini | 1 + plugins/obs-filters/expander-filter.c | 57 +++++++++++++++-------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/plugins/obs-filters/data/locale/en-US.ini b/plugins/obs-filters/data/locale/en-US.ini index 99fb894ca..a3def5ff5 100644 --- a/plugins/obs-filters/data/locale/en-US.ini +++ b/plugins/obs-filters/data/locale/en-US.ini @@ -115,6 +115,7 @@ Expander.None="None" Expander.Presets="Presets" Expander.Presets.Expander="Expander" Expander.Presets.Gate="Gate" +Expander.Knee.Width="Knee Width" LumaKeyFilter="Luma Key" Luma.LumaMax="Luma Max" Luma.LumaMin="Luma Min" diff --git a/plugins/obs-filters/expander-filter.c b/plugins/obs-filters/expander-filter.c index d9b7f0687..be3ca9fbd 100644 --- a/plugins/obs-filters/expander-filter.c +++ b/plugins/obs-filters/expander-filter.c @@ -34,6 +34,7 @@ #define S_OUTPUT_GAIN "output_gain" #define S_DETECTOR "detector" #define S_PRESETS "presets" +#define S_KNEE "knee_width" #define MT_ obs_module_text #define TEXT_RATIO MT_("expander.Ratio") @@ -48,6 +49,7 @@ #define TEXT_PRESETS MT_("expander.Presets") #define TEXT_PRESETS_EXP MT_("expander.Presets.Expander") #define TEXT_PRESETS_GATE MT_("expander.Presets.Gate") +#define TEXT_KNEE MT_("expander.Knee.Width") #define MIN_RATIO 1.0f #define MAX_RATIO 20.0f @@ -95,6 +97,7 @@ struct expander_data { float *env_in; size_t env_in_len; bool is_upwcomp; + float knee; }; enum { @@ -179,6 +182,7 @@ static void upward_compressor_defaults(obs_data_t *s) obs_data_set_default_int(s, S_RELEASE_TIME, 50); obs_data_set_default_double(s, S_OUTPUT_GAIN, 0.0); obs_data_set_default_string(s, S_DETECTOR, "RMS"); + obs_data_set_default_int(s, S_KNEE, 10); } static void expander_update(void *data, obs_data_t *s) @@ -208,6 +212,8 @@ static void expander_update(void *data, obs_data_t *s) (float)obs_data_get_int(s, S_RELEASE_TIME); const float output_gain_db = (float)obs_data_get_double(s, S_OUTPUT_GAIN); + const float knee = cd->is_upwcomp ? (float)obs_data_get_int(s, S_KNEE) + : 0.0f; cd->ratio = (float)obs_data_get_double(s, S_RATIO); @@ -220,6 +226,7 @@ static void expander_update(void *data, obs_data_t *s) cd->num_channels = num_channels; cd->sample_rate = sample_rate; cd->slope = 1.0f - cd->ratio; + cd->knee = knee; const char *detect_mode = obs_data_get_string(s, S_DETECTOR); if (strcmp(detect_mode, "RMS") == 0) @@ -343,7 +350,8 @@ static inline void process_sample(size_t idx, float *samples, float *env_buf, float channel_gain, float threshold, float slope, float attack_gain, float inv_attack_gain, float release_gain, - float inv_release_gain, float output_gain) + float inv_release_gain, float output_gain, + float knee) { /* --------------------------------- */ /* gain stage of expansion */ @@ -354,27 +362,33 @@ static inline void process_sample(size_t idx, float *samples, float *env_buf, if (is_upwcomp && env_db <= (threshold - 60.0f) / 2) diff = env_db + 60.0f; - float gain = diff > 0.0f ? fmaxf(slope * diff, -60.0f) : 0.0f; - float prev_gain = gain_db[idx - 1]; + float gain = 0.0f; + // Note that the gain is always >= 0 for the upward compressor + // but is always <=0 for the expander. + if (is_upwcomp) { + // gain above knee (included for clarity): + if (env_db >= threshold + knee / 2) + gain = 0.0f; + // gain below knee: + if (threshold - knee / 2 >= env_db) + gain = slope * diff; + // gain in knee: + if (env_db > threshold - knee / 2 && + threshold + knee / 2 > env_db) + gain = slope * powf(diff + knee / 2, 2) / (2.0f * knee); + } else { + gain = diff > 0.0f ? fmaxf(slope * diff, -60.0f) : 0.0f; + } + float prev_gain = idx > 0 ? gain_db[idx - 1] : channel_gain; /* --------------------------------- */ /* ballistics (attack/release) */ - if (idx > 0) { - if (gain > prev_gain) - gain_db[idx] = attack_gain * prev_gain + - inv_attack_gain * gain; - else - gain_db[idx] = release_gain * prev_gain + - inv_release_gain * gain; - } else { - if (gain > channel_gain) - gain_db[idx] = attack_gain * channel_gain + - inv_attack_gain * gain; - else - gain_db[idx] = release_gain * channel_gain + - inv_release_gain * gain; - } + if (gain > prev_gain) + gain_db[idx] = attack_gain * prev_gain + inv_attack_gain * gain; + else + gain_db[idx] = + release_gain * prev_gain + inv_release_gain * gain; /* --------------------------------- */ /* output */ @@ -400,6 +414,7 @@ static inline void process_expansion(struct expander_data *cd, float **samples, const float slope = cd->slope; const float output_gain = cd->output_gain; const bool is_upwcomp = cd->is_upwcomp; + const float knee = cd->knee; if (cd->gain_db_len < num_samples) resize_gain_db_buffer(cd, num_samples); @@ -419,7 +434,7 @@ static inline void process_expansion(struct expander_data *cd, float **samples, is_upwcomp, channel_gain, threshold, slope, attack_gain, inv_attack_gain, release_gain, inv_release_gain, - output_gain); + output_gain, knee); } cd->gain_db_buf[chan] = gain_db[num_samples - 1]; } @@ -484,6 +499,10 @@ static obs_properties_t *expander_properties(void *data) OBS_COMBO_FORMAT_STRING); obs_property_list_add_string(detect, TEXT_RMS, "RMS"); obs_property_list_add_string(detect, TEXT_PEAK, "peak"); + } else { + p = obs_properties_add_int_slider(props, S_KNEE, TEXT_KNEE, 0, + 20, 1); + obs_property_float_set_suffix(p, " dB"); } return props; } From d58efd64b1b49626c923600236e0d211a307ba37 Mon Sep 17 00:00:00 2001 From: Richard Stanway Date: Thu, 26 Jan 2023 01:20:38 +0100 Subject: [PATCH 39/47] virtualcam-module: Update filter size immediately when used in OBS Fixes a crash due to the previous output size being used when scaling the frame. (cherry picked from commit 9b1f7d6d21bbc11dd27660069ffb65f3c6dd7699) --- plugins/win-dshow/virtualcam-module/virtualcam-filter.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/win-dshow/virtualcam-module/virtualcam-filter.cpp b/plugins/win-dshow/virtualcam-module/virtualcam-filter.cpp index 5e432b7cb..9c36ac843 100644 --- a/plugins/win-dshow/virtualcam-module/virtualcam-filter.cpp +++ b/plugins/win-dshow/virtualcam-module/virtualcam-filter.cpp @@ -270,6 +270,11 @@ void VCamFilter::Frame(uint64_t ts) the format we present to match */ SetVideoFormat(GetVideoFormat(), new_obs_cx, new_obs_cy, new_obs_interval); + + /* Update the new filter size immediately since we + know it just changed above */ + new_filter_cx = new_obs_cx; + new_filter_cy = new_obs_cy; } /* Re-initialize the main scaler to use the new resolution */ From 5ee25058f82a3f7009c8896a84b4d9c68403d4d7 Mon Sep 17 00:00:00 2001 From: Richard Stanway Date: Fri, 27 Jan 2023 23:20:30 +0100 Subject: [PATCH 40/47] obs-filters: Fix wrong number of arguments to error macro (cherry picked from commit 062cfcf63d7b0f01edb3dbde843ba757898c9d9c) --- plugins/obs-filters/nvidia-greenscreen-filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/obs-filters/nvidia-greenscreen-filter.c b/plugins/obs-filters/nvidia-greenscreen-filter.c index e6f64b389..aadc957f5 100644 --- a/plugins/obs-filters/nvidia-greenscreen-filter.c +++ b/plugins/obs-filters/nvidia-greenscreen-filter.c @@ -256,14 +256,14 @@ static void init_images_greenscreen(struct nv_greenscreen_data *filter) filter->render = gs_texrender_create( gs_get_format_from_space(filter->space), GS_ZS_NONE); if (!filter->render) { - error("Failed to create render texrenderer", vfxErr); + error("Failed to create render texrenderer"); goto fail; } if (filter->render_unorm) gs_texrender_destroy(filter->render_unorm); filter->render_unorm = gs_texrender_create(GS_BGRA_UNORM, GS_ZS_NONE); if (!filter->render_unorm) { - error("Failed to create render_unorm texrenderer", vfxErr); + error("Failed to create render_unorm texrenderer"); goto fail; } From 3464772d3ca995df2dcc7ea134ad36b04ad2babd Mon Sep 17 00:00:00 2001 From: Richard Stanway Date: Fri, 27 Jan 2023 23:32:54 +0100 Subject: [PATCH 41/47] obs-ffmpeg: Use gai_strerrorA for error logging on Windows Avoids wide characters in the format string which cause truncation. (cherry picked from commit 668775f4f0d5b85cc934b3c3602c1d2bd798a889) --- plugins/obs-ffmpeg/obs-ffmpeg-srt.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-srt.h b/plugins/obs-ffmpeg/obs-ffmpeg-srt.h index 2046d56c6..66a8d83ad 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-srt.h +++ b/plugins/obs-ffmpeg/obs-ffmpeg-srt.h @@ -485,7 +485,13 @@ static int libsrt_setup(URLContext *h, const char *uri) if (ret) { blog(LOG_ERROR, "[obs-ffmpeg mpegts muxer / libsrt]: Failed to resolve hostname %s: %s", - hostname, gai_strerror(ret)); + hostname, +#ifdef _WIN32 + gai_strerrorA(ret) +#else + gai_strerror(ret) +#endif + ); return OBS_OUTPUT_CONNECT_FAILED; } From 78085b38a8ed4d606a5780f412bd8c7e0fe8d0d4 Mon Sep 17 00:00:00 2001 From: gxalpha Date: Sun, 22 Jan 2023 02:20:42 +0100 Subject: [PATCH 42/47] UI: Re-raise properties window after picking files on macOS (cherry picked from commit b5b293fe72a697e3d9a41abb152bcdf7cf6d513d) --- UI/properties-view.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/UI/properties-view.cpp b/UI/properties-view.cpp index 36d5ba1ef..6ceceb237 100644 --- a/UI/properties-view.cpp +++ b/UI/properties-view.cpp @@ -1750,6 +1750,11 @@ bool WidgetInfo::PathChanged(const char *setting) path = SaveFile(view, QT_UTF8(desc), QT_UTF8(default_path), QT_UTF8(filter)); +#ifdef __APPLE__ + // TODO: Revisit when QTBUG-42661 is fixed + widget->window()->raise(); +#endif + if (path.isEmpty()) return false; @@ -2217,6 +2222,10 @@ void WidgetInfo::EditListAddFiles() QStringList files = OpenFiles(App()->GetMainWindow(), title, QT_UTF8(default_path), QT_UTF8(filter)); +#ifdef __APPLE__ + // TODO: Revisit when QTBUG-42661 is fixed + widget->window()->raise(); +#endif if (files.count() == 0) return; @@ -2237,6 +2246,10 @@ void WidgetInfo::EditListAddDir() QString dir = SelectDirectory(App()->GetMainWindow(), title, QT_UTF8(default_path)); +#ifdef __APPLE__ + // TODO: Revisit when QTBUG-42661 is fixed + widget->window()->raise(); +#endif if (dir.isEmpty()) return; From ee7557e14cc69f9176bd956fa4bbab1eed7d918b Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 25 Jan 2023 22:01:31 +0100 Subject: [PATCH 43/47] UI: Unblock encoder comboboxes signals before change Signals are blocked while encoder is enforced, those need to be unblocked before setting the new encoder. (cherry picked from commit 10880d6b21cedd9b6dd43d5bbfa57fc19190eac2) --- UI/window-basic-settings-stream.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UI/window-basic-settings-stream.cpp b/UI/window-basic-settings-stream.cpp index 8dea18215..f691baefc 100644 --- a/UI/window-basic-settings-stream.cpp +++ b/UI/window-basic-settings-stream.cpp @@ -1481,6 +1481,7 @@ void OBSBasicSettings::ResetEncoders(bool streamOnly) } idx = ui->advOutEncoder->findData(lastAdvEnc); + s2.unblock(); ui->advOutEncoder->setCurrentIndex(idx); } @@ -1494,6 +1495,7 @@ void OBSBasicSettings::ResetEncoders(bool streamOnly) } idx = ui->simpleOutStrEncoder->findData(lastEnc); + s1.unblock(); ui->simpleOutStrEncoder->setCurrentIndex(idx); } } From 414dccb2c325ff994670ec5b51ee92e42013e66f Mon Sep 17 00:00:00 2001 From: Jim Date: Tue, 31 Jan 2023 22:58:00 -0800 Subject: [PATCH 44/47] libobs: Update version to 29.0.1 --- libobs/obs-config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libobs/obs-config.h b/libobs/obs-config.h index 5fcc6bea0..e38e35a8d 100644 --- a/libobs/obs-config.h +++ b/libobs/obs-config.h @@ -41,7 +41,7 @@ * * Reset to zero each major or minor version */ -#define LIBOBS_API_PATCH_VER 0 +#define LIBOBS_API_PATCH_VER 1 #define MAKE_SEMANTIC_VERSION(major, minor, patch) \ ((major << 24) | (minor << 16) | patch) From 96aef4f048b19f0813446886b80a677db9467685 Mon Sep 17 00:00:00 2001 From: derrod Date: Sun, 29 Jan 2023 09:05:33 +0100 Subject: [PATCH 45/47] CI: Publish docs to Cloudflare Pages (cherry picked from commit 0a18c006caeda47bf7897c266cdc54b20f4087ea) --- .github/workflows/docs.yml | 53 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 22bf2d79c..36e534a20 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -4,20 +4,34 @@ on: push: paths-ignore: - "cmake/**" + branches: ['*'] + tags: ['*'] pull_request: paths: - "docs/sphinx/**" + workflow_dispatch: jobs: docs: runs-on: ubuntu-latest + outputs: + commitHash: ${{ steps.setup.outputs.commitHash }} + commitBranch: ${{ steps.setup.outputs.commitBranch }} + fullCommitHash: ${{ steps.setup.outputs.fullCommitHash }} steps: - name: Checkout uses: actions/checkout@v3 + - name: Setup Environment id: setup run: | + BRANCH=$(git describe --exact-match --tags 2> /dev/null || git branch --show-current) + # Remove patch version from tag + BRANCH=$(echo ${BRANCH} | sed -e 's/\.[0-9]*$//') + echo "commitBranch=${BRANCH}" >> $GITHUB_OUTPUT echo "commitHash=$(git describe --exact-match --tags 2> /dev/null || git rev-parse --short HEAD)" >> $GITHUB_OUTPUT + echo "fullCommitHash=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + - name: Bump Version Number shell: bash if: github.event_name == 'push' @@ -40,6 +54,7 @@ jobs: SCOPY="copyright = '([A-Za-z0-9, ]+)'" RCOPY="copyright = '2017-$(date +"%Y"), Hugh Bailey'" sed -i -E -e "s/${SVER}/${RVER}/g" -e "s/${SREL}/${RREL}/g" -e "s/${SCOPY}/${RCOPY}/g" docs/sphinx/conf.py + - uses: totaldebug/sphinx-publish-action@1.2.0 with: sphinx_src: 'docs/sphinx' @@ -47,9 +62,47 @@ jobs: target_branch: 'master' target_path: '../home/_build' pre_build_commands: 'pip install -Iv sphinx==5.1.1' + - uses: actions/upload-artifact@v3 with: name: 'OBS Studio Docs ${{ steps.setup.outputs.commitHash }}' path: | ${{ runner.temp }}/_github_home/_build !${{ runner.temp }}/_github_home/_build/.doctrees + + deploy: + runs-on: ubuntu-latest + needs: docs + if: ${{ github.event_name == 'workflow_dispatch' || (github.repository_owner == 'obsproject' && startsWith(github.ref, 'refs/tags/') && github.event_name != 'pull_request') }} + environment: + name: cf-pages-deploy + concurrency: + group: "cf-pages-deployment" + cancel-in-progress: true + steps: + - uses: actions/download-artifact@v3 + with: + name: 'OBS Studio Docs ${{ needs.docs.outputs.commitHash }}' + path: docs + + - name: Setup redirects + run: | + echo "/previous/27.2 https://obsproject.com/docs/27.2 302" >> docs/_redirects + echo "/previous/:major.:minor https://:major-:minor.${{ vars.CF_PAGES_PROJECT }}.pages.dev 302" >> docs/_redirects + + - name: Publish to live page + uses: cloudflare/wrangler-action@4c10c1822abba527d820b29e6333e7f5dac2cabd + with: + workingDirectory: docs + apiToken: ${{ secrets.CF_API_TOKEN }} + accountId: ${{ secrets.CF_ACCOUNT_ID }} + command: pages publish . --project-name=${{ vars.CF_PAGES_PROJECT }} --commit-hash='${{ needs.docs.outputs.fullCommitHash }}' + + - name: Publish to tag alias + if: ${{ startsWith(github.ref, 'refs/tags/') }} + uses: cloudflare/wrangler-action@4c10c1822abba527d820b29e6333e7f5dac2cabd + with: + workingDirectory: docs + apiToken: ${{ secrets.CF_API_TOKEN }} + accountId: ${{ secrets.CF_ACCOUNT_ID }} + command: pages publish . --project-name=${{ vars.CF_PAGES_PROJECT }} --commit-hash='${{ needs.docs.outputs.fullCommitHash }}' --branch='${{ needs.docs.outputs.commitBranch }}' From eef0faf741b2245c9724ecb3f9f8fc89a8f397f1 Mon Sep 17 00:00:00 2001 From: R1CH Date: Sat, 4 Feb 2023 08:27:15 +0100 Subject: [PATCH 46/47] obs-filters: Ensure gain is positive for upward compressor The gain should be positive for an upward compressor. Initially, the gain would be zeroe'd below -60 dB to ensure noise is not amplified by the upward compressor. This created a discontinuity at -60 dB since just above -60 dB, the audio is boosted by +20 dB (at default settings). This was fixed in commit 50db097 which decreased smoothly the gain so that it's 0 dB at -60 dB. However that commit forgot to limit the gain decrease which was negative below -60 dB. This is fixed by the current commit. Additionally initialization allowed -inf gain. We hard limit to positive gains only as they should be for an upward compressor. The bugfix was found by R1ch and put in form by pkv. Co-authored-by: pkv Signed-off-by: pkv --- plugins/obs-filters/expander-filter.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/obs-filters/expander-filter.c b/plugins/obs-filters/expander-filter.c index be3ca9fbd..e162d4426 100644 --- a/plugins/obs-filters/expander-filter.c +++ b/plugins/obs-filters/expander-filter.c @@ -360,12 +360,15 @@ static inline void process_sample(size_t idx, float *samples, float *env_buf, float diff = threshold - env_db; if (is_upwcomp && env_db <= (threshold - 60.0f) / 2) - diff = env_db + 60.0f; + diff = env_db + 60.0f > 0 ? env_db + 60.0f : 0.0f; float gain = 0.0f; + float prev_gain = 0.0f; // Note that the gain is always >= 0 for the upward compressor // but is always <=0 for the expander. if (is_upwcomp) { + prev_gain = idx > 0 ? fmaxf(gain_db[idx - 1], 0) + : fmaxf(channel_gain, 0); // gain above knee (included for clarity): if (env_db >= threshold + knee / 2) gain = 0.0f; @@ -377,9 +380,9 @@ static inline void process_sample(size_t idx, float *samples, float *env_buf, threshold + knee / 2 > env_db) gain = slope * powf(diff + knee / 2, 2) / (2.0f * knee); } else { + prev_gain = idx > 0 ? gain_db[idx - 1] : channel_gain; gain = diff > 0.0f ? fmaxf(slope * diff, -60.0f) : 0.0f; } - float prev_gain = idx > 0 ? gain_db[idx - 1] : channel_gain; /* --------------------------------- */ /* ballistics (attack/release) */ From 0fb8bb4b1e18ee1c870c48d35ab5b598af3b59e9 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Sat, 4 Feb 2023 02:17:10 -0800 Subject: [PATCH 47/47] libobs: Update version to 29.0.2 --- libobs/obs-config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libobs/obs-config.h b/libobs/obs-config.h index e38e35a8d..1772f4790 100644 --- a/libobs/obs-config.h +++ b/libobs/obs-config.h @@ -41,7 +41,7 @@ * * Reset to zero each major or minor version */ -#define LIBOBS_API_PATCH_VER 1 +#define LIBOBS_API_PATCH_VER 2 #define MAKE_SEMANTIC_VERSION(major, minor, patch) \ ((major << 24) | (minor << 16) | patch)