Bug 1450658 - Should bring window to front when screen-sharing a window; r=pehrsons
authorDan Minor <dminor@mozilla.com>
Tue, 08 May 2018 15:55:36 -0400
changeset 474671 182095efdd8ee87e268cf59cd06cc51e80bb6cc0
parent 474670 1c736d73f5d927b85ddd21691ce4b36be5a81141
child 474672 d34ba6416eaab77e7c344c90d72e6d99d172f2d8
push id9374
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:43:20 +0000
treeherdermozilla-beta@160e085dfb0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspehrsons
bugs1450658
milestone62.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 1450658 - Should bring window to front when screen-sharing a window; r=pehrsons This adds a FocusOnSelectedSource method to PCameras and uses it to focus the selected window while window sharing. We can't just focus the window as soon as it is shared because we have a live preview in the getUserMedia permissions prompt which would cause the prompt to lose focus. Instead, this only focuses the window when the sharing is not done from a chrome context. MozReview-Commit-ID: 5jre75E3JLi
dom/media/MediaManager.cpp
dom/media/MediaManager.h
dom/media/systemservices/CamerasChild.cpp
dom/media/systemservices/CamerasChild.h
dom/media/systemservices/CamerasParent.cpp
dom/media/systemservices/CamerasParent.h
dom/media/systemservices/PCameras.ipdl
dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
dom/media/webrtc/MediaEngineRemoteVideoSource.h
dom/media/webrtc/MediaEngineSource.cpp
dom/media/webrtc/MediaEngineSource.h
dom/media/webrtc/MediaEngineTabVideoSource.cpp
dom/media/webrtc/MediaEngineTabVideoSource.h
media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_and_cursor_composer.cc
media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_and_cursor_composer.h
media/webrtc/trunk/webrtc/modules/video_capture/video_capture.h
media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc
media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1001,16 +1001,23 @@ MediaDevice::Reconfigure(const dom::Medi
   return mSource->Reconfigure(mAllocationHandle,
                               aConstraints,
                               aPrefs,
                               mID,
                               aOutBadConstraint);
 }
 
 nsresult
+MediaDevice::FocusOnSelectedSource()
+{
+  MOZ_ASSERT(MediaManager::IsInMediaThread());
+  return mSource->FocusOnSelectedSource(mAllocationHandle);
+}
+
+nsresult
 MediaDevice::Stop()
 {
   MOZ_ASSERT(MediaManager::IsInMediaThread());
   return mSource->Stop(mAllocationHandle);
 }
 
 nsresult
 MediaDevice::Deallocate()
@@ -1114,17 +1121,18 @@ public:
     const nsMainThreadPtrHandle<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
     uint64_t aWindowID,
     GetUserMediaWindowListener* aWindowListener,
     SourceListener* aSourceListener,
     const ipc::PrincipalInfo& aPrincipalInfo,
     const MediaStreamConstraints& aConstraints,
     MediaDevice* aAudioDevice,
     MediaDevice* aVideoDevice,
-    PeerIdentity* aPeerIdentity)
+    PeerIdentity* aPeerIdentity,
+    bool aIsChrome)
     : Runnable("GetUserMediaStreamRunnable")
     , mOnSuccess(aOnSuccess)
     , mOnFailure(aOnFailure)
     , mConstraints(aConstraints)
     , mAudioDevice(aAudioDevice)
     , mVideoDevice(aVideoDevice)
     , mWindowID(aWindowID)
     , mWindowListener(aWindowListener)
@@ -1704,16 +1712,23 @@ public:
           nsTArray<RefPtr<MediaDevice>> devices;
           devices.AppendElement(mVideoDevice);
           badConstraint = MediaConstraintsHelper::SelectSettings(
               NormalizedConstraints(constraints), devices, mIsChrome);
         }
         if (mAudioDevice) {
           mAudioDevice->Deallocate();
         }
