• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <WebRTC/RTCLogging.h>
14
15#import "ARDSettingsModel.h"
16
17const 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:(RTC_OBJC_TYPE(RTCCameraVideoCapturer) *)capturer
26                        settings:(ARDSettingsModel *)settings {
27  if (self = [super init]) {
28    _capturer = capturer;
29    _settings = settings;
30    _usingFrontCamera = YES;
31  }
32
33  return self;
34}
35
36- (void)startCapture {
37  AVCaptureDevicePosition position =
38      _usingFrontCamera ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack;
39  AVCaptureDevice *device = [self findDeviceForPosition:position];
40  AVCaptureDeviceFormat *format = [self selectFormatForDevice:device];
41
42  if (format == nil) {
43    RTCLogError(@"No valid formats for device %@", device);
44    NSAssert(NO, @"");
45
46    return;
47  }
48
49  NSInteger fps = [self selectFpsForFormat:format];
50
51  [_capturer startCaptureWithDevice:device format:format fps:fps];
52}
53
54- (void)stopCapture {
55  [_capturer stopCapture];
56}
57
58- (void)switchCamera {
59  _usingFrontCamera = !_usingFrontCamera;
60  [self startCapture];
61}
62
63#pragma mark - Private
64
65- (AVCaptureDevice *)findDeviceForPosition:(AVCaptureDevicePosition)position {
66  NSArray<AVCaptureDevice *> *captureDevices =
67      [RTC_OBJC_TYPE(RTCCameraVideoCapturer) captureDevices];
68  for (AVCaptureDevice *device in captureDevices) {
69    if (device.position == position) {
70      return device;
71    }
72  }
73  return captureDevices[0];
74}
75
76- (AVCaptureDeviceFormat *)selectFormatForDevice:(AVCaptureDevice *)device {
77  NSArray<AVCaptureDeviceFormat *> *formats =
78      [RTC_OBJC_TYPE(RTCCameraVideoCapturer) supportedFormatsForDevice:device];
79  int targetWidth = [_settings currentVideoResolutionWidthFromStore];
80  int targetHeight = [_settings currentVideoResolutionHeightFromStore];
81  AVCaptureDeviceFormat *selectedFormat = nil;
82  int currentDiff = INT_MAX;
83
84  for (AVCaptureDeviceFormat *format in formats) {
85    CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
86    FourCharCode pixelFormat = CMFormatDescriptionGetMediaSubType(format.formatDescription);
87    int diff = abs(targetWidth - dimension.width) + abs(targetHeight - dimension.height);
88    if (diff < currentDiff) {
89      selectedFormat = format;
90      currentDiff = diff;
91    } else if (diff == currentDiff && pixelFormat == [_capturer preferredOutputPixelFormat]) {
92      selectedFormat = format;
93    }
94  }
95
96  return selectedFormat;
97}
98
99- (NSInteger)selectFpsForFormat:(AVCaptureDeviceFormat *)format {
100  Float64 maxSupportedFramerate = 0;
101  for (AVFrameRateRange *fpsRange in format.videoSupportedFrameRateRanges) {
102    maxSupportedFramerate = fmax(maxSupportedFramerate, fpsRange.maxFrameRate);
103  }
104  return fmin(maxSupportedFramerate, kFramerateLimit);
105}
106
107@end
108