From c522e758f6a364c23e7232d4f402713601f0b35e Mon Sep 17 00:00:00 2001 From: sakal Date: Wed, 5 Apr 2017 12:17:48 -0700 Subject: [PATCH] Use new RTCCameraVideoCapturer in AppRTCMobile. Because the new API doesn't use constraints, refactors settings to instead have a video resolution setting. BUG=webrtc:7177 Review-Url: https://codereview.webrtc.org/2778163005 Cr-Commit-Position: refs/heads/master@{#17545} --- webrtc/examples/BUILD.gn | 2 + .../examples/objc/AppRTCMobile/ARDAppClient.h | 4 + .../examples/objc/AppRTCMobile/ARDAppClient.m | 26 +++--- .../objc/AppRTCMobile/ARDCaptureController.h | 24 +++++ .../objc/AppRTCMobile/ARDCaptureController.m | 92 +++++++++++++++++++ .../AppRTCMobile/ARDSettingsModel+Private.h | 2 - .../objc/AppRTCMobile/ARDSettingsModel.h | 37 +++----- .../objc/AppRTCMobile/ARDSettingsModel.m | 61 +++++------- .../objc/AppRTCMobile/ARDSettingsStore.h | 12 +-- .../objc/AppRTCMobile/ARDSettingsStore.m | 10 +- .../ios/ARDSettingsViewController.m | 48 +++++----- .../objc/AppRTCMobile/ios/ARDVideoCallView.m | 1 - .../ios/ARDVideoCallViewController.m | 44 ++++----- .../AppRTCMobile/mac/APPRTCViewController.m | 14 ++- .../tests/ARDSettingsModel_xctest.mm | 39 ++++---- 15 files changed, 244 insertions(+), 172 deletions(-) create mode 100644 webrtc/examples/objc/AppRTCMobile/ARDCaptureController.h create mode 100644 webrtc/examples/objc/AppRTCMobile/ARDCaptureController.m diff --git a/webrtc/examples/BUILD.gn b/webrtc/examples/BUILD.gn index ebe426f00c..10deaf27c4 100644 --- a/webrtc/examples/BUILD.gn +++ b/webrtc/examples/BUILD.gn @@ -192,6 +192,8 @@ if (is_ios || (is_mac && target_cpu != "x86")) { "objc/AppRTCMobile/ARDAppEngineClient.m", "objc/AppRTCMobile/ARDBitrateTracker.h", "objc/AppRTCMobile/ARDBitrateTracker.m", + "objc/AppRTCMobile/ARDCaptureController.h", + "objc/AppRTCMobile/ARDCaptureController.m", "objc/AppRTCMobile/ARDJoinResponse+Internal.h", "objc/AppRTCMobile/ARDJoinResponse.h", "objc/AppRTCMobile/ARDJoinResponse.m", diff --git a/webrtc/examples/objc/AppRTCMobile/ARDAppClient.h b/webrtc/examples/objc/AppRTCMobile/ARDAppClient.h index 933dc6b1a0..b613ec976f 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDAppClient.h +++ b/webrtc/examples/objc/AppRTCMobile/ARDAppClient.h @@ -10,6 +10,7 @@ #import +#import "WebRTC/RTCCameraVideoCapturer.h" #import "WebRTC/RTCPeerConnection.h" #import "WebRTC/RTCVideoTrack.h" @@ -36,6 +37,9 @@ typedef NS_ENUM(NSInteger, ARDAppClientState) { - (void)appClient:(ARDAppClient *)client didChangeConnectionState:(RTCIceConnectionState)state; +- (void)appClient:(ARDAppClient *)client + didCreateLocalCapturer:(RTCCameraVideoCapturer *)localCapturer; + - (void)appClient:(ARDAppClient *)client didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack; diff --git a/webrtc/examples/objc/AppRTCMobile/ARDAppClient.m b/webrtc/examples/objc/AppRTCMobile/ARDAppClient.m index ef38138319..7e06612e6a 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDAppClient.m +++ b/webrtc/examples/objc/AppRTCMobile/ARDAppClient.m @@ -12,6 +12,7 @@ #import "WebRTC/RTCAVFoundationVideoSource.h" #import "WebRTC/RTCAudioTrack.h" +#import "WebRTC/RTCCameraVideoCapturer.h" #import "WebRTC/RTCConfiguration.h" #import "WebRTC/RTCFileLogger.h" #import "WebRTC/RTCIceServer.h" @@ -21,6 +22,7 @@ #import "WebRTC/RTCPeerConnectionFactory.h" #import "WebRTC/RTCRtpSender.h" #import "WebRTC/RTCTracing.h" +#import "WebRTC/RTCVideoTrack.h" #import "ARDAppEngineClient.h" #import "ARDJoinResponse.h" @@ -100,6 +102,7 @@ static int const kKbpsMultiplier = 1000; RTCFileLogger *_fileLogger; ARDTimerProxy *_statsTimer; ARDSettingsModel *_settings; + RTCVideoTrack *_localVideoTrack; } @synthesize shouldGetStats = _shouldGetStats; @@ -305,6 +308,7 @@ static int const kKbpsMultiplier = 1000; _isInitiator = NO; _hasReceivedSdp = NO; _messageQueue = [NSMutableArray array]; + _localVideoTrack = nil; #if defined(WEBRTC_IOS) [_factory stopAecDump]; [_peerConnection stopRtcEventLog]; @@ -666,10 +670,10 @@ static int const kKbpsMultiplier = 1000; RTCRtpSender *sender = [_peerConnection senderWithKind:kRTCMediaStreamTrackKindVideo streamId:kARDMediaStreamId]; - RTCVideoTrack *track = [self createLocalVideoTrack]; - if (track) { - sender.track = track; - [_delegate appClient:self didReceiveLocalVideoTrack:track]; + _localVideoTrack = [self createLocalVideoTrack]; + if (_localVideoTrack) { + sender.track = _localVideoTrack; + [_delegate appClient:self didReceiveLocalVideoTrack:_localVideoTrack]; } return sender; @@ -716,10 +720,9 @@ static int const kKbpsMultiplier = 1000; // trying to open a local stream. #if !TARGET_IPHONE_SIMULATOR if (!_isAudioOnly) { - RTCMediaConstraints *cameraConstraints = - [self cameraConstraints]; - RTCAVFoundationVideoSource *source = - [_factory avFoundationVideoSourceWithConstraints:cameraConstraints]; + RTCVideoSource *source = [_factory videoSource]; + RTCCameraVideoCapturer *capturer = [[RTCCameraVideoCapturer alloc] initWithDelegate:source]; + [_delegate appClient:self didCreateLocalCapturer:capturer]; localVideoTrack = [_factory videoTrackWithSource:source trackId:kARDVideoTrackId]; @@ -764,13 +767,6 @@ static int const kKbpsMultiplier = 1000; return constraints; } -- (RTCMediaConstraints *)cameraConstraints { - RTCMediaConstraints *cameraConstraints = [[RTCMediaConstraints alloc] - initWithMandatoryConstraints:nil - optionalConstraints:[_settings currentMediaConstraintFromStoreAsRTCDictionary]]; - return cameraConstraints; -} - - (RTCMediaConstraints *)defaultAnswerConstraints { return [self defaultOfferConstraints]; } diff --git a/webrtc/examples/objc/AppRTCMobile/ARDCaptureController.h b/webrtc/examples/objc/AppRTCMobile/ARDCaptureController.h new file mode 100644 index 0000000000..bdae93a844 --- /dev/null +++ b/webrtc/examples/objc/AppRTCMobile/ARDCaptureController.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include + +@class ARDSettingsModel; + +// Controls the camera. Handles starting the capture, switching cameras etc. +@interface ARDCaptureController : NSObject + +- (instancetype)initWithCapturer:(RTCCameraVideoCapturer *)capturer + settings:(ARDSettingsModel *)settings; +- (void)startCapture; +- (void)stopCapture; +- (void)switchCamera; + +@end diff --git a/webrtc/examples/objc/AppRTCMobile/ARDCaptureController.m b/webrtc/examples/objc/AppRTCMobile/ARDCaptureController.m new file mode 100644 index 0000000000..328c422e5f --- /dev/null +++ b/webrtc/examples/objc/AppRTCMobile/ARDCaptureController.m @@ -0,0 +1,92 @@ +/* + * Copyright 2017 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#import "ARDCaptureController.h" + +#import "ARDSettingsModel.h" + +@implementation ARDCaptureController { + RTCCameraVideoCapturer *_capturer; + ARDSettingsModel *_settings; + BOOL _usingFrontCamera; +} + +- (instancetype)initWithCapturer:(RTCCameraVideoCapturer *)capturer + settings:(ARDSettingsModel *)settings { + if ([super init]) { + _capturer = capturer; + _settings = settings; + _usingFrontCamera = YES; + } + + return self; +} + +- (void)startCapture { + AVCaptureDevicePosition position = + _usingFrontCamera ? AVCaptureDevicePositionFront : AVCaptureDevicePositionBack; + AVCaptureDevice *device = [self findDeviceForPosition:position]; + AVCaptureDeviceFormat *format = [self selectFormatForDevice:device]; + int fps = [self selectFpsForFormat:format]; + + [_capturer startCaptureWithDevice:device format:format fps:fps]; +} + +- (void)stopCapture { + [_capturer stopCapture]; +} + +- (void)switchCamera { + _usingFrontCamera = !_usingFrontCamera; + [self startCapture]; +} + +#pragma mark - Private + +- (AVCaptureDevice *)findDeviceForPosition:(AVCaptureDevicePosition)position { + NSArray *captureDevices = [RTCCameraVideoCapturer captureDevices]; + for (AVCaptureDevice *device in captureDevices) { + if (device.position == position) { + return device; + } + } + return captureDevices[0]; +} + +- (AVCaptureDeviceFormat *)selectFormatForDevice:(AVCaptureDevice *)device { + NSArray *formats = + [RTCCameraVideoCapturer supportedFormatsForDevice:device]; + int targetWidth = [_settings currentVideoResolutionWidthFromStore]; + int targetHeight = [_settings currentVideoResolutionHeightFromStore]; + AVCaptureDeviceFormat *selectedFormat = nil; + int currentDiff = INT_MAX; + + for (AVCaptureDeviceFormat *format in formats) { + CMVideoDimensions dimension = CMVideoFormatDescriptionGetDimensions(format.formatDescription); + int diff = abs(targetWidth - dimension.width) + abs(targetHeight - dimension.height); + if (diff < currentDiff) { + selectedFormat = format; + currentDiff = diff; + } + } + + NSAssert(selectedFormat != nil, @"No suitable capture format found."); + return selectedFormat; +} + +- (int)selectFpsForFormat:(AVCaptureDeviceFormat *)format { + Float64 maxFramerate = 0; + for (AVFrameRateRange *fpsRange in format.videoSupportedFrameRateRanges) { + maxFramerate = fmax(maxFramerate, fpsRange.maxFrameRate); + } + return maxFramerate; +} + +@end diff --git a/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel+Private.h b/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel+Private.h index eba99d7245..08d863d59a 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel+Private.h +++ b/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel+Private.h @@ -16,7 +16,5 @@ NS_ASSUME_NONNULL_BEGIN @interface ARDSettingsModel () - (ARDSettingsStore *)settingsStore; -- (nullable NSString *)currentVideoResolutionWidthFromStore; -- (nullable NSString *)currentVideoResolutionHeightFromStore; @end NS_ASSUME_NONNULL_END diff --git a/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.h b/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.h index 0eb7b31aeb..1787bb2911 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.h +++ b/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.h @@ -14,12 +14,9 @@ NS_ASSUME_NONNULL_BEGIN /** * Model class for user defined settings. * - * Currently used for streaming media constraints and bitrate only. - * In future audio media constraints support can be added as well. - * Offers list of avaliable video resolutions that can construct streaming media constraint. - * Exposes methods for reading and storing media constraints from persistent store. - * Also translates current user defined media constraint into RTCMediaConstraints - * dictionary. + * Handles storing the settings and provides default values if setting is not + * set. Also provides list of available options for different settings. Stores + * for example video codec, video resolution and maximum bitrate. */ @interface ARDSettingsModel : NSObject @@ -29,24 +26,26 @@ NS_ASSUME_NONNULL_BEGIN * The capture resolutions are represented as strings in the following format * [width]x[height] */ -- (NSArray *)availableVideoResoultionsMediaConstraints; +- (NSArray *)availableVideoResolutions; /** - * Returns current video resolution media constraint string. - * If no constraint is in store, default value of 640x480 is returned. + * Returns current video resolution string. + * If no resolution is in store, default value of 640x480 is returned. * When defaulting to value, the default is saved in store for consistency reasons. */ -- (NSString *)currentVideoResoultionConstraintFromStore; +- (NSString *)currentVideoResolutionSettingFromStore; +- (int)currentVideoResolutionWidthFromStore; +- (int)currentVideoResolutionHeightFromStore; /** - * Stores the provided video resolution media constraint string into the store. + * Stores the provided video resolution string into the store. * - * If the provided constraint is no part of the available video resolutions + * If the provided resolution is no part of the available video resolutions * the store operation will not be executed and NO will be returned. - * @param constraint the string to be stored. + * @param resolution the string to be stored. * @return YES/NO depending on success. */ -- (BOOL)storeVideoResoultionConstraint:(NSString *)constraint; +- (BOOL)storeVideoResolutionSetting:(NSString *)resolution; /** * Returns array of available video codecs. @@ -61,21 +60,13 @@ NS_ASSUME_NONNULL_BEGIN /** * Stores the provided video codec setting into the store. * - * If the provided constraint is not part of the available video codecs + * If the provided video codec is not part of the available video codecs * the store operation will not be executed and NO will be returned. * @param video codec settings the string to be stored. * @return YES/NO depending on success. */ - (BOOL)storeVideoCodecSetting:(NSString *)videoCodec; -/** - * Converts the current media constraints from store into dictionary with RTCMediaConstraints - * values. - * - * @return NSDictionary with RTC width and height parameters - */ -- (nullable NSDictionary *)currentMediaConstraintFromStoreAsRTCDictionary; - /** * Returns current max bitrate setting from store if present. */ diff --git a/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.m b/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.m index 7514689add..ecb6ab344b 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.m +++ b/webrtc/examples/objc/AppRTCMobile/ARDSettingsModel.m @@ -28,25 +28,25 @@ static NSArray *videoCodecsStaticValues() { @implementation ARDSettingsModel -- (NSArray *)availableVideoResoultionsMediaConstraints { +- (NSArray *)availableVideoResolutions { return videoResolutionsStaticValues(); } -- (NSString *)currentVideoResoultionConstraintFromStore { - NSString *constraint = [[self settingsStore] videoResolutionConstraints]; - if (!constraint) { - constraint = [self defaultVideoResolutionMediaConstraint]; +- (NSString *)currentVideoResolutionSettingFromStore { + NSString *resolution = [[self settingsStore] videoResolution]; + if (!resolution) { + resolution = [self defaultVideoResolutionSetting]; // To ensure consistency add the default to the store. - [[self settingsStore] setVideoResolutionConstraints:constraint]; + [[self settingsStore] setVideoResolution:resolution]; } - return constraint; + return resolution; } -- (BOOL)storeVideoResoultionConstraint:(NSString *)constraint { - if (![[self availableVideoResoultionsMediaConstraints] containsObject:constraint]) { +- (BOOL)storeVideoResolutionSetting:(NSString *)resolution { + if (![[self availableVideoResolutions] containsObject:resolution]) { return NO; } - [[self settingsStore] setVideoResolutionConstraints:constraint]; + [[self settingsStore] setVideoResolution:resolution]; return YES; } @@ -88,54 +88,37 @@ static NSArray *videoCodecsStaticValues() { return _settingsStore; } -- (nullable NSString *)currentVideoResolutionWidthFromStore { - NSString *mediaConstraintFromStore = [self currentVideoResoultionConstraintFromStore]; +- (int)currentVideoResolutionWidthFromStore { + NSString *resolution = [self currentVideoResolutionSettingFromStore]; - return [self videoResolutionComponentAtIndex:0 inConstraintsString:mediaConstraintFromStore]; + return [self videoResolutionComponentAtIndex:0 inString:resolution]; } -- (nullable NSString *)currentVideoResolutionHeightFromStore { - NSString *mediaConstraintFromStore = [self currentVideoResoultionConstraintFromStore]; - return [self videoResolutionComponentAtIndex:1 inConstraintsString:mediaConstraintFromStore]; +- (int)currentVideoResolutionHeightFromStore { + NSString *resolution = [self currentVideoResolutionSettingFromStore]; + return [self videoResolutionComponentAtIndex:1 inString:resolution]; } #pragma mark - -- (NSString *)defaultVideoResolutionMediaConstraint { +- (NSString *)defaultVideoResolutionSetting { return videoResolutionsStaticValues()[0]; } -- (nullable NSString *)videoResolutionComponentAtIndex:(int)index - inConstraintsString:(NSString *)constraint { +- (int)videoResolutionComponentAtIndex:(int)index inString:(NSString *)resolution { if (index != 0 && index != 1) { - return nil; + return 0; } - NSArray *components = [constraint componentsSeparatedByString:@"x"]; + NSArray *components = [resolution componentsSeparatedByString:@"x"]; if (components.count != 2) { - return nil; + return 0; } - return components[index]; + return components[index].intValue; } - (NSString *)defaultVideoCodecSetting { return videoCodecsStaticValues()[0]; } -#pragma mark - Conversion to RTCMediaConstraints - -- (nullable NSDictionary *)currentMediaConstraintFromStoreAsRTCDictionary { - NSDictionary *mediaConstraintsDictionary = nil; - - NSString *widthConstraint = [self currentVideoResolutionWidthFromStore]; - NSString *heightConstraint = [self currentVideoResolutionHeightFromStore]; - if (widthConstraint && heightConstraint) { - mediaConstraintsDictionary = @{ - kRTCMediaConstraintsMinWidth : widthConstraint, - kRTCMediaConstraintsMinHeight : heightConstraint - }; - } - return mediaConstraintsDictionary; -} - @end NS_ASSUME_NONNULL_END diff --git a/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.h b/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.h index b010b7f124..3dd0f6431b 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.h +++ b/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.h @@ -19,19 +19,9 @@ NS_ASSUME_NONNULL_BEGIN */ @interface ARDSettingsStore : NSObject +@property(nonatomic) NSString *videoResolution; @property(nonatomic) NSString *videoCodec; -/** - * Returns current video resolution media constraint string stored in the store. - */ -- (nullable NSString *)videoResolutionConstraints; - -/** - * Stores the provided value as video resolution media constraint. - * @param value the string to be stored - */ -- (void)setVideoResolutionConstraints:(NSString *)value; - /** * Returns current max bitrate number stored in the store. */ diff --git a/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.m b/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.m index 6d9fa5bb26..e25b28860c 100644 --- a/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.m +++ b/webrtc/examples/objc/AppRTCMobile/ARDSettingsStore.m @@ -10,7 +10,7 @@ #import "ARDSettingsStore.h" -static NSString *const kMediaConstraintsKey = @"rtc_video_resolution_media_constraints_key"; +static NSString *const kVideoResolutionKey = @"rtc_video_resolution_key"; static NSString *const kVideoCodecKey = @"rtc_video_codec_key"; static NSString *const kBitrateKey = @"rtc_max_bitrate_key"; @@ -30,12 +30,12 @@ NS_ASSUME_NONNULL_BEGIN return _storage; } -- (nullable NSString *)videoResolutionConstraints { - return [self.storage objectForKey:kMediaConstraintsKey]; +- (NSString *)videoResolution { + return [self.storage objectForKey:kVideoResolutionKey]; } -- (void)setVideoResolutionConstraints:(NSString *)constraintsString { - [self.storage setObject:constraintsString forKey:kMediaConstraintsKey]; +- (void)setVideoResolution:(NSString *)resolution { + [self.storage setObject:resolution forKey:kVideoResolutionKey]; [self.storage synchronize]; } diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsViewController.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsViewController.m index fb59dd2769..3944480b0d 100644 --- a/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsViewController.m +++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDSettingsViewController.m @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(int, ARDSettingsSections) { - ARDSettingsSectionMediaConstraints = 0, + ARDSettingsSectionVideoResolution = 0, ARDSettingsSectionVideoCodec, ARDSettingsSectionBitRate, }; @@ -46,9 +46,9 @@ typedef NS_ENUM(int, ARDSettingsSections) { - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - [self addCheckmarkInSection:ARDSettingsSectionMediaConstraints - withArray:[self mediaConstraintsArray] - selecting:[_settingsModel currentVideoResoultionConstraintFromStore]]; + [self addCheckmarkInSection:ARDSettingsSectionVideoResolution + withArray:[self videoResolutionArray] + selecting:[_settingsModel currentVideoResolutionSettingFromStore]]; [self addCheckmarkInSection:ARDSettingsSectionVideoCodec withArray:[self videoCodecArray] selecting:[_settingsModel currentVideoCodecSettingFromStore]]; @@ -60,8 +60,8 @@ typedef NS_ENUM(int, ARDSettingsSections) { #pragma mark - Data source -- (NSArray *)mediaConstraintsArray { - return _settingsModel.availableVideoResoultionsMediaConstraints; +- (NSArray *)videoResolutionArray { + return _settingsModel.availableVideoResolutions; } - (NSArray *)videoCodecArray { @@ -102,8 +102,8 @@ typedef NS_ENUM(int, ARDSettingsSections) { - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { switch (section) { - case ARDSettingsSectionMediaConstraints: - return self.mediaConstraintsArray.count; + case ARDSettingsSectionVideoResolution: + return self.videoResolutionArray.count; case ARDSettingsSectionVideoCodec: return self.videoCodecArray.count; default: @@ -137,8 +137,8 @@ updateListSelectionAtIndexPath:(NSIndexPath *)indexPath - (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { switch (section) { - case ARDSettingsSectionMediaConstraints: - return @"Media constraints"; + case ARDSettingsSectionVideoResolution: + return @"Video resolution"; case ARDSettingsSectionVideoCodec: return @"Video codec"; case ARDSettingsSectionBitRate: @@ -151,8 +151,8 @@ updateListSelectionAtIndexPath:(NSIndexPath *)indexPath - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { switch (indexPath.section) { - case ARDSettingsSectionMediaConstraints: - return [self mediaConstraintsTableViewCellForTableView:tableView atIndexPath:indexPath]; + case ARDSettingsSectionVideoResolution: + return [self videoResolutionTableViewCellForTableView:tableView atIndexPath:indexPath]; case ARDSettingsSectionVideoCodec: return [self videoCodecTableViewCellForTableView:tableView atIndexPath:indexPath]; @@ -168,8 +168,8 @@ updateListSelectionAtIndexPath:(NSIndexPath *)indexPath - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { switch (indexPath.section) { - case ARDSettingsSectionMediaConstraints: - [self tableView:tableView didSelectMediaConstraintsCellAtIndexPath:indexPath]; + case ARDSettingsSectionVideoResolution: + [self tableView:tableView disSelectVideoResolutionAtIndex:indexPath]; break; case ARDSettingsSectionVideoCodec: @@ -178,28 +178,28 @@ updateListSelectionAtIndexPath:(NSIndexPath *)indexPath } } -#pragma mark - Table view delegate(Media Constraints) +#pragma mark - Table view delegate(Video Resolution) -- (UITableViewCell *)mediaConstraintsTableViewCellForTableView:(UITableView *)tableView - atIndexPath:(NSIndexPath *)indexPath { - NSString *dequeueIdentifier = @"ARDSettingsMediaConstraintsViewCellIdentifier"; +- (UITableViewCell *)videoResolutionTableViewCellForTableView:(UITableView *)tableView + atIndexPath:(NSIndexPath *)indexPath { + NSString *dequeueIdentifier = @"ARDSettingsVideoResolutionViewCellIdentifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:dequeueIdentifier]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:dequeueIdentifier]; } - cell.textLabel.text = self.mediaConstraintsArray[indexPath.row]; + cell.textLabel.text = self.videoResolutionArray[indexPath.row]; return cell; } - (void)tableView:(UITableView *)tableView - didSelectMediaConstraintsCellAtIndexPath:(NSIndexPath *)indexPath { + disSelectVideoResolutionAtIndex:(NSIndexPath *)indexPath { [self tableView:tableView - updateListSelectionAtIndexPath:indexPath - inSection:ARDSettingsSectionMediaConstraints]; + updateListSelectionAtIndexPath:indexPath + inSection:ARDSettingsSectionVideoResolution]; - NSString *mediaConstraintsString = self.mediaConstraintsArray[indexPath.row]; - [_settingsModel storeVideoResoultionConstraint:mediaConstraintsString]; + NSString *videoResolution = self.videoResolutionArray[indexPath.row]; + [_settingsModel storeVideoResolutionSetting:videoResolution]; } #pragma mark - Table view delegate(Video Codec) diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallView.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallView.m index 869d29cb6c..2241930d47 100644 --- a/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallView.m +++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallView.m @@ -31,7 +31,6 @@ static CGFloat const kStatusBarHeight = 20; UIButton *_cameraSwitchButton; UIButton *_hangupButton; CGSize _remoteVideoSize; - BOOL _useRearCamera; } @synthesize statusLabel = _statusLabel; diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m index cd42514a9f..732e4b6511 100644 --- a/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m +++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m @@ -13,6 +13,7 @@ #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" #import "ARDAppClient.h" +#import "ARDCaptureController.h" #import "ARDSettingsModel.h" #import "ARDVideoCallView.h" #import "WebRTC/RTCAVFoundationVideoSource.h" @@ -22,7 +23,6 @@ @interface ARDVideoCallViewController () -@property(nonatomic, strong) RTCVideoTrack *localVideoTrack; @property(nonatomic, strong) RTCVideoTrack *remoteVideoTrack; @property(nonatomic, readonly) ARDVideoCallView *videoCallView; @end @@ -30,12 +30,11 @@ @implementation ARDVideoCallViewController { ARDAppClient *_client; RTCVideoTrack *_remoteVideoTrack; - RTCVideoTrack *_localVideoTrack; + ARDCaptureController *_captureController; AVAudioSessionPortOverride _portOverride; } @synthesize videoCallView = _videoCallView; -@synthesize localVideoTrack = _localVideoTrack; @synthesize remoteVideoTrack = _remoteVideoTrack; @synthesize delegate = _delegate; @@ -48,6 +47,7 @@ if (self = [super init]) { ARDSettingsModel *settingsModel = [[ARDSettingsModel alloc] init]; _delegate = delegate; + _client = [[ARDAppClient alloc] initWithDelegate:self]; [_client connectToRoomWithId:room settings:settingsModel @@ -96,9 +96,17 @@ }); } +- (void)appClient:(ARDAppClient *)client + didCreateLocalCapturer:(RTCCameraVideoCapturer *)localCapturer { + _videoCallView.localVideoView.captureSession = localCapturer.captureSession; + ARDSettingsModel *settingsModel = [[ARDSettingsModel alloc] init]; + _captureController = + [[ARDCaptureController alloc] initWithCapturer:localCapturer settings:settingsModel]; + [_captureController startCapture]; +} + - (void)appClient:(ARDAppClient *)client didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack { - self.localVideoTrack = localVideoTrack; } - (void)appClient:(ARDAppClient *)client @@ -130,7 +138,7 @@ - (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view { // TODO(tkchin): Rate limit this so you can't tap continously on it. // Probably through an animation. - [self switchCamera]; + [_captureController switchCamera]; } - (void)videoCallViewDidChangeRoute:(ARDVideoCallView *)view { @@ -160,20 +168,6 @@ #pragma mark - Private -- (void)setLocalVideoTrack:(RTCVideoTrack *)localVideoTrack { - if (_localVideoTrack == localVideoTrack) { - return; - } - _localVideoTrack = nil; - _localVideoTrack = localVideoTrack; - RTCAVFoundationVideoSource *source = nil; - if ([localVideoTrack.source - isKindOfClass:[RTCAVFoundationVideoSource class]]) { - source = (RTCAVFoundationVideoSource*)localVideoTrack.source; - } - _videoCallView.localVideoView.captureSession = source.captureSession; -} - - (void)setRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack { if (_remoteVideoTrack == remoteVideoTrack) { return; @@ -187,19 +181,13 @@ - (void)hangup { self.remoteVideoTrack = nil; - self.localVideoTrack = nil; + _videoCallView.localVideoView.captureSession = nil; + [_captureController stopCapture]; + _captureController = nil; [_client disconnect]; [_delegate viewControllerDidFinish:self]; } -- (void)switchCamera { - RTCVideoSource* source = self.localVideoTrack.source; - if ([source isKindOfClass:[RTCAVFoundationVideoSource class]]) { - RTCAVFoundationVideoSource* avSource = (RTCAVFoundationVideoSource*)source; - avSource.useBackCamera = !avSource.useBackCamera; - } -} - - (NSString *)statusTextForState:(RTCIceConnectionState)state { switch (state) { case RTCIceConnectionStateNew: diff --git a/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m b/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m index 089901efda..9d36d9b2be 100644 --- a/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m +++ b/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m @@ -17,6 +17,7 @@ #import "WebRTC/RTCVideoTrack.h" #import "ARDAppClient.h" +#import "ARDCaptureController.h" #import "ARDSettingsModel.h" static NSUInteger const kContentWidth = 900; @@ -299,6 +300,7 @@ static NSUInteger const kBottomViewHeight = 200; ARDAppClient* _client; RTCVideoTrack* _localVideoTrack; RTCVideoTrack* _remoteVideoTrack; + ARDCaptureController* _captureController; } - (void)dealloc { @@ -353,6 +355,14 @@ static NSUInteger const kBottomViewHeight = 200; didChangeConnectionState:(RTCIceConnectionState)state { } +- (void)appClient:(ARDAppClient*)client + didCreateLocalCapturer:(RTCCameraVideoCapturer*)localCapturer { + _captureController = + [[ARDCaptureController alloc] initWithCapturer:localCapturer + settings:[[ARDSettingsModel alloc] init]]; + [_captureController startCapture]; +} + - (void)appClient:(ARDAppClient *)client didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack { _localVideoTrack = localVideoTrack; @@ -386,7 +396,7 @@ static NSUInteger const kBottomViewHeight = 200; return; } - [_client disconnect]; + [self disconnect]; ARDAppClient* client = [[ARDAppClient alloc] initWithDelegate:self]; [client connectToRoomWithId:roomId settings:[[ARDSettingsModel alloc] init] // Use default settings. @@ -420,6 +430,8 @@ static NSUInteger const kBottomViewHeight = 200; - (void)disconnect { [self resetUI]; + [_captureController stopCapture]; + _captureController = nil; [_client disconnect]; } diff --git a/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm b/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm index eee18db69c..64e05b195d 100644 --- a/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm +++ b/webrtc/examples/objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm @@ -25,9 +25,9 @@ @implementation ARDSettingsModelTests -- (id)setupMockStoreWithMediaConstraintString:(NSString *)constraintString { +- (id)setupMockStoreWithVideoResolution:(NSString *)videoResolution { id storeMock = [OCMockObject mockForClass:[ARDSettingsStore class]]; - [([[storeMock stub] andReturn:constraintString]) videoResolutionConstraints]; + [([[storeMock stub] andReturn:videoResolution])videoResolution]; id partialMock = [OCMockObject partialMockForObject:_model]; [[[partialMock stub] andReturn:storeMock] settingsStore]; @@ -40,45 +40,38 @@ } - (void)testDefaultMediaFromStore { - id storeMock = [self setupMockStoreWithMediaConstraintString:nil]; - [[storeMock expect] setVideoResolutionConstraints:@"640x480"]; + id storeMock = [self setupMockStoreWithVideoResolution:nil]; + [[storeMock expect] setVideoResolution:@"640x480"]; - NSString *string = [_model currentVideoResoultionConstraintFromStore]; + NSString *string = [_model currentVideoResolutionSettingFromStore]; XCTAssertEqualObjects(string, @"640x480"); [storeMock verify]; } - (void)testStoringInvalidConstraintReturnsNo { - __unused id storeMock = [self setupMockStoreWithMediaConstraintString:@"960x480"]; - XCTAssertFalse([_model storeVideoResoultionConstraint:@"960x480"]); + __unused id storeMock = [self setupMockStoreWithVideoResolution:@"960x480"]; + XCTAssertFalse([_model storeVideoResolutionSetting:@"960x480"]); } - (void)testWidthConstraintFromStore { - [self setupMockStoreWithMediaConstraintString:@"1270x480"]; - NSString *width = [_model currentVideoResolutionWidthFromStore]; + [self setupMockStoreWithVideoResolution:@"1270x480"]; + int width = [_model currentVideoResolutionWidthFromStore]; - XCTAssertEqualObjects(width, @"1270"); + XCTAssertEqual(width, 1270); } - (void)testHeightConstraintFromStore { - [self setupMockStoreWithMediaConstraintString:@"960x540"]; - NSString *height = [_model currentVideoResolutionHeightFromStore]; + [self setupMockStoreWithVideoResolution:@"960x540"]; + int height = [_model currentVideoResolutionHeightFromStore]; - XCTAssertEqualObjects(height, @"540"); + XCTAssertEqual(height, 540); } - (void)testConstraintComponentIsNilWhenInvalidConstraintString { - [self setupMockStoreWithMediaConstraintString:@"invalid"]; - NSString *width = [_model currentVideoResolutionWidthFromStore]; + [self setupMockStoreWithVideoResolution:@"invalid"]; + int width = [_model currentVideoResolutionWidthFromStore]; - XCTAssertNil(width); -} - -- (void)testConstraintsDictionaryIsNilWhenInvalidConstraintString { - [self setupMockStoreWithMediaConstraintString:@"invalid"]; - NSDictionary *constraintsDictionary = [_model currentMediaConstraintFromStoreAsRTCDictionary]; - - XCTAssertNil(constraintsDictionary); + XCTAssertEqual(width, 0); } @end