Wrap ScreenCapturer with ScreenCapturerDifferWrapper
This change is to add an DesktopCapturerOptions accurate_updated_region() with
default value as false to indicate whether a pixel-wise differentiation is
required. And ScreenCapturer::Create() function will wrap the implementation
with ScreenCapturerDifferWrapper.

Chromoting will use this option to filter out unchanged frames.

BUG=314516

Review-Url: https://codereview.webrtc.org/2314323002
Cr-Original-Commit-Position: refs/heads/master@{#14248}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: e9a3c7f43c697c3c1e7c8956baebeaf2a1a867f6
diff --git a/modules/desktop_capture/desktop_capture_options.h b/modules/desktop_capture/desktop_capture_options.h
index 2aa3e51..d872d7d 100644
--- a/modules/desktop_capture/desktop_capture_options.h
+++ b/modules/desktop_capture/desktop_capture_options.h
@@ -72,6 +72,16 @@
     disable_effects_ = disable_effects;
   }
 
+  // Flag that should be set if the consumer uses updated_region() and the
+  // capturer should try to provide correct updated_region() for the frames it
+  // generates (e.g. by comparing each frame with the previous one).
+  // TODO(zijiehe): WindowCapturer ignores this opinion until we merge
+  // ScreenCapturer and WindowCapturer interfaces.
+  bool detect_updated_region() const { return detect_updated_region_; }
+  void set_detect_updated_region(bool detect_updated_region) {
+    detect_updated_region_ = detect_updated_region;
+  }
+
 #if defined(WEBRTC_WIN)
   bool allow_use_magnification_api() const {
     return allow_use_magnification_api_;
@@ -110,6 +120,7 @@
   bool use_update_notifications_ = true;
 #endif
   bool disable_effects_ = true;
+  bool detect_updated_region_ = false;
 };
 
 }  // namespace webrtc
diff --git a/modules/desktop_capture/screen_capturer_mac.mm b/modules/desktop_capture/screen_capturer_mac.mm
index 7cb1720..451cd9e 100644
--- a/modules/desktop_capture/screen_capturer_mac.mm
+++ b/modules/desktop_capture/screen_capturer_mac.mm
@@ -14,6 +14,7 @@
 
 #include <memory>
 #include <set>
+#include <utility>
 
 #include <ApplicationServices/ApplicationServices.h>
 #include <Cocoa/Cocoa.h>
@@ -33,6 +34,7 @@
 #include "webrtc/modules/desktop_capture/mac/desktop_configuration_monitor.h"
 #include "webrtc/modules/desktop_capture/mac/scoped_pixel_buffer_object.h"
 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h"
+#include "webrtc/modules/desktop_capture/screen_capturer_differ_wrapper.h"
 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h"
 #include "webrtc/modules/desktop_capture/shared_desktop_frame.h"
 #include "webrtc/system_wrappers/include/logging.h"
@@ -937,10 +939,16 @@
   if (!options.configuration_monitor())
     return nullptr;
 
-  std::unique_ptr<ScreenCapturerMac> capturer(
+  std::unique_ptr<ScreenCapturer> capturer(
       new ScreenCapturerMac(options.configuration_monitor()));
-  if (!capturer->Init())
-    capturer.reset();
+  if (!static_cast<ScreenCapturerMac*>(capturer.get())->Init()) {
+    return nullptr;
+  }
+
+  if (options.detect_updated_region()) {
+    capturer.reset(new ScreenCapturerDifferWrapper(std::move(capturer)));
+  }
+
   return capturer.release();
 }
 
diff --git a/modules/desktop_capture/screen_capturer_unittest.cc b/modules/desktop_capture/screen_capturer_unittest.cc
index 0236e3b..5c36716 100644
--- a/modules/desktop_capture/screen_capturer_unittest.cc
+++ b/modules/desktop_capture/screen_capturer_unittest.cc
@@ -129,15 +129,21 @@
   }
 
 #if defined(WEBRTC_WIN)
+  // Enable allow_directx_capturer in DesktopCaptureOptions, but let
+  // ScreenCapturer::Create to decide whether a DirectX capturer should be used.
+  void MaybeCreateDirectxCapturer() {
+    DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault());
+    options.set_allow_directx_capturer(true);
+    capturer_.reset(ScreenCapturer::Create(options));
+  }
+
   bool CreateDirectxCapturer() {
     if (!ScreenCapturerWinDirectx::IsSupported()) {
       LOG(LS_WARNING) << "Directx capturer is not supported";
       return false;
     }
 
-    DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault());
-    options.set_allow_directx_capturer(true);
-    capturer_.reset(ScreenCapturer::Create(options));
+    MaybeCreateDirectxCapturer();
     return true;
   }
 
@@ -382,6 +388,16 @@
   TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
 }
 
