tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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