Changes of Revision 94

obs-studio.changes Changed
x
 
1
@@ -1,4 +1,32 @@
2
 -------------------------------------------------------------------
3
+Thu Mar 03 03:34:02 UTC 2022 - jimmy@boombatower.com
4
+
5
+- Update to version 27.2.3:
6
+  * virtualcam-module: Revert changes since 27.1.3 (for now)
7
+  * virtualcam-module: Prevent placeholder memory leak
8
+  * virtualcam-module: Only initialize placeholder once
9
+  * libobs: Update version to 27.2.3
10
+  * virtualcam-module: Fix incorrect correct res/fps
11
+  * UI: Remove conflicting setlocale call
12
+  * UI: Restore LC_NUMERIC to C locale on Mac/Linux
13
+  * libobs: Update version to 27.2.2
14
+  * virtualcam-module: Remove unnecessarily inlines
15
+  * virtualcam-module: Stop thread on Stop call
16
+  * win-dshow: Ensure thread is joinable before joining
17
+  * obs-scripting: Make callback "removed" variable atomic
18
+  * libobs/util: Use integer math for Windows timing
19
+  * libobs: Clamp video timing for safety
20
+  * libobs/util: Fix rounding error with os_sleepto_ns()
21
+  * UI: Additional product details
22
+  * linux-v4l2: scandir with alphasort on non-Linux
23
+  * libobs/graphics: gs_query_dmabuf_* on FreeBSD too
24
+  * UI: Refresh edit menu on item locked signal
25
+  * linux-v4l2: Fix warnings in mjpeg
26
+  * win-wasapi: Fall back to old code if RTWQ fails
27
+  * CI: Update workflow to copy SOVERSION symlinks
28
+  * libobs: Map wayland keymap with MAP_PRIVATE
29
+
30
+-------------------------------------------------------------------
31
 Tue Feb 22 16:22:47 UTC 2022 - Jimmy Berry <jimmy@boombatower.com>
32
 
33
 - Add new build dependencies:
34
obs-studio.spec Changed
8
 
1
@@ -1,5 +1,5 @@
2
 Name:           obs-studio
3
-Version:        27.2.1
4
+Version:        27.2.3
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/27.2.1</param>
6
+    <param name="revision">refs/tags/27.2.3</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">acad9dbaf7bcf8f567c3e5c613411ca04ba92fa9</param>
6
+    <param name="changesrevision">b65ee7e7fbca05e6c4bfd55b7ff721150b3c0735</param>
7
   </service>
8
 </servicedata>
9
obs-studio-27.2.1.tar.xz/.github/workflows/main.yml -> obs-studio-27.2.3.tar.xz/.github/workflows/main.yml Changed
10
 
1
@@ -215,6 +215,8 @@
2
             rm -rf ./OBS.app/Contents/Resources/data/obs-scripting/
3
           fi
4
 
5
+          /bin/cp -cpR /tmp/obsdeps/lib/*.dylib ./OBS.app/Contents/Frameworks
6
+
7
           BUNDLE_PLUGINS=(
8
             ./OBS.app/Contents/PlugIns/coreaudio-encoder.so
9
             ./OBS.app/Contents/PlugIns/decklink-ouput-ui.so
10
obs-studio-27.2.1.tar.xz/UI/obs-app.cpp -> obs-studio-27.2.3.tar.xz/UI/obs-app.cpp Changed
14
 
1
@@ -1156,6 +1156,12 @@
2
 OBSApp::OBSApp(int &argc, char **argv, profiler_name_store_t *store)
3
    : QApplication(argc, argv), profilerNameStore(store)
4
 {
5
+   /* fix float handling */
6
+#if defined(Q_OS_UNIX)
7
+   if (!setlocale(LC_NUMERIC, "C"))
8
+       blog(LOG_WARNING, "Failed to set LC_NUMERIC to C locale");
9
+#endif
10
+
11
    sleepInhibitor = os_inhibit_sleep_create("OBS Video/audio");
12
 
13
 #ifdef __APPLE__
