Bug 1266438 - Remove workaround on OSX when switching device, not necessary with duplex mode. r=jesup
authorPaul Adenot <paul@paul.cx>
Fri, 22 Apr 2016 16:24:19 +0200
changeset 332428 099d4414bd63296d586699b6e2b9bae068a4c4eb
parent 332427 5663efa6c13cb03d23f4b840b433fb4e4498611d
child 332429 333ca1faed5a9d1672c26b10d41f5593996325dc
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs1266438
milestone48.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 1266438 - Remove workaround on OSX when switching device, not necessary with duplex mode. r=jesup MozReview-Commit-ID: 7IontuEuiQj
dom/media/GraphDriver.cpp
dom/media/GraphDriver.h
dom/media/MediaStreamGraph.cpp
--- a/dom/media/GraphDriver.cpp
+++ b/dom/media/GraphDriver.cpp
@@ -18,17 +18,17 @@
 #include <sys/sysctl.h>
 #endif
 
 extern mozilla::LazyLogModule gMediaStreamGraphLog;
 #define STREAM_LOG(type, msg) MOZ_LOG(gMediaStreamGraphLog, type, msg)
 
 // We don't use NSPR log here because we want this interleaved with adb logcat
 // on Android/B2G
-#define ENABLE_LIFECYCLE_LOG
+// #define ENABLE_LIFECYCLE_LOG
 #ifdef ENABLE_LIFECYCLE_LOG
 #ifdef ANDROID
 #include "android/log.h"
 #define LIFECYCLE_LOG(...)  __android_log_print(ANDROID_LOG_INFO, "Gecko - MSG" , __VA_ARGS__); printf(__VA_ARGS__);printf("\n");
 #else
 #define LIFECYCLE_LOG(...) printf(__VA_ARGS__);printf("\n");
 #endif
 #else
@@ -83,28 +83,16 @@ void GraphDriver::SetGraphTime(GraphDriv
                                  ? "AudioCallbackDriver"
                                  : "SystemClockDriver"));
   SetPreviousDriver(aPreviousDriver);
 }
 
 void GraphDriver::SwitchAtNextIteration(GraphDriver* aNextDriver)
 {
   GraphImpl()->GetMonitor().AssertCurrentThreadOwns();
-  // This is the situation where `mPreviousDriver` is an AudioCallbackDriver
-  // that is switching device, and the graph has found the current driver is not
-  // an AudioCallbackDriver, but tries to switch to a _new_ AudioCallbackDriver
-  // because it found audio has to be output. In this case, simply ignore the
-  // request to switch, since we know we will switch back to the old
-  // AudioCallbackDriver when it has recovered from the device switching.
-  if (aNextDriver->AsAudioCallbackDriver() &&
-      PreviousDriver() &&
-      PreviousDriver()->AsAudioCallbackDriver()->IsSwitchingDevice() &&
-      PreviousDriver() != aNextDriver) {
-    return;
-  }
   LIFECYCLE_LOG("Switching to new driver: %p (%s)",
       aNextDriver, aNextDriver->AsAudioCallbackDriver() ?
       "AudioCallbackDriver" : "SystemClockDriver");
   if (mNextDriver &&
       mNextDriver != GraphImpl()->CurrentDriver()) {
     LIFECYCLE_LOG("Discarding previous next driver: %p (%s)",
                   mNextDriver.get(), mNextDriver->AsAudioCallbackDriver() ?
                   "AudioCallbackDriver" : "SystemClockDriver");
@@ -195,33 +183,29 @@ public:
       previousDriver = mDriver->PreviousDriver();
     }
     if (previousDriver) {
       LIFECYCLE_LOG("%p releasing an AudioCallbackDriver(%p), for graph %p\n",
                     mDriver,
                     previousDriver,
                     mDriver->GraphImpl());
       MOZ_ASSERT(!mDriver->AsAudioCallbackDriver());
-      // Stop and release the previous driver off-main-thread, but only if we're
-      // not in the situation where we've fallen back to a system clock driver
-      // because the osx audio stack is currently switching output device.
-      if (!previousDriver->AsAudioCallbackDriver()->IsSwitchingDevice()) {
-        RefPtr<AsyncCubebTask> releaseEvent =
-          new AsyncCubebTask(previousDriver->AsAudioCallbackDriver(), AsyncCubebOperation::SHUTDOWN);
-        releaseEvent->Dispatch();
+      RefPtr<AsyncCubebTask> releaseEvent =
+        new AsyncCubebTask(previousDriver->AsAudioCallbackDriver(), AsyncCubebOperation::SHUTDOWN);
+      releaseEvent->Dispatch();
 
-        MonitorAutoLock mon(mDriver->mGraphImpl->GetMonitor());
-        mDriver->SetPreviousDriver(nullptr);
-      }
+      MonitorAutoLock mon(mDriver->mGraphImpl->GetMonitor());
+      mDriver->SetPreviousDriver(nullptr);
     } else {
       MonitorAutoLock mon(mDriver->mGraphImpl->GetMonitor());
       MOZ_ASSERT(mDriver->mGraphImpl->MessagesQueued() ||
                  mDriver->mGraphImpl->mForceShutDown, "Don't start a graph without messages queued.");
       mDriver->mGraphImpl->SwapMessageQueues();
     }
+
     mDriver->RunThread();
     return NS_OK;
   }
 private:
   ThreadedDriver* mDriver;
 };
 
 void
