| 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..808f9863d5cd608c8d0571bdd656219efd7b2ee7
|
| --- /dev/null
|
| +++ b/webrtc/modules/desktop_capture/screen_capturer_differ_wrapper_unittest.cc
|
| @@ -0,0 +1,282 @@
|
| +/*
|
| + * 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 {
|
| +
|
| +// ScreenCapturerDifferWrapper always use a 32 x 32 pixel block. So we normalize
|
| +// the |rects|.
|
| +DesktopRect NormalizeDesktopRect(DesktopRect rect, DesktopSize size) {
|
| + DesktopRect block_size_rect = DesktopRect::MakeLTRB(
|
| + rect.left() / kBlockSize * kBlockSize,
|
| + rect.top() / kBlockSize * kBlockSize,
|
| + (rect.right() + kBlockSize - 1) / kBlockSize * kBlockSize,
|
| + (rect.bottom() + kBlockSize - 1) / kBlockSize * kBlockSize);
|
| + block_size_rect.IntersectWith(DesktopRect::MakeSize(size));
|
| + return block_size_rect;
|
| +}
|
| +
|
| +// Compares and asserts |frame|.updated_region() equals to |rects|. This
|
| +// function does not care about the order of the |rects|.
|
| +template <template <typename, typename...> class T = std::initializer_list,
|
| + typename... Rect>
|
| +void AssertUpdatedRegionIs(const DesktopFrame& frame,
|
| + const T<DesktopRect, Rect...>& rects) {
|
| + for (const DesktopRect& rect : rects) {
|
| + DesktopRect block_size_rect = NormalizeDesktopRect(rect, frame.size());
|
| + bool found = false;
|
| + for (DesktopRegion::Iterator it(frame.updated_region()); !it.IsAtEnd();
|
| + it.Advance()) {
|
| + if (it.rect().equals(block_size_rect)) {
|
| + found = true;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + ASSERT_TRUE(found);
|
| + }
|
| +}
|
| +
|
| +// 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(NormalizeDesktopRect(rect, frame.size()));
|
| + }
|
| + ASSERT_TRUE(frame.updated_region().Equals(region));
|
| +}
|
| +
|
| +// 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(BlackWhiteDesktopFrameGenerator* frame_generator,
|
| + 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_generator->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) {
|
| + BlackWhiteDesktopFrameGenerator frame_generator;
|
| + std::unique_ptr<FakeScreenCapturer> fake(new FakeScreenCapturer());
|
| + fake->set_frame_generator(&frame_generator);
|
| + ScreenCapturerDifferWrapper capturer(std::move(fake), !with_hints);
|
| + 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_generator, &capturer, &callback,
|
| + {DesktopRect::MakeLTRB(100, 100, 200, 200),
|
| + DesktopRect::MakeLTRB(300, 300, 400, 400)},
|
| + check_result, true);
|
| + ExecuteCapturer(&capturer, &callback);
|
| +
|
| + ExecuteDifferWrapperCase(
|
| + &frame_generator, &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, true);
|
| +
|
| + 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_generator, &capturer, &callback,
|
| + updated_region, check_result, false);
|
| + }
|
| +}
|
| +
|
| +} // 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);
|
| +}
|
| +
|
| +// SSE2 is not available on ARM / MIPS, so the performance should be extremely
|
| +// lower.
|
| +#if defined(WEBRTC_ARCH_X86_FAMILY)
|
| +// When hints are enabled, ScreenCapturerDifferWrapper has a slightly better
|
| +// performance in current configuration, but not so significant. Following is
|
| +// one run result.
|
| +// [ RUN ] DISABLED_CaptureWithoutHintsPerf
|
| +// [ OK ] DISABLED_CaptureWithoutHintsPerf (8889 ms)
|
| +// [ RUN ] DISABLED_CaptureWithHintsPerf
|
| +// [ OK ] DISABLED_CaptureWithHintsPerf (7814 ms)
|
| +// [ RUN ] DISABLED_CaptureWithEnlargedHintsPerf
|
| +// [ OK ] DISABLED_CaptureWithEnlargedHintsPerf (7999 ms)
|
| +// [ RUN ] DISABLED_CaptureWithRandomHintsPerf
|
| +// [ OK ] DISABLED_CaptureWithRandomHintsPerf (8429 ms)
|
| +// [ RUN ] DISABLED_CaptureWithEnlargedAndRandomHintsPerf
|
| +// [ OK ] DISABLED_CaptureWithEnlargedAndRandomHintsPerf (8552 ms)
|
| +TEST(ScreenCapturerDifferWrapperTest, DISABLED_CaptureWithoutHintsPerf) {
|
| + if (WebRtc_GetCPUInfo(kSSE2) == 0) {
|
| + return;
|
| + }
|
| +
|
| + int64_t started = rtc::TimeMillis();
|
| + ExecuteDifferWrapperTest(false, false, false, false);
|
| + ASSERT_LE(rtc::TimeMillis() - started, 15000);
|
| +}
|
| +
|
| +TEST(ScreenCapturerDifferWrapperTest, DISABLED_CaptureWithHintsPerf) {
|
| + if (WebRtc_GetCPUInfo(kSSE2) == 0) {
|
| + return;
|
| + }
|
| +
|
| + int64_t started = rtc::TimeMillis();
|
| + ExecuteDifferWrapperTest(true, false, false, false);
|
| + ASSERT_LE(rtc::TimeMillis() - started, 15000);
|
| +}
|
| +
|
| +TEST(ScreenCapturerDifferWrapperTest, DISABLED_CaptureWithEnlargedHintsPerf) {
|
| + if (WebRtc_GetCPUInfo(kSSE2) == 0) {
|
| + return;
|
| + }
|
| +
|
| + int64_t started = rtc::TimeMillis();
|
| + ExecuteDifferWrapperTest(true, true, false, false);
|
| + ASSERT_LE(rtc::TimeMillis() - started, 15000);
|
| +}
|
| +
|
| +TEST(ScreenCapturerDifferWrapperTest, DISABLED_CaptureWithRandomHintsPerf) {
|
| + if (WebRtc_GetCPUInfo(kSSE2) == 0) {
|
| + return;
|
| + }
|
| +
|
| + int64_t started = rtc::TimeMillis();
|
| + ExecuteDifferWrapperTest(true, false, true, false);
|
| + ASSERT_LE(rtc::TimeMillis() - started, 15000);
|
| +}
|
| +
|
| +TEST(ScreenCapturerDifferWrapperTest,
|
| + DISABLED_CaptureWithEnlargedAndRandomHintsPerf) {
|
| + if (WebRtc_GetCPUInfo(kSSE2) == 0) {
|
| + return;
|
| + }
|
| +
|
| + int64_t started = rtc::TimeMillis();
|
| + ExecuteDifferWrapperTest(true, true, true, false);
|
| + ASSERT_LE(rtc::TimeMillis() - started, 15000);
|
| +}
|
| +#endif
|
| +
|
| +} // namespace webrtc
|
|
|