1 /*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "modules/desktop_capture/blank_detector_desktop_capturer_wrapper.h"
12
13 #include <stdint.h>
14
15 #include <utility>
16
17 #include "modules/desktop_capture/desktop_geometry.h"
18 #include "modules/desktop_capture/desktop_region.h"
19 #include "rtc_base/checks.h"
20 #include "system_wrappers/include/metrics.h"
21
22 namespace webrtc {
23
BlankDetectorDesktopCapturerWrapper(std::unique_ptr<DesktopCapturer> capturer,RgbaColor blank_pixel)24 BlankDetectorDesktopCapturerWrapper::BlankDetectorDesktopCapturerWrapper(
25 std::unique_ptr<DesktopCapturer> capturer,
26 RgbaColor blank_pixel)
27 : capturer_(std::move(capturer)), blank_pixel_(blank_pixel) {
28 RTC_DCHECK(capturer_);
29 }
30
31 BlankDetectorDesktopCapturerWrapper::~BlankDetectorDesktopCapturerWrapper() =
32 default;
33
Start(DesktopCapturer::Callback * callback)34 void BlankDetectorDesktopCapturerWrapper::Start(
35 DesktopCapturer::Callback* callback) {
36 callback_ = callback;
37 capturer_->Start(this);
38 }
39
SetSharedMemoryFactory(std::unique_ptr<SharedMemoryFactory> shared_memory_factory)40 void BlankDetectorDesktopCapturerWrapper::SetSharedMemoryFactory(
41 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) {
42 capturer_->SetSharedMemoryFactory(std::move(shared_memory_factory));
43 }
44
CaptureFrame()45 void BlankDetectorDesktopCapturerWrapper::CaptureFrame() {
46 RTC_DCHECK(callback_);
47 capturer_->CaptureFrame();
48 }
49
SetExcludedWindow(WindowId window)50 void BlankDetectorDesktopCapturerWrapper::SetExcludedWindow(WindowId window) {
51 capturer_->SetExcludedWindow(window);
52 }
53
GetSourceList(SourceList * sources)54 bool BlankDetectorDesktopCapturerWrapper::GetSourceList(SourceList* sources) {
55 return capturer_->GetSourceList(sources);
56 }
57
SelectSource(SourceId id)58 bool BlankDetectorDesktopCapturerWrapper::SelectSource(SourceId id) {
59 return capturer_->SelectSource(id);
60 }
61
FocusOnSelectedSource()62 bool BlankDetectorDesktopCapturerWrapper::FocusOnSelectedSource() {
63 return capturer_->FocusOnSelectedSource();
64 }
65
IsOccluded(const DesktopVector & pos)66 bool BlankDetectorDesktopCapturerWrapper::IsOccluded(const DesktopVector& pos) {
67 return capturer_->IsOccluded(pos);
68 }
69
OnCaptureResult(Result result,std::unique_ptr<DesktopFrame> frame)70 void BlankDetectorDesktopCapturerWrapper::OnCaptureResult(
71 Result result,
72 std::unique_ptr<DesktopFrame> frame) {
73 RTC_DCHECK(callback_);
74 if (result != Result::SUCCESS || non_blank_frame_received_) {
75 callback_->OnCaptureResult(result, std::move(frame));
76 return;
77 }
78
79 RTC_DCHECK(frame);
80
81 // If nothing has been changed in current frame, we do not need to check it
82 // again.
83 if (!frame->updated_region().is_empty() || is_first_frame_) {
84 last_frame_is_blank_ = IsBlankFrame(*frame);
85 is_first_frame_ = false;
86 }
87 RTC_HISTOGRAM_BOOLEAN("WebRTC.DesktopCapture.BlankFrameDetected",
88 last_frame_is_blank_);
89 if (!last_frame_is_blank_) {
90 non_blank_frame_received_ = true;
91 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
92 return;
93 }
94
95 callback_->OnCaptureResult(Result::ERROR_TEMPORARY,
96 std::unique_ptr<DesktopFrame>());
97 }
98
IsBlankFrame(const DesktopFrame & frame) const99 bool BlankDetectorDesktopCapturerWrapper::IsBlankFrame(
100 const DesktopFrame& frame) const {
101 // We will check 7489 pixels for a frame with 1024 x 768 resolution.
102 for (int i = 0; i < frame.size().width() * frame.size().height(); i += 105) {
103 const int x = i % frame.size().width();
104 const int y = i / frame.size().width();
105 if (!IsBlankPixel(frame, x, y)) {
106 return false;
107 }
108 }
109
110 // We are verifying the pixel in the center as well.
111 return IsBlankPixel(frame, frame.size().width() / 2,
112 frame.size().height() / 2);
113 }
114
IsBlankPixel(const DesktopFrame & frame,int x,int y) const115 bool BlankDetectorDesktopCapturerWrapper::IsBlankPixel(
116 const DesktopFrame& frame,
117 int x,
118 int y) const {
119 uint8_t* pixel_data = frame.GetFrameDataAtPos(DesktopVector(x, y));
120 return RgbaColor(pixel_data) == blank_pixel_;
121 }
122
123 } // namespace webrtc
124