14
obs-studio-27.2.1.tar.xz/UI/platform-x11.cpp -> obs-studio-27.2.3.tar.xz/UI/platform-x11.cpp Changed
18
 
1
@@ -136,7 +136,7 @@
2
 void PIDFileCheck(bool &already_running)
3
 {
4
    std::string tmpfile_name =
5
-       "/tmp/obs-studio.lock." + to_string(geteuid());
6
+       "/tmp/obs-studio.lock." + std::to_string(geteuid());
7
    int fd = open(tmpfile_name.c_str(), O_RDWR | O_CREAT | O_EXLOCK, 0600);
8
    if (fd == -1) {
9
        already_running = true;
10
@@ -213,7 +213,6 @@
11
 
12
 vector<string> GetPreferredLocales()
13
 {
14
-   setlocale(LC_ALL, "");
15
    vector<string> matched;
16
    string messages = setlocale(LC_MESSAGES, NULL);
17
    if (!messages.size() || messages == "C" || messages == "POSIX")
18
obs-studio-27.2.1.tar.xz/UI/source-tree.cpp -> obs-studio-27.2.3.tar.xz/UI/source-tree.cpp Changed
9
 
1
@@ -520,6 +520,7 @@
2
 void SourceTreeItem::LockedChanged(bool locked)
3
 {
4
    lock->setChecked(locked);
5
+   OBSBasic::Get()->UpdateEditMenu();
6
 }
7
 
8
 void SourceTreeItem::Renamed(const QString &name)
9
obs-studio-27.2.1.tar.xz/UI/xdg-data/com.obsproject.Studio.appdata.xml.in -> obs-studio-27.2.3.tar.xz/UI/xdg-data/com.obsproject.Studio.appdata.xml.in Changed
33
 
1
@@ -9,6 +9,22 @@
2
   <summary>Live streaming and video recording software</summary>
3
   <description>
4
     <p>Free and open source software for video capturing, recording, and live streaming.</p>
5
+    <p>Features:</p>
6
+    <ul>
7
+      <li>High performance real time video/audio capturing and mixing. Create scenes made up of multiple sources including window captures, images, text, browser windows, webcams, capture cards and more.</li>
8
+      <li>Set up an unlimited number of scenes you can switch between seamlessly via custom transitions.</li>
9
+      <li>Intuitive audio mixer with per-source filters such as noise gate, noise suppression, and gain. Take full control with VST plugin support.</li>
10
+      <li>Powerful and easy to use configuration options. Add new Sources, duplicate existing ones, and adjust their properties effortlessly.</li>
11
+      <li>Streamlined Settings panel gives you access to a wide array of configuration options to tweak every aspect of your broadcast or recording.</li>
12
+      <li>Modular 'Dock' UI allows you to rearrange the layout exactly as you like. You can even pop out each individual Dock to its own window.</li>
13
+    </ul>
14
+    <p>Create Professional Productions:</p>
15
+    <ul>
16
+      <li>Choose from a number of different and customizable transitions for when you switch between your scenes or add your own stinger video files.</li>
17
+      <li>Set hotkeys for nearly every sort of action, such as switching between scenes, starting/stopping streams or recordings, muting audio sources, push to talk, and more.</li>
18
+      <li>Studio Mode lets you preview your scenes and sources before pushing them live. Adjust your scenes and sources or create new ones and ensure they're perfect before your viewers ever see them.</li>
19
+      <li>Get a high level view of your production using the Multiview. Monitor 8 different scenes and easily cue or transition to any of them with merely a single or double click.</li>
20
+    </ul>
21
   </description>
22
   <url type="homepage">https://obsproject.com</url>
23
   <url type="bugtracker">https://github.com/obsproject/obs-studio/issues</url>
24
@@ -16,7 +32,7 @@
25
   <url type="translate">https://crowdin.com/project/obs-studio</url>
26
   <screenshots>
27
     <screenshot type="default">
28
-      <image>https://obsproject.com/assets/images/OBSDemoApp.jpg</image>
29
+      <image>https://obsproject.com/assets/images/OBSDemoApp2610.png</image>
30
     </screenshot>
31
   </screenshots>
32
   <content_rating type="oars-1.1"/>
33
obs-studio-27.2.1.tar.xz/deps/obs-scripting/obs-scripting-callback.h -> obs-studio-27.2.3.tar.xz/deps/obs-scripting/obs-scripting-callback.h Changed
26
 
1
@@ -33,9 +33,14 @@
2
    obs_script_t *script;
3
    calldata_t extra;
4
 
5
-   bool removed;
6
+   volatile bool removed;
7
 };
8
 
9
+static inline bool script_callback_removed(struct script_callback *cb)
10
+{
11
+   return os_atomic_load_bool(&cb->removed);
12
+}
13
+
14
 static inline void *add_script_callback(struct script_callback **first,
15
                    obs_script_t *script, size_t extra_size)
16
 {
17
@@ -54,7 +59,7 @@
18
 
19
 static inline void remove_script_callback(struct script_callback *cb)
20
 {
21
-   cb->removed = true;
22
+   os_atomic_set_bool(&cb->removed, true);
23
 
24
    struct script_callback *next = cb->next;
25
    if (next)
26
obs-studio-27.2.1.tar.xz/deps/obs-scripting/obs-scripting-lua-frontend.c -> obs-studio-27.2.3.tar.xz/deps/obs-scripting/obs-scripting-lua-frontend.c Changed
19
 
1
@@ -206,7 +206,7 @@
2
    struct lua_obs_callback *cb = priv;
3
    lua_State *script = cb->script;
4
 
5
-   if (cb->base.removed) {
6
+   if (script_callback_removed(&cb->base)) {
7
        obs_frontend_remove_event_callback(frontend_event_callback, cb);
8
        return;
9
    }
10
@@ -254,7 +254,7 @@
11
    struct lua_obs_callback *cb = priv;
12
    lua_State *script = cb->script;
13
 
14
-   if (cb->base.removed) {
15
+   if (script_callback_removed(&cb->base)) {
16
        obs_frontend_remove_save_callback(frontend_save_callback, cb);
17
        return;
18
    }
19
obs-studio-27.2.1.tar.xz/deps/obs-scripting/obs-scripting-lua.c -> obs-studio-27.2.3.tar.xz/deps/obs-scripting/obs-scripting-lua.c Changed
127
 
1
@@ -288,7 +288,7 @@
2
 {
3
    struct lua_obs_callback *cb = (struct lua_obs_callback *)p_cb;
4
 
5
-   if (p_cb->removed)
6
+   if (script_callback_removed(p_cb))
7
        return;
8
 
9
    lock_callback();
10
@@ -329,7 +329,7 @@
11
    struct lua_obs_callback *cb = priv;
12
    lua_State *script = cb->script;
13
 
14
-   if (cb->base.removed) {
15
+   if (script_callback_removed(&cb->base)) {
16
        obs_remove_main_render_callback(obs_lua_main_render_callback,
17
                        cb);
18
        return;
19
@@ -377,7 +377,7 @@
20
    struct lua_obs_callback *cb = priv;
21
    lua_State *script = cb->script;
22
 
23
-   if (cb->base.removed) {
24
+   if (script_callback_removed(&cb->base)) {
25
        obs_remove_tick_callback(obs_lua_tick_callback, cb);
26
        return;
27
    }
28
@@ -423,7 +423,7 @@
29
    struct lua_obs_callback *cb = priv;
30
    lua_State *script = cb->script;
31
 
32
-   if (cb->base.removed) {
33
+   if (script_callback_removed(&cb->base)) {
34
        signal_handler_remove_current();
35
        return;
36
    }
37
@@ -505,7 +505,7 @@
38
    struct lua_obs_callback *cb = priv;
39
    lua_State *script = cb->script;
40
 
41
-   if (cb->base.removed) {
42
+   if (script_callback_removed(&cb->base)) {
43
        signal_handler_remove_current();
44
        return;
45
    }
46
@@ -663,7 +663,7 @@
47
    struct lua_obs_callback *cb = p_cb;
48
    lua_State *script = cb->script;
49
 
50
-   if (cb->base.removed)
51
+   if (script_callback_removed(&cb->base))
52
        return;
53
 
54
    lock_callback();
55
@@ -689,7 +689,7 @@
56
 {
57
    struct lua_obs_callback *cb = p_cb;
58
 
59
-   if (cb->base.removed)
60
+   if (script_callback_removed(&cb->base))
61
        return;
62
 
63
    if (pressed)
64
@@ -745,7 +745,7 @@
65
    lua_State *script = cb->script;
66
    bool ret = false;
67
 
68
-   if (cb->base.removed)
69
+   if (script_callback_removed(&cb->base))
70
        return false;
71
 
72
    lock_callback();
73
@@ -801,7 +801,7 @@
74
    lua_State *script = cb->script;
75
    bool ret = false;
76
 
77
-   if (cb->base.removed)
78
+   if (script_callback_removed(&cb->base))
79
        return false;
80
 
81
    lock_callback();
82
@@ -1078,7 +1078,7 @@
83
        struct lua_obs_timer *next = timer->next;
84
        struct lua_obs_callback *cb = lua_obs_timer_cb(timer);
85
 
86
-       if (cb->base.removed) {
87
+       if (script_callback_removed(&cb->base)) {
88
            lua_obs_timer_remove(timer);
89
        } else {
90
            uint64_t elapsed = ts - timer->last_ts;
91
@@ -1157,6 +1157,25 @@
92
    lua_State *script = data->script;
93
 
94
    /* ---------------------------- */
95
+   /* mark callbacks as removed    */
96
+
97
+   pthread_mutex_lock(&data->mutex);
98
+
99
+   /* XXX: scripts can potentially make callbacks when this happens, so
100
+    * this probably still isn't ideal as we can't predict how the
101
+    * processor or operating system is going to schedule things. a more
102
+    * ideal method would be to reference count the script objects and
103
+    * atomically share ownership with callbacks when they're called. */
104
+   struct lua_obs_callback *cb =
105
+       (struct lua_obs_callback *)data->first_callback;
106
+   while (cb) {
107
+       os_atomic_set_bool(&cb->base.removed, true);
108
+       cb = (struct lua_obs_callback *)cb->base.next;
109
+   }
110
+
111
+   pthread_mutex_unlock(&data->mutex);
112
+
113
+   /* ---------------------------- */
114
    /* undefine source types        */
115
 
116
    undef_lua_script_sources(data);
117
@@ -1189,8 +1208,7 @@
118
    /* ---------------------------- */
119
    /* remove all callbacks         */
120
 
121
-   struct lua_obs_callback *cb =
122
-       (struct lua_obs_callback *)data->first_callback;
123
+   cb = (struct lua_obs_callback *)data->first_callback;
124
    while (cb) {
125
        struct lua_obs_callback *next =
126
            (struct lua_obs_callback *)cb->base.next;
127
obs-studio-27.2.1.tar.xz/deps/obs-scripting/obs-scripting-python-frontend.c -> obs-studio-27.2.3.tar.xz/deps/obs-scripting/obs-scripting-python-frontend.c Changed
19
 
1
@@ -280,7 +280,7 @@
2
 {
3
    struct python_obs_callback *cb = priv;
4
 
5
-   if (cb->base.removed) {
6
+   if (script_callback_removed(&cb->base)) {
7
        obs_frontend_remove_save_callback(frontend_save_callback, cb);
8
        return;
9
    }
10
@@ -355,7 +355,7 @@
11
 {
12
    struct python_obs_callback *cb = priv;
13
 
14
-   if (cb->base.removed) {
15
+   if (script_callback_removed(&cb->base)) {
16
        obs_frontend_remove_event_callback(frontend_event_callback, cb);
17
        return;
18
    }
19
obs-studio-27.2.1.tar.xz/deps/obs-scripting/obs-scripting-python.c -> obs-studio-27.2.3.tar.xz/deps/obs-scripting/obs-scripting-python.c Changed
125
 
1
@@ -431,7 +431,7 @@
2
 {
3
    struct python_obs_callback *cb = (struct python_obs_callback *)p_cb;
4
 
5
-   if (p_cb->removed)
6
+   if (script_callback_removed(p_cb))
7
        return;
8
 
9
    lock_callback(cb);
10
@@ -476,7 +476,7 @@
11
 {
12
    struct python_obs_callback *cb = priv;
13
 
14
-   if (cb->base.removed) {
15
+   if (script_callback_removed(&cb->base)) {
16
        obs_remove_tick_callback(obs_python_tick_callback, cb);
17
        return;
18
    }
19
@@ -546,7 +546,7 @@
20
 {
21
    struct python_obs_callback *cb = priv;
22
 
23
-   if (cb->base.removed) {
24
+   if (script_callback_removed(&cb->base)) {
25
        signal_handler_remove_current();
26
        return;
27
    }
28
@@ -652,7 +652,7 @@
29
 {
30
    struct python_obs_callback *cb = priv;
31
 
32
-   if (cb->base.removed) {
33
+   if (script_callback_removed(&cb->base)) {
34
        signal_handler_remove_current();
35
        return;
36
    }
37
@@ -767,7 +767,7 @@
38
 {
39
    struct python_obs_callback *cb = p_cb;
40
 
41
-   if (cb->base.removed)
42
+   if (script_callback_removed(&cb->base))
43
        return;
44
 
45
    lock_callback(cb);
46
@@ -803,7 +803,7 @@
47
 {
48
    struct python_obs_callback *cb = p_cb;
49
 
50
-   if (cb->base.removed)
51
+   if (script_callback_removed(&cb->base))
52
        return;
53
 
54
    if (pressed)
55
@@ -873,7 +873,7 @@
56
    struct python_obs_callback *cb = p_cb;
57
    bool ret = false;
58
 
59
-   if (cb->base.removed)
60
+   if (script_callback_removed(&cb->base))
61
        return false;
62
 
63
    lock_callback(cb);
64
@@ -937,7 +937,7 @@
65
    struct python_obs_callback *cb = p_cb;
66
    bool ret = false;
67
 
68
-   if (cb->base.removed)
69
+   if (script_callback_removed(&cb->base))
70
        return false;
71
 
72
    lock_callback(cb);
73
@@ -1334,6 +1334,24 @@
74
        return;
75
 
76
    /* ---------------------------- */
77
+   /* mark callbacks as removed    */
78
+
79
+   lock_python();
80
+
81
+   /* XXX: scripts can potentially make callbacks when this happens, so
82
+    * this probably still isn't ideal as we can't predict how the
83
+    * processor or operating system is going to schedule things. a more
84
+    * ideal method would be to reference count the script objects and
85
+    * atomically share ownership with callbacks when they're called. */
86
+   struct script_callback *cb = data->first_callback;
87
+   while (cb) {
88
+       os_atomic_set_bool(&cb->removed, true);
89
+       cb = cb->next;
90
+   }
91
+
92
+   unlock_python();
93
+
94
+   /* ---------------------------- */
95
    /* unhook tick function         */
96
 
97
    if (data->p_prev_next_tick) {
98
@@ -1350,7 +1368,7 @@
99
        data->next_tick = NULL;
100
    }
101
 
102
-   lock_python();
103
+   relock_python();
104
 
105
    Py_XDECREF(data->tick);
106
    Py_XDECREF(data->save);
107
@@ -1364,7 +1382,7 @@
108
    /* ---------------------------- */
109
    /* remove all callbacks         */
110
 
111
-   struct script_callback *cb = data->first_callback;
112
+   cb = data->first_callback;
113
    while (cb) {
114
        struct script_callback *next = cb->next;
115
        remove_script_callback(cb);
116
@@ -1532,7 +1550,7 @@
117
        struct python_obs_timer *next = timer->next;
118
        struct python_obs_callback *cb = python_obs_timer_cb(timer);
119
 
120
-       if (cb->base.removed) {
121
+       if (script_callback_removed(&cb->base)) {
122
            python_obs_timer_remove(timer);
123
        } else {
124
            uint64_t elapsed = ts - timer->last_ts;
125
obs-studio-27.2.1.tar.xz/deps/obs-scripting/obs-scripting-python.h -> obs-studio-27.2.3.tar.xz/deps/obs-scripting/obs-scripting-python.h Changed
9
 
1
@@ -195,6 +195,7 @@
2
 #define py_error() py_error_(__FUNCTION__, __LINE__)
3
 
4
 #define lock_python() PyGILState_STATE gstate = PyGILState_Ensure()
5
+#define relock_python() gstate = PyGILState_Ensure()
6
 #define unlock_python() PyGILState_Release(gstate)
7
 
8
 struct py_source;
9
obs-studio-27.2.1.tar.xz/libobs/graphics/graphics.h -> obs-studio-27.2.3.tar.xz/libobs/graphics/graphics.h Changed
10
 
1
@@ -936,7 +936,7 @@
2
 EXPORT void gs_register_loss_callbacks(const struct gs_device_loss *callbacks);
3
 EXPORT void gs_unregister_loss_callbacks(void *data);
4
 
5
-#elif __linux__
6
+#elif defined(__linux__) || defined(__FreeBSD__)
7
 
8
 EXPORT gs_texture_t *gs_texture_create_from_dmabuf(
9
    unsigned int width, unsigned int height, uint32_t drm_format,
10
obs-studio-27.2.1.tar.xz/libobs/obs-config.h -> obs-studio-27.2.3.tar.xz/libobs/obs-config.h Changed
10
 
1
@@ -41,7 +41,7 @@
2
  *
3
  * Reset to zero each major or minor version
4
  */
5
-#define LIBOBS_API_PATCH_VER 1
6
+#define LIBOBS_API_PATCH_VER 3
7
 
8
 #define MAKE_SEMANTIC_VERSION(major, minor, patch) \
9
    ((major << 24) | (minor << 16) | patch)
10
obs-studio-27.2.1.tar.xz/libobs/obs-nix-wayland.c -> obs-studio-27.2.3.tar.xz/libobs/obs-nix-wayland.c Changed
10
 
1
@@ -84,7 +84,7 @@
2
    UNUSED_PARAMETER(format);
3
    obs_hotkeys_platform_t *plat = (obs_hotkeys_platform_t *)data;
4
 
5
-   char *keymap_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
6
+   char *keymap_shm = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
7
    if (keymap_shm == MAP_FAILED) {
8
        close(fd);
9
        return;
10
obs-studio-27.2.1.tar.xz/libobs/obs-video.c -> obs-studio-27.2.3.tar.xz/libobs/obs-video.c Changed
15
 
1
@@ -723,7 +723,12 @@
2
        *p_time = t;
3
        count = 1;
4
    } else {
5
-       count = (int)((os_gettime_ns() - cur_time) / interval_ns);
6
+       const uint64_t udiff = os_gettime_ns() - cur_time;
7
+       int64_t diff;
8
+       memcpy(&diff, &udiff, sizeof(diff));
9
+       const uint64_t clamped_diff =
10
+           (diff > (int64_t)interval_ns) ? diff : interval_ns;
11
+       count = (int)(clamped_diff / interval_ns);
12
        *p_time = cur_time + interval_ns * count;
13
    }
14
 
15
obs-studio-27.2.1.tar.xz/libobs/util/platform-windows.c -> obs-studio-27.2.3.tar.xz/libobs/util/platform-windows.c Changed
44
 
1
@@ -20,11 +20,13 @@
2
 #include <shlobj.h>
3
 #include <intrin.h>
4
 #include <psapi.h>
5
+#include <math.h>
6
 
7
 #include "base.h"
8
 #include "platform.h"
9
 #include "darray.h"
10
 #include "dstr.h"
11
+#include "util_uint64.h"
12
 #include "windows/win-registry.h"
13
 #include "windows/win-version.h"
14
 
15
@@ -331,9 +333,9 @@
16
 
17
 bool os_sleepto_ns(uint64_t time_target)
18
 {
19
-   const double freq = (double)get_clockfreq();
20
+   const uint64_t freq = get_clockfreq();
21
    const LONGLONG count_target =
22
-       (LONGLONG)((double)time_target * freq / 1000000000.0);
23
+       util_mul_div64(time_target, freq, 1000000000);
24
 
25
    LARGE_INTEGER count;
26
    QueryPerformanceCounter(&count);
27
@@ -370,14 +372,9 @@
28
 uint64_t os_gettime_ns(void)
29
 {
30
    LARGE_INTEGER current_time;
31
-   double time_val;
32
-
33
    QueryPerformanceCounter(&current_time);
34
-   time_val = (double)current_time.QuadPart;
35
-   time_val *= 1000000000.0;
36
-   time_val /= (double)get_clockfreq();
37
-
38
-   return (uint64_t)time_val;
39
+   return util_mul_div64(current_time.QuadPart, 1000000000,
40
+                 get_clockfreq());
41
 }
42
 
43
 /* returns [folder]\[name] on windows */
44
obs-studio-27.2.1.tar.xz/plugins/linux-v4l2/v4l2-mjpeg.c -> obs-studio-27.2.3.tar.xz/plugins/linux-v4l2/v4l2-mjpeg.c Changed
18
 
1
@@ -75,7 +75,6 @@
2
 int v4l2_decode_mjpeg(struct obs_source_frame *out, uint8_t *data,
3
              size_t length, struct v4l2_mjpeg_decoder *decoder)
4
 {
5
-
6
    decoder->packet->data = data;
7
    decoder->packet->size = length;
8
    if (avcodec_send_packet(decoder->context, decoder->packet) < 0) {
9
@@ -106,6 +105,8 @@
10
    case AV_PIX_FMT_YUV444P:
11
        out->format = VIDEO_FORMAT_I444;
12
        break;
13
+   default:
14
+       break;
15
    }
16
 
17
    return 0;
18
obs-studio-27.2.1.tar.xz/plugins/linux-v4l2/v4l2-mjpeg.h -> obs-studio-27.2.3.tar.xz/plugins/linux-v4l2/v4l2-mjpeg.h Changed
10
 
1
@@ -29,7 +29,7 @@
2
  * Data structure for mjpeg decoding
3
  */
4
 struct v4l2_mjpeg_decoder {
5
-   AVCodec *codec;
6
+   const AVCodec *codec;
7
    AVCodecContext *context;
8
    AVPacket *packet;
9
    AVFrame *frame;
10
obs-studio-27.2.1.tar.xz/plugins/linux-v4l2/v4l2-output.c -> obs-studio-27.2.3.tar.xz/plugins/linux-v4l2/v4l2-output.c Changed
17
 
1
@@ -185,7 +185,14 @@
2
            return false;
3
    }
4
 
5
-   n = scandir("/dev", &list, scanfilter, versionsort);
6
+   n = scandir("/dev", &list, scanfilter,
7
+#if defined(__linux__)
8
+           versionsort
9
+#else
10
+           alphasort
11
+#endif
12
+   );
13
+
14
    if (n == -1)
15
        return false;
16
 
17
obs-studio-27.2.1.tar.xz/plugins/win-dshow/virtualcam-module/placeholder.cpp -> obs-studio-27.2.3.tar.xz/plugins/win-dshow/virtualcam-module/placeholder.cpp Changed
11
 
1
@@ -123,6 +123,9 @@
2
 
3
 bool initialize_placeholder()
4
 {
5
+   if (initialized)
6
+       return true;
7
+
8
    GdiplusStartupInput si;
9
    ULONG_PTR token;
10
    GdiplusStartup(&token, &si, nullptr);
11
obs-studio-27.2.1.tar.xz/plugins/win-dshow/virtualcam-module/virtualcam-filter.cpp -> obs-studio-27.2.3.tar.xz/plugins/win-dshow/virtualcam-module/virtualcam-filter.cpp Changed
11
 
1
@@ -112,7 +112,8 @@
2
 VCamFilter::~VCamFilter()
3
 {
4
    SetEvent(thread_stop);
5
-   th.join();
6
+   if (th.joinable())
7
+       th.join();
8
    video_queue_close(vq);
9
 
10
    if (placeholder.scaled_data)
11
obs-studio-27.2.1.tar.xz/plugins/win-wasapi/win-wasapi.cpp -> obs-studio-27.2.3.tar.xz/plugins/win-wasapi/win-wasapi.cpp Changed
91
 
1
@@ -347,46 +347,54 @@
2
            (PFN_RtwqPutWaitingWorkItem)GetProcAddress(
3
                rtwq_module, "RtwqPutWaitingWorkItem");
4
 
5
-       hr = rtwq_create_async_result(nullptr, &startCapture, nullptr,
6
-                         &startCaptureAsyncResult);
7
-       if (FAILED(hr)) {
8
-           enumerator->UnregisterEndpointNotificationCallback(
9
-               notify);
10
-           throw HRError(
11
-               "Could not create startCaptureAsyncResult", hr);
12
-       }
13
+       try {
14
+           hr = rtwq_create_async_result(nullptr, &startCapture,
15
+                             nullptr,
16
+                             &startCaptureAsyncResult);
17
+           if (FAILED(hr)) {
18
+               throw HRError(
19
+                   "Could not create startCaptureAsyncResult",
20
+                   hr);
21
+           }
22
 
23
-       hr = rtwq_create_async_result(nullptr, &sampleReady, nullptr,
24
-                         &sampleReadyAsyncResult);
25
-       if (FAILED(hr)) {
26
-           enumerator->UnregisterEndpointNotificationCallback(
27
-               notify);
28
-           throw HRError("Could not create sampleReadyAsyncResult",
29
-                     hr);
30
-       }
31
+           hr = rtwq_create_async_result(nullptr, &sampleReady,
32
+                             nullptr,
33
+                             &sampleReadyAsyncResult);
34
+           if (FAILED(hr)) {
35
+               throw HRError(
36
+                   "Could not create sampleReadyAsyncResult",
37
+                   hr);
38
+           }
39
 
40
-       hr = rtwq_create_async_result(nullptr, &restart, nullptr,
41
-                         &restartAsyncResult);
42
-       if (FAILED(hr)) {
43
-           enumerator->UnregisterEndpointNotificationCallback(
44
-               notify);
45
-           throw HRError("Could not create restartAsyncResult",
46
-                     hr);
47
-       }
48
+           hr = rtwq_create_async_result(nullptr, &restart,
49
+                             nullptr,
50
+                             &restartAsyncResult);
51
+           if (FAILED(hr)) {
52
+               throw HRError(
53
+                   "Could not create restartAsyncResult",
54
+                   hr);
55
+           }
56
 
57
-       DWORD taskId = 0;
58
-       DWORD id = 0;
59
-       hr = rtwq_lock_shared_work_queue(L"Capture", 0, &taskId, &id);
60
-       if (FAILED(hr)) {
61
-           enumerator->UnregisterEndpointNotificationCallback(
62
-               notify);
63
-           throw HRError("RtwqLockSharedWorkQueue failed", hr);
64
+           DWORD taskId = 0;
65
+           DWORD id = 0;
66
+           hr = rtwq_lock_shared_work_queue(L"Capture", 0, &taskId,
67
+                            &id);
68
+           if (FAILED(hr)) {
69
+               throw HRError("RtwqLockSharedWorkQueue failed",
70
+                         hr);
71
+           }
72
+
73
+           startCapture.SetQueueId(id);
74
+           sampleReady.SetQueueId(id);
75
+           restart.SetQueueId(id);
76
+       } catch (HRError &err) {
77
+           blog(LOG_ERROR, "RTWQ setup failed: %s (0x%08X)",
78
+                err.str, err.hr);
79
+           rtwq_supported = false;
80
        }
81
+   }
82
 
83
-       startCapture.SetQueueId(id);
84
-       sampleReady.SetQueueId(id);
85
-       restart.SetQueueId(id);
86
-   } else {
87
+   if (!rtwq_supported) {
88
        captureThread = CreateThread(nullptr, 0,
89
                         WASAPISource::CaptureThread, this,
90
                         0, nullptr);
91