Bug 980096: fix leaks of VoiceEngines by reinstating use of ScopedCustomReleasePtr r=khuey
authorRandell Jesup <rjesup@jesup.org>
Sun, 09 Mar 2014 00:18:50 -0500
changeset 190888 e2ca2e77c0ef19cd723a1f1d18964ac059479681
parent 190887 e9e0d0ae787b7480bef0c003a9de6b6aa1a2bbaf
child 190889 7d406c9622a1dea15c252fb67a657372ef0ea213
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs980096
milestone30.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 980096: fix leaks of VoiceEngines by reinstating use of ScopedCustomReleasePtr r=khuey
content/media/webrtc/MediaEngineWebRTC.cpp
content/media/webrtc/MediaEngineWebRTC.h
content/media/webrtc/MediaEngineWebRTCAudio.cpp
media/webrtc/signaling/src/common/MediaEngineWrapper.h
media/webrtc/signaling/src/common/Wrapper.h
media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
media/webrtc/signaling/src/media-conduit/AudioConduit.h
media/webrtc/signaling/src/media-conduit/MediaEngineWrapper.h
media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
media/webrtc/signaling/src/media-conduit/VideoConduit.h
--- a/content/media/webrtc/MediaEngineWebRTC.cpp
+++ b/content/media/webrtc/MediaEngineWebRTC.cpp
@@ -103,18 +103,19 @@ MediaEngineWebRTC::EnumerateVideoDevices
       vSource = new MediaEngineWebRTCVideoSource(i);
       mVideoSources.Put(uuid, vSource); // Hashtable takes ownership.
       aVSources->AppendElement(vSource);
     }
   }
 
   return;
 #else
-  webrtc::ViEBase* ptrViEBase;
-  webrtc::ViECapture* ptrViECapture;
+  ScopedCustomReleasePtr<webrtc::ViEBase> ptrViEBase;
+  ScopedCustomReleasePtr<webrtc::ViECapture> ptrViECapture;
+
   // We spawn threads to handle gUM runnables, so we must protect the member vars
   MutexAutoLock lock(mMutex);
 
 #ifdef MOZ_WIDGET_ANDROID
   jobject context = mozilla::AndroidBridge::Bridge()->GetGlobalContextRef();
 
   // get the JVM
   JavaVM *jvm = mozilla::AndroidBridge::Bridge()->GetVM();
@@ -227,28 +228,25 @@ MediaEngineWebRTC::EnumerateVideoDevices
       aVSources->AppendElement(vSource.get());
     } else {
       vSource = new MediaEngineWebRTCVideoSource(mVideoEngine, i);
       mVideoSources.Put(uuid, vSource); // Hashtable takes ownership.
       aVSources->AppendElement(vSource);
     }
   }
 
-  ptrViEBase->Release();
-  ptrViECapture->Release();
-
   return;
 #endif
 }
 
 void
 MediaEngineWebRTC::EnumerateAudioDevices(nsTArray<nsRefPtr<MediaEngineAudioSource> >* aASources)
 {
-  webrtc::VoEBase* ptrVoEBase = nullptr;
-  webrtc::VoEHardware* ptrVoEHw = nullptr;
+  ScopedCustomReleasePtr<webrtc::VoEBase> ptrVoEBase;
+  ScopedCustomReleasePtr<webrtc::VoEHardware> ptrVoEHw;
   // We spawn threads to handle gUM runnables, so we must protect the member vars
   MutexAutoLock lock(mMutex);
 
 #ifdef MOZ_WIDGET_ANDROID
   jobject context = mozilla::AndroidBridge::Bridge()->GetGlobalContextRef();
 
   // get the JVM
   JavaVM *jvm = mozilla::AndroidBridge::Bridge()->GetVM();
@@ -331,19 +329,16 @@ MediaEngineWebRTC::EnumerateAudioDevices
     } else {
       aSource = new MediaEngineWebRTCAudioSource(
         mVoiceEngine, i, deviceName, uniqueId
       );
       mAudioSources.Put(uuid, aSource); // Hashtable takes ownership.
       aASources->AppendElement(aSource);
     }
   }