+// Disabled due to being flaky due to the fact that it useds rendering / UI,
+// see webrtc/6366.
+TEST_F(ScreenCapturerTest,
+       DISABLED_MaybeCaptureUpdatedRegionWithDirectxCapturer) {
+  // Even DirectX capturer is not supported in current system, we should be able
+  // to select a usable capturer.
+  MaybeCreateDirectxCapturer();
+  TestCaptureUpdatedRegion();
+}
+
 #endif  // defined(WEBRTC_WIN)
 
 }  // namespace webrtc
diff --git a/modules/desktop_capture/screen_capturer_win.cc b/modules/desktop_capture/screen_capturer_win.cc
index 6a83bec..1d05961 100644
--- a/modules/desktop_capture/screen_capturer_win.cc
+++ b/modules/desktop_capture/screen_capturer_win.cc
@@ -14,6 +14,7 @@
 #include <utility>
 
 #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
+#include "webrtc/modules/desktop_capture/screen_capturer_differ_wrapper.h"
 #include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
 #include "webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h"
 #include "webrtc/modules/desktop_capture/win/screen_capturer_win_magnifier.h"
@@ -30,8 +31,13 @@
     capturer.reset(new ScreenCapturerWinGdi(options));
   }
 
-  if (options.allow_use_magnification_api())
-    return new ScreenCapturerWinMagnifier(std::move(capturer));
+  if (options.allow_use_magnification_api()) {
+    capturer.reset(new ScreenCapturerWinMagnifier(std::move(capturer)));
+  }
+
+  if (options.detect_updated_region()) {
+    capturer.reset(new ScreenCapturerDifferWrapper(std::move(capturer)));
+  }
 
   return capturer.release();
 }
diff --git a/modules/desktop_capture/screen_capturer_x11.cc b/modules/desktop_capture/screen_capturer_x11.cc
index 57c2e5f..d274140 100644
--- a/modules/desktop_capture/screen_capturer_x11.cc
+++ b/modules/desktop_capture/screen_capturer_x11.cc
@@ -14,6 +14,7 @@
 
 #include <memory>
 #include <set>
+#include <utility>
 
 #include <X11/extensions/Xdamage.h>
 #include <X11/extensions/Xfixes.h>
@@ -27,6 +28,7 @@
 #include "webrtc/modules/desktop_capture/desktop_frame.h"
 #include "webrtc/modules/desktop_capture/differ.h"
 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h"
+#include "webrtc/modules/desktop_capture/screen_capturer_differ_wrapper.h"
 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h"
 #include "webrtc/modules/desktop_capture/shared_desktop_frame.h"
 #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
@@ -426,9 +428,15 @@
   if (!options.x_display())
     return nullptr;
 
-  std::unique_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux());
-  if (!capturer->Init(options))
-    capturer.reset();
+  std::unique_ptr<ScreenCapturer> capturer(new ScreenCapturerLinux());
+  if (!static_cast<ScreenCapturerLinux*>(capturer.get())->Init(options)) {
+    return nullptr;
+  }
+
+  if (options.detect_updated_region()) {
+    capturer.reset(new ScreenCapturerDifferWrapper(std::move(capturer)));
+  }
+
   return capturer.release();
 }
 
diff --git a/modules/desktop_capture/win/screen_capturer_win_directx.cc b/modules/desktop_capture/win/screen_capturer_win_directx.cc
index e4b2c3e..9e3f58b 100644
--- a/modules/desktop_capture/win/screen_capturer_win_directx.cc
+++ b/modules/desktop_capture/win/screen_capturer_win_directx.cc
@@ -21,6 +21,7 @@
 
 using Microsoft::WRL::ComPtr;
 
+// static
 bool ScreenCapturerWinDirectx::IsSupported() {
   // Forward IsSupported function call to DxgiDuplicatorController.
   return DxgiDuplicatorController::Instance()->IsSupported();
diff --git a/modules/desktop_capture/win/screen_capturer_win_directx.h b/modules/desktop_capture/win/screen_capturer_win_directx.h
index 119ffae..86232c7 100644
--- a/modules/desktop_capture/win/screen_capturer_win_directx.h
+++ b/modules/desktop_capture/win/screen_capturer_win_directx.h
@@ -28,10 +28,11 @@
 // implementation won't work when ScreenCaptureFrameQueue.kQueueLength is not 2.
 class ScreenCapturerWinDirectx : public ScreenCapturer {
  public:
-  // Whether the system support DirectX based capturing.
+  // Whether the system supports DirectX based capturing.
   static bool IsSupported();
 
   explicit ScreenCapturerWinDirectx(const DesktopCaptureOptions& options);
+
   virtual ~ScreenCapturerWinDirectx();
 
   void Start(Callback* callback) override;