Changes of Revision 82

obs-studio.changes Changed
x
 
1
@@ -1,4 +1,34 @@
2
 -------------------------------------------------------------------
3
+Mon Oct 05 15:46:17 UTC 2020 - jimmy@boombatower.com
4
+
5
+- Update to version 26.0.1:
6
+  * coreaudio-encoder: Fix path on windows
7
+  * coreaudio-encoder: Refactor windows import
8
+  * rtmp-services: Update AfreecaTV
9
+  * Revert "UI: Delete existing fullscreen projector"
10
+  * win-capture: Update hook version
11
+  * win-dshow: Fix decoupled audio with EVGA/magewell
12
+  * libobs-winrt: Use native cursor draw for WGC
13
+  * win-capture: Violate Vulkan spec for compatibility
14
+  * obs-ffmpeg: Add error detection to ffmpeg-mux
15
+  * obs-ffmpeg: Signal a remote disconnect for network streams from ffmpeg-mux
16
+  * Revert "mac-capture: show actual windows in Window Capture sources"
17
+  * UI: Greatly improve main window repaint performance
18
+  * win-capture: Fix mask handling on some color cursors
19
+  * CI: Fix swig dependency on FreeBSD
20
+  * cmake: Fix finding libfdk header path
21
+  * UI: Fix tab order for controls dock
22
+  * CI: Use tag number only for macOS plist when triggered by version tag
23
+  * rtmp-services: Remove weabook.live
24
+  * UI: Skip ChromeOS test on FreeBSD
25
+  * rtmp-services: Set actual integer value of bframes in services
26
+  * UI: Implement exit on CTRL + Q for linux
27
+  * UI: Disable QT's implicit colourspace conversion on macOS
28
+  * UI: Move "Add [transition]" to bottom of combo
29
+  * UI/updater: Fix cmd prompts popping up registering vcam
30
+  * UI/updater: Fix race condition
31
+
32
+-------------------------------------------------------------------
33
 Mon Sep 28 16:27:40 UTC 2020 - jimmy@boombatower.com
34
 
35
 - Update to version 26.0.0:
36
obs-studio.spec Changed
8
 
1
@@ -1,5 +1,5 @@
2
 Name:           obs-studio
3
-Version:        26.0.0
4
+Version:        26.0.1
5
 Release:        0
6
 Summary:        A recording/broadcasting program
7
 Group:          Productivity/Multimedia/Video/Editors and Convertors
8
_service Changed
10
 
1
@@ -1,7 +1,7 @@
2
 <services>
3
   <service name="tar_scm" mode="disabled">
4
     <param name="versionformat">@PARENT_TAG@</param>
5
-    <param name="revision">refs/tags/26.0.0</param>
6
+    <param name="revision">refs/tags/26.0.1</param>
7
     <param name="url">git://github.com/jp9000/obs-studio.git</param>
8
     <param name="scm">git</param>
9
     <param name="changesgenerate">enable</param>
10
_servicedata Changed
9
 
1
@@ -1,6 +1,6 @@
2
 <servicedata>
3
   <service name="tar_scm">
4
     <param name="url">git://github.com/jp9000/obs-studio.git</param>
5
-    <param name="changesrevision">e24aaa0b5847f0d61a74b46d52e472be02a5688a</param>
6
+    <param name="changesrevision">11602bc93341e8643878810d65d6a414c60b1ac7</param>
7
   </service>
8
 </servicedata>
9
obs-studio-26.0.0.tar.xz/.cirrus.yml -> obs-studio-26.0.1.tar.xz/.cirrus.yml Changed
10
 
1
@@ -9,7 +9,7 @@
2
 task:
3
   install_script:
4
   - pkg install -y
5
-    v4l_compat swig30 ffmpeg curl dbus fdk-aac fontconfig
6
+    v4l_compat swig ffmpeg curl dbus fdk-aac fontconfig
7
     freetype2 jackit jansson luajit mbedtls pulseaudio speexdsp
8
     libsysinfo libudev-devd libv4l libx264 cmake ninja
9
     mesa-libs lua52 pkgconf
10
obs-studio-26.0.0.tar.xz/.github/workflows/main.yml -> obs-studio-26.0.1.tar.xz/.github/workflows/main.yml Changed
18
 
1
@@ -236,8 +236,14 @@
2
 
3
           cp ../CI/scripts/macos/app/OBSPublicDSAKey.pem ./OBS.app/Contents/Resources
4
 
5
-          plutil -insert CFBundleVersion -string ${{ env.OBS_GIT_TAG }}-${{ env.OBS_GIT_HASH }} ./OBS.app/Contents/Info.plist
6
-          plutil -insert CFBundleShortVersionString -string ${{ env.OBS_GIT_TAG }}-${{ env.OBS_GIT_HASH }} ./OBS.app/Contents/Info.plist
7
+          if [ "${GITHUB_REF:0:10}" = "refs/tags/" ]; then
8
+            plutil -insert CFBundleVersion -string ${{ env.OBS_GIT_TAG }} ./OBS.app/Contents/Info.plist
9
+            plutil -insert CFBundleShortVersionString -string ${{ env.OBS_GIT_TAG }} ./OBS.app/Contents/Info.plist
10
+          else
11
+            plutil -insert CFBundleVersion -string ${{ env.OBS_GIT_TAG }}-${{ env.OBS_GIT_HASH }} ./OBS.app/Contents/Info.plist
12
+            plutil -insert CFBundleShortVersionString -string ${{ env.OBS_GIT_TAG }}-${{ env.OBS_GIT_HASH }} ./OBS.app/Contents/Info.plist
13
+          fi
14
+
15
           plutil -insert OBSFeedsURL -string https://obsproject.com/osx_update/feeds.xml ./OBS.app/Contents/Info.plist
16
           plutil -insert SUFeedURL -string https://obsproject.com/osx_update/stable/updates.xml ./OBS.app/Contents/Info.plist
17
           plutil -insert SUPublicDSAKeyFile -string OBSPublicDSAKey.pem ./OBS.app/Contents/Info.plist