@@ -556,20 +540,17 @@ AudioCallbackDriver::AudioCallbackDriver
   , mSampleRate(0)
   , mInputChannels(1)
   , mIterationDurationMS(MEDIA_GRAPH_TARGET_PERIOD_MS)
   , mStarted(false)
   , mAudioInput(nullptr)
   , mAudioChannel(aGraphImpl->AudioChannel())
   , mAddedMixer(false)
   , mInCallback(false)
-#ifdef XP_MACOSX
   , mMicrophoneActive(false)
-  , mCallbackReceivedWhileSwitching(0)
-#endif
 {
   STREAM_LOG(LogLevel::Debug, ("AudioCallbackDriver ctor for graph %p", aGraphImpl));
 }
 
 AudioCallbackDriver::~AudioCallbackDriver()
 {
   MOZ_ASSERT(mPromisesForOperation.IsEmpty());
 }
@@ -814,69 +795,28 @@ AudioCallbackDriver::AutoInCallback::Aut
 {
   mDriver->mInCallback = true;
 }
 
 AudioCallbackDriver::AutoInCallback::~AutoInCallback() {
   mDriver->mInCallback = false;
 }
 
-#ifdef XP_MACOSX
-bool
-AudioCallbackDriver::OSXDeviceSwitchingWorkaround()
-{
-  MonitorAutoLock mon(GraphImpl()->GetMonitor());
-  if (mSelfReference) {
-    // Apparently, depending on the osx version, on device switch, the
-    // callback is called "some" number of times, and then stops being called,
-    // and then gets called again. 10 is to be safe, it's a low-enough number
-    // of milliseconds anyways (< 100ms)
-    //STREAM_LOG(LogLevel::Debug, ("Callbacks during switch: %d", mCallbackReceivedWhileSwitching+1));
-    if (mCallbackReceivedWhileSwitching++ >= 10) {
-      STREAM_LOG(LogLevel::Debug, ("Got %d callbacks, switching back to CallbackDriver", mCallbackReceivedWhileSwitching));
-      // If we have a self reference, we have fallen back temporarily on a
-      // system clock driver, but we just got called back, that means the osx
-      // audio backend has switched to the new device.
-      // Ask the graph to switch back to the previous AudioCallbackDriver
-      // (`this`), and when the graph has effectively switched, we can drop
-      // the self reference and unref the SystemClockDriver we fallen back on.
-      if (GraphImpl()->CurrentDriver() == this) {
-        mSelfReference.Drop(this);
-        SetNextDriver(nullptr);
-      } else {
-        GraphImpl()->CurrentDriver()->SwitchAtNextIteration(this);
-      }
-
-    }
-    return true;
-  }
-
-  return false;
-}
-#endif // XP_MACOSX
-
 long
 AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer,
                                   AudioDataValue* aOutputBuffer, long aFrames)
 {
   bool stillProcessing;
 
   // Don't add the callback until we're inited and ready
   if (!mAddedMixer) {
     mGraphImpl->mMixer.AddCallback(this);
     mAddedMixer = true;
   }
 
-#ifdef XP_MACOSX
-  if (OSXDeviceSwitchingWorkaround()) {
-    PodZero(aOutputBuffer, aFrames * mGraphImpl->AudioChannelCount());
-    return aFrames;
-  }
-#endif
-
 #ifdef DEBUG
   // DebugOnly<> doesn't work here... it forces an initialization that will cause
   // mInCallback to be set back to false before we exit the statement.  Do it by
   // hand instead.
   AutoInCallback aic(this);
 #endif
 
   GraphTime stateComputedTime = StateComputedTime();
@@ -1076,21 +1016,21 @@ AudioCallbackDriver::DeviceChangedCallba
 #ifdef XP_MACOSX
   PanOutputIfNeeded(mMicrophoneActive);
 #endif
 }
 
 void
 AudioCallbackDriver::SetMicrophoneActive(bool aActive)
 {
-#ifdef XP_MACOSX
   MonitorAutoLock mon(mGraphImpl->GetMonitor());
 
   mMicrophoneActive = aActive;
 
+#ifdef XP_MACOSX
   PanOutputIfNeeded(mMicrophoneActive);
 #endif
 }
 
 uint32_t
 AudioCallbackDriver::IterationDuration()
 {
   // The real fix would be to have an API in cubeb to give us the number. Short
--- a/dom/media/GraphDriver.h
+++ b/dom/media/GraphDriver.h
@@ -425,24 +425,16 @@ public:
   }
 
   /* Enqueue a promise that is going to be resolved when a specific operation
    * occurs on the cubeb stream. */
   void EnqueueStreamAndPromiseForOperation(MediaStream* aStream,
                                          void* aPromise,
                                          dom::AudioContextOperation aOperation);
 
