Bug 1286096 - Consider competing audio constraints as well. r=padenot
authorJan-Ivar Bruaroey <jib@mozilla.com>
Fri, 15 Jul 2016 19:55:59 -0400
changeset 332119 274a3c105eb5925b05251990c519f78b6d46f436
parent 332118 e3354c94965925a82cf4c2d56c20aa07ad79bd99
child 332120 26085bd0d4289dd674d2da6cb52ec6a8fe37eef6
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs1286096
milestone50.0a1
Bug 1286096 - Consider competing audio constraints as well. r=padenot MozReview-Commit-ID: APPg2UBgNYo
dom/media/webrtc/MediaEngine.h
dom/media/webrtc/MediaEngineWebRTC.h
dom/media/webrtc/MediaEngineWebRTCAudio.cpp
--- a/dom/media/webrtc/MediaEngine.h
+++ b/dom/media/webrtc/MediaEngine.h
@@ -311,16 +311,17 @@ public:
   /* This call reserves but does not start the device. */
   virtual nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
                             const MediaEnginePrefs &aPrefs,
                             const nsString& aDeviceId,
                             const nsACString& aOrigin,
                             AllocationHandle** aOutHandle,
                             const char** aOutBadConstraint)
   {
+    AssertIsOnOwningThread();
     MOZ_ASSERT(aOutHandle);
     RefPtr<AllocationHandle> handle = new AllocationHandle(aConstraints, aOrigin,
                                                            aPrefs, aDeviceId);
     nsresult rv = ReevaluateAllocation(handle, nullptr, aPrefs, aDeviceId,
                                        aOutBadConstraint);
     if (NS_FAILED(rv)) {
       return rv;
     }
--- a/dom/media/webrtc/MediaEngineWebRTC.h
+++ b/dom/media/webrtc/MediaEngineWebRTC.h
@@ -427,17 +427,16 @@ public:
                                     const char* uuid)
     : MediaEngineAudioSource(kReleased)
     , mVoiceEngine(aVoiceEnginePtr)
     , mAudioInput(aAudioInput)
     , mMonitor("WebRTCMic.Monitor")
     , mThread(aThread)
     , mCapIndex(aIndex)
     , mChannel(-1)
-    , mNrAllocations(0)
     , mStarted(false)
     , mSampleFrequency(MediaEngine::DEFAULT_SAMPLE_RATE)
     , mPlayoutDelay(0)
     , mNullTransport(nullptr)
     , mSkipProcessing(false)
   {
     MOZ_ASSERT(aVoiceEnginePtr);
     MOZ_ASSERT(aAudioInput);
@@ -445,22 +444,16 @@ public:
     mDeviceUUID.Assign(uuid);
     mListener = new mozilla::WebRTCAudioDataListener(this);
     // We'll init lazily as needed
   }
 
   void GetName(nsAString& aName) const override;
   void GetUUID(nsACString& aUUID) const override;
 
-  nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
-                    const MediaEnginePrefs& aPrefs,
-                    const nsString& aDeviceId,
-                    const nsACString& aOrigin,
-                    AllocationHandle** aOutHandle,
-                    const char** aOutBadConstraint) override;
   nsresult Deallocate(AllocationHandle* aHandle) override;
   nsresult Start(SourceMediaStream* aStream,
                  TrackID aID,
                  const PrincipalHandle& aPrincipalHandle) override;
   nsresult Stop(SourceMediaStream* aSource, TrackID aID) override;
   nsresult Restart(AllocationHandle* aHandle,
                    const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
@@ -509,16 +502,23 @@ public:
   void Shutdown() override;
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
 protected:
   ~MediaEngineWebRTCMicrophoneSource() {}
 
 private:
+  nsresult
+  UpdateSingleSource(const AllocationHandle* aHandle,
+                     const NormalizedConstraints& aNetConstraints,
+                     const MediaEnginePrefs& aPrefs,
+                     const nsString& aDeviceId,
+                     const char** aOutBadConstraint) override;
+
   // These allocate/configure and release the channel
   bool AllocChannel();
   void FreeChannel();
   // These start/stop VoEBase and associated interfaces
   bool InitEngine();
   void DeInitEngine();
 
   // This is true when all processing is disabled, we can skip
@@ -559,17 +559,16 @@ private:
   // threads.
   Monitor mMonitor;
   nsTArray<RefPtr<SourceMediaStream>> mSources;
   nsTArray<PrincipalHandle> mPrincipalHandles; // Maps to mSources.
 
   nsCOMPtr<nsIThread> mThread;
   int mCapIndex;
   int mChannel;
-  int mNrAllocations; // Per-channel - When this becomes 0, we shut down HW for the channel
   TrackID mTrackID;
   bool mStarted;
 
   nsString mDeviceName;
   nsCString mDeviceUUID;
 
   int32_t mSampleFrequency;
   int32_t mPlayoutDelay;
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -214,83 +214,96 @@ uint32_t MediaEngineWebRTCMicrophoneSour
   for (const auto* cs : aConstraintSets) {
     distance = GetMinimumFitnessDistance(*cs, aDeviceId);
     break; // distance is read from first entry only
   }
   return distance;
 }
 
 nsresult