18
obs-studio-26.0.0.tar.xz/UI/obs-app.cpp -> obs-studio-26.0.1.tar.xz/UI/obs-app.cpp Changed
10
 
1
@@ -1981,7 +1981,7 @@
2
    run:
3
 #endif
4
 
5
-#if !defined(_WIN32) && !defined(__APPLE__)
6
+#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__FreeBSD__)
7
        // Mounted by termina during chromeOS linux container startup
8
        // https://chromium.googlesource.com/chromiumos/overlays/board-overlays/+/master/project-termina/chromeos-base/termina-lxd-scripts/files/lxd_setup.sh
9
        os_dir_t *crosDir = os_opendir("/opt/google/cros-containers");
10
obs-studio-26.0.0.tar.xz/UI/platform-osx.mm -> obs-studio-26.0.1.tar.xz/UI/platform-osx.mm Changed
15
 
1
@@ -144,6 +144,13 @@
2
    return (window->windowFlags() & Qt::WindowStaysOnTopHint) != 0;
3
 }
4
 
5
+void disableColorSpaceConversion(QWidget *window)
6
+{
7
+   NSView *view =
8
+       (__bridge NSView *)reinterpret_cast<void *>(window->winId());
9
+   view.window.colorSpace = NSColorSpace.sRGBColorSpace;
10
+}
11
+
12
 void SetAlwaysOnTop(QWidget *window, bool enable)
13
 {
14
    Qt::WindowFlags flags = window->windowFlags();
15
obs-studio-26.0.0.tar.xz/UI/platform.hpp -> obs-studio-26.0.1.tar.xz/UI/platform.hpp Changed
7
 
1
@@ -67,4 +67,5 @@
2
 void EnableOSXVSync(bool enable);
3
 void EnableOSXDockIcon(bool enable);
4
 void InstallNSApplicationSubclass();
5
+void disableColorSpaceConversion(QWidget *window);
6
 #endif
7
obs-studio-26.0.0.tar.xz/UI/volume-control.cpp -> obs-studio-26.0.1.tar.xz/UI/volume-control.cpp Changed
22
 
1
@@ -531,6 +531,8 @@
2
             bool vertical)
3
    : QWidget(parent), obs_volmeter(obs_volmeter), vertical(vertical)
