| Index: webrtc/modules/desktop_capture/screen_capturer_unittest.cc
|
| diff --git a/webrtc/modules/desktop_capture/screen_capturer_unittest.cc b/webrtc/modules/desktop_capture/screen_capturer_unittest.cc
|
| index 6d2c0eb0658221f98ebb4f34d18a22076de8521a..66f1d7e52afbb5641dc7e29af0ba3f265c912561 100644
|
| --- a/webrtc/modules/desktop_capture/screen_capturer_unittest.cc
|
| +++ b/webrtc/modules/desktop_capture/screen_capturer_unittest.cc
|
| @@ -8,8 +8,12 @@
|
| * be found in the AUTHORS file in the root of the source tree.
|
| */
|
|
|
| +#include <string.h>
|
| +
|
| +#include <algorithm>
|
| #include <memory>
|
| #include <utility>
|
| +#include <vector>
|
|
|
| #include "webrtc/modules/desktop_capture/screen_capturer.h"
|
|
|
| @@ -21,6 +25,8 @@
|
| #include "webrtc/modules/desktop_capture/desktop_frame.h"
|
| #include "webrtc/modules/desktop_capture/desktop_region.h"
|
| #include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
|
| +#include "webrtc/modules/desktop_capture/screen_painter.h"
|
| +#include "webrtc/system_wrappers/include/sleep.h"
|
|
|
| #if defined(WEBRTC_WIN)
|
| #include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
|
| @@ -34,6 +40,109 @@ const int kTestSharedMemoryId = 123;
|
|
|
| namespace webrtc {
|
|
|
| +namespace {
|
| +
|
| +ACTION_P(SaveUniquePtrArg, dest) {
|
| + *dest = std::move(*arg1);
|
| +}
|
| +
|
| +// Expects |capturer| to successfully capture a frame, and returns it.
|
| +std::unique_ptr<DesktopFrame> CaptureFrame(
|
| + ScreenCapturer* capturer,
|
| + MockScreenCapturerCallback* callback) {
|
| + std::unique_ptr<DesktopFrame> frame;
|
| + EXPECT_CALL(*callback,
|
| + OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
|
| + .WillOnce(SaveUniquePtrArg(&frame));
|
| + capturer->Capture(DesktopRegion());
|
| + EXPECT_TRUE(frame);
|
| + return frame;
|
| +}
|
| +
|
| +// Expects color in |rect| of |frame| is |color|.
|
| +void ExpectPixelsAreColoredBy(const DesktopFrame& frame,
|
| + DesktopRect rect,
|
| + ScreenPainter::Color color) {
|
| + uint8_t* row = frame.GetFrameDataAtPos(rect.top_left());
|
| + for (int i = 0; i < rect.height(); i++) {
|
| + uint8_t* column = row;
|
| + for (int j = 0; j < rect.width(); j++) {
|
| + ASSERT_EQ(color, column);
|
| + column += DesktopFrame::kBytesPerPixel;
|
| + }
|
| + row += frame.stride();
|
| + }
|
| +}
|
| +
|
| +// Finds the visible region and offset of ScreenDrawer drawable region in
|
| +// ScreenCapturer reachable area. The top left of the DesktopRect returned is
|
| +// the offset of ScreenDrawer drawable region, which maps to (0, 0) of
|
| +// ScreenDrawer::DrawableRegion(). The size of the DesktopRect indicates the
|
| +// size of visible region. So to ensure rendering a shape in the visible area of
|
| +// ScreenCapturer, you can randomize points within the DesktopRect::size() and
|
| +// use DesktopRect::Translate(-top_left().left(), -top_left().top()) or
|
| +// DesktopVector::subtract(top_left()) to translate into the coordinate of
|
| +// ScreenDrawer. This function returns an empty DesktopRect if calibration
|
| +// failed.
|
| +DesktopRect CalibrateScreenDrawerPosition(
|
| + ScreenPainter* painter,
|
| + ScreenCapturer* capturer,
|
| + MockScreenCapturerCallback* callback) {
|
| + const int kAnchorSize = 20;
|
| + if (painter->DrawableRegion().width() < kAnchorSize ||
|
| + painter->DrawableRegion().height() < 1) {
|
| + LOG(LS_WARNING) << "DrawableRegion is too small for calibration.";
|
| + return DesktopRect();
|
| + }
|
| + std::vector<ScreenPainter::Color> anchor_colors;
|
| + painter->Clear();
|
| + painter->DrawColorfulHorizontalLine(DesktopVector(), kAnchorSize,
|
| + &anchor_colors);
|
| + // We do not need a very accurate positiin, so reduce the sample rate by
|
| + // 1/256. This usually does not make too much difference.
|
| + for (int i = std::max(painter->DrawableRegion().width(),
|
| + painter->DrawableRegion().height()) -
|
| + 1;
|
| + i > 0; i -= 16) {
|
| + for (int j = i; j < std::max(painter->DrawableRegion().width(),
|
| + painter->DrawableRegion().height()) -
|
| + 1;
|
| + j += anchor_colors.size() * 16) {
|
| + painter->DrawColorfulHorizontalLine(DesktopVector(j, i), anchor_colors);
|
| + }
|
| + }
|
| + painter->WaitForPendingPaintings();
|
| +
|
| + std::unique_ptr<DesktopFrame> frame = CaptureFrame(capturer, callback);
|
| + painter->Clear();
|
| + if (!frame) {
|
| + return DesktopRect();
|
| + }
|
| +
|
| + const uint8_t* const end =
|
| + frame->data() + frame->stride() * frame->size().height() -
|
| + anchor_colors.size() * sizeof(ScreenPainter::Color);
|
| + DesktopVector top_left(-1, -1);
|
| + DesktopVector right_bottom;
|
| + for (const uint8_t* i = frame->data(); i < end;
|
| + i += DesktopFrame::kBytesPerPixel) {
|
| + if (ScreenPainter::Color::PixelsMatch(anchor_colors, i)) {
|
| + right_bottom = frame->GetPosAtFrameData(i);
|
| + if (top_left.x() < 0 && top_left.y() < 0) {
|
| + top_left = right_bottom;
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (top_left.x() >= 0 && top_left.y() >= 0) {
|
| + return DesktopRect::MakeLTRB(top_left, right_bottom);
|
| + }
|
| +
|
| + return DesktopRect();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| class ScreenCapturerTest : public testing::Test {
|
| public:
|
| void SetUp() override {
|
| @@ -74,10 +183,6 @@ class FakeSharedMemoryFactory : public SharedMemoryFactory {
|
| RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemoryFactory);
|
| };
|
|
|
| -ACTION_P(SaveUniquePtrArg, dest) {
|
| - *dest = std::move(*arg1);
|
| -}
|
| -
|
| TEST_F(ScreenCapturerTest, GetScreenListAndSelectScreen) {
|
| webrtc::ScreenCapturer::ScreenList screens;
|
| EXPECT_TRUE(capturer_->GetScreenList(&screens));
|
| @@ -117,6 +222,44 @@ TEST_F(ScreenCapturerTest, Capture) {
|
| EXPECT_TRUE(it.IsAtEnd());
|
| }
|
|
|
| +TEST_F(ScreenCapturerTest, CaptureUpdatedRegion) {
|
| + std::unique_ptr<ScreenPainter> painter = ScreenPainter::Create();
|
| + if (!painter || painter->DrawableRegion().is_empty()) {
|
| + LOG(LS_WARNING) << "No ScreenPainter implementation for current platform.";
|
| + return;
|
| + }
|
| + capturer_->Start(&callback_);
|
| +
|
| + const DesktopRect anchor =
|
| + CalibrateScreenDrawerPosition(painter.get(), capturer_.get(), &callback_);
|
| + if (anchor.is_empty()) {
|
| + LOG(LS_WARNING) << "Failed to calibrate ScreenDrawer, it usually means "
|
| + "ScreenDrawer cannot draw in ScreenCapturer reachable "
|
| + "area.";
|
| + return;
|
| + }
|
| +
|
| + painter->Clear();
|
| + ScreenPainter::Color color;
|
| + DesktopRect rect;
|
| + painter->DrawRandomColorRectangleIn(anchor.size(), &color, &rect);
|
| + rect.Translate(anchor.top_left());
|
| + painter->WaitForPendingPaintings();
|
| + std::unique_ptr<DesktopFrame> frame =
|
| + CaptureFrame(capturer_.get(), &callback_);
|
| + if (!frame) {
|
| + return;
|
| + }
|
| +
|
| + // updated_region() should cover the painted area.
|
| + DesktopRegion updated_region(frame->updated_region());
|
| + updated_region.IntersectWith(rect);
|
| + ASSERT_TRUE(updated_region.Equals(DesktopRegion(rect)));
|
| +
|
| + // Color in the |rect| should be |color|.
|
| + ExpectPixelsAreColoredBy(*frame, rect, color);
|
| +}
|
| +
|
| #if defined(WEBRTC_WIN)
|
|
|
| TEST_F(ScreenCapturerTest, UseSharedBuffers) {
|
|
|