11diff --git a/modules/audio_device/win/audio_device_core_win.cc b/modules/audio_device/win/audio_device_core_win.cc
2- index f1cc0474fc..f8e4f25bb9 100644
2+ index f1cc0474fc..2aacd1d309 100644
33--- a/modules/audio_device/win/audio_device_core_win.cc
44+++ b/modules/audio_device/win/audio_device_core_win.cc
55@@ -1845,8 +1845,8 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
@@ -142,14 +142,13 @@ index f1cc0474fc..f8e4f25bb9 100644
142142 RTC_LOG(LS_VERBOSE) << "Additional settings:";
143143 RTC_LOG(LS_VERBOSE) << "_playAudioFrameSize: " << _playAudioFrameSize;
144144 RTC_LOG(LS_VERBOSE) << "_playBlockSize : " << _playBlockSize;
145- @@ -1980,12 +2007,14 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
145+ @@ -1980,12 +2007,12 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
146146 }
147147 hr = _ptrClientOut->Initialize(
148148 AUDCLNT_SHAREMODE_SHARED, // share Audio Engine with other applications
149149- AUDCLNT_STREAMFLAGS_EVENTCALLBACK, // processing of the audio buffer by
150- + AUDCLNT_STREAMFLAGS_EVENTCALLBACK | // processing of the audio buffer by
151- // the client will be event driven
152- + AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM |
150+ - // the client will be event driven
151+ + AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | // let WASAPI handle format conversion
153152+ AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY,
154153 hnsBufferDuration, // requested buffer capacity as a time value (in
155154 // 100-nanosecond units)
@@ -159,7 +158,19 @@ index f1cc0474fc..f8e4f25bb9 100644
159158 NULL); // session GUID
160159
161160 if (FAILED(hr)) {
162- @@ -2031,7 +2060,7 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
161+ @@ -2016,11 +2043,6 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
162+ << bufferFrameCount * _playAudioFrameSize << " bytes)";
163+ }
164+
165+ - // Set the event handle that the system signals when an audio buffer is ready
166+ - // to be processed by the client.
167+ - hr = _ptrClientOut->SetEventHandle(_hRenderSamplesReadyEvent);
168+ - EXIT_ON_ERROR(hr);
169+ -
170+ // Get an IAudioRenderClient interface.
171+ SAFE_RELEASE(_ptrRenderClient);
172+ hr = _ptrClientOut->GetService(__uuidof(IAudioRenderClient),
173+ @@ -2031,7 +2053,7 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
163174 _playIsInitialized = true;
164175
165176 CoTaskMemFree(pWfxOut);
@@ -168,7 +179,7 @@ index f1cc0474fc..f8e4f25bb9 100644
168179
169180 RTC_LOG(LS_VERBOSE) << "render side is now initialized";
170181 return 0;
171- @@ -2039,7 +2068 ,7 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
182+ @@ -2039,7 +2061 ,7 @@ int32_t AudioDeviceWindowsCore::InitPlayout() {
172183 Exit:
173184 _TraceCOMError(hr);
174185 CoTaskMemFree(pWfxOut);
@@ -177,7 +188,7 @@ index f1cc0474fc..f8e4f25bb9 100644
177188 SAFE_RELEASE(_ptrClientOut);
178189 SAFE_RELEASE(_ptrRenderClient);
179190 return -1;
180- @@ -2163,7 +2192 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
191+ @@ -2163,7 +2185 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
181192 HRESULT hr = S_OK;
182193 WAVEFORMATEX* pWfxIn = NULL;
183194 WAVEFORMATEXTENSIBLE Wfx = WAVEFORMATEXTENSIBLE();
@@ -186,7 +197,7 @@ index f1cc0474fc..f8e4f25bb9 100644
186197
187198 // Create COM object with IAudioClient interface.
188199 SAFE_RELEASE(_ptrClientIn);
189- @@ -2201,7 +2230 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
200+ @@ -2201,7 +2223 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
190201 Wfx.Samples.wValidBitsPerSample = Wfx.Format.wBitsPerSample;
191202 Wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
192203
@@ -195,7 +206,7 @@ index f1cc0474fc..f8e4f25bb9 100644
195206 hr = S_FALSE;
196207
197208 // Iterate over frequencies and channels, in order of priority
198- @@ -2218,8 +2247 ,10 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
209+ @@ -2218,8 +2240 ,10 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
199210 // If the method succeeds and the audio endpoint device supports the
200211 // specified stream format, it returns S_OK. If the method succeeds and
201212 // provides a closest match to the specified format, it returns S_FALSE.
@@ -208,7 +219,7 @@ index f1cc0474fc..f8e4f25bb9 100644
208219 if (hr == S_OK) {
209220 break;
210221 } else {
211- @@ -2228,10 +2259 ,14 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
222+ @@ -2228,10 +2252 ,14 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
212223 << ", nSamplesPerSec=" << Wfx.Format.nSamplesPerSec
213224 << " is not supported. Closest match: "
214225 "nChannels="
@@ -227,7 +238,7 @@ index f1cc0474fc..f8e4f25bb9 100644
227238 } else {
228239 RTC_LOG(LS_INFO) << "nChannels=" << Wfx.Format.nChannels
229240 << ", nSamplesPerSec=" << Wfx.Format.nSamplesPerSec
230- @@ -2242,7 +2277 ,20 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
241+ @@ -2242,7 +2270 ,20 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
231242 if (hr == S_OK)
232243 break;
233244 }
@@ -249,7 +260,7 @@ index f1cc0474fc..f8e4f25bb9 100644
249260 if (hr == S_OK) {
250261 _recAudioFrameSize = Wfx.Format.nBlockAlign;
251262 _recSampleRate = Wfx.Format.nSamplesPerSec;
252- @@ -2270,6 +2318 ,8 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
263+ @@ -2270,6 +2311 ,8 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
253264 AUDCLNT_SHAREMODE_SHARED, // share Audio Engine with other applications
254265 AUDCLNT_STREAMFLAGS_EVENTCALLBACK | // processing of the audio buffer by
255266 // the client will be event driven
@@ -258,7 +269,7 @@ index f1cc0474fc..f8e4f25bb9 100644
258269 AUDCLNT_STREAMFLAGS_NOPERSIST, // volume and mute settings for an
259270 // audio session will not persist
260271 // across system restarts
261- @@ -2321,7 +2371 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
272+ @@ -2321,7 +2364 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
262273 _recIsInitialized = true;
263274
264275 CoTaskMemFree(pWfxIn);
@@ -267,7 +278,7 @@ index f1cc0474fc..f8e4f25bb9 100644
267278
268279 RTC_LOG(LS_VERBOSE) << "capture side is now initialized";
269280 return 0;
270- @@ -2329,7 +2379 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
281+ @@ -2329,7 +2372 ,7 @@ int32_t AudioDeviceWindowsCore::InitRecording() {
271282 Exit:
272283 _TraceCOMError(hr);
273284 CoTaskMemFree(pWfxIn);
@@ -276,3 +287,42 @@ index f1cc0474fc..f8e4f25bb9 100644
276287 SAFE_RELEASE(_ptrClientIn);
277288 SAFE_RELEASE(_ptrCaptureClient);
278289 return -1;
290+ @@ -2661,7 +2704,6 @@ DWORD WINAPI AudioDeviceWindowsCore::WSAPICaptureThreadPollDMO(LPVOID context) {
291+
292+ DWORD AudioDeviceWindowsCore::DoRenderThread() {
293+ bool keepPlaying = true;
294+ - HANDLE waitArray[2] = {_hShutdownRenderEvent, _hRenderSamplesReadyEvent};
295+ HRESULT hr = S_OK;
296+ HANDLE hMmTask = NULL;
297+
298+ @@ -2777,20 +2819,16 @@ DWORD AudioDeviceWindowsCore::DoRenderThread() {
299+ // >> ------------------ THREAD LOOP ------------------
300+
301+ while (keepPlaying) {
302+ - // Wait for a render notification event or a shutdown event
303+ - DWORD waitResult = WaitForMultipleObjects(2, waitArray, FALSE, 500);
304+ - switch (waitResult) {
305+ - case WAIT_OBJECT_0 + 0: // _hShutdownRenderEvent
306+ - keepPlaying = false;
307+ - break;
308+ - case WAIT_OBJECT_0 + 1: // _hRenderSamplesReadyEvent
309+ - break;
310+ - case WAIT_TIMEOUT: // timeout notification
311+ - RTC_LOG(LS_WARNING) << "render event timed out after 0.5 seconds";
312+ - goto Exit;
313+ - default: // unexpected error
314+ - RTC_LOG(LS_WARNING) << "unknown wait termination on render side";
315+ - goto Exit;
316+ + // Sleep for half the device period, then poll for available buffer space.
317+ + // We use the shutdown event wait as the sleep mechanism so we can still
318+ + // wake immediately on shutdown.
319+ + DWORD sleepMs = static_cast<DWORD>(devPeriod / 10000 / 2);
320+ + if (sleepMs < 1)
321+ + sleepMs = 1;
322+ + DWORD waitResult = WaitForSingleObject(_hShutdownRenderEvent, sleepMs);
323+ + if (waitResult == WAIT_OBJECT_0) {
324+ + keepPlaying = false;
325+ + break;
326+ }
327+
328+ while (keepPlaying) {
0 commit comments