Bug 1303419: Audio gUM allocate/free improvements and nullptr crash fix r=drno
authorRandell Jesup <rjesup@jesup.org>
Sat, 17 Sep 2016 04:13:00 -0400
changeset 342854 fbdc035f911fa847084af3772dfcceddaf68927a
parent 342853 a96d20959be2116edb706aa26a205439d912a0d7
child 342855 752f33561e8f624642291842f8963efa9e9290d5
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-esr52@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdrno
bugs1303419
milestone51.0a1
Bug 1303419: Audio gUM allocate/free improvements and nullptr crash fix r=drno
dom/media/webrtc/MediaEngineWebRTCAudio.cpp
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -295,31 +295,23 @@ MediaEngineWebRTCMicrophoneSource::Updat
       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 (prefs == mLastPrefs) {
         return NS_OK;
       }
       if (MOZ_LOG_TEST(GetMediaManagerLog(), LogLevel::Debug)) {
@@ -396,22 +388,17 @@ MediaEngineWebRTCMicrophoneSource::Deall
 
   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));
-    MOZ_ASSERT(sChannelsOpen > 0);
-    if (--sChannelsOpen == 0) {
-      DeInitEngine();
-    }
   } else {
     LOG(("Audio device %d deallocated but still in use", mCapIndex));
   }
   return NS_OK;
 }
 
 nsresult
 MediaEngineWebRTCMicrophoneSource::Start(SourceMediaStream *aStream,
@@ -677,81 +664,27 @@ bool
 MediaEngineWebRTCMicrophoneSource::InitEngine()
 {
   MOZ_ASSERT(!mVoEBase);
   mVoEBase = webrtc::VoEBase::GetInterface(mVoiceEngine);
 
   mVoEBase->Init();
 
   mVoERender = webrtc::VoEExternalMedia::GetInterface(mVoiceEngine);
-  if (!mVoERender) {
-    return false;
-  }
-  mVoENetwork = webrtc::VoENetwork::GetInterface(mVoiceEngine);
-  if (!mVoENetwork) {
-    return false;
-  }
-
-  mVoEProcessing = webrtc::VoEAudioProcessing::GetInterface(mVoiceEngine);
-  if (!mVoEProcessing) {
-    return false;
-  }
-  mNullTransport = new NullTransport();
-  return true;
-}
-
-bool
-MediaEngineWebRTCMicrophoneSource::AllocChannel()
-{
-  MOZ_ASSERT(mVoEBase);
-
-  mChannel = mVoEBase->CreateChannel();
-  if (mChannel < 0) {
-    return false;
-  }
-  if (mVoENetwork->RegisterExternalTransport(mChannel, *mNullTransport)) {
-    return false;
+  if (mVoERender) {
+    mVoENetwork = webrtc::VoENetwork::GetInterface(mVoiceEngine);
+    if (mVoENetwork) {
+      mVoEProcessing = webrtc::VoEAudioProcessing::GetInterface(mVoiceEngine);
+      if (mVoEProcessing) {
+        mNullTransport = new NullTransport();
+        return true;
+      }
+    }
   }
-
-  mSampleFrequency = MediaEngine::DEFAULT_SAMPLE_RATE;
-  LOG(("%s: sampling rate %u", __FUNCTION__, mSampleFrequency));
-
-  // Check for availability.
-  if (mAudioInput->SetRecordingDevice(mCapIndex)) {
-    return false;
-  }
-
-#ifndef MOZ_B2G
-  // Because of the permission mechanism of B2G, we need to skip the status
-  // check here.
-  bool avail = false;
-  mAudioInput->GetRecordingDeviceStatus(avail);
-  if (!avail) {
-    return false;
-  }
-#endif // MOZ_B2G
-
-  // Set "codec" to PCM, 32kHz on 1 channel
-  ScopedCustomReleasePtr<webrtc::VoECodec> ptrVoECodec(webrtc::VoECodec::GetInterface(mVoiceEngine));
-  if (!ptrVoECodec) {
-    return false;
-  }
-
-  webrtc::CodecInst codec;
-  strcpy(codec.plname, ENCODING);
-  codec.channels = CHANNELS;
-  MOZ_ASSERT(mSampleFrequency == 16000 || mSampleFrequency == 32000);
-  codec.rate = SAMPLE_RATE(mSampleFrequency);
-  codec.plfreq = mSampleFrequency;
-  codec.pacsize = SAMPLE_LENGTH(mSampleFrequency);
-  codec.pltype = 0; // Default payload type
-
-  if (!ptrVoECodec->SetSendCodec(mChannel, codec)) {
-    return true;
-  }
+  DeInitEngine();
   return false;
 }
 
 // This shuts down the engine when no channel is open
 void
 MediaEngineWebRTCMicrophoneSource::DeInitEngine()
 {
   if (mVoEBase) {
@@ -761,28 +694,94 @@ MediaEngineWebRTCMicrophoneSource::DeIni
 
     mVoEProcessing = nullptr;
     mVoENetwork = nullptr;
     mVoERender = nullptr;
     mVoEBase = nullptr;
   }
 }
 
-// This shuts down the engine when no channel is open
+// This shuts down the engine when no channel is open.
+// mState records if a channel is allocated (slightly redundantly to mChannel)
 void
 MediaEngineWebRTCMicrophoneSource::FreeChannel()
 {
-  if (mChannel != -1) {
-    if (mVoENetwork) {
-      mVoENetwork->DeRegisterExternalTransport(mChannel);
+  if (mState != kReleased) {
+    if (mChannel != -1) {
+      MOZ_ASSERT(mVoENetwork && mVoEBase);
+      if (mVoENetwork) {
+        mVoENetwork->DeRegisterExternalTransport(mChannel);
+      }
+      if (mVoEBase) {
+        mVoEBase->DeleteChannel(mChannel);
+      }
+      mChannel = -1;
+    }
+    mState = kReleased;
+
+    MOZ_ASSERT(sChannelsOpen > 0);
+    if (--sChannelsOpen == 0) {
+      DeInitEngine();
     }
-    mVoEBase->DeleteChannel(mChannel);
-    mChannel = -1;
   }
-  mState = kReleased;
+}
+
+bool
+MediaEngineWebRTCMicrophoneSource::AllocChannel()
+{
+  MOZ_ASSERT(mVoEBase);
+
+  mChannel = mVoEBase->CreateChannel();
+  if (mChannel >= 0) {
+    if (!mVoENetwork->RegisterExternalTransport(mChannel, *mNullTransport)) {
+      mSampleFrequency = MediaEngine::DEFAULT_SAMPLE_RATE;
+      LOG(("%s: sampling rate %u", __FUNCTION__, mSampleFrequency));
+
+      // Check for availability.
+      if (!mAudioInput->SetRecordingDevice(mCapIndex)) {
+#ifndef MOZ_B2G
+        // Because of the permission mechanism of B2G, we need to skip the status
+        // check here.
+        bool avail = false;
+        mAudioInput->GetRecordingDeviceStatus(avail);
+        if (!avail) {
+          if (sChannelsOpen == 0) {
+            DeInitEngine();
+          }
+          return false;
+        }
+#endif // MOZ_B2G
+
+        // Set "codec" to PCM, 32kHz on 1 channel
+        ScopedCustomReleasePtr<webrtc::VoECodec> ptrVoECodec(webrtc::VoECodec::GetInterface(mVoiceEngine));
+        if (ptrVoECodec) {
+          webrtc::CodecInst codec;
+          strcpy(codec.plname, ENCODING);
+          codec.channels = CHANNELS;
+          MOZ_ASSERT(mSampleFrequency == 16000 || mSampleFrequency == 32000);
+          codec.rate = SAMPLE_RATE(mSampleFrequency);
+          codec.plfreq = mSampleFrequency;
+          codec.pacsize = SAMPLE_LENGTH(mSampleFrequency);
+          codec.pltype = 0; // Default payload type
+
+          if (!ptrVoECodec->SetSendCodec(mChannel, codec)) {
+            mState = kAllocated;
+            sChannelsOpen++;
+            return true;
+          }
+        }
+      }
+    }
+  }
+  mVoEBase->DeleteChannel(mChannel);
+  mChannel = -1;
+  if (sChannelsOpen == 0) {
+    DeInitEngine();
+  }
+  return false;
 }
 
 void
 MediaEngineWebRTCMicrophoneSource::Shutdown()
 {
   Super::Shutdown();
   if (mListener) {
     // breaks a cycle, since the WebRTCAudioDataListener has a RefPtr to us
@@ -810,18 +809,16 @@ MediaEngineWebRTCMicrophoneSource::Shutd
   }
 
   while (mRegisteredHandles.Length()) {
     MOZ_ASSERT(mState == kAllocated || mState == kStopped);
     Deallocate(nullptr); // XXX Extend concurrent constraints code to mics.
   }
 
   FreeChannel();
-  DeInitEngine();
-
   mAudioInput = nullptr;
 }
 
 typedef int16_t sample;
 
 void
 MediaEngineWebRTCMicrophoneSource::Process(int channel,
                                            webrtc::ProcessingTypes type,