Bug 1213517 - Only restart camera if net settings actually change. draft
authorJan-Ivar Bruaroey <jib@mozilla.com>
Sat, 18 Jun 2016 14:16:47 -0400
changeset 388778 cf0d912ad220774d0b3661864ac01b51186fc8a5
parent 388777 09ff1385083590ce8b27cd83e857be7516c8d4de
child 388779 6ee7e68738a84ac7335183188f4014148f2dbfee
push id23232
push userjbruaroey@mozilla.com
push dateSun, 17 Jul 2016 21:00:46 +0000
bugs1213517
milestone50.0a1
Bug 1213517 - Only restart camera if net settings actually change. MozReview-Commit-ID: h01gJ3uCom
dom/media/webrtc/MediaEngineCameraVideoSource.cpp
dom/media/webrtc/MediaEngineCameraVideoSource.h
dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
dom/media/webrtc/MediaEngineRemoteVideoSource.h
--- a/dom/media/webrtc/MediaEngineCameraVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineCameraVideoSource.cpp
@@ -382,17 +382,34 @@ MediaEngineCameraVideoSource::GetUUID(ns
 }
 
 const nsCString&
 MediaEngineCameraVideoSource::GetUUID() const
 {
   return mUniqueId;
 }
 
-
 void
 MediaEngineCameraVideoSource::SetDirectListeners(bool aHasDirectListeners)
 {
   LOG((__FUNCTION__));
   mHasDirectListeners = aHasDirectListeners;
 }
 
+bool operator == (const webrtc::CaptureCapability& a,
+                  const webrtc::CaptureCapability& b)
+{
+  return a.width == b.width &&
+         a.height == b.height &&
+         a.maxFPS == b.maxFPS &&
+         a.rawType == b.rawType &&
+         a.codecType == b.codecType &&
+         a.expectedCaptureDelay == b.expectedCaptureDelay &&
+         a.interlaced == b.interlaced;
+};
+
+bool operator != (const webrtc::CaptureCapability& a,
+                  const webrtc::CaptureCapability& b)
+{
+  return !(a == b);
+}
+
 } // namespace mozilla
