tor-browser

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

ARDCaptureController.m (3761B)


      1 /*
      2 *  Copyright 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 #import "ARDCaptureController.h"
     12 
     13 #import "sdk/objc/base/RTCLogging.h"
     14 
     15 #import "ARDSettingsModel.h"
     16 
     17 const Float64 kFramerateLimit = 30.0;
     18 
     19 @implementation ARDCaptureController {
     20  RTC_OBJC_TYPE(RTCCameraVideoCapturer) * _capturer;
     21  ARDSettingsModel *_settings;
     22  BOOL _usingFrontCamera;
     23 }
     24 
     25 - (instancetype)initWithCapturer:
     26                    (RTC_OBJC_TYPE(RTCCameraVideoCapturer) *)capturer
     27                        settings:(ARDSettingsModel *)settings {
     28  self = [super init];
     29  if (self) {
     30    _capturer = capturer;
     31    _settings = settings;
     32    _usingFrontCamera = YES;
     33  }
     34  return self;
     35 }
     36 
     37 - (void)startCapture {
     38  [self startCapture:nil];
     39 }
     40 
     41 - (void)startCapture:(void (^)(NSError *))completion {
     42  AVCaptureDevicePosition position = _usingFrontCamera ?
     43      AVCaptureDevicePositionFront :
     44      AVCaptureDevicePositionBack;
     45  AVCaptureDevice *device = [self findDeviceForPosition:position];
     46  AVCaptureDeviceFormat *format = [self selectFormatForDevice:device];
     47 
     48  if (format == nil) {
     49    RTCLogError(@"No valid formats for device %@", device);
     50    NSAssert(NO, @"");
     51 
     52    return;
     53  }
     54 
     55  NSInteger fps = [self selectFpsForFormat:format];
     56 
     57  [_capturer startCaptureWithDevice:device
     58                             format:format
     59                                fps:fps
     60                  completionHandler:completion];
     61 }
     62 
     63 - (void)stopCapture {
     64  [_capturer stopCapture];
     65 }
     66 
     67 - (void)switchCamera {
     68  _usingFrontCamera = !_usingFrontCamera;
     69  [self startCapture:nil];
     70 }
     71 
     72 - (void)switchCamera:(void (^)(NSError *))completion {
     73  _usingFrontCamera = !_usingFrontCamera;
     74  [self startCapture:completion];
     75 }
     76 
     77 #pragma mark - Private
     78 
     79 - (AVCaptureDevice *)findDeviceForPosition:(AVCaptureDevicePosition)position {
     80  NSArray<AVCaptureDevice *> *captureDevices =
     81      [RTC_OBJC_TYPE(RTCCameraVideoCapturer) captureDevices];
     82  for (AVCaptureDevice *device in captureDevices) {
     83    if (device.position == position) {
     84      return device;
     85    }
     86  }
     87  return captureDevices[0];
     88 }
     89 
     90 - (AVCaptureDeviceFormat *)selectFormatForDevice:(AVCaptureDevice *)device {
     91  NSArray<AVCaptureDeviceFormat *> *formats =
     92      [RTC_OBJC_TYPE(RTCCameraVideoCapturer) supportedFormatsForDevice:device];
     93  int targetWidth = [_settings currentVideoResolutionWidthFromStore];
     94  int targetHeight = [_settings currentVideoResolutionHeightFromStore];
     95  AVCaptureDeviceFormat *selectedFormat = nil;
     96  int currentDiff = INT_MAX;
     97 
     98  for (AVCaptureDeviceFormat *format in formats) {
     99    CMVideoDimensions dimension =
    100        CMVideoFormatDescriptionGetDimensions(format.formatDescription);
    101    FourCharCode pixelFormat =
    102        CMFormatDescriptionGetMediaSubType(format.formatDescription);
    103    int diff = abs(targetWidth - dimension.width) +
    104        abs(targetHeight - dimension.height);
    105    if (diff < currentDiff) {
    106      selectedFormat = format;
    107      currentDiff = diff;
    108    } else if (diff == currentDiff &&
    109               pixelFormat == [_capturer preferredOutputPixelFormat]) {
    110      selectedFormat = format;
    111    }
    112  }
    113 
    114  return selectedFormat;
    115 }
    116 
    117 - (NSInteger)selectFpsForFormat:(AVCaptureDeviceFormat *)format {
    118  Float64 maxSupportedFramerate = 0;
    119  for (AVFrameRateRange *fpsRange in format.videoSupportedFrameRateRanges) {
    120    maxSupportedFramerate = fmax(maxSupportedFramerate, fpsRange.maxFrameRate);
    121  }
    122  return fmin(maxSupportedFramerate, kFramerateLimit);
    123 }
    124 
    125 @end