-  bool IsSwitchingDevice() {
-#ifdef XP_MACOSX
-    return mSelfReference;
-#else
-    return false;
-#endif
-  }
-
   /**
    * Whether the audio callback is processing. This is for asserting only.
    */
   bool InCallback();
 
   bool OnThread() override { return !mStarted || InCallback(); }
 
   /* Whether the underlying cubeb stream has been started. See comment for
@@ -529,30 +521,16 @@ private:
 
   /* This is atomic and is set by the audio callback thread. It can be read by
    * any thread safely. */
   Atomic<bool> mInCallback;
   /**
    * True if microphone is being used by this process. This is synchronized by
    * the graph's monitor. */
   bool mMicrophoneActive;
-
-
-#ifdef XP_MACOSX
-
-  /* Implements the workaround for the osx audio stack when changing output
-   * devices. See comments in .cpp */
-  bool OSXDeviceSwitchingWorkaround();
-  /* Self-reference that keep this driver alive when switching output audio
-   * device and making the graph running temporarily off a SystemClockDriver.  */
-  SelfReference<AudioCallbackDriver> mSelfReference;
-  /* While switching devices, we keep track of the number of callbacks received,
-   * since OSX seems to still call us _sometimes_. */
-  uint32_t mCallbackReceivedWhileSwitching;
-#endif
 };
 
 class AsyncCubebTask : public nsRunnable
 {
 public:
 
   AsyncCubebTask(AudioCallbackDriver* aDriver, AsyncCubebOperation aOperation);
 
--- a/dom/media/MediaStreamGraph.cpp
+++ b/dom/media/MediaStreamGraph.cpp
@@ -41,17 +41,17 @@ using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::media;
 
 namespace mozilla {
 
 LazyLogModule gMediaStreamGraphLog("MediaStreamGraph");
 #define STREAM_LOG(type, msg) MOZ_LOG(gMediaStreamGraphLog, type, msg)
 
-#define ENABLE_LIFECYCLE_LOG
+// #define ENABLE_LIFECYCLE_LOG
 
 // We don't use NSPR log here because we want this interleaved with adb logcat
 // on Android/B2G
 #ifdef ENABLE_LIFECYCLE_LOG
 #  ifdef ANDROID
 #    include "android/log.h"
 #    define LIFECYCLE_LOG(...)  __android_log_print(ANDROID_LOG_INFO, "Gecko - MSG", ## __VA_ARGS__); printf(__VA_ARGS__);printf("\n");
 #  else