tor-browser

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

sck_picker_handle.mm (3512B)


      1 /*
      2 *  Copyright (c) 2024 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 "sck_picker_handle.h"
     12 
     13 #import <ScreenCaptureKit/ScreenCaptureKit.h>
     14 
     15 #include "absl/base/attributes.h"
     16 #include "api/sequence_checker.h"
     17 
     18 #include <memory>
     19 #include <optional>
     20 
     21 namespace webrtc {
     22 
     23 class SckPickerProxy;
     24 
     25 class API_AVAILABLE(macos(14.0)) SckPickerProxy {
     26 public:
     27  static SckPickerProxy* Get() {
     28    static SckPickerProxy* g_picker = new SckPickerProxy();
     29    return g_picker;
     30  }
     31 
     32  bool AtCapacityLocked() const RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
     33    return handle_count_ == kMaximumStreamCount;
     34  }
     35 
     36  SCContentSharingPicker* GetPicker() const {
     37    return SCContentSharingPicker.sharedPicker;
     38  }
     39 
     40  ABSL_MUST_USE_RESULT std::optional<DesktopCapturer::SourceId>
     41      AcquireSourceId() {
     42    MutexLock lock(&mutex_);
     43    if (AtCapacityLocked()) {
     44      return std::nullopt;
     45    }
     46    if (handle_count_ == 0) {
     47      auto* picker = GetPicker();
     48      picker.maximumStreamCount =
     49          [NSNumber numberWithUnsignedInt:kMaximumStreamCount];
     50      picker.active = YES;
     51    }
     52    handle_count_ += 1;
     53    unique_source_id_ += 1;
     54    return unique_source_id_;
     55  }
     56 
     57  void RelinquishSourceId(DesktopCapturer::SourceId source) {
     58    MutexLock lock(&mutex_);
     59    handle_count_ -= 1;
     60    if (handle_count_ > 0) {
     61      return;
     62    }
     63    GetPicker().active = NO;
     64  }
     65 
     66 private:
     67  // SckPickerProxy is a process-wide singleton. ScreenCapturerSck and
     68  // SckPickerHandle are largely single-threaded but may be used on different
     69  // threads. For instance some clients use a capturer on one thread for
     70  // enumeration and on another for frame capture. Since all those capturers
     71  // share the same SckPickerProxy instance, it must be thread-safe.
     72  Mutex mutex_;
     73  // 100 is an arbitrary number that seems high enough to never get reached,
     74  // while still providing a reasonably low upper bound.
     75  static constexpr size_t kMaximumStreamCount = 100;
     76  size_t handle_count_ RTC_GUARDED_BY(mutex_) = 0;
     77  DesktopCapturer::SourceId unique_source_id_ RTC_GUARDED_BY(mutex_) = 0;
     78 };
     79 
     80 class API_AVAILABLE(macos(14.0)) SckPickerHandle
     81    : public SckPickerHandleInterface {
     82 public:
     83  static std::unique_ptr<SckPickerHandle> Create(SckPickerProxy* proxy) {
     84    std::optional<DesktopCapturer::SourceId> id = proxy->AcquireSourceId();
     85    if (!id) {
     86      return nullptr;
     87    }
     88    return std::unique_ptr<SckPickerHandle>(new SckPickerHandle(proxy, *id));
     89  }
     90 
     91  ~SckPickerHandle() {
     92    RTC_DCHECK_RUN_ON(&thread_checker_);
     93    proxy_->RelinquishSourceId(source_);
     94  }
     95 
     96  SCContentSharingPicker* GetPicker() const override {
     97    return proxy_->GetPicker();
     98  }
     99 
    100  DesktopCapturer::SourceId Source() const override { return source_; }
    101 
    102 private:
    103  SckPickerHandle(SckPickerProxy* proxy, DesktopCapturer::SourceId source)
    104      : proxy_(proxy), source_(source) {
    105    RTC_DCHECK_RUN_ON(&thread_checker_);
    106  }
    107 
    108  webrtc::SequenceChecker thread_checker_;
    109  SckPickerProxy* const proxy_;
    110  const DesktopCapturer::SourceId source_;
    111 };
    112 
    113 std::unique_ptr<SckPickerHandleInterface> CreateSckPickerHandle() {
    114  return SckPickerHandle::Create(SckPickerProxy::Get());
    115 }
    116 
    117 }  // namespace webrtc