4
 {
5
+   setAttribute(Qt::WA_OpaquePaintEvent, true);
6
+
7
    // Use a font that can be rendered small.
8
    tickFont = QFont("Arial");
9
    tickFont.setPixelSize(7);
10
@@ -1041,6 +1043,11 @@
11
 
12
    // Actual painting of the widget starts here.
13
    QPainter painter(this);
14
+
15
+   // Paint window background color (as widget is opaque)
16
+   QColor background = palette().color(QPalette::ColorRole::Window);
17
+   painter.fillRect(rect, background);
18
+
19
    if (vertical) {
20
        // Invert the Y axis to ease the math
21
        painter.translate(0, height);
22
obs-studio-26.0.0.tar.xz/UI/win-update/updater/hash.cpp -> obs-studio-26.0.1.tar.xz/UI/win-update/updater/hash.cpp Changed
33
 
1
@@ -45,11 +45,13 @@
2
 
3
 bool CalculateFileHash(const wchar_t *path, BYTE *hash)
4
 {
5
-   static BYTE hashBuffer[1048576];
6
+   static __declspec(thread) vector<BYTE> hashBuffer;
7
    blake2b_state blake2;
8
    if (blake2b_init(&blake2, BLAKE2_HASH_LENGTH) != 0)
9
        return false;
10
 
11
+   hashBuffer.resize(1048576);
12
+
13
    WinHandle handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ,
14
                       nullptr, OPEN_EXISTING, 0, nullptr);
15
    if (handle == INVALID_HANDLE_VALUE)
16
@@ -57,14 +59,14 @@
17
 
18
    for (;;) {
19
        DWORD read = 0;
20
-       if (!ReadFile(handle, hashBuffer, sizeof(hashBuffer), &read,
21
+       if (!ReadFile(handle, &hashBuffer[0], hashBuffer.size(), &read,
22
                  nullptr))
23
            return false;
24
 
25
        if (!read)
26
            break;
27
 
28
-       if (blake2b_update(&blake2, hashBuffer, read) != 0)
29
+       if (blake2b_update(&blake2, &hashBuffer[0], read) != 0)
30
            return false;
31
    }
32
 
33
obs-studio-26.0.0.tar.xz/UI/win-update/updater/updater.cpp -> obs-studio-26.0.1.tar.xz/UI/win-update/updater/updater.cpp Changed
51
 
1
@@ -1427,6 +1427,23 @@
2
    /* ------------------------------------- *
3
     * Install virtual camera                */
4
 
5
+   auto runcommand = [](wchar_t *cmd) {
6
+       STARTUPINFO si = {};
7
+       si.cb = sizeof(si);
8
+       si.dwFlags = STARTF_USESHOWWINDOW;
9
+       si.wShowWindow = SW_HIDE;
10
+
11
+       PROCESS_INFORMATION pi;
12
+       bool success = !!CreateProcessW(nullptr, cmd, nullptr, nullptr,
13
+                       false, CREATE_NEW_CONSOLE,
14
+                       nullptr, nullptr, &si, &pi);
15
+       if (success) {
16
+           WaitForSingleObject(pi.hProcess, INFINITE);
17
+           CloseHandle(pi.hThread);
18
+           CloseHandle(pi.hProcess);
19
+       }
20
+   };
21
+
22
    if (!bIsPortable) {
23
        wchar_t regsvr[MAX_PATH];
24
        wchar_t src[MAX_PATH];
25
@@ -1441,20 +1458,20 @@
26
        StringCbCat(src, sizeof(src),
27
                L"\\data\\obs-plugins\\win-dshow\\");
28
 
29
-       StringCbCopy(tmp, sizeof(tmp), L"\"\"");
30
+       StringCbCopy(tmp, sizeof(tmp), L"\"");
31
        StringCbCat(tmp, sizeof(tmp), regsvr);
32
        StringCbCat(tmp, sizeof(tmp), L"\" /s \"");
33
        StringCbCat(tmp, sizeof(tmp), src);
34
        StringCbCat(tmp, sizeof(tmp), L"obs-virtualcam-module");
35
 
36
        StringCbCopy(tmp2, sizeof(tmp2), tmp);
37
-       StringCbCat(tmp2, sizeof(tmp2), L"32.dll\"\"");
38
-       _wsystem(tmp2);
39
+       StringCbCat(tmp2, sizeof(tmp2), L"32.dll\"");
40
+       runcommand(tmp2);
41
 
42
        if (is_64bit_windows()) {
43
            StringCbCopy(tmp2, sizeof(tmp2), tmp);
44
-           StringCbCat(tmp2, sizeof(tmp2), L"64.dll\"\"");
45
-           _wsystem(tmp2);
46
+           StringCbCat(tmp2, sizeof(tmp2), L"64.dll\"");
47
+           runcommand(tmp2);
48
        }
49
    }
50
 
51
obs-studio-26.0.0.tar.xz/UI/window-basic-main-transitions.cpp -> obs-studio-26.0.1.tar.xz/UI/window-basic-main-transitions.cpp Changed
52
 
1
@@ -50,8 +50,14 @@
2
 
3
 void OBSBasic::InitDefaultTransitions()
4
 {
5
+   struct AddTransitionVal {
6
+       QString id;
7
+       QString name;
8
+   };
9
+
10
    ui->transitions->blockSignals(true);
11
    std::vector<OBSSource> transitions;
12
+   std::vector<AddTransitionVal> addables;
13
    size_t idx = 0;
14
    const char *id;
15
 
16
@@ -73,22 +79,26 @@
17
 
18
            obs_source_release(tr);
19
        } else {
20
-           QString addString = QTStr("Add") +
21
-                       QStringLiteral(": ") +
22
-                       QT_UTF8(name);
23
-           ui->transitions->addItem(
24
-               addString,
25
-               QVariant::fromValue(QString(QT_UTF8(id))));
26
+           AddTransitionVal val;
27
+           val.name = QTStr("Add") + QStringLiteral(": ") +
28
+                  QT_UTF8(name);
29
+           val.id = QT_UTF8(id);
30
+           addables.push_back(val);
31
        }
32
    }
33
 
34
-   if (ui->transitions->count())
35
-       ui->transitions->insertSeparator(ui->transitions->count());
36
-
37
    for (OBSSource &tr : transitions) {
38
        ui->transitions->addItem(QT_UTF8(obs_source_get_name(tr)),
39
                     QVariant::fromValue(OBSSource(tr)));
40
    }
41
+
42
+   if (addables.size())
43
+       ui->transitions->insertSeparator(ui->transitions->count());
44
+
45
+   for (AddTransitionVal &val : addables) {
46
+       ui->transitions->addItem(val.name, QVariant::fromValue(val.id));
47
+   }
48
+
49
    ui->transitions->blockSignals(false);
50
 }
51
 
52
obs-studio-26.0.0.tar.xz/UI/window-basic-main.cpp -> obs-studio-26.0.1.tar.xz/UI/window-basic-main.cpp Changed
69
 
1
@@ -326,6 +326,10 @@
2
    renameSource->setShortcut({Qt::Key_F2});
3
 #endif
4
 
5
+#ifdef __linux__
6
+   ui->actionE_xit->setShortcut(Qt::CTRL + Qt::Key_Q);
7
+#endif
8
+
9
    auto addNudge = [this](const QKeySequence &seq, const char *s) {
10
        QAction *nudge = new QAction(ui->preview);
11
        nudge->setShortcut(seq);
12
@@ -1554,6 +1558,8 @@
13
 
14
    vcamButton->setProperty("themeID", "vcamButton");
15
    ui->buttonsVLayout->insertWidget(2, vcamButton);
16
+   setTabOrder(ui->recordButton, vcamButton);
17
+   setTabOrder(vcamButton, ui->modeSwitch);
18
 }
19
 
20
 void OBSBasic::ResetOutputs()
21
@@ -1588,6 +1594,9 @@
22
            replayBufferButton->setProperty("themeID",
23
                            "replayBufferButton");
24
            ui->buttonsVLayout->insertLayout(2, replayLayout);
25
+           setTabOrder(ui->recordButton, replayBufferButton);
26
+           setTabOrder(replayBufferButton,
27
+                   ui->buttonsVLayout->itemAt(3)->widget());
28
        }
29
 
30
        if (sysTrayReplayBuffer)
31
@@ -1867,6 +1876,10 @@
32
    SystemTray(true);
33
 #endif
34
 
35
+#ifdef __APPLE__
36
+   disableColorSpaceConversion(this);
37
+#endif
38
+
39
    bool has_last_version = config_has_user_value(App()->GlobalConfig(),
40
                              "General", "LastVersion");
41
    bool first_run =
42
@@ -7035,15 +7048,6 @@
43
    if (monitor > 9 || monitor > QGuiApplication::screens().size() - 1)
44
        return nullptr;
45
 
46
-   if (monitor > -1) {
47
-       for (size_t i = 0; i < projectors.size(); i++) {
48
-           if (projectors[i]->GetMonitor() == monitor) {
49
-               DeleteProjector(projectors[i]);
50
-               break;
51
-           }
52
-       }
53
-   }
54
-
55
    OBSProjector *projector =
56
        new OBSProjector(nullptr, source, monitor, type);
57
 
58
@@ -8211,6 +8215,10 @@
59
    connect(replay.data(), &QAbstractButton::clicked, this,
60
        &OBSBasic::ReplayBufferSave);
61
    replayLayout->addWidget(replay.data());
62
+   setTabOrder(replayLayout->itemAt(0)->widget(),
63
+           replayLayout->itemAt(1)->widget());
64
+   setTabOrder(replayLayout->itemAt(1)->widget(),
65
+           ui->buttonsVLayout->itemAt(3)->widget());
66
 }