--- a/dom/media/webrtc/MediaEngineCameraVideoSource.h
+++ b/dom/media/webrtc/MediaEngineCameraVideoSource.h
@@ -11,16 +11,21 @@
 #include "nsDirectoryServiceDefs.h"
 
 // conflicts with #include of scoped_ptr.h
 #undef FF
 #include "webrtc/video_engine/include/vie_capture.h"
 
 namespace mozilla {
 
+bool operator == (const webrtc::CaptureCapability& a,
+                  const webrtc::CaptureCapability& b);
+bool operator != (const webrtc::CaptureCapability& a,
+                  const webrtc::CaptureCapability& b);
+
 class MediaEngineCameraVideoSource : public MediaEngineVideoSource,
                                      protected MediaConstraintsHelper
 {
 public:
   explicit MediaEngineCameraVideoSource(int aIndex,
                                         const char* aMonitorName = "Camera.Monitor")
     : MediaEngineVideoSource(kReleased)
     , mMonitor(aMonitorName)
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -290,53 +290,69 @@ MediaEngineRemoteVideoSource::Restart(Ba
                                       const char** aOutBadConstraint)
 {
   AssertIsOnOwningThread();
   if (!mInitDone) {
     LOG(("Init not done"));
     return NS_ERROR_FAILURE;
   }
   MOZ_ASSERT(aHandle);
-  auto handle = static_cast<AllocationHandle*>(aHandle);
-  RefPtr<AllocationHandle> temp = new AllocationHandle(aConstraints);
-  temp->mConstraints = NormalizedConstraints(aConstraints);
+  NormalizedConstraints constraints(aConstraints);
+  return UpdateExisting(static_cast<AllocationHandle*>(aHandle), &constraints,
+                        aPrefs, aDeviceId, aOutBadConstraint);
+}
+
+nsresult
+MediaEngineRemoteVideoSource::UpdateExisting(AllocationHandle* aHandle,
+                                             NormalizedConstraints* aNewConstraints,
+                                             const MediaEnginePrefs& aPrefs,
+                                             const nsString& aDeviceId,
+                                             const char** aOutBadConstraint)
+{
+  // aHandle and/or aNewConstraints may be nullptr
 
   AutoTArray<const NormalizedConstraints*, 10> allConstraints;
   for (auto& registered : mRegisteredHandles) {
-    if (registered.get() == handle) {
+    if (aNewConstraints && registered.get() == aHandle) {
       continue; // Don't count old constraints
     }
     allConstraints.AppendElement(&registered->mConstraints);
   }
-  allConstraints.AppendElement(&temp->mConstraints);
+  if (aNewConstraints) {
+    allConstraints.AppendElement(aNewConstraints);
+  } else if (aHandle) {
+    // In the case of UpdateNew, the handle isn't registered yet.
+    allConstraints.AppendElement(&aHandle->mConstraints);
+  }
 
   NormalizedConstraints netConstraints(allConstraints);
   if (netConstraints.mBadConstraint) {
     *aOutBadConstraint = netConstraints.mBadConstraint;
     return NS_ERROR_FAILURE;
   }
 
   if (!ChooseCapability(netConstraints, aPrefs, aDeviceId)) {
     *aOutBadConstraint = FindBadConstraint(netConstraints, *this, aDeviceId);
     return NS_ERROR_FAILURE;
   }
-  if (mState != kStarted) {
-    return NS_OK;
-  }
+  MOZ_ASSERT(mState == kStarted || !aNewConstraints);
 
-  mozilla::camera::GetChildAndCall(
-    &mozilla::camera::CamerasChild::StopCapture,
-    mCapEngine, mCaptureIndex);
-  if (mozilla::camera::GetChildAndCall(
-    &mozilla::camera::CamerasChild::StartCapture,
-    mCapEngine, mCaptureIndex, mCapability, this)) {
-    LOG(("StartCapture failed"));
-    return NS_ERROR_FAILURE;
+  if (mState == kStarted && mCapability != mLastCapability) {
+    camera::GetChildAndCall(&camera::CamerasChild::StopCapture,
+                            mCapEngine, mCaptureIndex);
+    if (camera::GetChildAndCall(&camera::CamerasChild::StartCapture,
+                                mCapEngine, mCaptureIndex, mCapability, this)) {
+      LOG(("StartCapture failed"));
+      return NS_ERROR_FAILURE;
+    }
+    mLastCapability = mCapability;
   }
-  handle->mConstraints = temp->mConstraints;
+  if (aHandle && aNewConstraints) {
+    aHandle->mConstraints = *aNewConstraints;
+  }
   return NS_OK;
 }
 
 void
 MediaEngineRemoteVideoSource::NotifyPull(MediaStreamGraph* aGraph,
                                          SourceMediaStream* aSource,
                                          TrackID aID, StreamTime aDesiredTime,
                                          const PrincipalHandle& aPrincipalHandle)
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.h
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.h
@@ -117,17 +117,45 @@ protected:
   ~MediaEngineRemoteVideoSource() { Shutdown(); }
 
 private:
   // Initialize the needed Video engine interfaces.
   void Init();
   size_t NumCapabilities() const override;
   void GetCapability(size_t aIndex, webrtc::CaptureCapability& aOut) const override;
 
+  /* UpdateExisting - Centralized function to apply constraints and restart
+   * device as needed, considering all allocations and changes to one.
+   *
+   * aHandle           - New or existing handle, or null to update after removal.
+   * aNewConstraints   - Constraints to be applied to existing handle, or null.
+   * aPrefs            - As passed in (in case of changes in about:config).
+   * aDeviceId         - As passed in (origin dependent).
+   * aOutBadConstraint - Result: nonzero if failed to apply. Name of culprit.
+   */
+
+  nsresult
+  UpdateExisting(AllocationHandle* aHandle,
+                 NormalizedConstraints* aNewConstraints,
+                 const MediaEnginePrefs& aPrefs,
+                 const nsString& aDeviceId,
+                 const char** aOutBadConstraint);
+
+  nsresult
+  UpdateNew(AllocationHandle* aHandle,
+            const MediaEnginePrefs& aPrefs,
+            const nsString& aDeviceId,
+            const char** aOutBadConstraint) {
+    return UpdateExisting(aHandle, nullptr, aPrefs, aDeviceId, aOutBadConstraint);
+  }
+
   dom::MediaSourceEnum mMediaSource; // source of media (camera | application | screen)
   mozilla::camera::CaptureEngine mCapEngine;
 
   nsTArray<RefPtr<AllocationHandle>> mRegisteredHandles;
+
+  // To only restart camera when needed, we keep track previous settings.
+  webrtc::CaptureCapability mLastCapability;
 };
 
 }
 
 #endif /* MEDIAENGINE_REMOTE_VIDEO_SOURCE_H_ */