Bug 1450658 - Should bring window to front when screen-sharing a window; r?pehrsons draft
authorDan Minor <dminor@mozilla.com>
Tue, 08 May 2018 15:55:36 -0400
changeset 801432 87b9fc6fe5e8122947a995a170d9ec11535909df
parent 800874 f01bb6245db1ea2a87e5360104a4110571265137
child 801433 2e2caebbdf6e688e40c015dbf2c0c030393d10e6
child 801739 6edb1d369bdc8e8d47f15ce46488ca7f6cb33ce6
push id111664
push userbmo:dminor@mozilla.com
push dateWed, 30 May 2018 12:24:50 +0000
reviewerspehrsons
bugs1450658
milestone62.0a1
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,