Bug 944707 - Stop locking when getting the preferred samplerate from the AudioStream. r=kinetik
authorPaul Adenot <paul@paul.cx>
Mon, 09 Dec 2013 20:54:49 +0100
changeset 160241 bc103864507b1eb7172e7abc94a74116d123fc0f
parent 160240 421def41b67092b672d5fd7316edb2c807753669
child 160242 55e6046395260e2cf449a7c628bea2a482972cb5
push id25827
push userkwierso@gmail.com
push dateFri, 13 Dec 2013 03:13:04 +0000
treeherdermozilla-central@1bc33fa19b24 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs944707
milestone29.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 944707 - Stop locking when getting the preferred samplerate from the AudioStream. r=kinetik
content/media/AudioStream.cpp
content/media/AudioStream.h
content/media/MediaStreamGraph.cpp
content/media/MediaStreamGraphImpl.h
content/media/webaudio/AudioContext.cpp
--- a/content/media/AudioStream.cpp
+++ b/content/media/AudioStream.cpp
@@ -71,16 +71,25 @@ bool AudioStream::sCubebLatencyPrefSet;
 }
 
 /*static*/ cubeb* AudioStream::GetCubebContext()
 {
   StaticMutexAutoLock lock(sMutex);
   return GetCubebContextUnlocked();
 }
 
+/*static*/ void AudioStream::InitPreferredSampleRate()
+{
+  StaticMutexAutoLock lock(sMutex);
+  if (sPreferredSampleRate != 0 ||
+      cubeb_get_preferred_sample_rate(GetCubebContextUnlocked(), &sPreferredSampleRate) != CUBEB_OK) {
+    sPreferredSampleRate = 44100;
+  }
+}
+
 /*static*/ cubeb* AudioStream::GetCubebContextUnlocked()
 {
   sMutex.AssertCurrentThreadOwns();
   if (sCubebContext ||
       cubeb_init(&sCubebContext, "AudioStream") == CUBEB_OK) {
     return sCubebContext;
   }
   NS_WARNING("cubeb_init failed");
@@ -261,35 +270,18 @@ int64_t AudioStream::GetWritten()
     return static_cast<int>(maxNumberOfChannels);
   }
 
   return 0;
 }
 
 /*static*/ int AudioStream::PreferredSampleRate()
 {
-  const int fallbackSampleRate = 44100;
-  StaticMutexAutoLock lock(sMutex);
-  if (sPreferredSampleRate != 0) {
-    return sPreferredSampleRate;
-  }
-
-  cubeb* cubebContext = GetCubebContextUnlocked();
-  if (!cubebContext) {
-    sPreferredSampleRate = fallbackSampleRate;
-  }
-  // Get the preferred samplerate for this platform, or fallback to something
-  // sensible if we fail. We cache the value, because this might be accessed
-  // often, and the complexity of the function call below depends on the
-  // backend used.
-  if (cubeb_get_preferred_sample_rate(cubebContext,
-                                      &sPreferredSampleRate) != CUBEB_OK) {
-    sPreferredSampleRate = fallbackSampleRate;
-  }
-
+  MOZ_ASSERT(sPreferredSampleRate,
+             "sPreferredSampleRate has not been initialized!");
   return sPreferredSampleRate;
 }
 
 static void SetUint16LE(uint8_t* aDest, uint16_t aValue)
 {
   aDest[0] = aValue & 0xFF;
   aDest[1] = aValue >> 8;
 }
--- a/content/media/AudioStream.h
+++ b/content/media/AudioStream.h
@@ -174,18 +174,21 @@ public:
 
   // Shutdown Audio Library. Some Audio backends require shutting down the
   // library after using it.
   static void ShutdownLibrary();
 
   // Returns the maximum number of channels supported by the audio hardware.
   static int MaxNumberOfChannels();
 