-
-  ptrVoEHw->Release();
-  ptrVoEBase->Release();
 }
 
 void
 MediaEngineWebRTC::Shutdown()
 {
   // This is likely paranoia
   MutexAutoLock lock(mMutex);
 
--- a/content/media/webrtc/MediaEngineWebRTC.h
+++ b/content/media/webrtc/MediaEngineWebRTC.h
@@ -23,16 +23,18 @@
 #include "VideoUtils.h"
 #include "MediaEngine.h"
 #include "VideoSegment.h"
 #include "AudioSegment.h"
 #include "StreamBuffer.h"
 #include "MediaStreamGraph.h"
 #include "LoadMonitor.h"
 
+#include "MediaEngineWrapper.h"
+
 // WebRTC library includes follow
 
 // Audio Engine
 #include "webrtc/voice_engine/include/voe_base.h"
 #include "webrtc/voice_engine/include/voe_codec.h"
 #include "webrtc/voice_engine/include/voe_hardware.h"
 #include "webrtc/voice_engine/include/voe_network.h"
 #include "webrtc/voice_engine/include/voe_audio_processing.h"
@@ -303,20 +305,20 @@ public:
 private:
   static const unsigned int KMaxDeviceNameLength = 128;
   static const unsigned int KMaxUniqueIdLength = 256;
 
   void Init();
   void Shutdown();
 
   webrtc::VoiceEngine* mVoiceEngine;
-  webrtc::VoEBase* mVoEBase;
-  webrtc::VoEExternalMedia* mVoERender;
-  webrtc::VoENetwork*  mVoENetwork;
-  webrtc::VoEAudioProcessing *mVoEProcessing;
+  ScopedCustomReleasePtr<webrtc::VoEBase> mVoEBase;
+  ScopedCustomReleasePtr<webrtc::VoEExternalMedia> mVoERender;
+  ScopedCustomReleasePtr<webrtc::VoENetwork> mVoENetwork;
+  ScopedCustomReleasePtr<webrtc::VoEAudioProcessing> mVoEProcessing;
 
   // mMonitor protects mSources[] access/changes, and transitions of mState
   // from kStarted to kStopped (which are combined with EndTrack()).
   // mSources[] is accessed from webrtc threads.
   Monitor mMonitor;
   nsTArray<SourceMediaStream *> mSources; // When this goes empty, we shut down HW
 
   int mCapIndex;
--- a/content/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -104,20 +104,18 @@ MediaEngineWebRTCAudioSource::Config(boo
   return NS_OK;
 }
 
 nsresult
 MediaEngineWebRTCAudioSource::Allocate(const MediaEnginePrefs &aPrefs)
 {
   if (mState == kReleased) {
     if (mInitDone) {
-      webrtc::VoEHardware* ptrVoEHw = webrtc::VoEHardware::GetInterface(mVoiceEngine);
-      int res = ptrVoEHw->SetRecordingDevice(mCapIndex);
-      ptrVoEHw->Release();
-      if (res) {
+      ScopedCustomReleasePtr<webrtc::VoEHardware> ptrVoEHw(webrtc::VoEHardware::GetInterface(mVoiceEngine));
+      if (!ptrVoEHw || ptrVoEHw->SetRecordingDevice(mCapIndex)) {
         return NS_ERROR_FAILURE;
       }
       mState = kAllocated;
       LOG(("Audio device %d allocated", mCapIndex));
     } else {
       LOG(("Audio device is not initalized"));
       return NS_ERROR_FAILURE;
     }
@@ -273,52 +271,48 @@ MediaEngineWebRTCAudioSource::Init()
     return;
   }
   mNullTransport = new NullTransport();
   if (mVoENetwork->RegisterExternalTransport(mChannel, *mNullTransport)) {
     return;
   }
 
   // Check for availability.
-  webrtc::VoEHardware* ptrVoEHw = webrtc::VoEHardware::GetInterface(mVoiceEngine);
-  if (ptrVoEHw->SetRecordingDevice(mCapIndex)) {
-    ptrVoEHw->Release();
+  ScopedCustomReleasePtr<webrtc::VoEHardware> ptrVoEHw(webrtc::VoEHardware::GetInterface(mVoiceEngine));
+  if (!ptrVoEHw || ptrVoEHw->SetRecordingDevice(mCapIndex)) {
     return;
   }
 
 #ifndef MOZ_B2G
   // Because of the permission mechanism of B2G, we need to skip the status
   // check here.
   bool avail = false;
   ptrVoEHw->GetRecordingDeviceStatus(avail);
-  ptrVoEHw->Release();
   if (!avail) {
     return;
   }
 #endif // MOZ_B2G
+
   // Set "codec" to PCM, 32kHz on 1 channel
-  webrtc::VoECodec* ptrVoECodec;
-  webrtc::CodecInst codec;
-  ptrVoECodec = webrtc::VoECodec::GetInterface(mVoiceEngine);
+  ScopedCustomReleasePtr<webrtc::VoECodec> ptrVoECodec(webrtc::VoECodec::GetInterface(mVoiceEngine));
   if (!ptrVoECodec) {
     return;
   }
 
+  webrtc::CodecInst codec;
   strcpy(codec.plname, ENCODING);
   codec.channels = CHANNELS;
   codec.rate = SAMPLE_RATE;
   codec.plfreq = SAMPLE_FREQUENCY;
   codec.pacsize = SAMPLE_LENGTH;
   codec.pltype = 0; // Default payload type
 
-  if (ptrVoECodec->SetSendCodec(mChannel, codec)) {
-    return;
+  if (!ptrVoECodec->SetSendCodec(mChannel, codec)) {
+    mInitDone = true;
   }
-
-  mInitDone = true;
 }
 
 void
 MediaEngineWebRTCAudioSource::Shutdown()
 {
   if (!mInitDone) {
     // duplicate these here in case we failed during Init()
     if (mChannel != -1) {
@@ -347,18 +341,20 @@ MediaEngineWebRTCAudioSource::Shutdown()
   if (mChannel != -1) {
     mVoENetwork->DeRegisterExternalTransport(mChannel);
   }
 
   if (mNullTransport) {
     delete mNullTransport;
   }
 
-  mVoERender->Release();
-  mVoEBase->Release();
+  mVoEProcessing = nullptr;
+  mVoENetwork = nullptr;
+  mVoERender = nullptr;
+  mVoEBase = nullptr;
 
   mState = kReleased;
   mInitDone = false;
 }
 
 typedef int16_t sample;
 
 void
rename from media/webrtc/signaling/src/media-conduit/MediaEngineWrapper.h
rename to media/webrtc/signaling/src/common/MediaEngineWrapper.h
--- a/media/webrtc/signaling/src/common/Wrapper.h
+++ b/media/webrtc/signaling/src/common/Wrapper.h
@@ -31,19 +31,17 @@
  *
  * Future enhancements:
  * - For now, objects remain in the map forever.  Better would be to add a releaseHandle() function which would
  *   allow the map to be emptied as underlying handles expired.  While we can't force the client to give up its
  *   shared_ptr<Foo> objects, we can remove our own copy, for instance on a call ended event.
  */
 
 #include <map>
-#include "SharedPtr.h"
 #include "prlock.h"
-#include "base/lock.h"
 #include "mozilla/Assertions.h"
 
 /*
  * Wrapper has its own autolock class because the instances are declared
  * statically and mozilla::Mutex will not work properly when instantiated
  * in a static constructor.
  */
 
--- a/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
@@ -69,64 +69,43 @@ WebrtcAudioConduit::~WebrtcAudioConduit(
 #endif
 
   CSFLogDebug(logTag,  "%s ", __FUNCTION__);
   for(std::vector<AudioCodecConfig*>::size_type i=0;i < mRecvCodecList.size();i++)
   {
     delete mRecvCodecList[i];
   }
   delete mCurSendCodecConfig;
-  if (mPtrVoERTP_RTCP) {
-    mPtrVoERTP_RTCP->Release();
-  }
 
   // The first one of a pair to be deleted shuts down media for both
   if(mPtrVoEXmedia)
   {
     if (!mShutDown) {
       mPtrVoEXmedia->SetExternalRecordingStatus(false);
       mPtrVoEXmedia->SetExternalPlayoutStatus(false);
     }
-    mPtrVoEXmedia->Release();
-  }
-
-  if(mPtrVoEProcessing)
-  {
-    mPtrVoEProcessing->Release();
   }
 
   //Deal with the transport
   if(mPtrVoENetwork)
   {
     if (!mShutDown) {
       mPtrVoENetwork->DeRegisterExternalTransport(mChannel);
     }
-    mPtrVoENetwork->Release();
-  }
-
-  if(mPtrVoECodec)
-  {
-    mPtrVoECodec->Release();
   }
 
   if(mPtrVoEBase)
   {
     if (!mShutDown) {
       mPtrVoEBase->StopPlayout(mChannel);
       mPtrVoEBase->StopSend(mChannel);
       mPtrVoEBase->StopReceive(mChannel);
       mPtrVoEBase->DeleteChannel(mChannel);
       mPtrVoEBase->Terminate();
     }
-    mPtrVoEBase->Release();
-  }
-
-  if (mPtrRTP)
-  {
-    mPtrRTP->Release();
   }
 
   if (mOtherDirection)
   {
     // mOtherDirection owns these now!
     mOtherDirection->mOtherDirection = nullptr;
     // let other side we terminated the channel
     mOtherDirection->mShutDown = true;
--- a/media/webrtc/signaling/src/media-conduit/AudioConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.h
@@ -6,16 +6,17 @@
 #ifndef AUDIO_SESSION_H_
 #define AUDIO_SESSION_H_
 
 #include "mozilla/Attributes.h"
 #include "mozilla/TimeStamp.h"
 #include "nsTArray.h"
 
 #include "MediaConduitInterface.h"
+#include "MediaEngineWrapper.h"
 
 // Audio Engine Includes
 #include "webrtc/common_types.h"
 #include "webrtc/voice_engine/include/voe_base.h"
 #include "webrtc/voice_engine/include/voe_volume_control.h"
 #include "webrtc/voice_engine/include/voe_codec.h"
 #include "webrtc/voice_engine/include/voe_file.h"
 #include "webrtc/voice_engine/include/voe_network.h"
@@ -151,17 +152,16 @@ public:
 
 
 
   WebrtcAudioConduit():
                       mOtherDirection(nullptr),
                       mShutDown(false),
                       mVoiceEngine(nullptr),
                       mTransport(nullptr),
-                      mPtrRTP(nullptr),
                       mEngineTransmitting(false),
                       mEngineReceiving(false),
                       mChannel(-1),
                       mCurSendCodecConfig(nullptr),
                       mCaptureDelay(150),
                       mEchoOn(true),
                       mEchoCancel(webrtc::kEcAec)
 #ifdef MOZILLA_INTERNAL_API
@@ -225,24 +225,24 @@ private:
   WebrtcAudioConduit*  mOtherDirection;
   // Other side has shut down our channel and related items already
   bool mShutDown;
 
   // These are shared by both directions.  They're released by the last
   // conduit to die
   webrtc::VoiceEngine* mVoiceEngine;
   mozilla::RefPtr<TransportInterface> mTransport;
-  webrtc::VoENetwork*  mPtrVoENetwork;
-  webrtc::VoEBase*     mPtrVoEBase;
-  webrtc::VoECodec*    mPtrVoECodec;
-  webrtc::VoEExternalMedia* mPtrVoEXmedia;
-  webrtc::VoEAudioProcessing* mPtrVoEProcessing;
-  webrtc::VoEVideoSync* mPtrVoEVideoSync;
-  webrtc::VoERTP_RTCP* mPtrVoERTP_RTCP;
-  webrtc::VoERTP_RTCP* mPtrRTP;
+  ScopedCustomReleasePtr<webrtc::VoENetwork>   mPtrVoENetwork;
+  ScopedCustomReleasePtr<webrtc::VoEBase>      mPtrVoEBase;
+  ScopedCustomReleasePtr<webrtc::VoECodec>     mPtrVoECodec;
+  ScopedCustomReleasePtr<webrtc::VoEExternalMedia> mPtrVoEXmedia;
+  ScopedCustomReleasePtr<webrtc::VoEAudioProcessing> mPtrVoEProcessing;
+  ScopedCustomReleasePtr<webrtc::VoEVideoSync> mPtrVoEVideoSync;
+  ScopedCustomReleasePtr<webrtc::VoERTP_RTCP>  mPtrVoERTP_RTCP;
+  ScopedCustomReleasePtr<webrtc::VoERTP_RTCP>  mPtrRTP;
   //engine states of our interets
   bool mEngineTransmitting; // If true => VoiceEngine Send-subsystem is up
   bool mEngineReceiving;    // If true => VoiceEngine Receive-subsystem is up
                             // and playout is enabled
   // Keep track of each inserted RTP block and the time it was inserted
   // so we can estimate the clock time for a specific TimeStamp coming out
   // (for when we send data to MediaStreamTracks).  Blocks are aged out as needed.
   struct Processing {
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -71,59 +71,45 @@ WebrtcVideoConduit::~WebrtcVideoConduit(
   {
     if (!mShutDown) {
       mPtrViECapture->DisconnectCaptureDevice(mCapId);
       mPtrViECapture->ReleaseCaptureDevice(mCapId);
       mPtrExtCapture = nullptr;
       if (mOtherDirection)
         mOtherDirection->mPtrExtCapture = nullptr;
     }
-    mPtrViECapture->Release();
   }
 
   //Deal with External Renderer
   if(mPtrViERender)
   {
     if (!mShutDown) {
       if(mRenderer) {
         mPtrViERender->StopRender(mChannel);
       }
       mPtrViERender->RemoveRenderer(mChannel);
     }
-    mPtrViERender->Release();
   }
 
   //Deal with the transport
   if(mPtrViENetwork)
   {
     if (!mShutDown) {
       mPtrViENetwork->DeregisterSendTransport(mChannel);
     }
-    mPtrViENetwork->Release();
-  }
-
-  if(mPtrViECodec)
-  {
-    mPtrViECodec->Release();
   }
 
   if(mPtrViEBase)
   {
     if (!mShutDown) {
       mPtrViEBase->StopSend(mChannel);
       mPtrViEBase->StopReceive(mChannel);
       SyncTo(nullptr);
       mPtrViEBase->DeleteChannel(mChannel);
     }
-    mPtrViEBase->Release();
-  }
-
-  if (mPtrRTP)
-  {
-    mPtrRTP->Release();
   }
 
   if (mOtherDirection)
   {
     // mOtherDirection owns these now!
     mOtherDirection->mOtherDirection = nullptr;
     // let other side we terminated the channel
     mOtherDirection->mShutDown = true;
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.h
@@ -3,16 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef VIDEO_SESSION_H_
 #define VIDEO_SESSION_H_
 
 #include "mozilla/Attributes.h"
 
 #include "MediaConduitInterface.h"
+#include "MediaEngineWrapper.h"
 
 // Video Engine Includes
 #include "webrtc/common_types.h"
 #include "webrtc/video_engine/include/vie_base.h"
 #include "webrtc/video_engine/include/vie_capture.h"
 #include "webrtc/video_engine/include/vie_codec.h"
 #include "webrtc/video_engine/include/vie_render.h"
 #include "webrtc/video_engine/include/vie_network.h"
@@ -180,23 +181,17 @@ public:
   }
 
   WebrtcVideoConduit():
                       mOtherDirection(nullptr),
                       mShutDown(false),
                       mVideoEngine(nullptr),
                       mTransport(nullptr),
                       mRenderer(nullptr),
-                      mPtrViEBase(nullptr),
-                      mPtrViECapture(nullptr),
-                      mPtrViECodec(nullptr),
-                      mPtrViENetwork(nullptr),
-                      mPtrViERender(nullptr),
                       mPtrExtCapture(nullptr),
-                      mPtrRTP(nullptr),
                       mEngineTransmitting(false),
                       mEngineReceiving(false),
                       mChannel(-1),
                       mCapId(-1),
                       mCurSendCodecConfig(nullptr),
                       mSendingWidth(0),
                       mSendingHeight(0)
   {
@@ -255,23 +250,24 @@ private:
   bool mShutDown;
 
   // A few of these are shared by both directions.  They're released by the last
   // conduit to die.
   webrtc::VideoEngine* mVideoEngine;          // shared
   mozilla::RefPtr<TransportInterface> mTransport;
   mozilla::RefPtr<VideoRenderer> mRenderer;
 
-  webrtc::ViEBase* mPtrViEBase;
-  webrtc::ViECapture* mPtrViECapture;
-  webrtc::ViECodec* mPtrViECodec;
-  webrtc::ViENetwork* mPtrViENetwork;
-  webrtc::ViERender* mPtrViERender;
-  webrtc::ViEExternalCapture*  mPtrExtCapture; // shared
-  webrtc::ViERTP_RTCP* mPtrRTP;
+  ScopedCustomReleasePtr<webrtc::ViEBase> mPtrViEBase;
+  ScopedCustomReleasePtr<webrtc::ViECapture> mPtrViECapture;
+  ScopedCustomReleasePtr<webrtc::ViECodec> mPtrViECodec;
+  ScopedCustomReleasePtr<webrtc::ViENetwork> mPtrViENetwork;
+  ScopedCustomReleasePtr<webrtc::ViERender> mPtrViERender;
+  ScopedCustomReleasePtr<webrtc::ViERTP_RTCP> mPtrRTP;
+
+  webrtc::ViEExternalCapture* mPtrExtCapture; // shared
 
   // Engine state we are concerned with.
   bool mEngineTransmitting; //If true ==> Transmit Sub-system is up and running
   bool mEngineReceiving;    // if true ==> Receive Sus-sysmtem up and running
 
   int mChannel; // Video Channel for this conduit
   int mCapId;   // Capturer for this conduit
   RecvCodecList    mRecvCodecList;