blob: 6afc6c894237041a9f012591fea3f3e289bada2a [file] [log] [blame]
sakalc522e752017-04-05 12:17:48 -07001/*
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
Anders Carlsson7bca8ca2018-08-30 09:30:29 +020013#import <WebRTC/RTCLogging.h>
14
sakalc522e752017-04-05 12:17:48 -070015#import "ARDSettingsModel.h"
16
Kári Tristan Helgason293865c2018-05-30 09:59:38 +020017const Float64 kFramerateLimit = 30.0;
18
sakalc522e752017-04-05 12:17:48 -070019@implementation ARDCaptureController {
20 RTCCameraVideoCapturer *_capturer;
21 ARDSettingsModel *_settings;
22 BOOL _usingFrontCamera;
23}
24
25- (instancetype)initWithCapturer:(RTCCameraVideoCapturer *)capturer
26 settings:(ARDSettingsModel *)settings {
Peter Hanspersd9b64cd2018-01-12 16:16:18 +010027 if (self = [super init]) {
sakalc522e752017-04-05 12:17:48 -070028 _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];
Peter Hanspersd92e0b52017-10-23 14:30:25 +020041
42 if (format == nil) {
43 RTCLogError(@"No valid formats for device %@", device);
44 NSAssert(NO, @"");
45
46 return;
47 }
48
sakalea12f4c2017-05-05 00:45:30 -070049 NSInteger fps = [self selectFpsForFormat:format];
sakalc522e752017-04-05 12:17:48 -070050
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 = [RTCCameraVideoCapturer captureDevices];
67 for (AVCaptureDevice *device in captureDevices) {
68 if (device.position == position) {
69 return device;
70 }
71 }
72 return captureDevices[0];
73}
74
75- (AVCaptureDeviceFormat *)selectFormatForDevice:(AVCaptureDevice *)device {
76 NSArray<AVCaptureDeviceFormat *> *formats =
77 [RTCCameraVideoCapturer supportedFormatsForDevice:device];
78 int targetWidth = [_settings currentVideoResolutionWidthFromStore];
79 int targetHeight = [_settings currentVideoResolutionHeightFromStore];
80 AVCaptureDeviceFormat *selectedFormat = nil;
81 int currentDiff = INT_MAX;
82
83 for (AVCaptureDeviceFormat *format in formats) {
84 CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
Anders Carlsson7dad2552017-11-15 15:59:50 +010085 FourCharCode pixelFormat = CMFormatDescriptionGetMediaSubType(format.formatDescription);
sakalc522e752017-04-05 12:17:48 -070086 int diff = abs(targetWidth - dimension.width) + abs(targetHeight - dimension.height);
87 if (diff < currentDiff) {
88 selectedFormat = format;
89 currentDiff = diff;
Anders Carlsson7dad2552017-11-15 15:59:50 +010090 } else if (diff == currentDiff && pixelFormat == [_capturer preferredOutputPixelFormat]) {
91 selectedFormat = format;
sakalc522e752017-04-05 12:17:48 -070092 }
93 }
94
sakalc522e752017-04-05 12:17:48 -070095 return selectedFormat;
96}
97
sakalea12f4c2017-05-05 00:45:30 -070098- (NSInteger)selectFpsForFormat:(AVCaptureDeviceFormat *)format {
Kári Tristan Helgason293865c2018-05-30 09:59:38 +020099 Float64 maxSupportedFramerate = 0;
sakalc522e752017-04-05 12:17:48 -0700100 for (AVFrameRateRange *fpsRange in format.videoSupportedFrameRateRanges) {
Kári Tristan Helgason293865c2018-05-30 09:59:38 +0200101 maxSupportedFramerate = fmax(maxSupportedFramerate, fpsRange.maxFrameRate);
sakalc522e752017-04-05 12:17:48 -0700102 }
Kári Tristan Helgason293865c2018-05-30 09:59:38 +0200103 return fmin(maxSupportedFramerate, kFramerateLimit);
sakalc522e752017-04-05 12:17:48 -0700104}
105
106@end