+      } else {
+        if (!mIsChrome) {
+          rv = mVideoDevice->FocusOnSelectedSource();
+          if (NS_FAILED(rv)) {
+            LOG(("FocusOnSelectedSource failed"));
+          }
+        }
       }
     }
     if (errorMsg) {
       LOG(("%s %" PRIu32, errorMsg, static_cast<uint32_t>(rv)));
       if (badConstraint) {
         Fail(MediaMgrError::Name::OverconstrainedError,
              NS_LITERAL_STRING(""),
              NS_ConvertUTF8toUTF16(badConstraint));
@@ -1736,17 +1751,17 @@ public:
       peerIdentity = new PeerIdentity(mConstraints.mPeerIdentity);
     }
 
     NS_DispatchToMainThread(do_AddRef(
         new GetUserMediaStreamRunnable(mOnSuccess, mOnFailure, mWindowID,
                                        mWindowListener, mSourceListener,
                                        mPrincipalInfo, mConstraints,
                                        mAudioDevice, mVideoDevice,
-                                       peerIdentity)));
+                                       peerIdentity, mIsChrome)));
     return NS_OK;
   }
 
   nsresult
   Denied(MediaMgrError::Name aName,
          const nsAString& aMessage = EmptyString())
   {
     MOZ_ASSERT(mOnSuccess);
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -84,16 +84,17 @@ public:
                     const char** aOutBadConstraint);
   nsresult SetTrack(const RefPtr<SourceMediaStream>& aStream,
                     TrackID aTrackID,
                     const PrincipalHandle& aPrincipal);
   nsresult Start();
   nsresult Reconfigure(const dom::MediaTrackConstraints& aConstraints,
                        const MediaEnginePrefs& aPrefs,
                        const char** aOutBadConstraint);
+  nsresult FocusOnSelectedSource();
   nsresult Stop();
   nsresult Deallocate();
 
   void Pull(const RefPtr<SourceMediaStream>& aStream,
             TrackID aTrackID,
             StreamTime aDesiredTime,
             const PrincipalHandle& aPrincipal);
 
--- a/dom/media/systemservices/CamerasChild.cpp
+++ b/dom/media/systemservices/CamerasChild.cpp
@@ -535,16 +535,32 @@ CamerasChild::StartCapture(CaptureEngine
       aCapEngine,
       capture_id,
       capCap);
   LockAndDispatch<> dispatcher(this, __func__, runnable, -1, mZero);
   return dispatcher.ReturnValue();
 }
 
 int
