1/* 2 * Copyright 2016 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 "ARDSettingsModel+Private.h" 12#import "ARDSettingsStore.h" 13 14#import "sdk/objc/api/peerconnection/RTCMediaConstraints.h" 15#import "sdk/objc/components/capturer/RTCCameraVideoCapturer.h" 16#import "sdk/objc/components/video_codec/RTCDefaultVideoEncoderFactory.h" 17 18NS_ASSUME_NONNULL_BEGIN 19 20@interface ARDSettingsModel () { 21 ARDSettingsStore *_settingsStore; 22} 23@end 24 25@implementation ARDSettingsModel 26 27- (NSArray<NSString *> *)availableVideoResolutions { 28 NSMutableSet<NSArray<NSNumber *> *> *resolutions = 29 [[NSMutableSet<NSArray<NSNumber *> *> alloc] init]; 30 for (AVCaptureDevice *device in [RTC_OBJC_TYPE(RTCCameraVideoCapturer) captureDevices]) { 31 for (AVCaptureDeviceFormat *format in 32 [RTC_OBJC_TYPE(RTCCameraVideoCapturer) supportedFormatsForDevice:device]) { 33 CMVideoDimensions resolution = 34 CMVideoFormatDescriptionGetDimensions(format.formatDescription); 35 NSArray<NSNumber *> *resolutionObject = @[ @(resolution.width), @(resolution.height) ]; 36 [resolutions addObject:resolutionObject]; 37 } 38 } 39 40 NSArray<NSArray<NSNumber *> *> *sortedResolutions = 41 [[resolutions allObjects] sortedArrayUsingComparator:^NSComparisonResult( 42 NSArray<NSNumber *> *obj1, NSArray<NSNumber *> *obj2) { 43 NSComparisonResult cmp = [obj1.firstObject compare:obj2.firstObject]; 44 if (cmp != NSOrderedSame) { 45 return cmp; 46 } 47 return [obj1.lastObject compare:obj2.lastObject]; 48 }]; 49 50 NSMutableArray<NSString *> *resolutionStrings = [[NSMutableArray<NSString *> alloc] init]; 51 for (NSArray<NSNumber *> *resolution in sortedResolutions) { 52 NSString *resolutionString = 53 [NSString stringWithFormat:@"%@x%@", resolution.firstObject, resolution.lastObject]; 54 [resolutionStrings addObject:resolutionString]; 55 } 56 57 return [resolutionStrings copy]; 58} 59 60- (NSString *)currentVideoResolutionSettingFromStore { 61 [self registerStoreDefaults]; 62 return [[self settingsStore] videoResolution]; 63} 64 65- (BOOL)storeVideoResolutionSetting:(NSString *)resolution { 66 if (![[self availableVideoResolutions] containsObject:resolution]) { 67 return NO; 68 } 69 [[self settingsStore] setVideoResolution:resolution]; 70 return YES; 71} 72 73- (NSArray<RTC_OBJC_TYPE(RTCVideoCodecInfo) *> *)availableVideoCodecs { 74 return [RTC_OBJC_TYPE(RTCDefaultVideoEncoderFactory) supportedCodecs]; 75} 76 77- (RTC_OBJC_TYPE(RTCVideoCodecInfo) *)currentVideoCodecSettingFromStore { 78 [self registerStoreDefaults]; 79 NSData *codecData = [[self settingsStore] videoCodec]; 80#if defined(WEBRTC_IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_13 81 Class expectedClass = [RTC_OBJC_TYPE(RTCVideoCodecInfo) class]; 82 NSError *error; 83 RTC_OBJC_TYPE(RTCVideoCodecInfo) *videoCodecSetting = 84 [NSKeyedUnarchiver unarchivedObjectOfClass:expectedClass fromData:codecData error:&error]; 85 if (!error) { 86 return videoCodecSetting; 87 } 88 return nil; 89#else 90 return [NSKeyedUnarchiver unarchiveObjectWithData:codecData]; 91#endif 92} 93 94- (BOOL)storeVideoCodecSetting:(RTC_OBJC_TYPE(RTCVideoCodecInfo) *)videoCodec { 95 if (![[self availableVideoCodecs] containsObject:videoCodec]) { 96 return NO; 97 } 98 99#if defined(WEBRTC_IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_13 100 NSError *error; 101 NSData *codecData = [NSKeyedArchiver archivedDataWithRootObject:videoCodec 102 requiringSecureCoding:NO 103 error:&error]; 104 if (error) { 105 return NO; 106 } 107#else 108 NSData *codecData = [NSKeyedArchiver archivedDataWithRootObject:videoCodec]; 109#endif 110 111 [[self settingsStore] setVideoCodec:codecData]; 112 return YES; 113} 114 115- (nullable NSNumber *)currentMaxBitrateSettingFromStore { 116 [self registerStoreDefaults]; 117 return [[self settingsStore] maxBitrate]; 118} 119 120- (void)storeMaxBitrateSetting:(nullable NSNumber *)bitrate { 121 [[self settingsStore] setMaxBitrate:bitrate]; 122} 123 124- (BOOL)currentAudioOnlySettingFromStore { 125 return [[self settingsStore] audioOnly]; 126} 127 128- (void)storeAudioOnlySetting:(BOOL)audioOnly { 129 [[self settingsStore] setAudioOnly:audioOnly]; 130} 131 132- (BOOL)currentCreateAecDumpSettingFromStore { 133 return [[self settingsStore] createAecDump]; 134} 135 136- (void)storeCreateAecDumpSetting:(BOOL)createAecDump { 137 [[self settingsStore] setCreateAecDump:createAecDump]; 138} 139 140- (BOOL)currentUseManualAudioConfigSettingFromStore { 141 return [[self settingsStore] useManualAudioConfig]; 142} 143 144- (void)storeUseManualAudioConfigSetting:(BOOL)useManualAudioConfig { 145 [[self settingsStore] setUseManualAudioConfig:useManualAudioConfig]; 146} 147 148#pragma mark - Testable 149 150- (ARDSettingsStore *)settingsStore { 151 if (!_settingsStore) { 152 _settingsStore = [[ARDSettingsStore alloc] init]; 153 [self registerStoreDefaults]; 154 } 155 return _settingsStore; 156} 157 158- (int)currentVideoResolutionWidthFromStore { 159 NSString *resolution = [self currentVideoResolutionSettingFromStore]; 160 161 return [self videoResolutionComponentAtIndex:0 inString:resolution]; 162} 163 164- (int)currentVideoResolutionHeightFromStore { 165 NSString *resolution = [self currentVideoResolutionSettingFromStore]; 166 return [self videoResolutionComponentAtIndex:1 inString:resolution]; 167} 168 169#pragma mark - 170 171- (NSString *)defaultVideoResolutionSetting { 172 return [self availableVideoResolutions].firstObject; 173} 174 175- (RTC_OBJC_TYPE(RTCVideoCodecInfo) *)defaultVideoCodecSetting { 176 return [self availableVideoCodecs].firstObject; 177} 178 179- (int)videoResolutionComponentAtIndex:(int)index inString:(NSString *)resolution { 180 if (index != 0 && index != 1) { 181 return 0; 182 } 183 NSArray<NSString *> *components = [resolution componentsSeparatedByString:@"x"]; 184 if (components.count != 2) { 185 return 0; 186 } 187 return components[index].intValue; 188} 189 190- (void)registerStoreDefaults { 191#if defined(WEBRTC_IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_13 192 NSError *error; 193 NSData *codecData = [NSKeyedArchiver archivedDataWithRootObject:[self defaultVideoCodecSetting] 194 requiringSecureCoding:NO 195 error:&error]; 196 if (error) { 197 return; 198 } 199#else 200 NSData *codecData = [NSKeyedArchiver archivedDataWithRootObject:[self defaultVideoCodecSetting]]; 201#endif 202 203 [ARDSettingsStore setDefaultsForVideoResolution:[self defaultVideoResolutionSetting] 204 videoCodec:codecData 205 bitrate:nil 206 audioOnly:NO 207 createAecDump:NO 208 useManualAudioConfig:YES]; 209} 210@end 211NS_ASSUME_NONNULL_END 212