Bug 945614: Don't track windowIDs in MediaEngine for B2G r=mikeh,schien
authorRandell Jesup <rjesup@jesup.org>
Fri, 06 Dec 2013 17:38:52 -0500
changeset 175091 1d72742584ad88fdaf7ce6adc900005f745d1ae7
parent 175090 a72c03a07567922c6025b6aa111ae9854ca60863
child 175092 3b563c306582e0dcc67227b35987add07c716974
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikeh, schien
bugs945614
milestone28.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 945614: Don't track windowIDs in MediaEngine for B2G r=mikeh,schien
content/media/webrtc/MediaEngineWebRTC.cpp
content/media/webrtc/MediaEngineWebRTC.h
content/media/webrtc/MediaEngineWebRTCVideo.cpp
dom/camera/DOMCameraManager.cpp
dom/camera/DOMCameraManager.h
dom/media/MediaManager.cpp
--- a/content/media/webrtc/MediaEngineWebRTC.cpp
+++ b/content/media/webrtc/MediaEngineWebRTC.cpp
@@ -94,17 +94,17 @@ MediaEngineWebRTC::EnumerateVideoDevices
     }
 
     nsRefPtr<MediaEngineWebRTCVideoSource> vSource;
     NS_ConvertUTF8toUTF16 uuid(cameraName);
     if (mVideoSources.Get(uuid, getter_AddRefs(vSource))) {
       // We've already seen this device, just append.
       aVSources->AppendElement(vSource.get());
     } else {
-      vSource = new MediaEngineWebRTCVideoSource(mCameraManager, i, mWindowId);
+      vSource = new MediaEngineWebRTCVideoSource(mCameraManager, i);
       mVideoSources.Put(uuid, vSource); // Hashtable takes ownership.
       aVSources->AppendElement(vSource);
     }
   }
 
   return;
 #else
   webrtc::ViEBase* ptrViEBase;
--- a/content/media/webrtc/MediaEngineWebRTC.h
+++ b/content/media/webrtc/MediaEngineWebRTC.h
@@ -47,16 +47,17 @@
 #include "webrtc/video_engine/include/vie_capture.h"
 #ifdef MOZ_B2G_CAMERA
 #include "CameraPreviewMediaStream.h"
 #include "DOMCameraManager.h"
 #include "GonkCameraControl.h"
 #include "ImageContainer.h"
 #include "nsGlobalWindow.h"
 #include "prprf.h"
