text: /*
   *  Copyright (c) 2017 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 "modules/desktop_capture/blank_detector_desktop_capturer_wrapper.h"
  
  #include <memory>
  #include <utility>
  
  #include "modules/desktop_capture/desktop_capturer.h"
  #include "modules/desktop_capture/desktop_frame.h"
  #include "modules/desktop_capture/desktop_frame_generator.h"
  #include "modules/desktop_capture/desktop_geometry.h"
  #include "modules/desktop_capture/desktop_region.h"
  #include "modules/desktop_capture/fake_desktop_capturer.h"
  #include "test/gtest.h"
  
  namespace webrtc {
  
  class BlankDetectorDesktopCapturerWrapperTest
      : public testing::Test,
        public DesktopCapturer::Callback {
   public:
    BlankDetectorDesktopCapturerWrapperTest();
    ~BlankDetectorDesktopCapturerWrapperTest() override;
  
   protected:
    void PerfTest(DesktopCapturer* capturer);
  
    const int frame_width_ = 1024;
    const int frame_height_ = 768;
    std::unique_ptr<BlankDetectorDesktopCapturerWrapper> wrapper_;
    DesktopCapturer* capturer_ = nullptr;
    BlackWhiteDesktopFramePainter painter_;
    int num_frames_captured_ = 0;
    DesktopCapturer::Result last_result_ = DesktopCapturer::Result::SUCCESS;
    std::unique_ptr<DesktopFrame> last_frame_;
  
   private:
    // DesktopCapturer::Callback interface.
    void OnCaptureResult(DesktopCapturer::Result result,
                         std::unique_ptr<DesktopFrame> frame) override;
  
    PainterDesktopFrameGenerator frame_generator_;
  };
  
  BlankDetectorDesktopCapturerWrapperTest::
      BlankDetectorDesktopCapturerWrapperTest() {
    frame_generator_.size()->set(frame_width_, frame_height_);
    frame_generator_.set_desktop_frame_painter(&painter_);
    std::unique_ptr<DesktopCapturer> capturer(new FakeDesktopCapturer());
    FakeDesktopCapturer* fake_capturer =
        static_cast<FakeDesktopCapturer*>(capturer.get());
    fake_capturer->set_frame_generator(&frame_generator_);
    capturer_ = fake_capturer;
    wrapper_.reset(new BlankDetectorDesktopCapturerWrapper(
        std::move(capturer), RgbaColor(0, 0, 0, 0)));
    wrapper_->Start(this);
  }
  
  BlankDetectorDesktopCapturerWrapperTest::
      ~BlankDetectorDesktopCapturerWrapperTest() = default;
  
  void BlankDetectorDesktopCapturerWrapperTest::OnCaptureResult(
      DesktopCapturer::Result result,
      std::unique_ptr<DesktopFrame> frame) {
    last_result_ = result;
    last_frame_ = std::move(frame);
    num_frames_captured_++;
  }
  
  void BlankDetectorDesktopCapturerWrapperTest::PerfTest(
      DesktopCapturer* capturer) {
    for (int i = 0; i < 10000; i++) {
      capturer->CaptureFrame();
      ASSERT_EQ(num_frames_captured_, i + 1);
    }
  }
  
  TEST_F(BlankDetectorDesktopCapturerWrapperTest, ShouldDetectBlankFrame) {
    wrapper_->CaptureFrame();
    ASSERT_EQ(num_frames_captured_, 1);
    ASSERT_EQ(last_result_, DesktopCapturer::Result::ERROR_TEMPORARY);
    ASSERT_FALSE(last_frame_);
  }
  
  TEST_F(BlankDetectorDesktopCapturerWrapperTest, ShouldPassBlankDetection) {
    painter_.updated_region()->AddRect(DesktopRect::MakeXYWH(0, 0, 100, 100));
    wrapper_->CaptureFrame();
    ASSERT_EQ(num_frames_captured_, 1);
    ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
    ASSERT_TRUE(last_frame_);
  
    painter_.updated_region()->AddRect(
        DesktopRect::MakeXYWH(frame_width_ - 100, frame_height_ - 100, 100, 100));
    wrapper_->CaptureFrame();
    ASSERT_EQ(num_frames_captured_, 2);
    ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
    ASSERT_TRUE(last_frame_);
  
    painter_.updated_region()->AddRect(
        DesktopRect::MakeXYWH(0, frame_height_ - 100, 100, 100));
    wrapper_->CaptureFrame();
    ASSERT_EQ(num_frames_captured_, 3);
    ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
    ASSERT_TRUE(last_frame_);
  
    painter_.updated_region()->AddRect(
        DesktopRect::MakeXYWH(frame_width_ - 100, 0, 100, 100));
    wrapper_->CaptureFrame();
    ASSERT_EQ(num_frames_captured_, 4);
    ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
    ASSERT_TRUE(last_frame_);
  
    painter_.updated_region()->AddRect(DesktopRect::MakeXYWH(
        (frame_width_ >> 1) - 50, (frame_height_ >> 1) - 50, 100, 100));
    wrapper_->CaptureFrame();
    ASSERT_EQ(num_frames_captured_, 5);
    ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
    ASSERT_TRUE(last_frame_);
  }
  
  TEST_F(BlankDetectorDesktopCapturerWrapperTest,
         ShouldNotCheckAfterANonBlankFrameReceived) {
    wrapper_->CaptureFrame();
    ASSERT_EQ(num_frames_captured_, 1);
    ASSERT_EQ(last_result_, DesktopCapturer::Result::ERROR_TEMPORARY);
    ASSERT_FALSE(last_frame_);
  
    painter_.updated_region()->AddRect(
        DesktopRect::MakeXYWH(frame_width_ - 100, 0, 100, 100));
    wrapper_->CaptureFrame();
    ASSERT_EQ(num_frames_captured_, 2);
    ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
    ASSERT_TRUE(last_frame_);
  
    for (int i = 0; i < 100; i++) {
      wrapper_->CaptureFrame();
      ASSERT_EQ(num_frames_captured_, i + 3);
      ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
      ASSERT_TRUE(last_frame_);
    }
  }
  
  // There is no perceptible impact by using BlankDetectorDesktopCapturerWrapper.
  // i.e. less than 0.2ms per frame.
  // [ OK ] DISABLED_Performance (10210 ms)
  // [ OK ] DISABLED_PerformanceComparison (8791 ms)
  TEST_F(BlankDetectorDesktopCapturerWrapperTest, DISABLED_Performance) {
    PerfTest(wrapper_.get());
  }
  
  TEST_F(BlankDetectorDesktopCapturerWrapperTest,
         DISABLED_PerformanceComparison) {
    capturer_->Start(this);
    PerfTest(capturer_);
  }
  
  }  // namespace webrtc
  