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