AppRTCMobile iOS: Use video encoder factory to manage codec preference.
List codecs from factory in settings, select by changing order in factory. Bug: webrtc:7925 Change-Id: If3c45e56713104c88705c67560325d002e6d6700 Reviewed-on: https://webrtc-review.googlesource.com/3720 Commit-Queue: Anders Carlsson <andersc@webrtc.org> Reviewed-by: Magnus Jedvert <magjed@webrtc.org> Cr-Commit-Position: refs/heads/master@{#20312}
This commit is contained in:
committed by
Commit Bot
parent
ce045acd94
commit
6bf43d2818
@ -217,8 +217,6 @@ if (is_ios || (is_mac && target_cpu != "x86")) {
|
|||||||
"objc/AppRTCMobile/ARDMessageResponse.h",
|
"objc/AppRTCMobile/ARDMessageResponse.h",
|
||||||
"objc/AppRTCMobile/ARDMessageResponse.m",
|
"objc/AppRTCMobile/ARDMessageResponse.m",
|
||||||
"objc/AppRTCMobile/ARDRoomServerClient.h",
|
"objc/AppRTCMobile/ARDRoomServerClient.h",
|
||||||
"objc/AppRTCMobile/ARDSDPUtils.h",
|
|
||||||
"objc/AppRTCMobile/ARDSDPUtils.m",
|
|
||||||
"objc/AppRTCMobile/ARDSettingsModel+Private.h",
|
"objc/AppRTCMobile/ARDSettingsModel+Private.h",
|
||||||
"objc/AppRTCMobile/ARDSettingsModel.h",
|
"objc/AppRTCMobile/ARDSettingsModel.h",
|
||||||
"objc/AppRTCMobile/ARDSettingsModel.m",
|
"objc/AppRTCMobile/ARDSettingsModel.m",
|
||||||
@ -279,6 +277,8 @@ if (is_ios || (is_mac && target_cpu != "x86")) {
|
|||||||
"objc/AppRTCMobile/ios/ARDVideoCallView.m",
|
"objc/AppRTCMobile/ios/ARDVideoCallView.m",
|
||||||
"objc/AppRTCMobile/ios/ARDVideoCallViewController.h",
|
"objc/AppRTCMobile/ios/ARDVideoCallViewController.h",
|
||||||
"objc/AppRTCMobile/ios/ARDVideoCallViewController.m",
|
"objc/AppRTCMobile/ios/ARDVideoCallViewController.m",
|
||||||
|
"objc/AppRTCMobile/ios/RTCVideoCodecInfo+HumanReadable.h",
|
||||||
|
"objc/AppRTCMobile/ios/RTCVideoCodecInfo+HumanReadable.m",
|
||||||
"objc/AppRTCMobile/ios/UIImage+ARDUtilities.h",
|
"objc/AppRTCMobile/ios/UIImage+ARDUtilities.h",
|
||||||
"objc/AppRTCMobile/ios/UIImage+ARDUtilities.m",
|
"objc/AppRTCMobile/ios/UIImage+ARDUtilities.m",
|
||||||
]
|
]
|
||||||
@ -436,7 +436,6 @@ if (is_ios || (is_mac && target_cpu != "x86")) {
|
|||||||
testonly = true
|
testonly = true
|
||||||
sources = [
|
sources = [
|
||||||
"objc/AppRTCMobile/tests/ARDAppClient_xctest.mm",
|
"objc/AppRTCMobile/tests/ARDAppClient_xctest.mm",
|
||||||
"objc/AppRTCMobile/tests/ARDSDPUtils_xctest.mm",
|
|
||||||
"objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm",
|
"objc/AppRTCMobile/tests/ARDSettingsModel_xctest.mm",
|
||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
|
|||||||
@ -27,7 +27,6 @@
|
|||||||
#import "ARDAppEngineClient.h"
|
#import "ARDAppEngineClient.h"
|
||||||
#import "ARDJoinResponse.h"
|
#import "ARDJoinResponse.h"
|
||||||
#import "ARDMessageResponse.h"
|
#import "ARDMessageResponse.h"
|
||||||
#import "ARDSDPUtils.h"
|
|
||||||
#import "ARDSettingsModel.h"
|
#import "ARDSettingsModel.h"
|
||||||
#import "ARDSignalingMessage.h"
|
#import "ARDSignalingMessage.h"
|
||||||
#import "ARDTURNClient+Internal.h"
|
#import "ARDTURNClient+Internal.h"
|
||||||
@ -165,10 +164,6 @@ static int const kKbpsMultiplier = 1000;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)configure {
|
- (void)configure {
|
||||||
ARDVideoDecoderFactory *decoderFactory = [[ARDVideoDecoderFactory alloc] init];
|
|
||||||
ARDVideoEncoderFactory *encoderFactory = [[ARDVideoEncoderFactory alloc] init];
|
|
||||||
_factory = [[RTCPeerConnectionFactory alloc] initWithEncoderFactory:encoderFactory
|
|
||||||
decoderFactory:decoderFactory];
|
|
||||||
_messageQueue = [NSMutableArray array];
|
_messageQueue = [NSMutableArray array];
|
||||||
_iceServers = [NSMutableArray array];
|
_iceServers = [NSMutableArray array];
|
||||||
_fileLogger = [[RTCFileLogger alloc] init];
|
_fileLogger = [[RTCFileLogger alloc] init];
|
||||||
@ -223,6 +218,12 @@ static int const kKbpsMultiplier = 1000;
|
|||||||
_isLoopback = isLoopback;
|
_isLoopback = isLoopback;
|
||||||
self.state = kARDAppClientStateConnecting;
|
self.state = kARDAppClientStateConnecting;
|
||||||
|
|
||||||
|
ARDVideoDecoderFactory *decoderFactory = [[ARDVideoDecoderFactory alloc] init];
|
||||||
|
ARDVideoEncoderFactory *encoderFactory = [[ARDVideoEncoderFactory alloc] init];
|
||||||
|
encoderFactory.preferredCodec = [settings currentVideoCodecSettingFromStore];
|
||||||
|
_factory = [[RTCPeerConnectionFactory alloc] initWithEncoderFactory:encoderFactory
|
||||||
|
decoderFactory:decoderFactory];
|
||||||
|
|
||||||
#if defined(WEBRTC_IOS)
|
#if defined(WEBRTC_IOS)
|
||||||
if (kARDAppClientEnableTracing) {
|
if (kARDAppClientEnableTracing) {
|
||||||
NSString *filePath = [self documentsFilePathForFileName:@"webrtc-trace.txt"];
|
NSString *filePath = [self documentsFilePathForFileName:@"webrtc-trace.txt"];
|
||||||
@ -447,20 +448,15 @@ static int const kKbpsMultiplier = 1000;
|
|||||||
[_delegate appClient:self didError:sdpError];
|
[_delegate appClient:self didError:sdpError];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Prefer codec from settings if available.
|
|
||||||
RTCSessionDescription *sdpPreferringCodec =
|
|
||||||
[ARDSDPUtils descriptionForDescription:sdp
|
|
||||||
preferredVideoCodec:[_settings currentVideoCodecSettingFromStore]];
|
|
||||||
__weak ARDAppClient *weakSelf = self;
|
__weak ARDAppClient *weakSelf = self;
|
||||||
[_peerConnection setLocalDescription:sdpPreferringCodec
|
[_peerConnection setLocalDescription:sdp
|
||||||
completionHandler:^(NSError *error) {
|
completionHandler:^(NSError *error) {
|
||||||
ARDAppClient *strongSelf = weakSelf;
|
ARDAppClient *strongSelf = weakSelf;
|
||||||
[strongSelf peerConnection:strongSelf.peerConnection
|
[strongSelf peerConnection:strongSelf.peerConnection
|
||||||
didSetSessionDescriptionWithError:error];
|
didSetSessionDescriptionWithError:error];
|
||||||
}];
|
}];
|
||||||
ARDSessionDescriptionMessage *message =
|
ARDSessionDescriptionMessage *message =
|
||||||
[[ARDSessionDescriptionMessage alloc]
|
[[ARDSessionDescriptionMessage alloc] initWithDescription:sdp];
|
||||||
initWithDescription:sdpPreferringCodec];
|
|
||||||
[self sendSignalingMessage:message];
|
[self sendSignalingMessage:message];
|
||||||
[self setMaxBitrateForPeerConnectionVideoSender];
|
[self setMaxBitrateForPeerConnectionVideoSender];
|
||||||
});
|
});
|
||||||
@ -600,17 +596,13 @@ static int const kKbpsMultiplier = 1000;
|
|||||||
ARDSessionDescriptionMessage *sdpMessage =
|
ARDSessionDescriptionMessage *sdpMessage =
|
||||||
(ARDSessionDescriptionMessage *)message;
|
(ARDSessionDescriptionMessage *)message;
|
||||||
RTCSessionDescription *description = sdpMessage.sessionDescription;
|
RTCSessionDescription *description = sdpMessage.sessionDescription;
|
||||||
// Prefer codec from settings if available.
|
|
||||||
RTCSessionDescription *sdpPreferringCodec =
|
|
||||||
[ARDSDPUtils descriptionForDescription:description
|
|
||||||
preferredVideoCodec:[_settings currentVideoCodecSettingFromStore]];
|
|
||||||
__weak ARDAppClient *weakSelf = self;
|
__weak ARDAppClient *weakSelf = self;
|
||||||
[_peerConnection setRemoteDescription:sdpPreferringCodec
|
[_peerConnection setRemoteDescription:description
|
||||||
completionHandler:^(NSError *error) {
|
completionHandler:^(NSError *error) {
|
||||||
ARDAppClient *strongSelf = weakSelf;
|
ARDAppClient *strongSelf = weakSelf;
|
||||||
[strongSelf peerConnection:strongSelf.peerConnection
|
[strongSelf peerConnection:strongSelf.peerConnection
|
||||||
didSetSessionDescriptionWithError:error];
|
didSetSessionDescriptionWithError:error];
|
||||||
}];
|
}];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kARDSignalingMessageTypeCandidate: {
|
case kARDSignalingMessageTypeCandidate: {
|
||||||
|
|||||||
@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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 <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
@class RTCSessionDescription;
|
|
||||||
|
|
||||||
@interface ARDSDPUtils : NSObject
|
|
||||||
|
|
||||||
// Updates the original SDP description to instead prefer the specified video
|
|
||||||
// codec. We do this by placing the specified codec at the beginning of the
|
|
||||||
// codec list if it exists in the sdp.
|
|
||||||
+ (RTCSessionDescription *)
|
|
||||||
descriptionForDescription:(RTCSessionDescription *)description
|
|
||||||
preferredVideoCodec:(NSString *)codec;
|
|
||||||
|
|
||||||
@end
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2015 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 "ARDSDPUtils.h"
|
|
||||||
|
|
||||||
#import "WebRTC/RTCLogging.h"
|
|
||||||
#import "WebRTC/RTCSessionDescription.h"
|
|
||||||
|
|
||||||
@implementation ARDSDPUtils
|
|
||||||
|
|
||||||
+ (RTCSessionDescription *)
|
|
||||||
descriptionForDescription:(RTCSessionDescription *)description
|
|
||||||
preferredVideoCodec:(NSString *)codec {
|
|
||||||
NSString *sdpString = description.sdp;
|
|
||||||
NSString *lineSeparator = @"\r\n";
|
|
||||||
NSString *mLineSeparator = @" ";
|
|
||||||
// Copied from PeerConnectionClient.java.
|
|
||||||
// TODO(tkchin): Move this to a shared C++ file.
|
|
||||||
NSMutableArray *lines =
|
|
||||||
[NSMutableArray arrayWithArray:
|
|
||||||
[sdpString componentsSeparatedByString:lineSeparator]];
|
|
||||||
// Find the line starting with "m=video".
|
|
||||||
NSInteger mLineIndex = -1;
|
|
||||||
for (NSInteger i = 0; i < lines.count; ++i) {
|
|
||||||
if ([lines[i] hasPrefix:@"m=video"]) {
|
|
||||||
mLineIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mLineIndex == -1) {
|
|
||||||
RTCLog(@"No m=video line, so can't prefer %@", codec);
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
// An array with all payload types with name |codec|. The payload types are
|
|
||||||
// integers in the range 96-127, but they are stored as strings here.
|
|
||||||
NSMutableArray *codecPayloadTypes = [[NSMutableArray alloc] init];
|
|
||||||
// a=rtpmap:<payload type> <encoding name>/<clock rate>
|
|
||||||
// [/<encoding parameters>]
|
|
||||||
NSString *pattern =
|
|
||||||
[NSString stringWithFormat:@"^a=rtpmap:(\\d+) %@(/\\d+)+[\r]?$", codec];
|
|
||||||
NSRegularExpression *regex =
|
|
||||||
[NSRegularExpression regularExpressionWithPattern:pattern
|
|
||||||
options:0
|
|
||||||
error:nil];
|
|
||||||
for (NSString *line in lines) {
|
|
||||||
NSTextCheckingResult *codecMatches =
|
|
||||||
[regex firstMatchInString:line
|
|
||||||
options:0
|
|
||||||
range:NSMakeRange(0, line.length)];
|
|
||||||
if (codecMatches) {
|
|
||||||
[codecPayloadTypes
|
|
||||||
addObject:[line substringWithRange:[codecMatches rangeAtIndex:1]]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ([codecPayloadTypes count] == 0) {
|
|
||||||
RTCLog(@"No payload types with name %@", codec);
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
NSArray *origMLineParts =
|
|
||||||
[lines[mLineIndex] componentsSeparatedByString:mLineSeparator];
|
|
||||||
// The format of ML should be: m=<media> <port> <proto> <fmt> ...
|
|
||||||
const int kHeaderLength = 3;
|
|
||||||
if (origMLineParts.count <= kHeaderLength) {
|
|
||||||
RTCLogWarning(@"Wrong SDP media description format: %@", lines[mLineIndex]);
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
// Split the line into header and payloadTypes.
|
|
||||||
NSRange headerRange = NSMakeRange(0, kHeaderLength);
|
|
||||||
NSRange payloadRange =
|
|
||||||
NSMakeRange(kHeaderLength, origMLineParts.count - kHeaderLength);
|
|
||||||
NSArray *header = [origMLineParts subarrayWithRange:headerRange];
|
|
||||||
NSMutableArray *payloadTypes = [NSMutableArray
|
|
||||||
arrayWithArray:[origMLineParts subarrayWithRange:payloadRange]];
|
|
||||||
// Reconstruct the line with |codecPayloadTypes| moved to the beginning of the
|
|
||||||
// payload types.
|
|
||||||
NSMutableArray *newMLineParts = [NSMutableArray arrayWithCapacity:origMLineParts.count];
|
|
||||||
[newMLineParts addObjectsFromArray:header];
|
|
||||||
[newMLineParts addObjectsFromArray:codecPayloadTypes];
|
|
||||||
[payloadTypes removeObjectsInArray:codecPayloadTypes];
|
|
||||||
[newMLineParts addObjectsFromArray:payloadTypes];
|
|
||||||
|
|
||||||
NSString *newMLine = [newMLineParts componentsJoinedByString:mLineSeparator];
|
|
||||||
[lines replaceObjectAtIndex:mLineIndex
|
|
||||||
withObject:newMLine];
|
|
||||||
|
|
||||||
NSString *mangledSdpString = [lines componentsJoinedByString:lineSeparator];
|
|
||||||
return [[RTCSessionDescription alloc] initWithType:description.type
|
|
||||||
sdp:mangledSdpString];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import "WebRTC/RTCVideoCodec.h"
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,12 +53,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
/**
|
/**
|
||||||
* Returns array of available video codecs.
|
* Returns array of available video codecs.
|
||||||
*/
|
*/
|
||||||
- (NSArray<NSString *> *)availableVideoCodecs;
|
- (NSArray<RTCVideoCodecInfo *> *)availableVideoCodecs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns current video codec setting from store if present or default (H264) otherwise.
|
* Returns current video codec setting from store if present or default (H264) otherwise.
|
||||||
*/
|
*/
|
||||||
- (NSString *)currentVideoCodecSettingFromStore;
|
- (RTCVideoCodecInfo *)currentVideoCodecSettingFromStore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the provided video codec setting into the store.
|
* Stores the provided video codec setting into the store.
|
||||||
@ -66,7 +68,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
* @param video codec settings the string to be stored.
|
* @param video codec settings the string to be stored.
|
||||||
* @return YES/NO depending on success.
|
* @return YES/NO depending on success.
|
||||||
*/
|
*/
|
||||||
- (BOOL)storeVideoCodecSetting:(NSString *)videoCodec;
|
- (BOOL)storeVideoCodecSetting:(RTCVideoCodecInfo *)videoCodec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns current max bitrate setting from store if present.
|
* Returns current max bitrate setting from store if present.
|
||||||
|
|||||||
@ -10,15 +10,12 @@
|
|||||||
|
|
||||||
#import "ARDSettingsModel+Private.h"
|
#import "ARDSettingsModel+Private.h"
|
||||||
#import "ARDSettingsStore.h"
|
#import "ARDSettingsStore.h"
|
||||||
|
#import "ARDVideoEncoderFactory.h"
|
||||||
#import "WebRTC/RTCCameraVideoCapturer.h"
|
#import "WebRTC/RTCCameraVideoCapturer.h"
|
||||||
#import "WebRTC/RTCMediaConstraints.h"
|
#import "WebRTC/RTCMediaConstraints.h"
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
static NSArray<NSString *> *videoCodecsStaticValues() {
|
|
||||||
return @[ @"H264", @"VP8", @"VP9" ];
|
|
||||||
}
|
|
||||||
|
|
||||||
@interface ARDSettingsModel () {
|
@interface ARDSettingsModel () {
|
||||||
ARDSettingsStore *_settingsStore;
|
ARDSettingsStore *_settingsStore;
|
||||||
}
|
}
|
||||||
@ -68,20 +65,24 @@ static NSArray<NSString *> *videoCodecsStaticValues() {
|
|||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<NSString *> *)availableVideoCodecs {
|
- (NSArray<RTCVideoCodecInfo *> *)availableVideoCodecs {
|
||||||
return videoCodecsStaticValues();
|
NSArray<RTCVideoCodecInfo *> *supportedCodecs =
|
||||||
|
[[[ARDVideoEncoderFactory alloc] init] supportedCodecs];
|
||||||
|
return supportedCodecs;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)currentVideoCodecSettingFromStore {
|
- (RTCVideoCodecInfo *)currentVideoCodecSettingFromStore {
|
||||||
[self registerStoreDefaults];
|
[self registerStoreDefaults];
|
||||||
return [[self settingsStore] videoCodec];
|
NSData *codecData = [[self settingsStore] videoCodec];
|
||||||
|
return [NSKeyedUnarchiver unarchiveObjectWithData:codecData];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)storeVideoCodecSetting:(NSString *)videoCodec {
|
- (BOOL)storeVideoCodecSetting:(RTCVideoCodecInfo *)videoCodec {
|
||||||
if (![[self availableVideoCodecs] containsObject:videoCodec]) {
|
if (![[self availableVideoCodecs] containsObject:videoCodec]) {
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
[[self settingsStore] setVideoCodec:videoCodec];
|
NSData *codecData = [NSKeyedArchiver archivedDataWithRootObject:videoCodec];
|
||||||
|
[[self settingsStore] setVideoCodec:codecData];
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,8 +154,8 @@ static NSArray<NSString *> *videoCodecsStaticValues() {
|
|||||||
return [self availableVideoResolutions][0];
|
return [self availableVideoResolutions][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)defaultVideoCodecSetting {
|
- (RTCVideoCodecInfo *)defaultVideoCodecSetting {
|
||||||
return videoCodecsStaticValues()[0];
|
return [self availableVideoCodecs][0];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int)videoResolutionComponentAtIndex:(int)index inString:(NSString *)resolution {
|
- (int)videoResolutionComponentAtIndex:(int)index inString:(NSString *)resolution {
|
||||||
@ -169,8 +170,9 @@ static NSArray<NSString *> *videoCodecsStaticValues() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)registerStoreDefaults {
|
- (void)registerStoreDefaults {
|
||||||
|
NSData *codecData = [NSKeyedArchiver archivedDataWithRootObject:[self defaultVideoCodecSetting]];
|
||||||
[ARDSettingsStore setDefaultsForVideoResolution:[self defaultVideoResolutionSetting]
|
[ARDSettingsStore setDefaultsForVideoResolution:[self defaultVideoResolutionSetting]
|
||||||
videoCodec:[self defaultVideoCodecSetting]
|
videoCodec:codecData
|
||||||
bitrate:nil
|
bitrate:nil
|
||||||
audioOnly:NO
|
audioOnly:NO
|
||||||
createAecDump:NO
|
createAecDump:NO
|
||||||
|
|||||||
@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
* @param dictionary of values to store
|
* @param dictionary of values to store
|
||||||
*/
|
*/
|
||||||
+ (void)setDefaultsForVideoResolution:(NSString *)videoResolution
|
+ (void)setDefaultsForVideoResolution:(NSString *)videoResolution
|
||||||
videoCodec:(NSString *)videoCodec
|
videoCodec:(NSData *)videoCodec
|
||||||
bitrate:(nullable NSNumber *)bitrate
|
bitrate:(nullable NSNumber *)bitrate
|
||||||
audioOnly:(BOOL)audioOnly
|
audioOnly:(BOOL)audioOnly
|
||||||
createAecDump:(BOOL)createAecDump
|
createAecDump:(BOOL)createAecDump
|
||||||
@ -32,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
useManualAudioConfig:(BOOL)useManualAudioConfig;
|
useManualAudioConfig:(BOOL)useManualAudioConfig;
|
||||||
|
|
||||||
@property(nonatomic) NSString *videoResolution;
|
@property(nonatomic) NSString *videoResolution;
|
||||||
@property(nonatomic) NSString *videoCodec;
|
@property(nonatomic) NSData *videoCodec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns current max bitrate number stored in the store.
|
* Returns current max bitrate number stored in the store.
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
#import "ARDSettingsStore.h"
|
#import "ARDSettingsStore.h"
|
||||||
|
|
||||||
static NSString *const kVideoResolutionKey = @"rtc_video_resolution_key";
|
static NSString *const kVideoResolutionKey = @"rtc_video_resolution_key";
|
||||||
static NSString *const kVideoCodecKey = @"rtc_video_codec_key";
|
static NSString *const kVideoCodecKey = @"rtc_video_codec_info_key";
|
||||||
static NSString *const kBitrateKey = @"rtc_max_bitrate_key";
|
static NSString *const kBitrateKey = @"rtc_max_bitrate_key";
|
||||||
static NSString *const kAudioOnlyKey = @"rtc_audio_only_key";
|
static NSString *const kAudioOnlyKey = @"rtc_audio_only_key";
|
||||||
static NSString *const kCreateAecDumpKey = @"rtc_create_aec_dump_key";
|
static NSString *const kCreateAecDumpKey = @"rtc_create_aec_dump_key";
|
||||||
@ -28,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@implementation ARDSettingsStore
|
@implementation ARDSettingsStore
|
||||||
|
|
||||||
+ (void)setDefaultsForVideoResolution:(NSString *)videoResolution
|
+ (void)setDefaultsForVideoResolution:(NSString *)videoResolution
|
||||||
videoCodec:(NSString *)videoCodec
|
videoCodec:(NSData *)videoCodec
|
||||||
bitrate:(nullable NSNumber *)bitrate
|
bitrate:(nullable NSNumber *)bitrate
|
||||||
audioOnly:(BOOL)audioOnly
|
audioOnly:(BOOL)audioOnly
|
||||||
createAecDump:(BOOL)createAecDump
|
createAecDump:(BOOL)createAecDump
|
||||||
@ -64,11 +64,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
[self.storage synchronize];
|
[self.storage synchronize];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)videoCodec {
|
- (NSData *)videoCodec {
|
||||||
return [self.storage objectForKey:kVideoCodecKey];
|
return [self.storage objectForKey:kVideoCodecKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setVideoCodec:(NSString *)videoCodec {
|
- (void)setVideoCodec:(NSData *)videoCodec {
|
||||||
[self.storage setObject:videoCodec forKey:kVideoCodecKey];
|
[self.storage setObject:videoCodec forKey:kVideoCodecKey];
|
||||||
[self.storage synchronize];
|
[self.storage synchronize];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,4 +13,6 @@
|
|||||||
|
|
||||||
@interface ARDVideoEncoderFactory : NSObject<RTCVideoEncoderFactory>
|
@interface ARDVideoEncoderFactory : NSObject<RTCVideoEncoderFactory>
|
||||||
|
|
||||||
|
@property(nonatomic, retain) RTCVideoCodecInfo* preferredCodec;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#import "ARDVideoEncoderFactory.h"
|
#import "ARDVideoEncoderFactory.h"
|
||||||
|
|
||||||
|
#import "ARDSettingsModel.h"
|
||||||
#import "WebRTC/RTCVideoCodecH264.h"
|
#import "WebRTC/RTCVideoCodecH264.h"
|
||||||
#import "WebRTC/RTCVideoEncoderVP8.h"
|
#import "WebRTC/RTCVideoEncoderVP8.h"
|
||||||
#import "WebRTC/RTCVideoEncoderVP9.h"
|
#import "WebRTC/RTCVideoEncoderVP9.h"
|
||||||
@ -19,6 +20,8 @@ static NSString *kLevel31ConstrainedBaseline = @"42e01f";
|
|||||||
|
|
||||||
@implementation ARDVideoEncoderFactory
|
@implementation ARDVideoEncoderFactory
|
||||||
|
|
||||||
|
@synthesize preferredCodec;
|
||||||
|
|
||||||
- (id<RTCVideoEncoder>)createEncoder:(RTCVideoCodecInfo *)info {
|
- (id<RTCVideoEncoder>)createEncoder:(RTCVideoCodecInfo *)info {
|
||||||
if ([info.name isEqualToString:@"H264"]) {
|
if ([info.name isEqualToString:@"H264"]) {
|
||||||
return [[RTCVideoEncoderH264 alloc] initWithCodecInfo:info];
|
return [[RTCVideoEncoderH264 alloc] initWithCodecInfo:info];
|
||||||
@ -58,7 +61,15 @@ static NSString *kLevel31ConstrainedBaseline = @"42e01f";
|
|||||||
RTCVideoCodecInfo *vp9Info = [[RTCVideoCodecInfo alloc] initWithName:@"VP9" parameters:nil];
|
RTCVideoCodecInfo *vp9Info = [[RTCVideoCodecInfo alloc] initWithName:@"VP9" parameters:nil];
|
||||||
[codecs addObject:vp9Info];
|
[codecs addObject:vp9Info];
|
||||||
|
|
||||||
return [codecs copy];
|
NSMutableArray<RTCVideoCodecInfo *> *orderedCodecs = [NSMutableArray array];
|
||||||
|
NSUInteger index = [codecs indexOfObject:self.preferredCodec];
|
||||||
|
if (index != NSNotFound) {
|
||||||
|
[orderedCodecs addObject:[codecs objectAtIndex:index]];
|
||||||
|
[codecs removeObjectAtIndex:index];
|
||||||
|
}
|
||||||
|
[orderedCodecs addObjectsFromArray:codecs];
|
||||||
|
|
||||||
|
return [orderedCodecs copy];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#import "ARDSettingsViewController.h"
|
#import "ARDSettingsViewController.h"
|
||||||
#import "ARDSettingsModel.h"
|
#import "ARDSettingsModel.h"
|
||||||
|
#import "RTCVideoCodecInfo+HumanReadable.h"
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@ -62,7 +63,7 @@ typedef NS_ENUM(int, ARDAudioSettingsOptions) {
|
|||||||
return [_settingsModel availableVideoResolutions];
|
return [_settingsModel availableVideoResolutions];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<NSString *> *)videoCodecArray {
|
- (NSArray<RTCVideoCodecInfo *> *)videoCodecArray {
|
||||||
return [_settingsModel availableVideoCodecs];
|
return [_settingsModel availableVideoCodecs];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,9 +215,9 @@ updateListSelectionAtIndexPath:(NSIndexPath *)indexPath
|
|||||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
|
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
|
||||||
reuseIdentifier:dequeueIdentifier];
|
reuseIdentifier:dequeueIdentifier];
|
||||||
}
|
}
|
||||||
NSString *codec = self.videoCodecArray[indexPath.row];
|
RTCVideoCodecInfo *codec = self.videoCodecArray[indexPath.row];
|
||||||
cell.textLabel.text = codec;
|
cell.textLabel.text = [codec humanReadableDescription];
|
||||||
if ([codec isEqualToString:[_settingsModel currentVideoCodecSettingFromStore]]) {
|
if ([codec isEqualToCodecInfo:[_settingsModel currentVideoCodecSettingFromStore]]) {
|
||||||
cell.accessoryType = UITableViewCellAccessoryCheckmark;
|
cell.accessoryType = UITableViewCellAccessoryCheckmark;
|
||||||
} else {
|
} else {
|
||||||
cell.accessoryType = UITableViewCellAccessoryNone;
|
cell.accessoryType = UITableViewCellAccessoryNone;
|
||||||
@ -231,7 +232,7 @@ updateListSelectionAtIndexPath:(NSIndexPath *)indexPath
|
|||||||
updateListSelectionAtIndexPath:indexPath
|
updateListSelectionAtIndexPath:indexPath
|
||||||
inSection:ARDSettingsSectionVideoCodec];
|
inSection:ARDSettingsSectionVideoCodec];
|
||||||
|
|
||||||
NSString *videoCodec = self.videoCodecArray[indexPath.row];
|
RTCVideoCodecInfo *videoCodec = self.videoCodecArray[indexPath.row];
|
||||||
[_settingsModel storeVideoCodecSetting:videoCodec];
|
[_settingsModel storeVideoCodecSetting:videoCodec];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* 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 "WebRTC/RTCVideoCodec.h"
|
||||||
|
|
||||||
|
@interface RTCVideoCodecInfo (HumanReadable)
|
||||||
|
|
||||||
|
- (NSString *)humanReadableDescription;
|
||||||
|
|
||||||
|
@end
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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 "RTCVideoCodecInfo+HumanReadable.h"
|
||||||
|
|
||||||
|
@implementation RTCVideoCodecInfo (HumanReadable)
|
||||||
|
|
||||||
|
- (NSString *)humanReadableDescription {
|
||||||
|
if ([self.name isEqualToString:@"H264"]) {
|
||||||
|
NSString *profileId = self.parameters[@"profile-level-id"];
|
||||||
|
if ([profileId isEqualToString:@"640c1f"]) {
|
||||||
|
return @"H264 (High)";
|
||||||
|
} else if ([profileId isEqualToString:@"42e01f"]) {
|
||||||
|
return @"H264 (Baseline)";
|
||||||
|
} else {
|
||||||
|
return [NSString stringWithFormat:@"H264 (%@)", profileId];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return self.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -21,7 +21,6 @@
|
|||||||
#import "ARDAppClient+Internal.h"
|
#import "ARDAppClient+Internal.h"
|
||||||
#import "ARDJoinResponse+Internal.h"
|
#import "ARDJoinResponse+Internal.h"
|
||||||
#import "ARDMessageResponse+Internal.h"
|
#import "ARDMessageResponse+Internal.h"
|
||||||
#import "ARDSDPUtils.h"
|
|
||||||
#import "ARDSettingsModel.h"
|
#import "ARDSettingsModel.h"
|
||||||
|
|
||||||
@interface ARDAppClientTest : XCTestCase
|
@interface ARDAppClientTest : XCTestCase
|
||||||
|
|||||||
@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 <Foundation/Foundation.h>
|
|
||||||
#import <XCTest/XCTest.h>
|
|
||||||
|
|
||||||
#import "WebRTC/RTCSessionDescription.h"
|
|
||||||
|
|
||||||
#import "ARDSDPUtils.h"
|
|
||||||
|
|
||||||
@interface ARDSDPUtilsTest : XCTestCase
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation ARDSDPUtilsTest
|
|
||||||
|
|
||||||
- (void)testPreferVideoCodecH264 {
|
|
||||||
NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\r\n"
|
|
||||||
"a=rtpmap:120 H264/90000\r\n"
|
|
||||||
"a=rtpmap:97 H264/90000\r\n");
|
|
||||||
NSString *expectedSdp = @("m=video 9 RTP/SAVPF 120 97 100 116 117 96\r\n"
|
|
||||||
"a=rtpmap:120 H264/90000\r\n"
|
|
||||||
"a=rtpmap:97 H264/90000\r\n");
|
|
||||||
[self preferVideoCodec:@"H264" sdp:sdp expected:expectedSdp];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)testPreferVideoCodecVP8 {
|
|
||||||
NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\r\n"
|
|
||||||
"a=rtpmap:116 VP8/90000\r\n");
|
|
||||||
NSString *expectedSdp = @("m=video 9 RTP/SAVPF 116 100 117 96 120 97\r\n"
|
|
||||||
"a=rtpmap:116 VP8/90000\r\n");
|
|
||||||
[self preferVideoCodec:@"VP8" sdp:sdp expected:expectedSdp];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)testNoMLine {
|
|
||||||
NSString *sdp = @("a=rtpmap:116 VP8/90000\r\n");
|
|
||||||
[self preferVideoCodec:@"VP8" sdp:sdp expected:sdp];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)testMissingCodec {
|
|
||||||
NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120 97\r\n"
|
|
||||||
"a=rtpmap:116 VP8/90000\r\n");
|
|
||||||
[self preferVideoCodec:@"foo" sdp:sdp expected:sdp];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark - Helpers
|
|
||||||
|
|
||||||
- (void)preferVideoCodec:(NSString *)codec
|
|
||||||
sdp:(NSString *)sdp
|
|
||||||
expected:(NSString *)expectedSdp{
|
|
||||||
RTCSessionDescription* desc =
|
|
||||||
[[RTCSessionDescription alloc] initWithType:RTCSdpTypeOffer sdp:sdp];
|
|
||||||
RTCSessionDescription *outputDesc =
|
|
||||||
[ARDSDPUtils descriptionForDescription:desc
|
|
||||||
preferredVideoCodec:codec];
|
|
||||||
XCTAssertTrue([outputDesc.description rangeOfString:expectedSdp].location != NSNotFound);
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
@ -89,6 +89,18 @@
|
|||||||
return codec;
|
return codec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - NSCoding
|
||||||
|
|
||||||
|
- (instancetype)initWithCoder:(NSCoder *)decoder {
|
||||||
|
return [self initWithName:[decoder decodeObjectForKey:@"name"]
|
||||||
|
parameters:[decoder decodeObjectForKey:@"parameters"]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)encodeWithCoder:(NSCoder *)encoder {
|
||||||
|
[encoder encodeObject:_name forKey:@"name"];
|
||||||
|
[encoder encodeObject:_parameters forKey:@"parameters"];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation RTCVideoEncoderQpThresholds
|
@implementation RTCVideoEncoderQpThresholds
|
||||||
|
|||||||
@ -84,7 +84,7 @@ typedef NS_ENUM(NSUInteger, RTCVideoCodecMode) {
|
|||||||
|
|
||||||
/** Holds information to identify a codec. Corresponds to cricket::VideoCodec. */
|
/** Holds information to identify a codec. Corresponds to cricket::VideoCodec. */
|
||||||
RTC_EXPORT
|
RTC_EXPORT
|
||||||
@interface RTCVideoCodecInfo : NSObject
|
@interface RTCVideoCodecInfo : NSObject <NSCoding>
|
||||||
|
|
||||||
- (instancetype)init NS_UNAVAILABLE;
|
- (instancetype)init NS_UNAVAILABLE;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user