-MediaEngineWebRTCMicrophoneSource::Allocate(const dom::MediaTrackConstraints &aConstraints,
-                                            const MediaEnginePrefs &aPrefs,
-                                            const nsString& aDeviceId,
-                                            const nsACString& aOrigin,
-                                            AllocationHandle** aOutHandle,
-                                            const char** aOutBadConstraint)
-{
-  AssertIsOnOwningThread();
-  if (mState == kReleased) {
-    if (sChannelsOpen == 0) {
-      if (!InitEngine()) {
-        LOG(("Audio engine is not initalized"));
-        return NS_ERROR_FAILURE;
-      }
-    }
-    if (!AllocChannel()) {
-      if (sChannelsOpen == 0) {
-        DeInitEngine();
-      }
-      LOG(("Audio device is not initalized"));
-      return NS_ERROR_FAILURE;
-    }
-    if (mAudioInput->SetRecordingDevice(mCapIndex)) {
-      FreeChannel();
-      if (sChannelsOpen == 0) {
-        DeInitEngine();
-      }
-      return NS_ERROR_FAILURE;
-    }
-    sChannelsOpen++;
-    mState = kAllocated;
-    LOG(("Audio device %d allocated", mCapIndex));
-  } else if (MOZ_LOG_TEST(GetMediaManagerLog(), LogLevel::Debug)) {
-    MonitorAutoLock lock(mMonitor);
-    if (mSources.IsEmpty()) {
-      LOG(("Audio device %d reallocated", mCapIndex));
-    } else {
-      LOG(("Audio device %d allocated shared", mCapIndex));
-    }
-  }
-  ++mNrAllocations;
-  aOutHandle = nullptr;
-  return Restart(nullptr, aConstraints, aPrefs, aDeviceId, aOutBadConstraint);
-}
-
-nsresult
 MediaEngineWebRTCMicrophoneSource::Restart(AllocationHandle* aHandle,
                                            const dom::MediaTrackConstraints& aConstraints,
                                            const MediaEnginePrefs &aPrefs,
                                            const nsString& aDeviceId,
                                            const char** aOutBadConstraint)
 {
-  MOZ_ASSERT(!aHandle);
-  FlattenedConstraints c(aConstraints);
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(aHandle);
+  NormalizedConstraints constraints(aConstraints);
+  return ReevaluateAllocation(aHandle, &constraints, aPrefs, aDeviceId,
+                              aOutBadConstraint);
+}
+
+nsresult
+MediaEngineWebRTCMicrophoneSource::UpdateSingleSource(
+    const AllocationHandle* aHandle,
+    const NormalizedConstraints& aNetConstraints,
+    const MediaEnginePrefs& aPrefs,
+    const nsString& aDeviceId,
+    const char** aOutBadConstraint)
+{
+  FlattenedConstraints c(aNetConstraints);
 
   bool aec_on = c.mEchoCancellation.Get(aPrefs.mAecOn);
   bool agc_on = c.mMozAutoGainControl.Get(aPrefs.mAgcOn);
   bool noise_on = c.mMozNoiseSuppression.Get(aPrefs.mNoiseOn);
 
   LOG(("Audio config: aec: %d, agc: %d, noise: %d, delay: %d",
        aec_on ? aPrefs.mAec : -1,
        agc_on ? aPrefs.mAgc : -1,
        noise_on ? aPrefs.mNoise : -1,
        aPrefs.mPlayoutDelay));
 
   mPlayoutDelay = aPrefs.mPlayoutDelay;
 
+  switch (mState) {
+    case kReleased:
+      MOZ_ASSERT(aHandle);
+      if (sChannelsOpen == 0) {
+        if (!InitEngine()) {
+          LOG(("Audio engine is not initalized"));
+          return NS_ERROR_FAILURE;
+        }
+      }
+      if (!AllocChannel()) {
+        if (sChannelsOpen == 0) {
+          DeInitEngine();
+        }
+        LOG(("Audio device is not initalized"));
+        return NS_ERROR_FAILURE;
+      }
+      if (mAudioInput->SetRecordingDevice(mCapIndex)) {
+        FreeChannel();
+        if (sChannelsOpen == 0) {
+          DeInitEngine();
+        }
+        return NS_ERROR_FAILURE;
+      }
+      sChannelsOpen++;
+      mState = kAllocated;
+      LOG(("Audio device %d allocated", mCapIndex));
+      break;
+
+    case kStarted:
+      if (MOZ_LOG_TEST(GetMediaManagerLog(), LogLevel::Debug)) {
+        MonitorAutoLock lock(mMonitor);
+        if (mSources.IsEmpty()) {
+          LOG(("Audio device %d reallocated", mCapIndex));
+        } else {
+          LOG(("Audio device %d allocated shared", mCapIndex));
+        }
+      }
+      break;
+
+    default:
+      LOG(("Audio device %d %s in ignored state %d", mCapIndex,
+           (aHandle? aHandle->mOrigin.get() : ""), mState));
+      break;
+  }
+
   if (sChannelsOpen > 0) {
     int error;
 
     if (0 != (error = mVoEProcessing->SetEcStatus(aec_on, (webrtc::EcModes) aPrefs.mAec))) {
       LOG(("%s Error setting Echo Status: %d ",__FUNCTION__, error));
       // Overhead of capturing all the time is very low (<0.1% of an audio only call)
       if (aec_on) {
         if (0 != (error = mVoEProcessing->SetEcMetricsStatus(true))) {
@@ -305,28 +318,27 @@ MediaEngineWebRTCMicrophoneSource::Resta
       LOG(("%s Error setting NoiseSuppression Status: %d ",__FUNCTION__, error));
     }
   }
 
   mSkipProcessing = !(aec_on || agc_on || noise_on);
   if (mSkipProcessing) {
     mSampleFrequency = MediaEngine::USE_GRAPH_RATE;
   }
-
   return NS_OK;
 }
 
 nsresult
 MediaEngineWebRTCMicrophoneSource::Deallocate(AllocationHandle* aHandle)
 {
   AssertIsOnOwningThread();
-  MOZ_ASSERT(!aHandle);
-  --mNrAllocations;
-  MOZ_ASSERT(mNrAllocations >= 0, "Double-deallocations are prohibited");
-  if (mNrAllocations == 0) {
+
+  Super::Deallocate(aHandle);
+
+  if (!mRegisteredHandles.Length()) {
     // If empty, no callbacks to deliver data should be occuring
     if (mState != kStopped && mState != kAllocated) {
       return NS_ERROR_FAILURE;
     }
 
     FreeChannel();
     mState = kReleased;
     LOG(("Audio device %d deallocated", mCapIndex));
@@ -735,17 +747,17 @@ MediaEngineWebRTCMicrophoneSource::Shutd
         }
         source = mSources[0];
       }
       Stop(source, kAudioTrack); // XXX change to support multiple tracks
     }
     MOZ_ASSERT(mState == kStopped);
   }
 
-  while (mNrAllocations) {
+  while (mRegisteredHandles.Length()) {
     MOZ_ASSERT(mState == kAllocated || mState == kStopped);
     Deallocate(nullptr); // XXX Extend concurrent constraints code to mics.
   }
 
   FreeChannel();
   DeInitEngine();
 
   mAudioInput = nullptr;