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.
The current path would prevent the browser source from loading if OBS
itself is in the "Application Support" folder, where it might end up
when being installed via certain distribution platforms.
This adjusts the existing hack to specifically check for the obs-studio
subfolder where the old browser source library would reside.
With this, you can now cast normal obs objects (services, outputs,
sources, encoders) to an obs_object_t, and then use obs_object_*
functions to get references, release references, and similar for weak
object references as well. This allows the ability for the frontend to
use an object of any of those types interchangeably in certain
situations without having to handle each specific type individually.
This is useful because the properties view in particular doesn't care
what type of object it uses, it just needs to be able to hold weak
references to abstract OBS objects.
Currently if a module fails its load callback, it remains loaded and OBS
continues to call additional exports such as obs_module_post_load. This
goes against the documented behavior, which states that a module that
fails its load callback is unloaded.
This commit releases locale resources and frees the module's
information, preventing further callbacks from libobs. The module itself
(the DLL) is not yet unloaded from memory as os_dlclose is commented out
for causing unspecified issues - this should be revisited in the future.
The audio capture callback's mute parameter internally respects the
push to talk/mute state, whereas obs_source_muted() and the "mute"
signal don't. This resulted in meters looking entirely unmuted even
though both monitoring and output were not receiving audio.
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.
This prevents double destroys from happening on sources and causing
crashes. If someone's doing a double destroy it'll probably crash anyway
but at least we'll know what happened if it does. (Jim note: I suspect
third party plugins are calling addref on sources when they shouldn't
be. Either that or we're missing something ourselves, but I suppose
we'll see.)
These were operated on by atomic functions but were not marked as
volatile or loaded with os_atomic_load_long, potentially introducing
subtle race conditions. Detected by ThreadSanitizer.
Removes all callbacks in use on sources right when a source is about to
be destroyed.
Fixes a crash where callbacks would still be executed while in a
destroyed state (particularly sidechain filters). Could also just mark
the source as being in a destroyed state and not accept anymore
obs_source_output_[audio/video] calls.
The *AutoRelease helpers should not take references from OBSRef objects.
Instead, make an OBSRefAutoRelease base class, and OBSRef a subclass of
that to allow moves, and then perform moves from those objects.
This fixes an issue where *AutoRelease OBSRef objects would cause an
unintended double release of objects after having been assigned values
from non-*AutoRelease OBSRef objects.
When sharing DMA-BUFs it is required the announce the underlying
hardware capabilities via supported modifiers.
Add new device_query_dmabuf_capabilities vfunc to gs_exports and connect it
to the egl implementation stubs in the supported render platforms. Add a new
public method gs_query_dmabuf_capabilities() that calls the vfunc above.
Add new device_query_dmabuf_modifiers vfunc to gs_exports and connect it
to the egl implementation in the supported render platforms. Add a new
public method gs_query_dmabuf_modifiers() that calls the vfunc above.
(This also modifies the UI)
The purpose of deferring destruction of sources is to ensure that:
1.) Hard locks from enumeration cannot occur with source destruction.
For example, if the browser source is destroyed while in the graphics
thread, the browser thread would wait for the graphics thread, but the
graphics thread would still be waiting for the browser thread, causing
a hard lock.
2.) When destroys occur during source enumeration, that the integrity of
the context's next pointer in the linked list can no longer be
compromised
3.) Source releases are fully asynchronous rather than having the risk
of stalling the calling thread
4.) We can wait for source destruction when switching scene collections
or when shutting down rather than hoping for threads to be finished
with sources.
This introduces a new requirement when cleaning up scene/source data:
the obs_wait_for_destroy_queue() function. It is highly recommended that
this function be called after cleaning up sources. It will return true
if at least one or more sources were destroyed. Otherwise it will return
false. Forks are highly advised to call this function manually on source
cleanup -- preferably in a loop, in conjunction with processing
outstanding OBS signals and UI events.
Holds an active reference to a source during signaling of the
`source_remove` signal, to prevent receivers from being given an
already-destroyed source.
- Call obs_source_remove(source)
- Receiver 1 gets signal, calls `obs_source_release(source)`
- Receiver 2 gets signal, calls `obs_source_release(source)`,
refs == -1, source destroyed
- Receiver 3 gets signal, source already destroyed, is forced to ignore
signal due to invalid source
This is a theoretical situation which is currently possible in
obs-websocket.
Users on Wayland are displeased that they cannot see their hotkey
bindings. This enables key reporting like X11, and has the infrastructure
in place in case Wayland ever decides to allow for capturing input.
obs_source_release should not be called while iterating through the
global sources linked list, otherwise the linked list will be
compromised. Annoying.
Basically the same fix as obsproject/obs-studio#5600, but should be
slightly more optimal and a bit more explicit.
Fixes an issue pointed out in obsproject/obs-browser#333 where a source
may destroy the next source in obs_source_video_tick(), thus
invalidating the next source in the linked list. Get the next source in
the list *after* calling obs_source_video_tick() rather than before.
Closesobsproject/obs-studio#5600
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.
These AutoRelease versions of the C++ OBSRef types do not add a ref on
construction, which is useful when accepting the result of a function
that turns a raw C pointer type that has had a reference added.
Not having these types has resulted in multiple awkward anti-patterns.
Such as immediately releasing after construction to account for the
extra addref, or avoiding using the C++ type entirely and manually
releasing it later.
Example:
```
OBSSource source = obs_get_source_by_name(name.c_str());
obs_source_release(source);
```
The whole point of these types is to avoid the need for manual releases,
and rely on the RAII mechanisms inside of C++. Additionally, the
immediate release isn't commented anywhere, resulting in confusion for
other developers looking at the code as to why things are being
immediately released.
The AutoRelease types and names are taken from obs-websocket.
When sources output NULL frames, it is generally used to disable the
source and prevent the last frame from being left on screen. However,
when the source begins outputting video again, the last frame is
still in the async cache.
Depending on the stability of the source's frame output, this still
frame can end up being shown for 5+ output frames.
By freeing the async cache when a NULL frame is submitted, we avoid
the issue of old frames being re-displayed.
Currently, ifdefs are used to determine if monitoring is supported.
This is difficult to maintain and restricts plugins from knowing if
monitoring is supported by OBS. This adds a runtime function to fix
that issue.
Adds support for using shared textures that were made with the
D3D11_RESOURCE_MISC_SHARED_NTHANDLE flag.
This increases the minimum required Windows version to Windows 8 or the
Platform Update for Windows 7. As official support is only for Win 8+
this does not change official support.
Previously we would wait for pulse to attempt to read from the monitor
source and obs buffered at least 5ms of audio data before we tried to
fill the buffer. In some cases this resulted in consistently triggering
underruns in pulse.
Instead we try to fill the buffer immediately as obs outputs audio data
and while the pa buffer is not full. We also stop trying to grow the
buffer to prevent underruns after we reach 1s of latency.
(This commit also modifies UI)
This makes it more trivial for encoder plugins to communicate to users
why specifically an encoder error might have occurred mid-stream.
When signed 32-bit audio arrived to pulseaudio-output and volume was
lowered, audio data was broken. In the function `process_volume`, the
type of the data is switched by `bytes_per_channel`. However the size of
signed 32-bit integer and the size of float are same so that the signed
32-bit integer is processed as float.
This commit changes these items.
- Use `format` instead of `bytes_per_channel` so that all the sample
types can be differentiated.
- Change `short` to `int16_t` and renames existing function
`process_short` to `process_s16` to clarify the function is
processing signed 16-bit.
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.
Apparently, some audio filters do not check the audio channel/plane
count, and instead check to see if a pointer is valid. Instead of
requiring the caller to initialize these values to 0 manually (they
shouldn't have to), set them to zero upon input in
obs_source_output_audio() itself.
Closesobsproject/obs-studio#3744
Fixes a bug where if an audio source's implementation disappears (i.e.
a plugin vanishes or is removed), it would turn all mixing channels off,
effectively muting the source
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 are some cases where an item may attempt to be created for a
removed source.
Previously, items created from removed sources would lead to the item
itself being saved, but the underlying source not being saved. While
this does not break OBS immediately, it means that the source along
with all associated items will disappear on OBS reload.
This prevents the item from being created in the first place, reducing
the chances of user work being lost.
66c27c2cea (#4664) was mistakenly merged. It was also the incorrect
way to fix the deadlock. Because duplicate_item_data() already defers
the texture creation process, we can just add a param to
obs_scene_add_internal() which allows us to exclude the creation of the
item texture for this specific case. The texture will then automatically
be created later before it's used. There was no reason to be creating
the texture there, as it was unnecessary.
Properly fixesobsproject/obs-studio#3166
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.
As logic in video render thread, gs lock (obs_enter_graphics) should be requested before full_lock(scene).
However in function obs_sceneitem_group_ungroup called from UI thread, the order for requesting locks are contrary.
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.
Fixes a long-standing issue with Dynamic Bitrate where the RTMP output
thread could try to reconfigure an encoder while the encoder is in the
middle of encoding. x264 seems to handle multithreaded calls well, but
NVENC would deadlock in this situation with no error visible to the
user.
These local copies of CheckForPthreads.c and FindThreads.cmake override
the ones included with CMake. These versions create CMake::Threads, but
Qt6 expects Threads::Threads created by CMake 3.1+. These local versions
seem to be based on old copies from CMake from late 2014 with some
customizations. Let's just use the built-in ones that CMake ships.
This commit also changes CMakeLists.txt files in UI and libobs to
require and link to Threads::Threads.
Co-authored-by: Kurt Kartaltepe <kkartaltepe@gmail.com>