blob: 6830e88c23e589090546d39f1466d4b02f33549f [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
13#import "ARDSettingsModel.h"
Peter Hanspersd92e0b52017-10-23 14:30:25 +020014#import "WebRTC/RTCLogging.h"
sakalc522e752017-04-05 12:17:48 -070015
16@implementation ARDCaptureController {
17 RTCCameraVideoCapturer *_capturer;
18 ARDSettingsModel *_settings;
19 BOOL _usingFrontCamera;
20}
21
22- (instancetype)initWithCapturer:(RTCCameraVideoCapturer *)capturer
23 settings:(ARDSettingsModel *)settings {
24 if ([super init]) {
25 _capturer = capturer;
26 _settings = settings;
27 _usingFrontCamera = YES;
28 }
29
30 return self;
31}
32
33- (void)startCapture {
34 AVCaptureDevicePosition position =
35 _usingFrontCamera ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack;
36 AVCaptureDevice *device = [self findDeviceForPosition:position];
37 AVCaptureDeviceFormat *format = [self selectFormatForDevice:device];
Peter Hanspersd92e0b52017-10-23 14:30:25 +020038
39 if (format == nil) {
40 RTCLogError(@"No valid formats for device %@", device);
41 NSAssert(NO, @"");
42
43 return;
44 }
45
sakalea12f4c2017-05-05 00:45:30 -070046 NSInteger fps = [self selectFpsForFormat:format];
sakalc522e752017-04-05 12:17:48 -070047
48 [_capturer startCaptureWithDevice:device format:format fps:fps];
49}
50
51- (void)stopCapture {
52 [_capturer stopCapture];
53}
54
55- (void)switchCamera {
56 _usingFrontCamera = !_usingFrontCamera;
57 [self startCapture];
58}
59
60#pragma mark - Private
61
62- (AVCaptureDevice *)findDeviceForPosition:(AVCaptureDevicePosition)position {
63 NSArray<AVCaptureDevice *> *captureDevices = [RTCCameraVideoCapturer captureDevices];
64 for (AVCaptureDevice *device in captureDevices) {
65 if (device.position == position) {
66 return device;
67 }
68 }
69 return captureDevices[0];
70}
71
72- (AVCaptureDeviceFormat *)selectFormatForDevice:(AVCaptureDevice *)device {
73 NSArray<AVCaptureDeviceFormat *> *formats =
74 [RTCCameraVideoCapturer supportedFormatsForDevice:device];
75 int targetWidth = [_settings currentVideoResolutionWidthFromStore];
76 int targetHeight = [_settings currentVideoResolutionHeightFromStore];
77 AVCaptureDeviceFormat *selectedFormat = nil;
78 int currentDiff = INT_MAX;
79
80 for (AVCaptureDeviceFormat *format in formats) {
81 CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
Anders Carlsson7dad2552017-11-15 15:59:50 +010082 FourCharCode pixelFormat = CMFormatDescriptionGetMediaSubType(format.formatDescription);
sakalc522e752017-04-05 12:17:48 -070083 int diff = abs(targetWidth - dimension.width) + abs(targetHeight - dimension.height);
84 if (diff < currentDiff) {
85 selectedFormat = format;
86 currentDiff = diff;
Anders Carlsson7dad2552017-11-15 15:59:50 +010087 } else if (diff == currentDiff && pixelFormat == [_capturer preferredOutputPixelFormat]) {
88 selectedFormat = format;
sakalc522e752017-04-05 12:17:48 -070089 }
90 }
91
sakalc522e752017-04-05 12:17:48 -070092 return selectedFormat;
93}
94
sakalea12f4c2017-05-05 00:45:30 -070095- (NSInteger)selectFpsForFormat:(AVCaptureDeviceFormat *)format {
sakalc522e752017-04-05 12:17:48 -070096 Float64 maxFramerate = 0;
97 for (AVFrameRateRange *fpsRange in format.videoSupportedFrameRateRanges) {
98 maxFramerate = fmax(maxFramerate, fpsRange.maxFrameRate);
99 }
100 return maxFramerate;
101}
102
103@end