+#include "nsProxyRelease.h"
 #endif
 
 #include "NullTransport.h"
 
 namespace mozilla {
 
 #ifdef MOZ_B2G_CAMERA
 class CameraAllocateRunnable;
@@ -68,17 +69,17 @@ class GetCameraNameRunnable;
  *
  * On B2G platform, member data may accessed from different thread after construction:
  *
  * MediaThread:
  *   mState, mImage, mWidth, mHeight, mCapability, mPrefs, mDeviceName, mUniqueId, mInitDone,
  *   mSources, mImageContainer, mSources, mState, mImage, mLastCapture
  *
  * MainThread:
- *   mDOMCameraControl, mCaptureIndex, mCameraThread, mWindowId, mCameraManager,
+ *   mDOMCameraControl, mCaptureIndex, mCameraThread, mCameraManager,
  *   mNativeCameraControl, mPreviewStream, mState, mLastCapture, mWidth, mHeight
  *
  * Where mWidth, mHeight, mImage are protected by mMonitor
  *       mState, mLastCapture is protected by mCallbackMonitor
  * Other variable is accessed only from single thread
  */
 class MediaEngineWebRTCVideoSource : public MediaEngineVideoSource
                                    , public nsRunnable
@@ -91,21 +92,20 @@ class MediaEngineWebRTCVideoSource : pub
                                    , public CameraPreviewFrameCallback
 #else
                                    , public webrtc::ExternalRenderer
 #endif
 {
 public:
 #ifdef MOZ_B2G_CAMERA
   MediaEngineWebRTCVideoSource(nsDOMCameraManager* aCameraManager,
-    int aIndex, uint64_t aWindowId)
+    int aIndex)
     : mCameraManager(aCameraManager)
     , mNativeCameraControl(nullptr)
     , mPreviewStream(nullptr)
-    , mWindowId(aWindowId)
     , mCallbackMonitor("WebRTCCamera.CallbackMonitor")
     , mCaptureIndex(aIndex)
     , mMonitor("WebRTCCamera.Monitor")
     , mWidth(0)
     , mHeight(0)
     , mInitDone(false)
     , mInSnapshotMode(false)
     , mSnapshotPath(nullptr)
@@ -218,17 +218,16 @@ private:
   // We need raw pointer here since such DOM-object should not addref/release on
   // any thread other than main thread, but we must use this object for now. To
   // avoid any bad thing do to addref/release DOM-object on other thread, we use
   // raw-pointer for now.
   nsDOMCameraManager* mCameraManager;
   nsRefPtr<nsDOMCameraControl> mDOMCameraControl;
   nsRefPtr<nsGonkCameraControl> mNativeCameraControl;
   nsRefPtr<DOMCameraPreview> mPreviewStream;
-  uint64_t mWindowId;
   mozilla::ReentrantMonitor mCallbackMonitor; // Monitor for camera callback handling
   nsRefPtr<nsIThread> mCameraThread;
   nsRefPtr<nsIDOMFile> mLastCapture;
 #else
   webrtc::VideoEngine* mVideoEngine; // Weak reference, don't free.
   webrtc::ViEBase* mViEBase;
   webrtc::ViECapture* mViECapture;
   webrtc::ViERender* mViERender;
@@ -347,25 +346,24 @@ private:
 
   NullTransport *mNullTransport;
 };
 
 class MediaEngineWebRTC : public MediaEngine
 {
 public:
 #ifdef MOZ_B2G_CAMERA
-  MediaEngineWebRTC(nsDOMCameraManager* aCameraManager, uint64_t aWindowId)
+  MediaEngineWebRTC(nsDOMCameraManager* aCameraManager)
     : mMutex("mozilla::MediaEngineWebRTC")
     , mVideoEngine(nullptr)
     , mVoiceEngine(nullptr)
     , mVideoEngineInit(false)
     , mAudioEngineInit(false)
+    , mHasTabVideoSource(false)
     , mCameraManager(aCameraManager)
-    , mWindowId(aWindowId)
-    , mHasTabVideoSource(false)
   {
     AsyncLatencyLogger::Get(true)->AddRef();
     mLoadMonitor = new LoadMonitor();
     mLoadMonitor->Init(mLoadMonitor);
   }
 #else
   MediaEngineWebRTC();
 #endif
@@ -396,25 +394,26 @@ private:
   bool mHasTabVideoSource;
 
   // Store devices we've already seen in a hashtable for quick return.
   // Maps UUID to MediaEngineSource (one set for audio, one for video).
   nsRefPtrHashtable<nsStringHashKey, MediaEngineWebRTCVideoSource > mVideoSources;
   nsRefPtrHashtable<nsStringHashKey, MediaEngineWebRTCAudioSource > mAudioSources;
 
 #ifdef MOZ_B2G_CAMERA
+  // XXX Should use nsMainThreadPtrHandle/etc
+
   // MediaEngine hold this DOM object, and the MediaEngine is hold by Navigator
   // Their life time is always much longer than this object. Use a raw-pointer
   // here should be safe.
   // We need raw pointer here since such DOM-object should not addref/release on
   // any thread other than main thread, but we must use this object for now. To
   // avoid any bad thing do to addref/release DOM-object on other thread, we use
   // raw-pointer for now.
   nsDOMCameraManager* mCameraManager;
-  uint64_t mWindowId;
 #endif
 
    nsRefPtr<LoadMonitor> mLoadMonitor;
 };
 
 }
 
 #endif /* NSMEDIAENGINEWEBRTC_H_ */
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -307,17 +307,16 @@ MediaEngineWebRTCVideoSource::Deallocate
   }
   return NS_OK;
 }
 
 nsresult
 MediaEngineWebRTCVideoSource::Start(SourceMediaStream* aStream, TrackID aID)
 {
   LOG((__FUNCTION__));
-  int error = 0;
   if (!mInitDone || !aStream) {
     return NS_ERROR_FAILURE;
   }
 
   mSources.AppendElement(aStream);
 
   aStream->AddTrack(aID, USECS_PER_S, 0, new VideoSegment());
   aStream->AdvanceKnownTracksTime(STREAM_TIME_MAX);
@@ -336,17 +335,17 @@ MediaEngineWebRTCVideoSource::Start(Sour
                                        &MediaEngineWebRTCVideoSource::StartImpl,
                                        mCapability));
   mCallbackMonitor.Wait();
   if (mState != kStarted) {
     return NS_ERROR_FAILURE;
   }
 #else
   mState = kStarted;
-  error = mViERender->AddRenderer(mCaptureIndex, webrtc::kVideoI420, (webrtc::ExternalRenderer*)this);
+  int error = mViERender->AddRenderer(mCaptureIndex, webrtc::kVideoI420, (webrtc::ExternalRenderer*)this);
   if (error == -1) {
     return NS_ERROR_FAILURE;
   }
 
   error = mViERender->StartRender(mCaptureIndex);
   if (error == -1) {
     return NS_ERROR_FAILURE;
   }