+CamerasChild::FocusOnSelectedSource(CaptureEngine aCapEngine,
+                                    const int aCaptureId)
+{
+  LOG((__PRETTY_FUNCTION__));
+  nsCOMPtr<nsIRunnable> runnable =
+    mozilla::NewRunnableMethod<CaptureEngine, int>(
+      "camera::PCamerasChild::SendFocusOnSelectedSource",
+      this,
+      &CamerasChild::SendFocusOnSelectedSource,
+      aCapEngine,
+      aCaptureId);
+  LockAndDispatch<> dispatcher(this, __func__, runnable, -1, mZero);
+  return dispatcher.ReturnValue();
+}
+
+int
 CamerasChild::StopCapture(CaptureEngine aCapEngine, const int capture_id)
 {
   LOG((__PRETTY_FUNCTION__));
   nsCOMPtr<nsIRunnable> runnable =
     mozilla::NewRunnableMethod<CaptureEngine, int>(
       "camera::PCamerasChild::SendStopCapture",
       this,
       &CamerasChild::SendStopCapture,
--- a/dom/media/systemservices/CamerasChild.h
+++ b/dom/media/systemservices/CamerasChild.h
@@ -187,16 +187,17 @@ public:
   int NumberOfCaptureDevices(CaptureEngine aCapEngine);
   int NumberOfCapabilities(CaptureEngine aCapEngine,
                            const char* deviceUniqueIdUTF8);
   int ReleaseCaptureDevice(CaptureEngine aCapEngine,
                            const int capture_id);
   int StartCapture(CaptureEngine aCapEngine,
                    const int capture_id, webrtc::VideoCaptureCapability& capability,
                    FrameRelay* func);
+  int FocusOnSelectedSource(CaptureEngine aCapEngine, const int capture_id);
   int StopCapture(CaptureEngine aCapEngine, const int capture_id);
   int AllocateCaptureDevice(CaptureEngine aCapEngine,
                             const char* unique_idUTF8,
                             const unsigned int unique_idUTF8Length,
                             int& capture_id,
                             const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
   int GetCaptureCapability(CaptureEngine aCapEngine,
                            const char* unique_idUTF8,
--- a/dom/media/systemservices/CamerasParent.cpp
+++ b/dom/media/systemservices/CamerasParent.cpp
@@ -972,16 +972,53 @@ CamerasParent::RecvStartCapture(const Ca
         });
       self->mPBackgroundEventTarget->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
       return NS_OK;
     });
   DispatchToVideoCaptureThread(webrtc_runnable);
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult
+CamerasParent::RecvFocusOnSelectedSource(const CaptureEngine& aCapEngine,
+                                         const int& aCapNum)
+{
+  LOG((__PRETTY_FUNCTION__));
+  RefPtr<Runnable> webrtc_runnable =
+    media::NewRunnableFrom([self = RefPtr<CamerasParent>(this),
+                            aCapEngine, aCapNum]() -> nsresult {
+      if (auto engine = self->EnsureInitialized(aCapEngine)) {
+        engine->WithEntry(aCapNum, [self](VideoEngine::CaptureEntry& cap){
+          if (cap.VideoCapture()) {
+            bool result = cap.VideoCapture()->FocusOnSelectedSource();
+            RefPtr<nsIRunnable> ipc_runnable =
+              media::NewRunnableFrom([self, result]() -> nsresult {
+                if (!self->mChildIsAlive) {
+                  return NS_ERROR_FAILURE;
+                }
+
+                if (result) {
+                  Unused << self->SendReplySuccess();
+                  return NS_OK;
+                }
+
+                Unused << self->SendReplyFailure();
+                return NS_ERROR_FAILURE;
+              });
+            self->mPBackgroundEventTarget->Dispatch(ipc_runnable,
+                                                    NS_DISPATCH_NORMAL);
+          }
+        });
+      }
+      return NS_ERROR_FAILURE;
+  });
+  DispatchToVideoCaptureThread(webrtc_runnable);
+  return IPC_OK();
+}
+
 void
 CamerasParent::StopCapture(const CaptureEngine& aCapEngine,
                            const int& capnum)
 {
   if (auto engine = EnsureInitialized(aCapEngine)) {
     // we're removing elements, iterate backwards
     for (size_t i = mCallbacks.Length(); i > 0; i--) {
       if (mCallbacks[i - 1]->mCapEngine == aCapEngine &&
--- a/dom/media/systemservices/CamerasParent.h
+++ b/dom/media/systemservices/CamerasParent.h
@@ -94,16 +94,18 @@ public:
   mozilla::ipc::IPCResult RecvNumberOfCaptureDevices(const CaptureEngine&) override;
   mozilla::ipc::IPCResult RecvNumberOfCapabilities(const CaptureEngine&,
                                                    const nsCString&) override;
   mozilla::ipc::IPCResult RecvGetCaptureCapability(const CaptureEngine&, const nsCString&,
                                                    const int&) override;
   mozilla::ipc::IPCResult RecvGetCaptureDevice(const CaptureEngine&, const int&) override;
   mozilla::ipc::IPCResult RecvStartCapture(const CaptureEngine&, const int&,
                                            const VideoCaptureCapability&) override;
+  mozilla::ipc::IPCResult RecvFocusOnSelectedSource(const CaptureEngine&,
+                                                    const int&) override;
   mozilla::ipc::IPCResult RecvStopCapture(const CaptureEngine&, const int&) override;
   mozilla::ipc::IPCResult RecvReleaseFrame(mozilla::ipc::Shmem&&) override;
   mozilla::ipc::IPCResult RecvAllDone() override;
   void ActorDestroy(ActorDestroyReason aWhy) override;
   mozilla::ipc::IPCResult RecvEnsureInitialized(const CaptureEngine&) override;
 
   nsIEventTarget* GetBackgroundEventTarget() { return mPBackgroundEventTarget; };
   bool IsShuttingDown()
--- a/dom/media/systemservices/PCameras.ipdl
+++ b/dom/media/systemservices/PCameras.ipdl
@@ -75,16 +75,17 @@ parent:
   async GetCaptureCapability(CaptureEngine engine, nsCString unique_idUTF8,
                              int capability_number);
   async GetCaptureDevice(CaptureEngine engine, int num);
 
   async AllocateCaptureDevice(CaptureEngine engine, nsCString unique_idUTF8,
                               PrincipalInfo principal);
   async ReleaseCaptureDevice(CaptureEngine engine, int numdev);
   async StartCapture(CaptureEngine engine, int numdev, VideoCaptureCapability capability);
+  async FocusOnSelectedSource(CaptureEngine engine, int numdev);
   async StopCapture(CaptureEngine engine, int numdev);
   // transfers frame back
   async ReleaseFrame(Shmem s);
 
   // Ask parent to delete us
   async AllDone();
   // setup camera engine
   async EnsureInitialized(CaptureEngine engine);
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -338,16 +338,28 @@ MediaEngineRemoteVideoSource::Start(cons
     }
     settings->mFrameRate.Value() = cap.maxFPS;
   }));
 
   return NS_OK;
 }
 
 nsresult
+MediaEngineRemoteVideoSource::FocusOnSelectedSource(const RefPtr<const AllocationHandle>& aHandle)
+{
+  LOG((__PRETTY_FUNCTION__));
+  AssertIsOnOwningThread();
+
+  int result;
+  result = camera::GetChildAndCall(&camera::CamerasChild::FocusOnSelectedSource,
+                                   mCapEngine, mCaptureIndex);
+  return result == 0 ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult
 MediaEngineRemoteVideoSource::Stop(const RefPtr<const AllocationHandle>& aHandle)
 {
   LOG((__PRETTY_FUNCTION__));
   AssertIsOnOwningThread();
 
   if (mState == kStopped || mState == kAllocated) {
     return NS_OK;
   }
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.h
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.h
@@ -139,16 +139,17 @@ public:
                     TrackID aTrackID,
                     const PrincipalHandle& aPrincipal) override;
   nsresult Start(const RefPtr<const AllocationHandle>& aHandle) override;
   nsresult Reconfigure(const RefPtr<AllocationHandle>& aHandle,
                        const dom::MediaTrackConstraints& aConstraints,
                        const MediaEnginePrefs& aPrefs,
                        const nsString& aDeviceId,
                        const char** aOutBadConstraint) override;
+  nsresult FocusOnSelectedSource(const RefPtr<const AllocationHandle>& aHandle) override;
   nsresult Stop(const RefPtr<const AllocationHandle>& aHandle) override;
   void Pull(const RefPtr<const AllocationHandle>& aHandle,
             const RefPtr<SourceMediaStream>& aStream,
             TrackID aTrackID,
             StreamTime aDesiredTime,
             const PrincipalHandle& aPrincipalHandle) override;
 
 
--- a/dom/media/webrtc/MediaEngineSource.cpp
+++ b/dom/media/webrtc/MediaEngineSource.cpp
@@ -50,16 +50,22 @@ MediaEngineSource::IsFake() const
 }
 
 bool
 MediaEngineSource::GetScary() const
 {
   return false;
 }
 
+nsresult
+MediaEngineSource::FocusOnSelectedSource(const RefPtr<const AllocationHandle>& aHandle)
+{
+  return NS_ERROR_NOT_AVAILABLE;
+}
+
 void
 MediaEngineSource::Shutdown()
 {
 }
 
 nsresult
 MediaEngineSource::TakePhoto(MediaEnginePhotoCallback* aCallback)
 {
--- a/dom/media/webrtc/MediaEngineSource.h
+++ b/dom/media/webrtc/MediaEngineSource.h
@@ -147,16 +147,29 @@ public:
    * the given AllocationHandle.
    *
    * If this is the first AllocationHandle to start, the underlying device
    * will be started.
    */
   virtual nsresult Start(const RefPtr<const AllocationHandle>& aHandle) = 0;
 
   /**
+   * This brings focus to the selected source, e.g. to bring a captured window
+   * to the front.
+   *
+   * We return one of the following:
+   * NS_OK                    - Success.
+   * NS_ERROR_NOT_AVAILABLE   - For backends where focusing does not make sense.
+   * NS_ERROR_NOT_IMPLEMENTED - For backends where focusing makes sense, but
+   *                            is not yet implemented.
+   * NS_ERROR_FAILURE         - Failures reported from underlying code.
+   */
+  virtual nsresult FocusOnSelectedSource(const RefPtr<const AllocationHandle>& aHandle) = 0;
+
+  /**
    * Applies new constraints to the capability selection for the underlying
    * device.
    *
    * Should the constraints lead to choosing a new capability while the device
    * is actively being captured, the device will restart using the new
    * capability.
    *
    * We return one of the following:
@@ -274,16 +287,19 @@ public:
   bool RequiresSharing() const override;
 
   // Not fake by default.
   bool IsFake() const override;
 
   // Not scary by default.
   bool GetScary() const override;
 
+  // Returns NS_ERROR_NOT_AVAILABLE by default.
+  nsresult FocusOnSelectedSource(const RefPtr<const AllocationHandle>& aHandle) override;
+
   // Shutdown does nothing by default.
   void Shutdown() override;
 
   // TakePhoto returns NS_ERROR_NOT_IMPLEMENTED by default,
   // to tell the caller to fallback to other methods.
   nsresult TakePhoto(MediaEnginePhotoCallback* aCallback) override;
 
   // Makes aOutSettings empty by default.
--- a/dom/media/webrtc/MediaEngineTabVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.cpp
@@ -392,16 +392,22 @@ MediaEngineTabVideoSource::Draw() {
   RefPtr<layers::SourceSurfaceImage> image = new layers::SourceSurfaceImage(size, surface);
 
   MutexAutoLock lock(mMutex);
   mImage = image;
   mImageSize = size;
 }
 
 nsresult
+MediaEngineTabVideoSource::FocusOnSelectedSource(const RefPtr<const AllocationHandle>& aHandle)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
 MediaEngineTabVideoSource::Stop(const RefPtr<const AllocationHandle>& aHandle)
 {
   AssertIsOnOwningThread();
 
   if (mState == kStopped || mState == kAllocated) {
     return NS_OK;
   }
 
--- a/dom/media/webrtc/MediaEngineTabVideoSource.h
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.h
@@ -41,16 +41,17 @@ public:
                     TrackID aTrackID,
                     const PrincipalHandle& aPrincipal) override;
   nsresult Start(const RefPtr<const AllocationHandle>& aHandle) override;
   nsresult Reconfigure(const RefPtr<AllocationHandle>& aHandle,
                        const dom::MediaTrackConstraints& aConstraints,
                        const MediaEnginePrefs& aPrefs,
                        const nsString& aDeviceId,
                        const char** aOutBadConstraint) override;
+  nsresult FocusOnSelectedSource(const RefPtr<const AllocationHandle>& aHandle) override;
   nsresult Stop(const RefPtr<const AllocationHandle>& aHandle) override;
 
   void Pull(const RefPtr<const AllocationHandle>& aHandle,
             const RefPtr<SourceMediaStream>& aStream,
             TrackID aTrackID,
             StreamTime aDesiredTime,
             const PrincipalHandle& aPrincipalHandle) override;
 
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_and_cursor_composer.cc
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_and_cursor_composer.cc
@@ -179,9 +179,13 @@ void DesktopAndCursorComposer::OnMouseCu
 
 void DesktopAndCursorComposer::OnMouseCursorPosition(
     MouseCursorMonitor::CursorState state,
     const DesktopVector& position) {
   cursor_state_ = state;
   cursor_position_ = position;
 }
 
+bool DesktopAndCursorComposer::FocusOnSelectedSource() {
+  return desktop_capturer_->FocusOnSelectedSource();
+}
+
 }  // namespace webrtc
--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_and_cursor_composer.h
+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_and_cursor_composer.h
@@ -35,16 +35,17 @@ class DesktopAndCursorComposer : public 
 
   // DesktopCapturer interface.
   void Start(DesktopCapturer::Callback* callback) override;
   void Stop() override;
   void SetSharedMemoryFactory(
       std::unique_ptr<SharedMemoryFactory> shared_memory_factory) override;
   void CaptureFrame() override;
   void SetExcludedWindow(WindowId window) override;
+  bool FocusOnSelectedSource() override;
 
  private:
   // DesktopCapturer::Callback interface.
   void OnCaptureResult(DesktopCapturer::Result result,
                        std::unique_ptr<DesktopFrame> frame) override;
 
   // MouseCursorMonitor::Callback interface.
   void OnMouseCursor(MouseCursor* cursor) override;
--- a/media/webrtc/trunk/webrtc/modules/video_capture/video_capture.h
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/video_capture.h
@@ -163,16 +163,18 @@ class VideoCaptureModule: public rtc::Re
       rtc::VideoSinkInterface<VideoFrame> *dataCallback) = 0;
 
   // Start capture device
   virtual int32_t StartCapture(
       const VideoCaptureCapability& capability) = 0;
 
   virtual int32_t StopCaptureIfAllClientsClose() = 0;
 
+  virtual bool FocusOnSelectedSource() { return false; };
+
   virtual int32_t StopCapture() = 0;
 
   // Returns the name of the device used by this module.
   virtual const char* CurrentDeviceName() const = 0;
 
   // Returns true if the capture device is running
   virtual bool CaptureStarted() = 0;
 
--- a/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.cc
@@ -667,16 +667,21 @@ int32_t DesktopCaptureImpl::StartCapture
 
   desktop_capturer_cursor_composer_->Start(this);
   capturer_thread_->Start();
   started_ = true;
 
   return 0;
 }
 
+bool DesktopCaptureImpl::FocusOnSelectedSource()
+{
+  return desktop_capturer_cursor_composer_->FocusOnSelectedSource();
+}
+
 int32_t DesktopCaptureImpl::StopCapture() {
   if (started_) {
     capturer_thread_->Stop(); // thread is guaranteed stopped before this returns
     desktop_capturer_cursor_composer_->Stop();
     started_ = false;
     return 0;
   }
   return -1;
--- a/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h
+++ b/media/webrtc/trunk/webrtc/video_engine/desktop_capture_impl.h
@@ -187,16 +187,17 @@ public:
   // |capture_time| must be specified in the NTP time format in milliseconds.
   virtual int32_t IncomingFrame(uint8_t* videoFrame,
                                 size_t videoFrameLength,
                                 const VideoCaptureCapability& frameInfo,
                                 int64_t captureTime = 0) override;
 
   // Platform dependent
   virtual int32_t StartCapture(const VideoCaptureCapability& capability) override;
+  virtual bool FocusOnSelectedSource() override;
   virtual int32_t StopCapture() override;
   virtual bool CaptureStarted() override;
   virtual int32_t CaptureSettings(VideoCaptureCapability& settings) override;
 
 protected:
   DesktopCaptureImpl(const int32_t id);
   virtual ~DesktopCaptureImpl();
   int32_t DeliverCapturedFrame(webrtc::VideoFrame& captureFrame,