os_sleepto_ns() can occasionally return false on times that the
processor may not have reached yet. The reason is because the
count_target, which converts time_target into a QPC counter, is subject
to a rounding error.
Using numbers I generated from an actual clock cycle on my own CPU, I
can show an example of this occurring: if the clock frequency value is
10000000.0, and you call os_sleepto_ns(42164590320600), it will convert
that number first to a double floating point of its QPC value:
421645903205.99994. Then, because it converts that to a LONGLONG
integer, it of course strips off the decimal point. If you convert
421645903205 *back* to a time value, the new value will be
42164590320500, which is lower than the original value by approximately
100 nanoseconds. While this may seem insignificant, it was apparently
enough to cause the os_sleepto_ns() call in video_sleep() to sometimes
return false despite the current time being lower than the target time,
which would cause it to incorrectly calculate how many frames were
duplicated by subtracting the frame time from the current system time,
divide that by the current frame interval, set the vframe_info.count
value to 0, and thus cause an infinite loop in the encode_gpu()
function because queue_frame now starts returning negative numbers in
perpetuity.
This change fixes some rare reports of users having their video lock up
and disconnect, forcing the user to have to forcibly shut down the
program.
Thanks to Twitch user SNLabat for having the patience to kindly provide
us with a dump file from the freeze, and to Matt for coordinating with
that user to obtain it from them.
Deprecates:
obs_source_addref()
obs_output_addref()
obs_encoder_addref()
obs_service_addref()
obs_scene_addref()
These functions should be considered unsafe and not used. Instead, use:
obs_source_get_ref()
obs_output_get_ref()
obs_encoder_get_ref()
obs_service_get_ref()
obs_scene_get_ref()
These functions return a pointer to the incremented object only if the
object is still valid, otherwise they will return null, indicating that
the object is no longer valid or is unsafe to use.
The reason why this is being done is because certain third party plugins
seem to be using addref, and are somehow managing to call addref on
sources that have already been fully released. For the sake of safety,
almost all usage of these functions within OBS have also been replaced
as well.
When pushing to the front of an empty circular buffer, it would not
update the end_pos, so end_pos would be left on 0, and it would break
when trying to push to the back after that. The reason why this bug was
never discovered until now is because breakage only happens when pushing
to the front of an empty buffer, then pushing to the back right after
that.
Avoid nanosecond abstraction to reduce math operations.
Replace Sleep(0) with YieldProcessor(). We want the thread to remain
scheduled, the current CPU core to do less work, and the hyperthread
sibling to perform better.
Hacky profiling showed maybe 10-25 µs skid reduction per function call.
I think power/performance gains would be hard to measure, so I haven't
tried, but it would be shocking if they got worse.
Previously darray macros did not test the types of arguments so that
developers cannot notice even if a wrong type of a variable is passed.
This commit add a type test that relys on GCC's extension. Since OBS
Studio is built with GCC for Ubuntu, testing only under GCC is
sufficient to catch future bugs.
Currently, libobs contains two inhibitors: the portal-based one, and the
regular one based on each desktop environment's session manager. The portal
inhibitor takes precedence over the session manager one, when available.
Like the session manager inhibitor, the portal inhibitor performs all D-Bus
calls synchronously in the calling thread, which can lead to stalls. This is
not a good practice.
Make the portal inhibitor asynchronous, by using g_dbus_connection_call()
instead of g_dbus_connection_call_sync(). If an uninhibit call is made
before the previous inhibit call finishes, cancel the inhibit call instead.
Fixesobsproject/obs-studio#5314
There is a new toolchain called ARM64EC on MSVC which allows linking x64 objects to ARM64 objects.
It defines multiple architecture preprocessor definition including but not limited to `_M_X64`, `_M_ARM64` and `_M_ARM64EC`.
The original implementation will fail if compiling to ARM64EC.
These defs inadvertently redefinine `std::strtoll` in C++ code
that includes the header, causing lots of problems. They only
serve to provide compatability with very old MSVC versions.
As such, they can just be removed entirely.
Since the darray `sys_include_dirs` is an array of `char *`, it is
required to take a pointer to `char *`, that is `char **`. However,
`char *` was passed.
Since this function never called, another fix is removing entire
function `cf_preprocessor_add_sys_include_dir`.
XDG Portals provide a plethora of features meant to be used inside and
outside sandboxed environments. OBS Studio currently uses portals to
implement Wayland-compatible monitor and window captures.
However, OBS Studio performs another action that can be done through
portals: inhibit the screensaver. Under the Desktop portal (the same
used by the captures mentioned above), there is an "Inhibit" portal
that provides session inhibition.
Add a new portal-based inhibitor. This inhibitor is only used when the
Desktop portal is available and running; the previous D-Bus implementation
is used in the absence of the portal. Because it's basically another set
of D-Bus operations, wrap the new portal inhibitor under the HAVE_DBUS
call too.
macOS should use the function clock_gettime_nsec_np() to get the
current clock in nanoseconds, instead of manually using
mach_absolute_time() and manually adjusting the timebase. This
greatly simplifies the platform-specific code to manage the
current time in nanoseconds.
When calling D-Bus methods, three fields are required:
* The bus name, which is what applications own when they
want to expose themselves to D-Bus;
* The object path, which represents a D-Bus object exported
under a bus name;
* The interface, which holds the methods and signals;
While out of pure coincidence all the D-Bus buses have a
matching interface name, it is technically incorrect to assume
that.
Add a new 'interface' field to service_info, and split the bus
name.
GDBus is more and better maintained than libdbus these days. In the
future, a potential Wayland-compatible capture plugin will need to
interact with D-Bus in a way that's way too complicated for libdbus,
and it won't be nice to have both libraries talking to the D-Bus
socket.
Replace the libdbus usage by GDBus. As it turns out, it results in less
code.
Add exchange functions to alias the poorly named set functions.
Add store without reading previous. Faster on non-x86 processors.
Add compare-exchange that updates previous to avoid redundant fetch.
On Windows, load bool without conversion from char.
On Windows, load using mov with compiler barrier. Still seq_cst.
On POSIX, use GCC __atomic builtins.
This function determines if something is an OBS plugin before attempting
to load it. On Windows, many plugins ship their dependent DLLs alongside
the plugin DLL, so OBS would load things like libcef.dll on startup only
to immediately free it. For other platforms, this is less of a concern
so this function is a no-op for now.
This improves startup time and reduces risk from dependent DLLs
potentially running code with unwanted side effects in DllMain.
c3d7abfaba
Simplify usage of the SIMDe header
This obviates the need for sse2neon as well and fixes compilation of all
plugins that referenced sse-intrin.h on all architectures, not just
arm*.
Adds a cmake variable (DEBUG_FFMPEG_MUX) which enables FFmpeg debug
output in the ffmpeg-mux subprocess, and if on Windows, shows the
console window of the ffmpeg-mux subprocess so the current output can be
seen.