Bug 788005 - Work around Vista's higher latency requirements in WinMM. r=doublec
authorMatthew Gregan <kinetik@flim.org>
Tue, 13 Nov 2012 18:19:00 +1300
changeset 113189 d8d95ee60a9fd7098f49cd454ead29d70f305632
parent 113188 875aceabf236b75d5b6631d39d4a75d56d55a64d
child 113190 22e38380a1615bb7f1179e8798a5576f618a2b94
push id23859
push useremorley@mozilla.com
push dateWed, 14 Nov 2012 14:36:31 +0000
treeherdermozilla-central@87928cd21b40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdoublec
bugs788005
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 788005 - Work around Vista's higher latency requirements in WinMM. r=doublec
media/libcubeb/README_MOZILLA
media/libcubeb/src/cubeb_winmm.c
--- a/media/libcubeb/README_MOZILLA
+++ b/media/libcubeb/README_MOZILLA
@@ -1,10 +1,8 @@
 The source from this directory was copied from the cubeb 
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
 
-The git commit ID used was dfdf4a3c0f813717819f633f8bd3099c3e58ee8a.
-Plus the single commit 1bc23c6e2e4920f38f7aa56ec56ef5e379e18cf7.
-Plus the single commit 6e9ffc59202f95f09e5adb895d10eaedf36a6ea2.
+The git commit ID used was 6e9ffc59202f95f09e5adb895d10eaedf36a6ea2.
--- a/media/libcubeb/src/cubeb_winmm.c
+++ b/media/libcubeb/src/cubeb_winmm.c
@@ -28,16 +28,17 @@ struct cubeb_stream_item {
 
 struct cubeb {
   HANDLE event;
   HANDLE thread;
   int shutdown;
   PSLIST_HEADER work;
   CRITICAL_SECTION lock;
   unsigned int active_streams;
+  int minimum_latency;
 };
 
 struct cubeb_stream {
   cubeb * context;
   cubeb_stream_params params;
   cubeb_data_callback data_callback;
   cubeb_state_callback state_callback;
   void * user_ptr;
@@ -185,16 +186,44 @@ cubeb_buffer_callback(HWAVEOUT waveout, 
   item = _aligned_malloc(sizeof(struct cubeb_stream_item), MEMORY_ALLOCATION_ALIGNMENT);
   assert(item);
   item->stream = stm;
   InterlockedPushEntrySList(stm->context->work, &item->head);
 
   SetEvent(stm->context->event);
 }
 
+static int
+calculate_minimum_latency(void)
+{
+  OSVERSIONINFOEX osvi;
+  DWORDLONG mask;
+
+  /* Vista's WinMM implementation underruns when less than 200ms of audio is buffered. */
+  memset(&osvi, 0, sizeof(OSVERSIONINFOEX));
+  osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+  osvi.dwMajorVersion = 6;
+  osvi.dwMinorVersion = 0;
+
+  mask = 0;
+  VER_SET_CONDITION(mask, VER_MAJORVERSION, VER_EQUAL);
+  VER_SET_CONDITION(mask, VER_MINORVERSION, VER_EQUAL);
+
+  if (VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, mask) != 0) {
+    return 200;
+  }
+
+  /* Running under Terminal Services results in underruns with low latency. */
+  if (GetSystemMetrics(SM_REMOTESESSION) == TRUE) {
+    return 500;
+  }
+
+  return 0;
+}
+
 int
 cubeb_init(cubeb ** context, char const * context_name)
 {
   cubeb * ctx;
 
   assert(context);
   *context = NULL;
 
@@ -217,16 +246,18 @@ cubeb_init(cubeb ** context, char const 
     return CUBEB_ERROR;
   }
 
   SetThreadPriority(ctx->thread, THREAD_PRIORITY_TIME_CRITICAL);
 
   InitializeCriticalSection(&ctx->lock);
   ctx->active_streams = 0;
 
+  ctx->minimum_latency = calculate_minimum_latency();
+
   *context = ctx;
 
   return CUBEB_OK;
 }
 
 char const *
 cubeb_get_backend_id(cubeb * ctx)
 {
@@ -337,16 +368,20 @@ cubeb_stream_init(cubeb * context, cubeb
   stm->context = context;
 
   stm->params = stream_params;
 
   stm->data_callback = data_callback;
   stm->state_callback = state_callback;
   stm->user_ptr = user_ptr;
 
+  if (latency < context->minimum_latency) {
+    latency = context->minimum_latency;
+  }
+
   bufsz = (size_t) (stm->params.rate / 1000.0 * latency * bytes_per_frame(stm->params) / NBUFS);
   if (bufsz % bytes_per_frame(stm->params) != 0) {
     bufsz += bytes_per_frame(stm->params) - (bufsz % bytes_per_frame(stm->params));
   }
   assert(bufsz % bytes_per_frame(stm->params) == 0);
 
   stm->buffer_size = bufsz;