67
 
68
 #define MBYTE (1024ULL * 1024ULL)
69
obs-studio-26.0.0.tar.xz/cmake/Modules/FindLibfdk.cmake -> obs-studio-26.0.1.tar.xz/cmake/Modules/FindLibfdk.cmake Changed
12
 
1
@@ -32,7 +32,9 @@
2
        ${DepsPath}
3
        ${_LIBFDK_INCLUDE_DIRS}
4
    PATHS
5
-       /usr/include /usr/local/include /opt/local/include /sw/include)
6
+       /usr/include /usr/local/include /opt/local/include /sw/include
7
+   PATH_SUFFIXES
8
+       include)
9
 
10
 find_library(Libfdk_LIB
11
    NAMES ${_LIBFDK_LIBRARIES} fdk-aac libfdk-aac
12
obs-studio-26.0.0.tar.xz/libobs-winrt/winrt-capture.cpp -> obs-studio-26.0.1.tar.xz/libobs-winrt/winrt-capture.cpp Changed
112
 
1
@@ -137,58 +137,6 @@
2
    BOOL active;
3
    struct winrt_capture *next;
4
 
5
-   void draw_cursor()
6
-   {
7
-       CURSORINFO ci{};
8
-       ci.cbSize = sizeof(CURSORINFO);
9
-       if (!GetCursorInfo(&ci))
10
-           return;
11
-
12
-       if (!(ci.flags & CURSOR_SHOWING))
13
-           return;
14
-
15
-       HICON icon = CopyIcon(ci.hCursor);
16
-       if (!icon)
17
-           return;
18
-
19
-       ICONINFO ii;
20
-       if (GetIconInfo(icon, &ii)) {
21
-           POINT win_pos{};
22
-           if (window) {
23
-               if (client_area) {
24
-                   ClientToScreen(window, &win_pos);
25
-               } else {
26
-                   RECT window_rect;
27
-                   if (DwmGetWindowAttribute(
28
-                           window,
29
-                           DWMWA_EXTENDED_FRAME_BOUNDS,
30
-                           &window_rect,
31
-                           sizeof(window_rect)) ==
32
-                       S_OK) {
33
-                       win_pos.x = window_rect.left;
34
-                       win_pos.y = window_rect.top;
35
-                   }
36
-               }
37
-           }
38
-
39
-           POINT pos;
40
-           pos.x = ci.ptScreenPos.x - (int)ii.xHotspot - win_pos.x;
41
-           pos.y = ci.ptScreenPos.y - (int)ii.yHotspot - win_pos.y;
42
-
43
-           HDC hdc = (HDC)gs_texture_get_dc(texture);
44
-
45
-           DrawIconEx(hdc, pos.x, pos.y, icon, 0, 0, 0, NULL,
46
-                  DI_NORMAL);
47
-
48
-           gs_texture_release_dc(texture);
49
-
50
-           DeleteObject(ii.hbmColor);
51
-           DeleteObject(ii.hbmMask);
52
-       }
53
-
54
-       DestroyIcon(icon);
55
-   }
56
-
57
    void on_closed(
58
        winrt::Windows::Graphics::Capture::GraphicsCaptureItem const &,
59
        winrt::Windows::Foundation::IInspectable const &)
60
@@ -256,10 +204,6 @@
61
                    frame_surface.get());
62
            }
63
 
64
-           if (capture_cursor && cursor_visible) {
65
-               draw_cursor();
66
-           }
67
-
68
            texture_written = true;
69
        }
70
 
71
@@ -342,9 +286,9 @@
72
    const winrt::Windows::Graphics::Capture::GraphicsCaptureSession session =
73
        frame_pool.CreateCaptureSession(item);
74
 
75
-   /* disable cursor capture if possible since ours performs better */
76
    if (winrt_capture_cursor_toggle_supported())
77
-       session.IsCursorCaptureEnabled(false);
78
+       session.IsCursorCaptureEnabled(capture->capture_cursor &&
79
+                          capture->cursor_visible);
80
 
81
    capture->item = item;
82
    capture->device = device;
83
@@ -425,12 +369,13 @@
84
    const BOOL cursor_toggle_supported =
85
        winrt_capture_cursor_toggle_supported();
86
    if (cursor_toggle_supported)
87
-       session.IsCursorCaptureEnabled(false);
88
+       session.IsCursorCaptureEnabled(cursor);
89
 
90
    struct winrt_capture *capture = new winrt_capture{};
91
    capture->window = window;
92
    capture->client_area = client_area;
93
    capture->capture_cursor = cursor && cursor_toggle_supported;
94
+   capture->cursor_visible = cursor;
95
    capture->item = item;
96
    capture->device = device;
97
    d3d_device->GetImmediateContext(&capture->context);
98
@@ -523,7 +468,12 @@
99
 extern "C" EXPORT void winrt_capture_show_cursor(struct winrt_capture *capture,
100
                         BOOL visible)
101
 {
102
-   capture->cursor_visible = visible;
103
+   if (capture->capture_cursor) {
104
+       if (capture->cursor_visible != visible) {
105
+           capture->session.IsCursorCaptureEnabled(visible);
106
+           capture->cursor_visible = visible;
107
+       }
108
+   }
109
 }
110
 
