Bug 1144199 - Require multiple consecutive timeouts to accumulate before triggering timeout error handling in libcubeb's WASAPI backend; this avoids spurious timeout errors triggered by system sleep/wake cycles. r=padenot, a=sledru
authorMatthew Gregan <kinetik@flim.org>
Sat, 11 Apr 2015 13:24:52 +1200
changeset 258483 ea342656f3cb
parent 258482 c82fcbeb7194
child 258484 a27fb9b83867
push id4678
push userryanvm@gmail.com
push date2015-04-15 13:36 +0000
treeherdermozilla-beta@e487ace8d7f9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot, sledru
bugs1144199
milestone38.0
Bug 1144199 - Require multiple consecutive timeouts to accumulate before triggering timeout error handling in libcubeb's WASAPI backend; this avoids spurious timeout errors triggered by system sleep/wake cycles. r=padenot, a=sledru
media/libcubeb/src/cubeb_wasapi.cpp
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -491,22 +491,30 @@ wasapi_stream_render_loop(LPVOID stream)
   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\n", GetLastError());
   }
 
 
+  /* 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) {
     DWORD waitResult = WaitForMultipleObjects(ARRAY_LENGTH(wait_array),
                                               wait_array,
                                               FALSE,
                                               1000);
-
+    if (waitResult != WAIT_TIMEOUT) {
+      timeout_count = 0;
+    }
     switch (waitResult) {
     case WAIT_OBJECT_0: { /* shutdown */
       is_playing = false;
       /* We don't check if the drain is actually finished here, we just want to
        * shutdown. */
       if (stm->draining) {
         stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
       }
@@ -570,18 +578,20 @@ wasapi_stream_render_loop(LPVOID stream)
       } else {
         LOG("failed to get buffer.\n");
         is_playing = false;
       }
     }
       break;
     case WAIT_TIMEOUT:
       XASSERT(stm->shutdown_event == wait_array[0]);
-      is_playing = false;
-      hr = -1;
+      if (++timeout_count >= timeout_limit) {
+        is_playing = false;
+        hr = -1;
+      }
       break;
     default:
       LOG("case %d not handled in render loop.", waitResult);
       abort();
     }
   }
 
   if (FAILED(hr)) {