Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Unified Diff: webrtc/modules/desktop_capture/screen_capturer_differ_wrapper_unittest.cc

Issue 2202443002: [WebRTC] Add ScreenCapturerDifferWrapper to share Differ across ScreenCapturers (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Sync latest changes Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/modules/desktop_capture/screen_capturer_differ_wrapper.cc ('k') | webrtc/modules/modules.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/modules/desktop_capture/screen_capturer_differ_wrapper_unittest.cc
diff --git a/webrtc/modules/desktop_capture/screen_capturer_differ_wrapper_unittest.cc b/webrtc/modules/desktop_capture/screen_capturer_differ_wrapper_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e667553b1474151980c38d6fcfb3365dda4ff9f5
--- /dev/null
+++ b/webrtc/modules/desktop_capture/screen_capturer_differ_wrapper_unittest.cc
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/desktop_capture/screen_capturer_differ_wrapper.h"
+
+#include <initializer_list>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/base/random.h"
+#include "webrtc/base/timeutils.h"
+#include "webrtc/modules/desktop_capture/desktop_geometry.h"
+#include "webrtc/modules/desktop_capture/desktop_region.h"
+#include "webrtc/modules/desktop_capture/differ_block.h"
+#include "webrtc/modules/desktop_capture/fake_screen_capturer.h"
+#include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
+#include "webrtc/system_wrappers/include/cpu_features_wrapper.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+
+namespace {
+
+// Compares and asserts |frame|.updated_region() equals to |rects|. This
+// function does not care about the order of the |rects| and it does not expect
+// DesktopRegion to return an exact area for each rectangle in |rects|.
+template <template <typename, typename...> class T = std::initializer_list,
+ typename... Rect>
+void AssertUpdatedRegionIs(const DesktopFrame& frame,
+ const T<DesktopRect, Rect...>& rects) {
+ DesktopRegion region;
+ for (const auto& rect : rects) {
+ region.AddRect(rect);
+ }
+ ASSERT_TRUE(frame.updated_region().Equals(region));
+}
+
+// Compares and asserts |frame|.updated_region() covers all rectangles in
+// |rects|, but does not cover areas other than a kBlockSize expansion. This
+// function does not care about the order of the |rects|, and it does not expect
+// DesktopRegion to return an exact area of each rectangle in |rects|.
+template <template <typename, typename...> class T = std::initializer_list,
+ typename... Rect>
+void AssertUpdatedRegionCovers(const DesktopFrame& frame,
+ const T<DesktopRect, Rect...>& rects) {
+ DesktopRegion region;
+ for (const auto& rect : rects) {
+ region.AddRect(rect);
+ }
+
+ // Intersect of |rects| and |frame|.updated_region() should be |rects|. i.e.
+ // |frame|.updated_region() should be a superset of |rects|.
+ DesktopRegion intersect(region);
+ intersect.IntersectWith(frame.updated_region());
+ ASSERT_TRUE(region.Equals(intersect));
+
+ // Difference between |rects| and |frame|.updated_region() should not cover
+ // areas which have larger than twice of kBlockSize width and height.
+ //
+ // Explanation of the 'twice' of kBlockSize (indeed kBlockSize * 2 - 2) is
+ // following,
+ // (Each block in the following grid is a 8 x 8 pixels area. X means the real
+ // updated area, m means the updated area marked by
+ // ScreenCapturerDifferWrapper.)
+ // +---+---+---+---+---+---+---+---+
+ // | X | m | m | m | m | m | m | m |
+ // +---+---+---+---+---+---+---+---+
+ // | m | m | m | m | m | m | m | m |
+ // +---+---+---+---+---+---+---+---+
+ // | m | m | m | m | m | m | m | m |
+ // +---+---+---+---+---+---+---+---+
+ // | m | m | m | m | m | m | m | X |
+ // +---+---+---+---+---+---+---+---+
+ // The top left [0, 0] - [8, 8] and right bottom [56, 24] - [64, 32] blocks of
+ // this area are updated. But since ScreenCapturerDifferWrapper compares
+ // 32 x 32 blocks by default, this entire area is marked as updated. So the
+ // [8, 8] - [56, 32] is expected to be covered in the difference.
+ //
+ // But if [0, 0] - [8, 8] and [64, 24] - [72, 32] blocks are updated,
+ // +---+---+---+---+---+---+---+---+---+---+---+---+
+ // | X | m | m | m | | | | | m | m | m | m |
+ // +---+---+---+---+---+---+---+---+---+---+---+---+
+ // | m | m | m | m | | | | | m | m | m | m |
+ // +---+---+---+---+---+---+---+---+---+---+---+---+
+ // | m | m | m | m | | | | | m | m | m | m |
+ // +---+---+---+---+---+---+---+---+---+---+---+---+
+ // | m | m | m | m | | | | | X | m | m | m |
+ // +---+---+---+---+---+---+---+---+---+---+---+---+
+ // the [8, 8] - [64, 32] is not expected to be covered in the difference. As
+ // ScreenCapturerDifferWrapper should only mark [0, 0] - [32, 32] and
+ // [64, 0] - [96, 32] as updated.
+ DesktopRegion differ(frame.updated_region());
+ differ.Subtract(region);
+ for (DesktopRegion::Iterator it(differ); !it.IsAtEnd(); it.Advance()) {
+ ASSERT_TRUE(it.rect().width() <= kBlockSize * 2 - 2 ||
+ it.rect().height() <= kBlockSize * 2 - 2);
+ }
+}
+
+// Executes a ScreenCapturerDifferWrapper::Capture() and compares its output
+// DesktopFrame::updated_region() with |updated_region| if |check_result| is
+// true. If |exactly_match| is true, AssertUpdatedRegionIs() will be used,
+// otherwise AssertUpdatedRegionCovers() will be used.
+template <template <typename, typename...> class T = std::initializer_list,
+ typename... Rect>
+void ExecuteDifferWrapperCase(BlackWhiteDesktopFramePainter* frame_painter,
+ ScreenCapturerDifferWrapper* capturer,
+ MockScreenCapturerCallback* callback,
+ const T<DesktopRect, Rect...>& updated_region,
+ bool check_result,
+ bool exactly_match) {
+ EXPECT_CALL(*callback,
+ OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, testing::_))
+ .Times(1)
+ .WillOnce(testing::Invoke([&updated_region, check_result, exactly_match](
+ DesktopCapturer::Result result,
+ std::unique_ptr<DesktopFrame>* frame) {
+ ASSERT_EQ(result, DesktopCapturer::Result::SUCCESS);
+ if (check_result) {
+ if (exactly_match) {
+ AssertUpdatedRegionIs(**frame, updated_region);
+ } else {
+ AssertUpdatedRegionCovers(**frame, updated_region);
+ }
+ }
+ }));
+ for (const auto& rect : updated_region) {
+ frame_painter->updated_region()->AddRect(rect);
+ }
+ capturer->Capture(DesktopRegion());
+}
+
+// Executes a ScreenCapturerDifferWrapper::Capture(), if updated_region() is not
+// set, this function will reset ScreenCapturerDifferWrapper internal
+// DesktopFrame into white.
+void ExecuteCapturer(ScreenCapturerDifferWrapper* capturer,
+ MockScreenCapturerCallback* callback) {
+ EXPECT_CALL(*callback,
+ OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, testing::_))
+ .Times(1);
+ capturer->Capture(DesktopRegion());
+}
+
+void ExecuteDifferWrapperTest(bool with_hints,
+ bool enlarge_updated_region,
+ bool random_updated_region,
+ bool check_result) {
+ const bool updated_region_should_exactly_match =
+ with_hints && !enlarge_updated_region && !random_updated_region;
+ BlackWhiteDesktopFramePainter frame_painter;
+ PainterDesktopFrameGenerator frame_generator;
+ frame_generator.set_desktop_frame_painter(&frame_painter);
+ std::unique_ptr<FakeScreenCapturer> fake(new FakeScreenCapturer());
+ fake->set_frame_generator(&frame_generator);
+ ScreenCapturerDifferWrapper capturer(std::move(fake));
+ MockScreenCapturerCallback callback;
+ frame_generator.set_provide_updated_region_hints(with_hints);
+ frame_generator.set_enlarge_updated_region(enlarge_updated_region);
+ frame_generator.set_add_random_updated_region(random_updated_region);
+
+ capturer.Start(&callback);
+
+ EXPECT_CALL(callback,
+ OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, testing::_))
+ .Times(1)
+ .WillOnce(testing::Invoke([](DesktopCapturer::Result result,
+ std::unique_ptr<DesktopFrame>* frame) {
+ ASSERT_EQ(result, DesktopCapturer::Result::SUCCESS);
+ AssertUpdatedRegionIs(**frame,
+ {DesktopRect::MakeSize((*frame)->size())});
+ }));
+ capturer.Capture(DesktopRegion());
+
+ ExecuteDifferWrapperCase(&frame_painter, &capturer, &callback,
+ {DesktopRect::MakeLTRB(100, 100, 200, 200),
+ DesktopRect::MakeLTRB(300, 300, 400, 400)},
+ check_result, updated_region_should_exactly_match);
+ ExecuteCapturer(&capturer, &callback);
+
+ ExecuteDifferWrapperCase(
+ &frame_painter, &capturer, &callback,
+ {DesktopRect::MakeLTRB(0, 0, 40, 40),
+ DesktopRect::MakeLTRB(0, frame_generator.size()->height() - 40, 40,
+ frame_generator.size()->height()),
+ DesktopRect::MakeLTRB(frame_generator.size()->width() - 40, 0,
+ frame_generator.size()->width(), 40),
+ DesktopRect::MakeLTRB(frame_generator.size()->width() - 40,
+ frame_generator.size()->height() - 40,
+ frame_generator.size()->width(),
+ frame_generator.size()->height())},
+ check_result, updated_region_should_exactly_match);
+
+ Random random(rtc::TimeMillis());
+ // Fuzzing tests.
+ for (int i = 0; i < 1000; i++) {
+ if (enlarge_updated_region) {
+ frame_generator.set_enlarge_range(random.Rand(1, 50));
+ }
+ frame_generator.size()->set(random.Rand(500, 2000), random.Rand(500, 2000));
+ ExecuteCapturer(&capturer, &callback);
+ std::vector<DesktopRect> updated_region;
+ for (int j = random.Rand(50); j >= 0; j--) {
+ // At least a 1 x 1 updated region.
+ const int left = random.Rand(0, frame_generator.size()->width() - 2);
+ const int top = random.Rand(0, frame_generator.size()->height() - 2);
+ const int right = random.Rand(left + 1, frame_generator.size()->width());
+ const int bottom = random.Rand(top + 1, frame_generator.size()->height());
+ updated_region.push_back(DesktopRect::MakeLTRB(left, top, right, bottom));
+ }
+ ExecuteDifferWrapperCase(&frame_painter, &capturer, &callback,
+ updated_region, check_result,
+ updated_region_should_exactly_match);
+ }
+}
+
+} // namespace
+
+TEST(ScreenCapturerDifferWrapperTest, CaptureWithoutHints) {
+ ExecuteDifferWrapperTest(false, false, false, true);
+}
+
+TEST(ScreenCapturerDifferWrapperTest, CaptureWithHints) {
+ ExecuteDifferWrapperTest(true, false, false, true);
+}
+
+TEST(ScreenCapturerDifferWrapperTest, CaptureWithEnlargedHints) {
+ ExecuteDifferWrapperTest(true, true, false, true);
+}
+
+TEST(ScreenCapturerDifferWrapperTest, CaptureWithRandomHints) {
+ ExecuteDifferWrapperTest(true, false, true, true);
+}
+
+TEST(ScreenCapturerDifferWrapperTest, CaptureWithEnlargedAndRandomHints) {
+ ExecuteDifferWrapperTest(true, true, true, true);
+}
+
+// When hints are provided, ScreenCapturerDifferWrapper has a slightly better
+// performance in current configuration, but not so significant. Following is
+// one run result.
+// [ RUN ] DISABLED_CaptureWithoutHintsPerf
+// [ OK ] DISABLED_CaptureWithoutHintsPerf (7118 ms)
+// [ RUN ] DISABLED_CaptureWithHintsPerf
+// [ OK ] DISABLED_CaptureWithHintsPerf (5580 ms)
+// [ RUN ] DISABLED_CaptureWithEnlargedHintsPerf
+// [ OK ] DISABLED_CaptureWithEnlargedHintsPerf (5974 ms)
+// [ RUN ] DISABLED_CaptureWithRandomHintsPerf
+// [ OK ] DISABLED_CaptureWithRandomHintsPerf (6184 ms)
+// [ RUN ] DISABLED_CaptureWithEnlargedAndRandomHintsPerf
+// [ OK ] DISABLED_CaptureWithEnlargedAndRandomHintsPerf (6347 ms)
+TEST(ScreenCapturerDifferWrapperTest, DISABLED_CaptureWithoutHintsPerf) {
+ int64_t started = rtc::TimeMillis();
+ ExecuteDifferWrapperTest(false, false, false, false);
+ ASSERT_LE(rtc::TimeMillis() - started, 15000);
+}
+
+TEST(ScreenCapturerDifferWrapperTest, DISABLED_CaptureWithHintsPerf) {
+ int64_t started = rtc::TimeMillis();
+ ExecuteDifferWrapperTest(true, false, false, false);
+ ASSERT_LE(rtc::TimeMillis() - started, 15000);
+}
+
+TEST(ScreenCapturerDifferWrapperTest, DISABLED_CaptureWithEnlargedHintsPerf) {
+ int64_t started = rtc::TimeMillis();
+ ExecuteDifferWrapperTest(true, true, false, false);
+ ASSERT_LE(rtc::TimeMillis() - started, 15000);
+}
+
+TEST(ScreenCapturerDifferWrapperTest, DISABLED_CaptureWithRandomHintsPerf) {
+ int64_t started = rtc::TimeMillis();
+ ExecuteDifferWrapperTest(true, false, true, false);
+ ASSERT_LE(rtc::TimeMillis() - started, 15000);
+}
+
+TEST(ScreenCapturerDifferWrapperTest,
+ DISABLED_CaptureWithEnlargedAndRandomHintsPerf) {
+ int64_t started = rtc::TimeMillis();
+ ExecuteDifferWrapperTest(true, true, true, false);
+ ASSERT_LE(rtc::TimeMillis() - started, 15000);
+}
+
+} // namespace webrtc
« no previous file with comments | « webrtc/modules/desktop_capture/screen_capturer_differ_wrapper.cc ('k') | webrtc/modules/modules.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698