@@ -487,30 +486,28 @@ MediaEngineWebRTCVideoSource::Shutdown()
 
 #ifdef MOZ_B2G_CAMERA
 
 // All these functions must be run on MainThread!
 void
 MediaEngineWebRTCVideoSource::AllocImpl() {
   MOZ_ASSERT(NS_IsMainThread());
 
-  mDOMCameraControl = new nsDOMCameraControl(mCaptureIndex,
-                                             mCameraThread,
-                                             this,
-                                             this,
-                                             nsGlobalWindow::GetInnerWindowWithId(mWindowId));
-  mCameraManager->Register(mDOMCameraControl);
+  ErrorResult rv;
+  mDOMCameraControl = mCameraManager->GetCameraControl(mCaptureIndex,
+                                                       this, this, rv);
 }
 
 void
 MediaEngineWebRTCVideoSource::DeallocImpl() {
   MOZ_ASSERT(NS_IsMainThread());
 
   mNativeCameraControl->ReleaseHardware(this, this);
   mNativeCameraControl = nullptr;
+  mDOMCameraControl = nullptr;
 }
 
 void
 MediaEngineWebRTCVideoSource::StartImpl(webrtc::CaptureCapability aCapability) {
   MOZ_ASSERT(NS_IsMainThread());
 
   idl::CameraSize size;
   size.width = aCapability.width;
--- a/dom/camera/DOMCameraManager.cpp
+++ b/dom/camera/DOMCameraManager.cpp
@@ -100,43 +100,56 @@ nsDOMCameraManager::CreateInstance(nsPID
     new nsDOMCameraManager(aWindow);
 
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   obs->AddObserver(cameraManager, "xpcom-shutdown", true);
 
   return cameraManager.forget();
 }
 
+nsDOMCameraControl*
+nsDOMCameraManager::GetCameraControl(uint32_t aDeviceNum,
+                                     nsICameraGetCameraCallback* onSuccess,
+                                     nsICameraErrorCallback* onError,
+                                     ErrorResult& aRv)
+{
+  aRv = NS_OK;
+
+  // reuse the same camera thread to conserve resources
+  if (!mCameraThread) {
+    aRv = NS_NewThread(getter_AddRefs(mCameraThread));
+    if (aRv.Failed()) {
+      return nullptr;
+    }
+  }
+
+  // Creating this object will trigger the onSuccess handler
+  nsDOMCameraControl* cameraControl =  new nsDOMCameraControl(aDeviceNum, mCameraThread,
+                                                              onSuccess, onError, mWindow);
+  if (cameraControl) {
+    Register(cameraControl);
+  }
+  return cameraControl;
+}
+
 void
 nsDOMCameraManager::GetCamera(const CameraSelector& aOptions,
                               nsICameraGetCameraCallback* onSuccess,
                               const Optional<nsICameraErrorCallback*>& onError,
                               ErrorResult& aRv)
 {
   uint32_t cameraId = 0;  // back (or forward-facing) camera by default
   if (aOptions.mCamera.EqualsLiteral("front")) {
     cameraId = 1;
   }
 
-  // reuse the same camera thread to conserve resources
-  if (!mCameraThread) {
-    aRv = NS_NewThread(getter_AddRefs(mCameraThread));
-    if (aRv.Failed()) {
-      return;
-    }
-  }
-
   DOM_CAMERA_LOGT("%s:%d\n", __func__, __LINE__);
 
-  // Creating this object will trigger the onSuccess handler
   nsRefPtr<nsDOMCameraControl> cameraControl =
-    new nsDOMCameraControl(cameraId, mCameraThread,
-                           onSuccess, onError.WasPassed() ? onError.Value() : nullptr, mWindow);
-
-  Register(cameraControl);
+    GetCameraControl(cameraId, onSuccess, onError.WasPassed() ? onError.Value() : nullptr, aRv);
 }
 
 void
 nsDOMCameraManager::Register(nsDOMCameraControl* aDOMCameraControl)
 {
   DOM_CAMERA_LOGI(">>> Register( aDOMCameraControl = %p ) mWindowId = 0x%llx\n", aDOMCameraControl, mWindowId);
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/dom/camera/DOMCameraManager.h
+++ b/dom/camera/DOMCameraManager.h
@@ -44,16 +44,21 @@ public:
                                                          nsIObserver)
   NS_DECL_NSIOBSERVER
 
   static bool CheckPermission(nsPIDOMWindow* aWindow);
   static already_AddRefed<nsDOMCameraManager>
     CreateInstance(nsPIDOMWindow* aWindow);
   static bool IsWindowStillActive(uint64_t aWindowId);
 
+  // Build us an nsDOMCameraControl
+  mozilla::nsDOMCameraControl* GetCameraControl(uint32_t aDeviceNum,
+                                                nsICameraGetCameraCallback* onSuccess,
+                                                nsICameraErrorCallback* onError,
+                                                mozilla::ErrorResult& aRv);
   void Register(mozilla::nsDOMCameraControl* aDOMCameraControl);
   void OnNavigation(uint64_t aWindowId);
 
   nsresult GetNumberOfCameras(int32_t& aDeviceCount);
   nsresult GetCameraName(uint32_t aDeviceNum, nsCString& aDeviceName);
 
   // WebIDL
   void GetCamera(const mozilla::dom::CameraSelector& aOptions,
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1404,17 +1404,17 @@ MediaManager::GetBackend(uint64_t aWindo
   // includes picture support for Android.
   // This IS called off main-thread.
   MutexAutoLock lock(mMutex);
   if (!mBackend) {
 #if defined(MOZ_WEBRTC)
 #ifndef MOZ_B2G_CAMERA
     mBackend = new MediaEngineWebRTC();
 #else
-    mBackend = new MediaEngineWebRTC(mCameraManager, aWindowId);
+    mBackend = new MediaEngineWebRTC(mCameraManager);
 #endif
 #else
     mBackend = new MediaEngineDefault();
 #endif
   }
   return mBackend;
 }