Backed out changeset dd1417716d76 (bug 1103824) for Android issues. CLOSED TREE.
authorMatthew Gregan <kinetik@flim.org>
Tue, 19 May 2015 17:08:18 +1200
changeset 244482 e7cd988251979d27a012c80fc2747168bb1c87e1
parent 244481 dd1417716d7698bf4bf292715aa82afc04994b3e
child 244483 4fb7ff694bf5944b76c20b2240fb3abdc55f9a4e
child 244610 b48ef53d5d96427c802b669adddf23988379d4a8
push idunknown
push userunknown
push dateunknown
bugs1103824
milestone41.0a1
backs outdd1417716d7698bf4bf292715aa82afc04994b3e
Backed out changeset dd1417716d76 (bug 1103824) for Android issues. CLOSED TREE.
dom/media/CubebUtils.cpp
media/libcubeb/src/cubeb_wasapi.cpp
--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -126,23 +126,16 @@ bool CubebLatencyPrefSet()
 
 void InitLibrary()
 {
   gAudioStreamLog = PR_NewLogModule("AudioStream");
   PrefChanged(PREF_VOLUME_SCALE, nullptr);
   Preferences::RegisterCallback(PrefChanged, PREF_VOLUME_SCALE);
   PrefChanged(PREF_CUBEB_LATENCY, nullptr);
   Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LATENCY);
