fallback_desktop_capturer_wrapper.cc (6522B)
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/fallback_desktop_capturer_wrapper.h" 12 13 #include <cstddef> 14 #include <memory> 15 #include <utility> 16 17 #include "api/sequence_checker.h" 18 #include "modules/desktop_capture/desktop_capture_types.h" 19 #include "modules/desktop_capture/desktop_capturer.h" 20 #include "modules/desktop_capture/desktop_frame.h" 21 #include "modules/desktop_capture/desktop_geometry.h" 22 #include "modules/desktop_capture/shared_memory.h" 23 #include "rtc_base/checks.h" 24 #include "system_wrappers/include/metrics.h" 25 26 namespace webrtc { 27 28 namespace { 29 30 // Implementation to share a SharedMemoryFactory between DesktopCapturer 31 // instances. This class is designed for synchronized DesktopCapturer 32 // implementations only. 33 class SharedMemoryFactoryProxy : public SharedMemoryFactory { 34 public: 35 // Users should maintain the lifetime of `factory` to ensure it overlives 36 // current instance. 37 static std::unique_ptr<SharedMemoryFactory> Create( 38 SharedMemoryFactory* factory); 39 ~SharedMemoryFactoryProxy() override; 40 41 // Forwards CreateSharedMemory() calls to `factory_`. Users should always call 42 // this function in one thread. Users should not call this function after the 43 // SharedMemoryFactory which current instance created from has been destroyed. 44 std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override; 45 46 private: 47 explicit SharedMemoryFactoryProxy(SharedMemoryFactory* factory); 48 49 SharedMemoryFactory* factory_ = nullptr; 50 SequenceChecker thread_checker_; 51 }; 52 53 } // namespace 54 55 SharedMemoryFactoryProxy::SharedMemoryFactoryProxy( 56 SharedMemoryFactory* factory) { 57 RTC_DCHECK(factory); 58 factory_ = factory; 59 } 60 61 // static 62 std::unique_ptr<SharedMemoryFactory> SharedMemoryFactoryProxy::Create( 63 SharedMemoryFactory* factory) { 64 return std::unique_ptr<SharedMemoryFactory>( 65 new SharedMemoryFactoryProxy(factory)); 66 } 67 68 SharedMemoryFactoryProxy::~SharedMemoryFactoryProxy() = default; 69 70 std::unique_ptr<SharedMemory> SharedMemoryFactoryProxy::CreateSharedMemory( 71 size_t size) { 72 RTC_DCHECK(thread_checker_.IsCurrent()); 73 return factory_->CreateSharedMemory(size); 74 } 75 76 FallbackDesktopCapturerWrapper::FallbackDesktopCapturerWrapper( 77 std::unique_ptr<DesktopCapturer> main_capturer, 78 std::unique_ptr<DesktopCapturer> secondary_capturer) 79 : main_capturer_(std::move(main_capturer)), 80 secondary_capturer_(std::move(secondary_capturer)) { 81 RTC_DCHECK(main_capturer_); 82 RTC_DCHECK(secondary_capturer_); 83 } 84 85 FallbackDesktopCapturerWrapper::~FallbackDesktopCapturerWrapper() = default; 86 87 void FallbackDesktopCapturerWrapper::Start( 88 DesktopCapturer::Callback* callback) { 89 callback_ = callback; 90 // FallbackDesktopCapturerWrapper catchs the callback of the main capturer, 91 // and checks its return value to decide whether the secondary capturer should 92 // be involved. 93 main_capturer_->Start(this); 94 // For the secondary capturer, we do not have a backup plan anymore, so 95 // FallbackDesktopCapturerWrapper won't check its return value any more. It 96 // will directly return to the input `callback`. 97 secondary_capturer_->Start(callback); 98 } 99 100 void FallbackDesktopCapturerWrapper::SetSharedMemoryFactory( 101 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) { 102 shared_memory_factory_ = std::move(shared_memory_factory); 103 if (shared_memory_factory_) { 104 main_capturer_->SetSharedMemoryFactory( 105 SharedMemoryFactoryProxy::Create(shared_memory_factory_.get())); 106 secondary_capturer_->SetSharedMemoryFactory( 107 SharedMemoryFactoryProxy::Create(shared_memory_factory_.get())); 108 } else { 109 main_capturer_->SetSharedMemoryFactory( 110 std::unique_ptr<SharedMemoryFactory>()); 111 secondary_capturer_->SetSharedMemoryFactory( 112 std::unique_ptr<SharedMemoryFactory>()); 113 } 114 } 115 116 void FallbackDesktopCapturerWrapper::CaptureFrame() { 117 RTC_DCHECK(callback_); 118 if (main_capturer_permanent_error_) { 119 secondary_capturer_->CaptureFrame(); 120 } else { 121 main_capturer_->CaptureFrame(); 122 } 123 } 124 125 void FallbackDesktopCapturerWrapper::SetExcludedWindow(WindowId window) { 126 main_capturer_->SetExcludedWindow(window); 127 secondary_capturer_->SetExcludedWindow(window); 128 } 129 130 bool FallbackDesktopCapturerWrapper::GetSourceList(SourceList* sources) { 131 if (main_capturer_permanent_error_) { 132 return secondary_capturer_->GetSourceList(sources); 133 } 134 return main_capturer_->GetSourceList(sources); 135 } 136 137 bool FallbackDesktopCapturerWrapper::SelectSource(SourceId id) { 138 if (main_capturer_permanent_error_) { 139 return secondary_capturer_->SelectSource(id); 140 } 141 const bool main_capturer_result = main_capturer_->SelectSource(id); 142 RTC_HISTOGRAM_BOOLEAN( 143 "WebRTC.DesktopCapture.PrimaryCapturerSelectSourceError", 144 main_capturer_result); 145 if (!main_capturer_result) { 146 main_capturer_permanent_error_ = true; 147 } 148 149 return secondary_capturer_->SelectSource(id); 150 } 151 152 bool FallbackDesktopCapturerWrapper::FocusOnSelectedSource() { 153 if (main_capturer_permanent_error_) { 154 return secondary_capturer_->FocusOnSelectedSource(); 155 } 156 return main_capturer_->FocusOnSelectedSource() || 157 secondary_capturer_->FocusOnSelectedSource(); 158 } 159 160 bool FallbackDesktopCapturerWrapper::IsOccluded(const DesktopVector& pos) { 161 // Returns true if either capturer returns true. 162 if (main_capturer_permanent_error_) { 163 return secondary_capturer_->IsOccluded(pos); 164 } 165 return main_capturer_->IsOccluded(pos) || 166 secondary_capturer_->IsOccluded(pos); 167 } 168 169 void FallbackDesktopCapturerWrapper::OnCaptureResult( 170 Result result, 171 std::unique_ptr<DesktopFrame> frame) { 172 RTC_DCHECK(callback_); 173 RTC_HISTOGRAM_BOOLEAN("WebRTC.DesktopCapture.PrimaryCapturerError", 174 result != Result::SUCCESS); 175 RTC_HISTOGRAM_BOOLEAN("WebRTC.DesktopCapture.PrimaryCapturerPermanentError", 176 result == Result::ERROR_PERMANENT); 177 if (result == Result::SUCCESS) { 178 callback_->OnCaptureResult(result, std::move(frame)); 179 return; 180 } 181 182 if (result == Result::ERROR_PERMANENT) { 183 main_capturer_permanent_error_ = true; 184 } 185 secondary_capturer_->CaptureFrame(); 186 } 187 188 } // namespace webrtc