111
 extern "C" EXPORT void winrt_capture_render(struct winrt_capture *capture,
112
obs-studio-26.0.0.tar.xz/plugins/coreaudio-encoder/windows-imports.h -> obs-studio-26.0.1.tar.xz/plugins/coreaudio-encoder/windows-imports.h Changed
89
 
1
@@ -361,49 +361,58 @@
2
 
3
 static void release_lib(void)
4
 {
5
-#define RELEASE_LIB(x)          \
6
-   if (x) {                \
7
-       FreeLibrary(x); \
8
-       x = NULL;       \
9
+   if (audio_toolbox) {
10
+       FreeLibrary(audio_toolbox);
11
+       audio_toolbox = NULL;
12
    }
13
-
14
-   RELEASE_LIB(audio_toolbox);
15
-#undef RELEASE_LIB
16
 }
17
 
18
-static bool load_lib(void)
19
+static bool load_from_shell_path(REFKNOWNFOLDERID rfid, const wchar_t *subpath)
20
 {
21
-   PWSTR common_path;
22
-   if (SHGetKnownFolderPath(FOLDERID_ProgramFilesCommon, 0, NULL,
23
-                &common_path) != S_OK) {
24
-       CA_LOG(LOG_WARNING, "Could not retrieve common files path");
25
+   wchar_t *sh_path;
26
+   if (SHGetKnownFolderPath(rfid, 0, NULL, &sh_path) != S_OK) {
27
+       CA_LOG(LOG_WARNING, "Could not retrieve shell path");
28
        return false;
29
    }
30
 
31
-   struct dstr path = {0};
32
-   dstr_printf(&path, "%S\\Apple\\Apple Application Support", common_path);
33
-   CoTaskMemFree(common_path);
34
+   wchar_t path[MAX_PATH];
35
+   _snwprintf(path, MAX_PATH, L"%s\\%s\\%s", sh_path, subpath,
36
+          L"CoreAudioToolbox.dll");
37
+   CoTaskMemFree(sh_path);
38
 
39
-   wchar_t *w_path = dstr_to_wcs(&path);
40
-   dstr_free(&path);
41
+   audio_toolbox = LoadLibraryW(path);
42
+   return !!audio_toolbox;
43
+}
44
+
45
+static bool load_lib(void)
46
+{
47
+   /* -------------------------------------------- */
48
+   /* attempt to load from path                    */
49
 
50
-   SetDllDirectory(w_path);
51
-   bfree(w_path);
52
+   audio_toolbox = LoadLibraryW(L"CoreAudioToolbox.dll");
53
+   if (!!audio_toolbox)
54
+       return true;
55
 
56
-#define LOAD_LIB(x, n)            \
57
-   x = LoadLibrary(TEXT(n)); \
58
-   if (!x)                   \
59
-       CA_LOG(LOG_DEBUG, "Failed loading library '" n "'");
60
+   /* -------------------------------------------- */
61
+   /* attempt to load from known install locations */
62
 
63
-   LOAD_LIB(audio_toolbox, "CoreAudioToolbox.dll");
64
-#undef LOAD_LIB
65
+   struct path_list_t {
66
+       REFKNOWNFOLDERID rfid;
67
+       const wchar_t *subpath;
68
+   };
69
 
70
-   SetDllDirectory(NULL);
71
+   path_list_t path_list[] = {
72
+       {FOLDERID_ProgramFilesCommon,
73
+        L"Apple\\Apple Application Support"},
74
+       {FOLDERID_ProgramFiles, L"iTunes"},
75
+   };
76
 
77
-   if (audio_toolbox)
78
-       return true;
79
+   for (auto &val : path_list) {
80
+       if (load_from_shell_path(val.rfid, val.subpath)) {
81
+           return true;
82
+       }
83
+   }
84
 
85
-   release_lib();
86
    return false;
87
 }
88
 
89
obs-studio-26.0.0.tar.xz/plugins/mac-capture/window-utils.h -> obs-studio-26.0.1.tar.xz/plugins/mac-capture/window-utils.h Changed
10
 
1
@@ -18,8 +18,6 @@
2
 
3
 NSArray *enumerate_cocoa_windows(void);
4
 
5
-NSArray *filter_nonzero_kcgwindowlayer_sources(NSArray *windows_arr);
6
-
7
 bool find_window(cocoa_window_t cw, obs_data_t *settings, bool force);
8
 
9
 void init_window(cocoa_window_t cw, obs_data_t *settings);
10
obs-studio-26.0.0.tar.xz/plugins/mac-capture/window-utils.m -> obs-studio-26.0.1.tar.xz/plugins/mac-capture/window-utils.m Changed
28
 
1
@@ -23,25 +23,14 @@
2
    return [o1[WINDOW_NUMBER] compare:o2[WINDOW_NUMBER]];
3
 };
4
 
5
-NSArray *filter_nonzero_kcgwindowlayer_sources(NSArray *windows_arr)
6
-{
7
-   NSPredicate *pred =
8
-       [NSPredicate predicateWithFormat:@"(kCGWindowLayer == 0)"];
9
-   NSArray *new_windows_arr =
10
-       [windows_arr filteredArrayUsingPredicate:pred];
11
-
12
-   return new_windows_arr;
13
-}
14
-
15
 NSArray *enumerate_windows(void)
16
 {
17
    NSArray *arr = (NSArray *)CGWindowListCopyWindowInfo(
18
        kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
19
-   NSArray *filtered_arr = filter_nonzero_kcgwindowlayer_sources(arr);
20
 
21
    [arr autorelease];
22
 
23
-   return [filtered_arr sortedArrayUsingComparator:win_info_cmp];
24
+   return [arr sortedArrayUsingComparator:win_info_cmp];
25
 }
26
 
27
 #define WAIT_TIME_MS 500
28
obs-studio-26.0.0.tar.xz/plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c -> obs-studio-26.0.1.tar.xz/plugins/obs-ffmpeg/ffmpeg-mux/ffmpeg-mux.c Changed
62
 
1
@@ -304,7 +304,7 @@
2
 
3
    *codec = avcodec_find_encoder(desc->id);
4
    if (!*codec) {
5
-       fprintf(stderr, "Couldn't create encoder");
6
+       fprintf(stderr, "Couldn't create encoder\n");
7
        return false;
8
    }
9
 
10
@@ -520,7 +520,7 @@
11
        ret = avio_open(&ffm->output->pb, ffm->params.file,
12
                AVIO_FLAG_WRITE);
13
        if (ret < 0) {
14
-           fprintf(stderr, "Couldn't open '%s', %s",
15
+           fprintf(stderr, "Couldn't open '%s', %s\n",
16
                ffm->params.file, av_err2str(ret));
17
            return FFM_ERROR;
18
        }
19
@@ -529,7 +529,7 @@
20
    AVDictionary *dict = NULL;
21
    if ((ret = av_dict_parse_string(&dict, ffm->params.muxer_settings, "=",
22
                    " ", 0))) {
23
-       fprintf(stderr, "Failed to parse muxer settings: %s\n%s",
24
+       fprintf(stderr, "Failed to parse muxer settings: %s\n%s\n",
25
            av_err2str(ret), ffm->params.muxer_settings);
26
 
27
        av_dict_free(&dict);
28
@@ -548,7 +548,7 @@
29
 
30
    ret = avformat_write_header(ffm->output, &dict);
31
    if (ret < 0) {
32
-       fprintf(stderr, "Error opening '%s': %s", ffm->params.file,
33
+       fprintf(stderr, "Error opening '%s': %s\n", ffm->params.file,
34
            av_err2str(ret));
35
 
36
        av_dict_free(&dict);
37
@@ -723,7 +723,14 @@
38
    if (info->keyframe)
39
        packet.flags = AV_PKT_FLAG_KEY;
40
 
41
-   return av_interleaved_write_frame(ffm->output, &packet) >= 0;
42
+   int ret = av_interleaved_write_frame(ffm->output, &packet);
43
+
44
+   if (ret < 0) {
45
+       fprintf(stderr, "av_interleaved_write_frame failed: %s\n",
46
+           av_err2str(ret));
47
+   }
48
+
49
+   return ret >= 0;
50
 }
51
 
52
 /* ------------------------------------------------------------------------- */
53
@@ -772,7 +779,7 @@
54
        resize_buf_resize(&rb, info.size);
55
 
56
        if (safe_read(rb.buf, info.size) == info.size) {
57
-           ffmpeg_mux_packet(&ffm, rb.buf, &info);
58
+           fail = !ffmpeg_mux_packet(&ffm, rb.buf, &info);
59
        } else {
60
            fail = true;
61
        }
62
obs-studio-26.0.0.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-mux.c -> obs-studio-26.0.1.tar.xz/plugins/obs-ffmpeg/obs-ffmpeg-mux.c Changed
14
 
1
@@ -440,7 +440,11 @@
2
        code = OBS_OUTPUT_UNSUPPORTED;
3
        break;
4
    default:
5
-       code = OBS_OUTPUT_ERROR;
6
+       if (stream->is_network) {
7
+           code = OBS_OUTPUT_DISCONNECTED;
8
+       } else {
9
+           code = OBS_OUTPUT_ENCODE_ERROR;
10
+       }
11
    }
12
 
13
    obs_output_signal_stop(stream->output, code);
14
obs-studio-26.0.0.tar.xz/plugins/rtmp-services/data/package.json -> obs-studio-26.0.1.tar.xz/plugins/rtmp-services/data/package.json Changed
14
 
1
@@ -1,10 +1,10 @@
2
 {
3
    "url": "https://obsproject.com/obs2_update/rtmp-services",
4
-   "version": 147,
5
+   "version": 148,
6
    "files": [
7
        {
8
            "name": "services.json",
9
-           "version": 147
10
+           "version": 148
11
        }
12
    ]
13
 }
14
obs-studio-26.0.0.tar.xz/plugins/rtmp-services/data/services.json -> obs-studio-26.0.1.tar.xz/plugins/rtmp-services/data/services.json Changed
45
 
1
@@ -760,6 +760,10 @@
2
                     "url": "rtmp://rtmp-wsu.afreecatv.com/app"
3
                 },
4
                 {
5
+                    "name": "Europe : UK",
6
+                    "url": "rtmp://rtmp-uk.afreecatv.com/app"
7
+                },
8
+                {
9
                     "name": "Asia : Singapore",
10
                     "url": "rtmp://rtmp-sgp.afreecatv.com/app"
11
                 }
12
@@ -1727,32 +1731,6 @@
13
             }
14
         },
15
         {
16
-            "name": "weabook.live",
17
-            "servers": [
18
-                {
19
-                    "name": "N.Virgina, US",
20
-                    "url": "rtmp://us-api.weabook.live/live"
21
-                },
22
-                {
23
-                    "name": "Singapore, SG",
24
-                    "url": "rtmp://sg-api.weabook.live/live"
25
-                },
26
-                {
27
-                    "name": "Tokyo, JP",
28
-                    "url": "rtmp://jp-api.weabook.live/live"
29
-                },
30
-                {
31
-                    "name": "Premium Streaming",
32
-                    "url": "rtmp://premium.rtmp.weabook.live/live"
33
-                }
34
-            ],
35
-            "recommended": {
36
-                "keyint": 2,
37
-                "max audio bitrate": 256,
38
-                "max video bitrate": 20480
39
-            }
40
-        },
41
-        {
42
             "name": "Taryana - Apachat | تاریانا - آپاچت",
43
             "servers": [
44
                 {
45
obs-studio-26.0.0.tar.xz/plugins/rtmp-services/rtmp-common.c -> obs-studio-26.0.1.tar.xz/plugins/rtmp-services/rtmp-common.c Changed
14
 
1
@@ -515,8 +515,10 @@
2
    }
3
 
4
    item = json_object_get(recommended, "bframes");
5
-   if (json_is_integer(item))
6
-       obs_data_set_int(settings, "bf", 0);
7
+   if (json_is_integer(item)) {
8
+       int bframes = json_integer_value(item);
9
+       obs_data_set_int(settings, "bf", bframes);
10
+   }
11
 
12
    item = json_object_get(recommended, "x264opts");
13
    if (json_is_string(item)) {
14
obs-studio-26.0.0.tar.xz/plugins/win-capture/cursor-capture.c -> obs-studio-26.0.1.tar.xz/plugins/win-capture/cursor-capture.c Changed
41
 
1
@@ -6,8 +6,7 @@
2
 {
3
    if (GetObject(hbmp, sizeof(*bmp), bmp) != 0) {
4
        uint8_t *output;
5
-       unsigned int size =
6
-           (bmp->bmHeight * bmp->bmWidth * bmp->bmBitsPixel) / 8;
7
+       unsigned int size = bmp->bmHeight * bmp->bmWidthBytes;
8
 
9
        output = bmalloc(size);
10
        GetBitmapBits(hbmp, size, output);
11
@@ -40,10 +39,17 @@
12
    return false;
13
 }
14
 
15
-static inline void apply_mask(uint8_t *color, uint8_t *mask, long num_pixels)
16
+static inline void apply_mask(uint8_t *color, uint8_t *mask, BITMAP *bmp_mask)
17
 {
18
-   for (long i = 0; i < num_pixels; i++)
19
-       color[i * 4 + 3] = bit_to_alpha(mask, i, false);
20
+   long mask_pix_offs;
21
+
22
+   for (long y = 0; y < bmp_mask->bmHeight; y++) {
23
+       for (long x = 0; x < bmp_mask->bmWidth; x++) {
24
+           mask_pix_offs = y * (bmp_mask->bmWidthBytes * 8) + x;
25
+           color[(y * bmp_mask->bmWidth + x) * 4 + 3] =
26
+               bit_to_alpha(mask, mask_pix_offs, false);
27
+       }
28
+   }
29
 }
30
 
31
 static inline uint8_t *copy_from_color(ICONINFO *ii, uint32_t *width,
32
@@ -69,7 +75,7 @@
33
        long pixels = bmp_color.bmHeight * bmp_color.bmWidth;
34
 
35
        if (!bitmap_has_alpha(color, pixels))
36
-           apply_mask(color, mask, pixels);
37
+           apply_mask(color, mask, &bmp_mask);
38
 
39
        bfree(mask);
40
    }
41
obs-studio-26.0.0.tar.xz/plugins/win-capture/graphics-hook-ver.h -> obs-studio-26.0.1.tar.xz/plugins/win-capture/graphics-hook-ver.h Changed
10
 
1
@@ -13,7 +13,7 @@
2
 
3
 #define HOOK_VER_MAJOR 1
4
 #define HOOK_VER_MINOR 2
5
-#define HOOK_VER_PATCH 1
6
+#define HOOK_VER_PATCH 2
7
 
8
 #define STRINGIFY(s) #s
9
 #define MAKE_VERSION_NAME(major, minor, patch) \
10
obs-studio-26.0.0.tar.xz/plugins/win-capture/graphics-hook/vulkan-capture.c -> obs-studio-26.0.1.tar.xz/plugins/win-capture/graphics-hook/vulkan-capture.c Changed
96
 
1
@@ -1742,21 +1742,21 @@
2
    destroy_surface(inst, surf, ac);
3
 }
4
 
5
-#define GETPROCADDR(func)              \
6
-   if (!strcmp(name, "vk" #func)) \
7
+#define GETPROCADDR(func)               \
8
+   if (!strcmp(pName, "vk" #func)) \
9
        return (PFN_vkVoidFunction)&OBS_##func;
10
 
11
-#define GETPROCADDR_IF_SUPPORTED(func) \
12
-   if (!strcmp(name, "vk" #func)) \
13
+#define GETPROCADDR_IF_SUPPORTED(func)  \
14
+   if (!strcmp(pName, "vk" #func)) \
15
        return funcs->func ? (PFN_vkVoidFunction)&OBS_##func : NULL;
16
 
17
-static PFN_vkVoidFunction VKAPI_CALL OBS_GetDeviceProcAddr(VkDevice dev,
18
-                              const char *name)
19
+static PFN_vkVoidFunction VKAPI_CALL OBS_GetDeviceProcAddr(VkDevice device,
20
+                              const char *pName)
21
 {
22
-   struct vk_data *data = get_device_data(dev);
23
+   struct vk_data *data = get_device_data(device);
24
    struct vk_device_funcs *funcs = &data->funcs;
25
 
26
-   debug_procaddr("vkGetDeviceProcAddr(%p, \"%s\")", dev, name);
27
+   debug_procaddr("vkGetDeviceProcAddr(%p, \"%s\")", device, pName);
28
 
29
    GETPROCADDR(GetDeviceProcAddr);
30
    GETPROCADDR(DestroyDevice);
31
@@ -1766,24 +1766,43 @@
32
 
33
    if (funcs->GetDeviceProcAddr == NULL)
34
        return NULL;
35
-   return funcs->GetDeviceProcAddr(dev, name);
36
+   return funcs->GetDeviceProcAddr(device, pName);
37
 }
38
 
39
-static PFN_vkVoidFunction VKAPI_CALL OBS_GetInstanceProcAddr(VkInstance inst,
40
-                                const char *name)
41
+/* bad layers require spec violation */
42
+#define RETURN_FP_FOR_NULL_INSTANCE 1
43
+
44
+static PFN_vkVoidFunction VKAPI_CALL
45
+OBS_GetInstanceProcAddr(VkInstance instance, const char *pName)
46
 {
47
-   debug_procaddr("vkGetInstanceProcAddr(%p, \"%s\")", inst, name);
48
+   debug_procaddr("vkGetInstanceProcAddr(%p, \"%s\")", instance, pName);
49
 
50
    /* instance chain functions we intercept */
51
    GETPROCADDR(GetInstanceProcAddr);
52
    GETPROCADDR(CreateInstance);
53
 
54
-   if (inst == NULL)
55
+#if RETURN_FP_FOR_NULL_INSTANCE
56
+   /* other instance chain functions we intercept */
57
+   GETPROCADDR(DestroyInstance);
58
+   GETPROCADDR(CreateWin32SurfaceKHR);
59
+   GETPROCADDR(DestroySurfaceKHR);
60
+
61
+   /* device chain functions we intercept */
62
+   GETPROCADDR(GetDeviceProcAddr);
63
+   GETPROCADDR(CreateDevice);
64
+   GETPROCADDR(DestroyDevice);
65
+
66
+   if (instance == NULL)
67
+       return NULL;
68
+
69
+   struct vk_inst_funcs *const funcs = get_inst_funcs(instance);
70
+#else
71
+   if (instance == NULL)
72
        return NULL;
73
 
74
-   struct vk_inst_funcs *funcs = get_inst_funcs(inst);
75
+   struct vk_inst_funcs *const funcs = get_inst_funcs(instance);
76
 
77
-   /* instance chain functions we intercept */
78
+   /* other instance chain functions we intercept */
79
    GETPROCADDR(DestroyInstance);
80
    GETPROCADDR_IF_SUPPORTED(CreateWin32SurfaceKHR);
81
    GETPROCADDR_IF_SUPPORTED(DestroySurfaceKHR);
82
@@ -1792,9 +1811,10 @@
83
    GETPROCADDR(GetDeviceProcAddr);
84
    GETPROCADDR(CreateDevice);
85
    GETPROCADDR(DestroyDevice);
86
-   if (funcs->GetInstanceProcAddr == NULL)
87
-       return NULL;
88
-   return funcs->GetInstanceProcAddr(inst, name);
89
+#endif
90
+
91
+   const PFN_vkGetInstanceProcAddr gipa = funcs->GetInstanceProcAddr;
92
+   return gipa ? gipa(instance, pName) : NULL;
93
 }
94
 
95
 #undef GETPROCADDR
96
obs-studio-26.0.0.tar.xz/plugins/win-dshow/libdshowcapture/source/dshow-base.cpp -> obs-studio-26.0.1.tar.xz/plugins/win-dshow/libdshowcapture/source/dshow-base.cpp Changed
108
 
1
@@ -671,7 +671,16 @@
2
    return wcscmp(audParentDevInstPath, vidParentDevInstPath) == 0;
3
 }
4
 
5
-static bool IsElgatoDevice(const wchar_t *vidDevInstPath)
6
+#define VEN_ID_SIZE 4
7
+
8
+static inline bool MatchingStartToken(const wstring &path,
9
+                     const wstring &start_token)
10
+{
11
+   return path.find(start_token) == 0 &&
12
+          path.size() >= start_token.size() + VEN_ID_SIZE;
13
+}
14
+
15
+static bool IsUncoupledDevice(const wchar_t *vidDevInstPath)
16
 {
17
    /* Sanity checks */
18
    if (!vidDevInstPath)
19
@@ -681,35 +690,52 @@
20
 
21
    /* USB */
22
    wstring usbToken = L"USB\\VID_";
23
-   wstring usbVidElgato = L"0FD9";
24
-
25
-   if (path.find(usbToken) == 0) {
26
-       if (path.size() >= usbToken.size() + usbVidElgato.size()) {
27
-
28
-           /* Get USB vendor ID */
29
-           wstring vid = path.substr(usbToken.size(),
30
-                         usbVidElgato.size());
31
-           if (vid == usbVidElgato)
32
+   wstring usbVidIdWhitelist[] = {
33
+       L"0FD9", /* elgato */
34
+       L"3842", /* evga */
35
+   };
36
+
37
+   if (MatchingStartToken(path, usbToken)) {
38
+       /* Get USB vendor ID */
39
+       wstring vid = path.substr(usbToken.size(), VEN_ID_SIZE);
40
+       for (wstring &whitelistId : usbVidIdWhitelist) {
41
+           if (vid == whitelistId) {
42
                return true;
43
+           }
44
        }
45
    }
46
 
47
    /* PCI */
48
-   wstring pciToken = L"PCI\\VEN_";
49
+   wstring pciVenToken = L"PCI\\VEN_";
50
    wstring pciSubsysToken = L"SUBSYS_";
51
-   wstring pciVidElgato = L"1CFA";
52
+   wstring pciVenIdWhitelist[] = {
53
+       L"1CD7", /* magewell */
54
+   };
55
+   wstring pciSubsysIdWhitelist[] = {
56
+       L"1CFA", /* elgato */
57
+   };
58
+
59
+   if (MatchingStartToken(path, pciVenToken)) {
60
+       wstring vid = path.substr(usbToken.size(), VEN_ID_SIZE);
61
+       for (wstring &whitelistId : pciVenIdWhitelist) {
62
+           if (vid == whitelistId) {
63
+               return true;
64
+           }
65
+       }
66
 
67
-   if (path.find(pciToken) == 0) {
68
-       size_t pos = path.find(pciSubsysToken);
69
-       size_t devSize =
70
-           pos + pciSubsysToken.size() + 4; /* skip product ID*/
71
-       size_t expectedSize = devSize + pciVidElgato.size();
72
+       size_t subsysPos = path.find(pciSubsysToken);
73
+       size_t subsysIdPos =
74
+           subsysPos + pciSubsysToken.size() + VEN_ID_SIZE;
75
+       size_t expectedSize = subsysIdPos + VEN_ID_SIZE;
76
 
77
-       if (pos != string::npos && path.size() >= expectedSize) {
78
+       if (subsysPos != string::npos && path.size() >= expectedSize) {
79
            /* Get PCI subsystem vendor ID */
80
-           wstring vid = path.substr(devSize, pciVidElgato.size());
81
-           if (vid == pciVidElgato)
82
-               return true;
83
+           wstring ssid = path.substr(subsysIdPos, VEN_ID_SIZE);
84
+           for (wstring &whitelistId : pciSubsysIdWhitelist) {
85
+               if (ssid == whitelistId) {
86
+                   return true;
87
+               }
88
+           }
89
        }
90
    }
91
 
92
@@ -762,11 +788,12 @@
93
    wchar_t vidDevInstPath[512];
94
    HRESULT hr = DevicePathToDeviceInstancePath(vidDevPath, vidDevInstPath,
95
                            _ARRAYSIZE(vidDevInstPath));
96
+   if (FAILED(hr))
97
+       return false;
98
 
99
-   /* Only enabled for Elgato devices for now to do not change behavior
100
-    * for any other devices (e.g. webcams) */
101
 #if 1
102
-   if (!IsElgatoDevice(vidDevInstPath))
103
+   /* Only enabled for certain whitelisted devices for now */
104
+   if (!IsUncoupledDevice(vidDevInstPath))
105
        return false;
106
 #endif
107
 
108