-
-  // Ensure the first call to cubeb_init is made from the main thread.
-  MOZ_ASSERT(NS_IsMainThread() && !sCubebContext);
-  cubeb * context;
-  if (cubeb_init(&context, "FirstInitContext") == CUBEB_OK) {
-    cubeb_destroy(context);
-  }
 }
 
 void ShutdownLibrary()
 {
   Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE);
   Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY);
 
   StaticMutexAutoLock lock(sMutex);
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -139,27 +139,38 @@ struct auto_lock {
   {
     lock->leave();
   }
 private:
   owned_critical_section * lock;
 };
 
 struct auto_com {
-  auto_com(DWORD dwCoInit = COINIT_MULTITHREADED) {
-    result = CoInitializeEx(NULL, dwCoInit);
+  auto_com() {
+    result = CoInitializeEx(NULL, COINIT_MULTITHREADED);
   }
   ~auto_com() {
-    if (ok()) {
+    if (result == RPC_E_CHANGED_MODE) {
+      // This is not an error, COM was not initialized by this function, so it is
+      // not necessary to uninit it.
+      LOG("COM already initialized in STA.\n");
+    } else if (result == S_FALSE) {
+      // This is not an error. We are allowed to call CoInitializeEx more than
+      // once, as long as it is matches by an CoUninitialize call.
+      // We do that in the dtor which is guaranteed to be called.
+      LOG("COM already initialized in MTA\n");
+    }
+    if (SUCCEEDED(result)) {
       CoUninitialize();
     }
   }
   bool ok() {
-    return SUCCEEDED(result);
+    return result == RPC_E_CHANGED_MODE || SUCCEEDED(result);
   }
+private:
   HRESULT result;
 };
 
 typedef HANDLE (WINAPI *set_mm_thread_characteristics_function)(
                                       const char * TaskName, LPDWORD TaskIndex);
 typedef BOOL (WINAPI *revert_mm_thread_characteristics_function)(HANDLE handle);
 
 extern cubeb_ops const wasapi_ops;
@@ -476,17 +487,16 @@ wasapi_stream_render_loop(LPVOID stream)
   HANDLE wait_array[3] = {stm->shutdown_event, stm->reconfigure_event, stm->refill_event};
   HANDLE mmcss_handle = NULL;
   HRESULT hr = 0;
   bool first = true;
   DWORD mmcss_task_index = 0;
   auto_com com;
   if (!com.ok()) {
     LOG("COM initialization failed on render_loop thread.\n");
-    stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
     return 0;
   }
 
   /* We could consider using "Pro Audio" here for WebAudio and
    * maybe WebRTC. */
   mmcss_handle =
     stm->context->set_mm_thread_characteristics("Audio", &mmcss_task_index);
   if (!mmcss_handle) {
@@ -673,67 +683,37 @@ HRESULT get_default_endpoint(IMMDevice *
     SafeRelease(enumerator);
     return hr;
   }
 
   SafeRelease(enumerator);
 
   return ERROR_SUCCESS;
 }
-
-owned_critical_section g_first_init_lock;
-bool g_first_init = false;
 } // namespace anonymous
 
 extern "C" {
 int wasapi_init(cubeb ** context, char const * context_name)
 {
-  auto_lock lock(&g_first_init_lock);
-  if (!g_first_init) {
-    // Per the MSDN documentation for IAudioClient, the first use *must* be made from an STA thread.
-    auto_com com(COINIT_APARTMENTTHREADED);
-    if (FAILED(com.result)) {
-      return CUBEB_ERROR;
-    }
+  HRESULT hr;
+  auto_com com;
+  if (!com.ok()) {
+    return CUBEB_ERROR;
+  }
 
-    /* We don't use the device yet, but need to make sure we can initialize one
-       so that this backend is not incorrectly enabled on platforms that don't
-       support WASAPI. */
-    IMMDevice * device;
-    HRESULT hr = get_default_endpoint(&device);
-    if (FAILED(hr)) {
-      LOG("Could not get device: %x\n", hr);
-      return CUBEB_ERROR;
-    }
-    IAudioClient * client;
-    hr = device->Activate(__uuidof(IAudioClient),
-                          CLSCTX_INPROC_SERVER,
-                          NULL, (void **)&client);
-    if (SUCCEEDED(hr)) {
-      WAVEFORMATEX * mix_format;
-      hr = client->GetMixFormat(&mix_format);
-      if (SUCCEEDED(hr)) {
-        hr = client->Initialize(AUDCLNT_SHAREMODE_SHARED,
-                                AUDCLNT_STREAMFLAGS_EVENTCALLBACK |
-                                AUDCLNT_STREAMFLAGS_NOPERSIST,
-                                ms_to_hns(100),
-                                0,
-                                mix_format,
-                                NULL);
-        CoTaskMemFree(mix_format);
-        g_first_init = true;
-      }
-      SafeRelease(client);
-    }
-    SafeRelease(device);
-    if (FAILED(hr)) {
-      LOG("Could not initialize IAudioClient: %x\n", hr);
-      return CUBEB_ERROR;
-    }
+  /* We don't use the device yet, but need to make sure we can initialize one
+     so that this backend is not incorrectly enabled on platforms that don't
+     support WASAPI. */
+  IMMDevice * device;
+  hr = get_default_endpoint(&device);
+  if (FAILED(hr)) {
+    LOG("Could not get device.\n");
+    return CUBEB_ERROR;
   }
+  SafeRelease(device);
 
   cubeb * ctx = (cubeb *)calloc(1, sizeof(cubeb));
 
   ctx->ops = &wasapi_ops;
 
   ctx->mmcss_module = LoadLibraryA("Avrt.dll");
 
   if (ctx->mmcss_module) {
@@ -799,18 +779,20 @@ char const * wasapi_get_backend_id(cubeb
 }
 
 int
 wasapi_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
 {
   HRESULT hr;
   IAudioClient * client;
   WAVEFORMATEX * mix_format;
-  XASSERT(g_first_init);
-  auto_com com; /* don't care what COM mode we're in here */
+  auto_com com;
+  if (!com.ok()) {
+    return CUBEB_ERROR;
+  }
 
   XASSERT(ctx && max_channels);
 
   IMMDevice * device;
   hr = get_default_endpoint(&device);
   if (FAILED(hr)) {
     return CUBEB_ERROR;
   }
@@ -838,18 +820,20 @@ wasapi_get_max_channel_count(cubeb * ctx
 }
 
 int
 wasapi_get_min_latency(cubeb * ctx, cubeb_stream_params params, uint32_t * latency_ms)
 {
   HRESULT hr;
   IAudioClient * client;
   REFERENCE_TIME default_period;
-  XASSERT(g_first_init);
-  auto_com com; /* don't care what COM mode we're in here */
+  auto_com com;
+  if (!com.ok()) {
+    return CUBEB_ERROR;
+  }
 
   IMMDevice * device;
   hr = get_default_endpoint(&device);
   if (FAILED(hr)) {
     LOG("Could not get default endpoint:%x.\n", hr);
     return CUBEB_ERROR;
   }
 
@@ -883,18 +867,20 @@ wasapi_get_min_latency(cubeb * ctx, cube
 }
 
 int
 wasapi_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
 {
   HRESULT hr;
   IAudioClient * client;
   WAVEFORMATEX * mix_format;
-  XASSERT(g_first_init);
-  auto_com com; /* don't care what COM mode we're in here */
+  auto_com com;
+  if (!com.ok()) {
+    return CUBEB_ERROR;
+  }
 
   IMMDevice * device;
   hr = get_default_endpoint(&device);
   if (FAILED(hr)) {
     return CUBEB_ERROR;
   }
 
   hr = device->Activate(__uuidof(IAudioClient),