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