-  // Returns the samplerate the systems prefer, because it is the
-  // samplerate the hardware/mixer supports.
+  // Queries the samplerate the hardware/mixer runs at, and stores it.
+  // Can be called on any thread. When this returns, it is safe to call
+  // PreferredSampleRate without locking.
+  static void InitPreferredSampleRate();
+  // Get the aformentionned sample rate. Does not lock.
   static int PreferredSampleRate();
 
   AudioStream();
   ~AudioStream();
 
   enum LatencyRequest {
     HighLatency,
     LowLatency
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -1323,28 +1323,35 @@ MediaStreamGraphImpl::ForceShutDown()
   STREAM_LOG(PR_LOG_DEBUG, ("MediaStreamGraph %p ForceShutdown", this));
   {
     MonitorAutoLock lock(mMonitor);
     mForceShutDown = true;
     EnsureImmediateWakeUpLocked(lock);
   }
 }
 
+void
+MediaStreamGraphImpl::Init()
+{
+  AudioStream::InitPreferredSampleRate();
+}
+
 namespace {
 
 class MediaStreamGraphInitThreadRunnable : public nsRunnable {
 public:
   explicit MediaStreamGraphInitThreadRunnable(MediaStreamGraphImpl* aGraph)
     : mGraph(aGraph)
   {
   }
   NS_IMETHOD Run()
   {
     char aLocal;
     profiler_register_thread("MediaStreamGraph", &aLocal);
+    mGraph->Init();
     mGraph->RunThread();
     return NS_OK;
   }
 private:
   MediaStreamGraphImpl* mGraph;
 };
 
 class MediaStreamGraphThreadRunnable : public nsRunnable {
--- a/content/media/MediaStreamGraphImpl.h
+++ b/content/media/MediaStreamGraphImpl.h
@@ -145,16 +145,20 @@ public:
    * This is called during application shutdown.
    */
   void ForceShutDown();
   /**
    * Shutdown() this MediaStreamGraph's threads and return when they've shut down.
    */
   void ShutdownThreads();
 
+  /**
+   * Called before the thread runs.
+   */
+  void Init();
   // The following methods run on the graph thread (or possibly the main thread if
   // mLifecycleState > LIFECYCLE_RUNNING)
   /**
    * Runs main control loop on the graph thread. Normally a single invocation
    * of this runs for the entire lifetime of the graph thread.
    */
   void RunThread();
   /**
--- a/content/media/webaudio/AudioContext.cpp
+++ b/content/media/webaudio/AudioContext.cpp
@@ -29,16 +29,17 @@
 #include "ChannelMergerNode.h"
 #include "ChannelSplitterNode.h"
 #include "MediaStreamAudioDestinationNode.h"
 #include "WaveShaperNode.h"
 #include "PeriodicWave.h"
 #include "ConvolverNode.h"
 #include "OscillatorNode.h"
 #include "nsNetUtil.h"
+#include "AudioStream.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(AudioContext)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDestination)
@@ -60,22 +61,32 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(AudioContext, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(AudioContext, nsDOMEventTargetHelper)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioContext)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 static uint8_t gWebAudioOutputKey;
 
+float GetSampleRateForAudioContext(bool aIsOffline, float aSampleRate)
+{
+  if (aIsOffline) {
+    return aSampleRate;
+  } else {
+    AudioStream::InitPreferredSampleRate();
+    return static_cast<float>(AudioStream::PreferredSampleRate());
+  }
+}
+
 AudioContext::AudioContext(nsPIDOMWindow* aWindow,
                            bool aIsOffline,
                            uint32_t aNumberOfChannels,
                            uint32_t aLength,
                            float aSampleRate)
-  : mSampleRate(aIsOffline ? aSampleRate : IdealAudioRate())
+  : mSampleRate(GetSampleRateForAudioContext(aIsOffline, aSampleRate))
   , mNumberOfChannels(aNumberOfChannels)
   , mIsOffline(aIsOffline)
   , mIsStarted(!aIsOffline)
   , mIsShutDown(false)
 {
   nsDOMEventTargetHelper::BindToOwner(aWindow);
   aWindow->AddAudioContext(this);
   SetIsDOMBinding();