Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 50 additions & 14 deletions src/cubeb_wasapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,10 @@ struct cubeb_stream {
* practice, we read from the input stream in the output callback, so
* this is not used, but it is necessary to start getting input data. */
HANDLE input_available_event = 0;
/* Signaled by stream_start/stream_stop when the active state changes,
so the render thread can promote/demote its MMCSS task accordingly
instead of remaining promoted while idle. */
HANDLE mmcss_event = 0;
/* Each cubeb_stream has its own thread. */
HANDLE thread = 0;
/* The lock protects all members that are touched by the render thread or
Expand Down Expand Up @@ -1503,8 +1507,9 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
} com;

bool is_playing = true;
HANDLE wait_array[4] = {stm->shutdown_event, stm->reconfigure_event,
stm->refill_event, stm->input_available_event};
HANDLE wait_array[5] = {stm->shutdown_event, stm->mmcss_event,
stm->reconfigure_event, stm->refill_event,
stm->input_available_event};
HANDLE mmcss_handle = NULL;
HRESULT hr = 0;
DWORD mmcss_task_index = 0;
Expand All @@ -1517,15 +1522,6 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
return 0;
}

/* We could consider using "Pro Audio" here for WebAudio and
maybe WebRTC. */
mmcss_handle = AvSetMmThreadCharacteristicsA("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: %lx",
GetLastError());
}

while (is_playing) {
DWORD waitResult = WaitForMultipleObjects(ARRAY_LENGTH(wait_array),
wait_array, FALSE, INFINITE);
Expand All @@ -1539,7 +1535,30 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
}
continue;
}
case WAIT_OBJECT_0 + 1: { /* reconfigure */
case WAIT_OBJECT_0 + 1: { /* mmcss: active state changed */
/* stm->active was set by wasapi_stream_start/_stop before signaling,
and SetEvent provides the necessary memory barrier. */
if (stm->active && !mmcss_handle) {
/* We could consider using "Pro Audio" here for WebAudio and
maybe WebRTC. */
mmcss_handle =
AvSetMmThreadCharacteristicsA("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: %lx",
GetLastError());
} else {
LOG("MMCSS render thread promoted (task index %lu)",
mmcss_task_index);
}
} else if (!stm->active && mmcss_handle) {
AvRevertMmThreadCharacteristics(mmcss_handle);
mmcss_handle = NULL;
LOG("MMCSS render thread demoted");
}
continue;
}
case WAIT_OBJECT_0 + 2: { /* reconfigure */
auto_lock lock(stm->stream_reset_lock);
if (!stm->active) {
/* Avoid reconfiguring, stream start will handle it. */
Expand Down Expand Up @@ -1592,12 +1611,12 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
}
break;
}
case WAIT_OBJECT_0 + 2: /* refill */
case WAIT_OBJECT_0 + 3: /* refill */
XASSERT((has_input(stm) && has_output(stm)) ||
(!has_input(stm) && has_output(stm)));
is_playing = stm->refill_callback(stm);
break;
case WAIT_OBJECT_0 + 3: { /* input available */
case WAIT_OBJECT_0 + 4: { /* input available */
bool rv = get_input_buffer(stm);
if (!rv) {
is_playing = false;
Expand Down Expand Up @@ -2946,6 +2965,12 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
return CUBEB_ERROR;
}

stm->mmcss_event = CreateEvent(NULL, 0, 0, NULL);
if (!stm->mmcss_event) {
LOG("Can't create the mmcss event, error: %lx", GetLastError());
return CUBEB_ERROR;
}

stm->thread_ready_event = CreateEvent(NULL, 0, 0, NULL);
if (!stm->thread_ready_event) {
LOG("Can't create the thread ready event, error: %lx", GetLastError());
Expand Down Expand Up @@ -3071,6 +3096,7 @@ wasapi_stream_release(cubeb_stream * stm)
CloseHandle(stm->reconfigure_event);
CloseHandle(stm->refill_event);
CloseHandle(stm->input_available_event);
CloseHandle(stm->mmcss_event);

CloseHandle(stm->thread);

Expand Down Expand Up @@ -3167,6 +3193,11 @@ wasapi_stream_start(cubeb_stream * stm)

stm->active = true;

if (!SetEvent(stm->mmcss_event)) {
LOG("wasapi_stream_start: SetEvent(mmcss_event) failed: %lx",
GetLastError());
}

stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);

return CUBEB_OK;
Expand Down Expand Up @@ -3199,6 +3230,11 @@ wasapi_stream_stop(cubeb_stream * stm)

stm->active = false;

if (!SetEvent(stm->mmcss_event)) {
LOG("wasapi_stream_stop: SetEvent(mmcss_event) failed: %lx",
GetLastError());
}

wasapi_state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
}

Expand Down
Loading