Bug 1103824 - Back out changeset for causing regression reported in bug 1176499.
authorMatthew Gregan <kinetik@flim.org>
Tue, 23 Jun 2015 17:02:51 -0700
changeset 250057 b10c59539ec8b9ac1b1c9346f2fdc29330bbfd6e
parent 250056 d854bedb4980b39fa86d9b6add80475fdf4edc62
child 250058 4f4ceae7be1a481e0df0f53a7e87c34d33561bf5
push idunknown
push userunknown
push dateunknown
bugs1103824, 1176499
milestone41.0a1
Bug 1103824 - Back out changeset for causing regression reported in bug 1176499.
dom/media/CubebUtils.cpp
dom/media/MediaDecoder.cpp
dom/media/webaudio/AudioContext.cpp
media/libcubeb/src/cubeb_wasapi.cpp
--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -99,23 +99,22 @@ void InitPreferredSampleRate()
     // Query failed, use a sensible default.
     sPreferredSampleRate = 44100;
   }
 }
 
 cubeb* GetCubebContextUnlocked()
 {
   sMutex.AssertCurrentThreadOwns();
-  if (!sCubebContext) {
-    MOZ_ASSERT(NS_IsMainThread());
-    if (cubeb_init(&sCubebContext, "CubebUtils") != CUBEB_OK) {
-      NS_WARNING("cubeb_init failed");
-    }
+  if (sCubebContext ||
+      cubeb_init(&sCubebContext, "CubebUtils") == CUBEB_OK) {
+    return sCubebContext;
   }
-  return sCubebContext;
+  NS_WARNING("cubeb_init failed");
+  return nullptr;
 }
 
 uint32_t GetCubebLatency()
 {
   StaticMutexAutoLock lock(sMutex);
   return sCubebLatency;
 }
 
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaDecoder.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/MathAlgorithms.h"
 #include <limits>
 #include "nsIObserver.h"
 #include "nsTArray.h"
-#include "CubebUtils.h"
 #include "VideoUtils.h"
 #include "MediaDecoderStateMachine.h"
 #include "ImageContainer.h"
 #include "MediaResource.h"
 #include "nsError.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPtr.h"
 #include "nsIMemoryReporter.h"
@@ -397,21 +396,16 @@ MediaDecoder::MediaDecoder() :
 }
 
 bool MediaDecoder::Init(MediaDecoderOwner* aOwner)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mOwner = aOwner;
   mVideoFrameContainer = aOwner->GetVideoFrameContainer();
   MediaShutdownManager::Instance().Register(this);
-  // We don't use the cubeb context yet, but need to ensure it is created on
-  // the main thread.
-  if (!CubebUtils::GetCubebContext()) {
-    NS_WARNING("Audio backend initialization failed.");
-  }
   return true;
 }
 
 void MediaDecoder::Shutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mShuttingDown)
--- a/dom/media/webaudio/AudioContext.cpp
+++ b/dom/media/webaudio/AudioContext.cpp
@@ -105,21 +105,16 @@ AudioContext::AudioContext(nsPIDOMWindow
   // bound to the window.
   mDestination = new AudioDestinationNode(this, aIsOffline, aChannel,
                                           aNumberOfChannels, aLength, aSampleRate);
   // We skip calling SetIsOnlyNodeForContext and the creation of the
   // audioChannelAgent during mDestination's constructor, because we can only
   // call them after mDestination has been set up.
   mDestination->CreateAudioChannelAgent();
   mDestination->SetIsOnlyNodeForContext(true);
-  // We don't use the cubeb context yet, but need to ensure it is created on
-  // the main thread.
-  if (!aIsOffline && !CubebUtils::GetCubebContext()) {
-    NS_WARNING("Audio backend initialization failed.");
-  }
 }
 
 AudioContext::~AudioContext()
 {
   nsPIDOMWindow* window = GetOwner();
   if (window) {
     window->RemoveAudioContext(this);
   }
--- 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),