119 lines
3.9 KiB
Diff
119 lines
3.9 KiB
Diff
|
# HG changeset patch
|
||
|
# User Alex Chronopoulos <achronop@gmail.com>
|
||
|
# Parent b7bb31e5a851d6f8e142c39dc077e3774719eced
|
||
|
Bug 1342363 - Uplift wasapi fixes in Beta. r?kinetik
|
||
|
|
||
|
diff --git a/media/libcubeb/src/cubeb_wasapi.cpp b/media/libcubeb/src/cubeb_wasapi.cpp
|
||
|
--- a/media/libcubeb/src/cubeb_wasapi.cpp
|
||
|
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
|
||
|
@@ -807,16 +807,20 @@ wasapi_stream_render_loop(LPVOID stream)
|
||
|
maybe WebRTC. */
|
||
|
mmcss_handle =
|
||
|
stm->context->set_mm_thread_characteristics("Audio", &mmcss_task_index);
|
||
|
if (!mmcss_handle) {
|
||
|
/* This is not fatal, but we might glitch under heavy load. */
|
||
|
LOG("Unable to use mmcss to bump the render thread priority: %x", GetLastError());
|
||
|
}
|
||
|
|
||
|
+ // This has already been nulled out, simply exit.
|
||
|
+ if (!emergency_bailout) {
|
||
|
+ is_playing = false;
|
||
|
+ }
|
||
|
|
||
|
/* WaitForMultipleObjects timeout can trigger in cases where we don't want to
|
||
|
treat it as a timeout, such as across a system sleep/wake cycle. Trigger
|
||
|
the timeout error handling only when the timeout_limit is reached, which is
|
||
|
reset on each successful loop. */
|
||
|
unsigned timeout_count = 0;
|
||
|
const unsigned timeout_limit = 5;
|
||
|
while (is_playing) {
|
||
|
@@ -1158,22 +1162,26 @@ bool stop_and_join_render_thread(cubeb_s
|
||
|
|
||
|
/* Wait five seconds for the rendering thread to return. It's supposed to
|
||
|
* check its event loop very often, five seconds is rather conservative. */
|
||
|
DWORD r = WaitForSingleObject(stm->thread, 5000);
|
||
|
if (r == WAIT_TIMEOUT) {
|
||
|
/* Something weird happened, leak the thread and continue the shutdown
|
||
|
* process. */
|
||
|
*(stm->emergency_bailout) = true;
|
||
|
+ // We give the ownership to the rendering thread.
|
||
|
+ stm->emergency_bailout = nullptr;
|
||
|
LOG("Destroy WaitForSingleObject on thread timed out,"
|
||
|
" leaking the thread: %d", GetLastError());
|
||
|
rv = false;
|
||
|
}
|
||
|
if (r == WAIT_FAILED) {
|
||
|
*(stm->emergency_bailout) = true;
|
||
|
+ // We give the ownership to the rendering thread.
|
||
|
+ stm->emergency_bailout = nullptr;
|
||
|
LOG("Destroy WaitForSingleObject on thread failed: %d", GetLastError());
|
||
|
rv = false;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Only attempts to close and null out the thread and event if the
|
||
|
// WaitForSingleObject above succeeded, so that calling this function again
|
||
|
// attemps to clean up the thread and event each time.
|
||
|
@@ -1798,19 +1806,16 @@ void wasapi_stream_destroy(cubeb_stream
|
||
|
XASSERT(stm);
|
||
|
|
||
|
// Only free stm->emergency_bailout if we could not join the thread.
|
||
|
// If we could not join the thread, stm->emergency_bailout is true
|
||
|
// and is still alive until the thread wakes up and exits cleanly.
|
||
|
if (stop_and_join_render_thread(stm)) {
|
||
|
delete stm->emergency_bailout.load();
|
||
|
stm->emergency_bailout = nullptr;
|
||
|
- } else {
|
||
|
- // If we're leaking, it must be that this is true.
|
||
|
- assert(*(stm->emergency_bailout));
|
||
|
}
|
||
|
|
||
|
unregister_notification_client(stm);
|
||
|
|
||
|
SafeRelease(stm->reconfigure_event);
|
||
|
SafeRelease(stm->refill_event);
|
||
|
SafeRelease(stm->input_available_event);
|
||
|
|
||
|
@@ -1865,21 +1870,21 @@ int stream_start_one_side(cubeb_stream *
|
||
|
return CUBEB_ERROR;
|
||
|
}
|
||
|
|
||
|
return CUBEB_OK;
|
||
|
}
|
||
|
|
||
|
int wasapi_stream_start(cubeb_stream * stm)
|
||
|
{
|
||
|
+ auto_lock lock(stm->stream_reset_lock);
|
||
|
+
|
||
|
XASSERT(stm && !stm->thread && !stm->shutdown_event);
|
||
|
XASSERT(stm->output_client || stm->input_client);
|
||
|
|
||
|
- auto_lock lock(stm->stream_reset_lock);
|
||
|
-
|
||
|
stm->emergency_bailout = new std::atomic<bool>(false);
|
||
|
|
||
|
if (stm->output_client) {
|
||
|
int rv = stream_start_one_side(stm, OUTPUT);
|
||
|
if (rv != CUBEB_OK) {
|
||
|
return rv;
|
||
|
}
|
||
|
}
|
||
|
@@ -1932,16 +1937,17 @@ int wasapi_stream_stop(cubeb_stream * st
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
|
||
|
}
|
||
|
|
||
|
if (stop_and_join_render_thread(stm)) {
|
||
|
+ // This is null if we've given the pointer to the other thread
|
||
|
if (stm->emergency_bailout.load()) {
|
||
|
delete stm->emergency_bailout.load();
|
||
|
stm->emergency_bailout = nullptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return CUBEB_OK;
|
||
|
}
|