| Index: talk/examples/objc/AppRTCDemo/ARDAppClient.m
|
| diff --git a/talk/examples/objc/AppRTCDemo/ARDAppClient.m b/talk/examples/objc/AppRTCDemo/ARDAppClient.m
|
| deleted file mode 100644
|
| index e043da23b55769eceb0ba4075b6b262ba2ddbc00..0000000000000000000000000000000000000000
|
| --- a/talk/examples/objc/AppRTCDemo/ARDAppClient.m
|
| +++ /dev/null
|
| @@ -1,658 +0,0 @@
|
| -/*
|
| - * libjingle
|
| - * Copyright 2014 Google Inc.
|
| - *
|
| - * Redistribution and use in source and binary forms, with or without
|
| - * modification, are permitted provided that the following conditions are met:
|
| - *
|
| - * 1. Redistributions of source code must retain the above copyright notice,
|
| - * this list of conditions and the following disclaimer.
|
| - * 2. Redistributions in binary form must reproduce the above copyright notice,
|
| - * this list of conditions and the following disclaimer in the documentation
|
| - * and/or other materials provided with the distribution.
|
| - * 3. The name of the author may not be used to endorse or promote products
|
| - * derived from this software without specific prior written permission.
|
| - *
|
| - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
| - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
| - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
| - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
| - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
| - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
| - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
| - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
| - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| - */
|
| -
|
| -#import "ARDAppClient+Internal.h"
|
| -
|
| -#if defined(WEBRTC_IOS)
|
| -#import "RTCAVFoundationVideoSource.h"
|
| -#endif
|
| -#import "RTCFileLogger.h"
|
| -#import "RTCICEServer.h"
|
| -#import "RTCLogging.h"
|
| -#import "RTCMediaConstraints.h"
|
| -#import "RTCMediaStream.h"
|
| -#import "RTCPair.h"
|
| -#import "RTCPeerConnectionInterface.h"
|
| -#import "RTCVideoCapturer.h"
|
| -
|
| -#import "ARDAppEngineClient.h"
|
| -#import "ARDCEODTURNClient.h"
|
| -#import "ARDJoinResponse.h"
|
| -#import "ARDMessageResponse.h"
|
| -#import "ARDSDPUtils.h"
|
| -#import "ARDSignalingMessage.h"
|
| -#import "ARDUtilities.h"
|
| -#import "ARDWebSocketChannel.h"
|
| -#import "RTCICECandidate+JSON.h"
|
| -#import "RTCSessionDescription+JSON.h"
|
| -
|
| -
|
| -static NSString * const kARDDefaultSTUNServerUrl =
|
| - @"stun:stun.l.google.com:19302";
|
| -// TODO(tkchin): figure out a better username for CEOD statistics.
|
| -static NSString * const kARDTurnRequestUrl =
|
| - @"https://computeengineondemand.appspot.com"
|
| - @"/turn?username=iapprtc&key=4080218913";
|
| -
|
| -static NSString * const kARDAppClientErrorDomain = @"ARDAppClient";
|
| -static NSInteger const kARDAppClientErrorUnknown = -1;
|
| -static NSInteger const kARDAppClientErrorRoomFull = -2;
|
| -static NSInteger const kARDAppClientErrorCreateSDP = -3;
|
| -static NSInteger const kARDAppClientErrorSetSDP = -4;
|
| -static NSInteger const kARDAppClientErrorInvalidClient = -5;
|
| -static NSInteger const kARDAppClientErrorInvalidRoom = -6;
|
| -
|
| -@implementation ARDAppClient {
|
| - RTCFileLogger *_fileLogger;
|
| -}
|
| -
|
| -@synthesize delegate = _delegate;
|
| -@synthesize state = _state;
|
| -@synthesize roomServerClient = _roomServerClient;
|
| -@synthesize channel = _channel;
|
| -@synthesize turnClient = _turnClient;
|
| -@synthesize peerConnection = _peerConnection;
|
| -@synthesize factory = _factory;
|
| -@synthesize messageQueue = _messageQueue;
|
| -@synthesize isTurnComplete = _isTurnComplete;
|
| -@synthesize hasReceivedSdp = _hasReceivedSdp;
|
| -@synthesize roomId = _roomId;
|
| -@synthesize clientId = _clientId;
|
| -@synthesize isInitiator = _isInitiator;
|
| -@synthesize iceServers = _iceServers;
|
| -@synthesize webSocketURL = _websocketURL;
|
| -@synthesize webSocketRestURL = _websocketRestURL;
|
| -@synthesize defaultPeerConnectionConstraints =
|
| - _defaultPeerConnectionConstraints;
|
| -
|
| -- (instancetype)init {
|
| - if (self = [super init]) {
|
| - _roomServerClient = [[ARDAppEngineClient alloc] init];
|
| - NSURL *turnRequestURL = [NSURL URLWithString:kARDTurnRequestUrl];
|
| - _turnClient = [[ARDCEODTURNClient alloc] initWithURL:turnRequestURL];
|
| - [self configure];
|
| - }
|
| - return self;
|
| -}
|
| -
|
| -- (instancetype)initWithDelegate:(id<ARDAppClientDelegate>)delegate {
|
| - if (self = [super init]) {
|
| - _roomServerClient = [[ARDAppEngineClient alloc] init];
|
| - _delegate = delegate;
|
| - NSURL *turnRequestURL = [NSURL URLWithString:kARDTurnRequestUrl];
|
| - _turnClient = [[ARDCEODTURNClient alloc] initWithURL:turnRequestURL];
|
| - [self configure];
|
| - }
|
| - return self;
|
| -}
|
| -
|
| -// TODO(tkchin): Provide signaling channel factory interface so we can recreate
|
| -// channel if we need to on network failure. Also, make this the default public
|
| -// constructor.
|
| -- (instancetype)initWithRoomServerClient:(id<ARDRoomServerClient>)rsClient
|
| - signalingChannel:(id<ARDSignalingChannel>)channel
|
| - turnClient:(id<ARDTURNClient>)turnClient
|
| - delegate:(id<ARDAppClientDelegate>)delegate {
|
| - NSParameterAssert(rsClient);
|
| - NSParameterAssert(channel);
|
| - NSParameterAssert(turnClient);
|
| - if (self = [super init]) {
|
| - _roomServerClient = rsClient;
|
| - _channel = channel;
|
| - _turnClient = turnClient;
|
| - _delegate = delegate;
|
| - [self configure];
|
| - }
|
| - return self;
|
| -}
|
| -
|
| -- (void)configure {
|
| - _factory = [[RTCPeerConnectionFactory alloc] init];
|
| - _messageQueue = [NSMutableArray array];
|
| - _iceServers = [NSMutableArray arrayWithObject:[self defaultSTUNServer]];
|
| - _fileLogger = [[RTCFileLogger alloc] init];
|
| - [_fileLogger start];
|
| -}
|
| -
|
| -- (void)dealloc {
|
| - [self disconnect];
|
| -}
|
| -
|
| -- (void)setState:(ARDAppClientState)state {
|
| - if (_state == state) {
|
| - return;
|
| - }
|
| - _state = state;
|
| - [_delegate appClient:self didChangeState:_state];
|
| -}
|
| -
|
| -- (void)connectToRoomWithId:(NSString *)roomId
|
| - options:(NSDictionary *)options {
|
| - NSParameterAssert(roomId.length);
|
| - NSParameterAssert(_state == kARDAppClientStateDisconnected);
|
| - self.state = kARDAppClientStateConnecting;
|
| -
|
| - // Request TURN.
|
| - __weak ARDAppClient *weakSelf = self;
|
| - [_turnClient requestServersWithCompletionHandler:^(NSArray *turnServers,
|
| - NSError *error) {
|
| - if (error) {
|
| - RTCLogError("Error retrieving TURN servers: %@",
|
| - error.localizedDescription);
|
| - }
|
| - ARDAppClient *strongSelf = weakSelf;
|
| - [strongSelf.iceServers addObjectsFromArray:turnServers];
|
| - strongSelf.isTurnComplete = YES;
|
| - [strongSelf startSignalingIfReady];
|
| - }];
|
| -
|
| - // Join room on room server.
|
| - [_roomServerClient joinRoomWithRoomId:roomId
|
| - completionHandler:^(ARDJoinResponse *response, NSError *error) {
|
| - ARDAppClient *strongSelf = weakSelf;
|
| - if (error) {
|
| - [strongSelf.delegate appClient:strongSelf didError:error];
|
| - return;
|
| - }
|
| - NSError *joinError =
|
| - [[strongSelf class] errorForJoinResultType:response.result];
|
| - if (joinError) {
|
| - RTCLogError(@"Failed to join room:%@ on room server.", roomId);
|
| - [strongSelf disconnect];
|
| - [strongSelf.delegate appClient:strongSelf didError:joinError];
|
| - return;
|
| - }
|
| - RTCLog(@"Joined room:%@ on room server.", roomId);
|
| - strongSelf.roomId = response.roomId;
|
| - strongSelf.clientId = response.clientId;
|
| - strongSelf.isInitiator = response.isInitiator;
|
| - for (ARDSignalingMessage *message in response.messages) {
|
| - if (message.type == kARDSignalingMessageTypeOffer ||
|
| - message.type == kARDSignalingMessageTypeAnswer) {
|
| - strongSelf.hasReceivedSdp = YES;
|
| - [strongSelf.messageQueue insertObject:message atIndex:0];
|
| - } else {
|
| - [strongSelf.messageQueue addObject:message];
|
| - }
|
| - }
|
| - strongSelf.webSocketURL = response.webSocketURL;
|
| - strongSelf.webSocketRestURL = response.webSocketRestURL;
|
| - [strongSelf registerWithColliderIfReady];
|
| - [strongSelf startSignalingIfReady];
|
| - }];
|
| -}
|
| -
|
| -- (void)disconnect {
|
| - if (_state == kARDAppClientStateDisconnected) {
|
| - return;
|
| - }
|
| - if (self.hasJoinedRoomServerRoom) {
|
| - [_roomServerClient leaveRoomWithRoomId:_roomId
|
| - clientId:_clientId
|
| - completionHandler:nil];
|
| - }
|
| - if (_channel) {
|
| - if (_channel.state == kARDSignalingChannelStateRegistered) {
|
| - // Tell the other client we're hanging up.
|
| - ARDByeMessage *byeMessage = [[ARDByeMessage alloc] init];
|
| - [_channel sendMessage:byeMessage];
|
| - }
|
| - // Disconnect from collider.
|
| - _channel = nil;
|
| - }
|
| - _clientId = nil;
|
| - _roomId = nil;
|
| - _isInitiator = NO;
|
| - _hasReceivedSdp = NO;
|
| - _messageQueue = [NSMutableArray array];
|
| - _peerConnection = nil;
|
| - self.state = kARDAppClientStateDisconnected;
|
| -}
|
| -
|
| -#pragma mark - ARDSignalingChannelDelegate
|
| -
|
| -- (void)channel:(id<ARDSignalingChannel>)channel
|
| - didReceiveMessage:(ARDSignalingMessage *)message {
|
| - switch (message.type) {
|
| - case kARDSignalingMessageTypeOffer:
|
| - case kARDSignalingMessageTypeAnswer:
|
| - // Offers and answers must be processed before any other message, so we
|
| - // place them at the front of the queue.
|
| - _hasReceivedSdp = YES;
|
| - [_messageQueue insertObject:message atIndex:0];
|
| - break;
|
| - case kARDSignalingMessageTypeCandidate:
|
| - [_messageQueue addObject:message];
|
| - break;
|
| - case kARDSignalingMessageTypeBye:
|
| - // Disconnects can be processed immediately.
|
| - [self processSignalingMessage:message];
|
| - return;
|
| - }
|
| - [self drainMessageQueueIfReady];
|
| -}
|
| -
|
| -- (void)channel:(id<ARDSignalingChannel>)channel
|
| - didChangeState:(ARDSignalingChannelState)state {
|
| - switch (state) {
|
| - case kARDSignalingChannelStateOpen:
|
| - break;
|
| - case kARDSignalingChannelStateRegistered:
|
| - break;
|
| - case kARDSignalingChannelStateClosed:
|
| - case kARDSignalingChannelStateError:
|
| - // TODO(tkchin): reconnection scenarios. Right now we just disconnect
|
| - // completely if the websocket connection fails.
|
| - [self disconnect];
|
| - break;
|
| - }
|
| -}
|
| -
|
| -#pragma mark - RTCPeerConnectionDelegate
|
| -// Callbacks for this delegate occur on non-main thread and need to be
|
| -// dispatched back to main queue as needed.
|
| -
|
| -- (void)peerConnection:(RTCPeerConnection *)peerConnection
|
| - signalingStateChanged:(RTCSignalingState)stateChanged {
|
| - RTCLog(@"Signaling state changed: %d", stateChanged);
|
| -}
|
| -
|
| -- (void)peerConnection:(RTCPeerConnection *)peerConnection
|
| - addedStream:(RTCMediaStream *)stream {
|
| - dispatch_async(dispatch_get_main_queue(), ^{
|
| - RTCLog(@"Received %lu video tracks and %lu audio tracks",
|
| - (unsigned long)stream.videoTracks.count,
|
| - (unsigned long)stream.audioTracks.count);
|
| - if (stream.videoTracks.count) {
|
| - RTCVideoTrack *videoTrack = stream.videoTracks[0];
|
| - [_delegate appClient:self didReceiveRemoteVideoTrack:videoTrack];
|
| - }
|
| - });
|
| -}
|
| -
|
| -- (void)peerConnection:(RTCPeerConnection *)peerConnection
|
| - removedStream:(RTCMediaStream *)stream {
|
| - RTCLog(@"Stream was removed.");
|
| -}
|
| -
|
| -- (void)peerConnectionOnRenegotiationNeeded:
|
| - (RTCPeerConnection *)peerConnection {
|
| - RTCLog(@"WARNING: Renegotiation needed but unimplemented.");
|
| -}
|
| -
|
| -- (void)peerConnection:(RTCPeerConnection *)peerConnection
|
| - iceConnectionChanged:(RTCICEConnectionState)newState {
|
| - RTCLog(@"ICE state changed: %d", newState);
|
| - dispatch_async(dispatch_get_main_queue(), ^{
|
| - [_delegate appClient:self didChangeConnectionState:newState];
|
| - });
|
| -}
|
| -
|
| -- (void)peerConnection:(RTCPeerConnection *)peerConnection
|
| - iceGatheringChanged:(RTCICEGatheringState)newState {
|
| - RTCLog(@"ICE gathering state changed: %d", newState);
|
| -}
|
| -
|
| -- (void)peerConnection:(RTCPeerConnection *)peerConnection
|
| - gotICECandidate:(RTCICECandidate *)candidate {
|
| - dispatch_async(dispatch_get_main_queue(), ^{
|
| - ARDICECandidateMessage *message =
|
| - [[ARDICECandidateMessage alloc] initWithCandidate:candidate];
|
| - [self sendSignalingMessage:message];
|
| - });
|
| -}
|
| -
|
| -- (void)peerConnection:(RTCPeerConnection*)peerConnection
|
| - didOpenDataChannel:(RTCDataChannel*)dataChannel {
|
| -}
|
| -
|
| -#pragma mark - RTCSessionDescriptionDelegate
|
| -// Callbacks for this delegate occur on non-main thread and need to be
|
| -// dispatched back to main queue as needed.
|
| -
|
| -- (void)peerConnection:(RTCPeerConnection *)peerConnection
|
| - didCreateSessionDescription:(RTCSessionDescription *)sdp
|
| - error:(NSError *)error {
|
| - dispatch_async(dispatch_get_main_queue(), ^{
|
| - if (error) {
|
| - RTCLogError(@"Failed to create session description. Error: %@", error);
|
| - [self disconnect];
|
| - NSDictionary *userInfo = @{
|
| - NSLocalizedDescriptionKey: @"Failed to create session description.",
|
| - };
|
| - NSError *sdpError =
|
| - [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
| - code:kARDAppClientErrorCreateSDP
|
| - userInfo:userInfo];
|
| - [_delegate appClient:self didError:sdpError];
|
| - return;
|
| - }
|
| - // Prefer H264 if available.
|
| - RTCSessionDescription *sdpPreferringH264 =
|
| - [ARDSDPUtils descriptionForDescription:sdp
|
| - preferredVideoCodec:@"H264"];
|
| - [_peerConnection setLocalDescriptionWithDelegate:self
|
| - sessionDescription:sdpPreferringH264];
|
| - ARDSessionDescriptionMessage *message =
|
| - [[ARDSessionDescriptionMessage alloc]
|
| - initWithDescription:sdpPreferringH264];
|
| - [self sendSignalingMessage:message];
|
| - });
|
| -}
|
| -
|
| -- (void)peerConnection:(RTCPeerConnection *)peerConnection
|
| - didSetSessionDescriptionWithError:(NSError *)error {
|
| - dispatch_async(dispatch_get_main_queue(), ^{
|
| - if (error) {
|
| - RTCLogError(@"Failed to set session description. Error: %@", error);
|
| - [self disconnect];
|
| - NSDictionary *userInfo = @{
|
| - NSLocalizedDescriptionKey: @"Failed to set session description.",
|
| - };
|
| - NSError *sdpError =
|
| - [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
| - code:kARDAppClientErrorSetSDP
|
| - userInfo:userInfo];
|
| - [_delegate appClient:self didError:sdpError];
|
| - return;
|
| - }
|
| - // If we're answering and we've just set the remote offer we need to create
|
| - // an answer and set the local description.
|
| - if (!_isInitiator && !_peerConnection.localDescription) {
|
| - RTCMediaConstraints *constraints = [self defaultAnswerConstraints];
|
| - [_peerConnection createAnswerWithDelegate:self
|
| - constraints:constraints];
|
| -
|
| - }
|
| - });
|
| -}
|
| -
|
| -#pragma mark - Private
|
| -
|
| -- (BOOL)hasJoinedRoomServerRoom {
|
| - return _clientId.length;
|
| -}
|
| -
|
| -// Begins the peer connection connection process if we have both joined a room
|
| -// on the room server and tried to obtain a TURN server. Otherwise does nothing.
|
| -// A peer connection object will be created with a stream that contains local
|
| -// audio and video capture. If this client is the caller, an offer is created as
|
| -// well, otherwise the client will wait for an offer to arrive.
|
| -- (void)startSignalingIfReady {
|
| - if (!_isTurnComplete || !self.hasJoinedRoomServerRoom) {
|
| - return;
|
| - }
|
| - self.state = kARDAppClientStateConnected;
|
| -
|
| - // Create peer connection.
|
| - RTCMediaConstraints *constraints = [self defaultPeerConnectionConstraints];
|
| - RTCConfiguration *config = [[RTCConfiguration alloc] init];
|
| - config.iceServers = _iceServers;
|
| - _peerConnection = [_factory peerConnectionWithConfiguration:config
|
| - constraints:constraints
|
| - delegate:self];
|
| - // Create AV media stream and add it to the peer connection.
|
| - RTCMediaStream *localStream = [self createLocalMediaStream];
|
| - [_peerConnection addStream:localStream];
|
| - if (_isInitiator) {
|
| - // Send offer.
|
| - [_peerConnection createOfferWithDelegate:self
|
| - constraints:[self defaultOfferConstraints]];
|
| - } else {
|
| - // Check if we've received an offer.
|
| - [self drainMessageQueueIfReady];
|
| - }
|
| -}
|
| -
|
| -// Processes the messages that we've received from the room server and the
|
| -// signaling channel. The offer or answer message must be processed before other
|
| -// signaling messages, however they can arrive out of order. Hence, this method
|
| -// only processes pending messages if there is a peer connection object and
|
| -// if we have received either an offer or answer.
|
| -- (void)drainMessageQueueIfReady {
|
| - if (!_peerConnection || !_hasReceivedSdp) {
|
| - return;
|
| - }
|
| - for (ARDSignalingMessage *message in _messageQueue) {
|
| - [self processSignalingMessage:message];
|
| - }
|
| - [_messageQueue removeAllObjects];
|
| -}
|
| -
|
| -// Processes the given signaling message based on its type.
|
| -- (void)processSignalingMessage:(ARDSignalingMessage *)message {
|
| - NSParameterAssert(_peerConnection ||
|
| - message.type == kARDSignalingMessageTypeBye);
|
| - switch (message.type) {
|
| - case kARDSignalingMessageTypeOffer:
|
| - case kARDSignalingMessageTypeAnswer: {
|
| - ARDSessionDescriptionMessage *sdpMessage =
|
| - (ARDSessionDescriptionMessage *)message;
|
| - RTCSessionDescription *description = sdpMessage.sessionDescription;
|
| - // Prefer H264 if available.
|
| - RTCSessionDescription *sdpPreferringH264 =
|
| - [ARDSDPUtils descriptionForDescription:description
|
| - preferredVideoCodec:@"H264"];
|
| - [_peerConnection setRemoteDescriptionWithDelegate:self
|
| - sessionDescription:sdpPreferringH264];
|
| - break;
|
| - }
|
| - case kARDSignalingMessageTypeCandidate: {
|
| - ARDICECandidateMessage *candidateMessage =
|
| - (ARDICECandidateMessage *)message;
|
| - [_peerConnection addICECandidate:candidateMessage.candidate];
|
| - break;
|
| - }
|
| - case kARDSignalingMessageTypeBye:
|
| - // Other client disconnected.
|
| - // TODO(tkchin): support waiting in room for next client. For now just
|
| - // disconnect.
|
| - [self disconnect];
|
| - break;
|
| - }
|
| -}
|
| -
|
| -// Sends a signaling message to the other client. The caller will send messages
|
| -// through the room server, whereas the callee will send messages over the
|
| -// signaling channel.
|
| -- (void)sendSignalingMessage:(ARDSignalingMessage *)message {
|
| - if (_isInitiator) {
|
| - __weak ARDAppClient *weakSelf = self;
|
| - [_roomServerClient sendMessage:message
|
| - forRoomId:_roomId
|
| - clientId:_clientId
|
| - completionHandler:^(ARDMessageResponse *response,
|
| - NSError *error) {
|
| - ARDAppClient *strongSelf = weakSelf;
|
| - if (error) {
|
| - [strongSelf.delegate appClient:strongSelf didError:error];
|
| - return;
|
| - }
|
| - NSError *messageError =
|
| - [[strongSelf class] errorForMessageResultType:response.result];
|
| - if (messageError) {
|
| - [strongSelf.delegate appClient:strongSelf didError:messageError];
|
| - return;
|
| - }
|
| - }];
|
| - } else {
|
| - [_channel sendMessage:message];
|
| - }
|
| -}
|
| -
|
| -- (RTCMediaStream *)createLocalMediaStream {
|
| - RTCMediaStream* localStream = [_factory mediaStreamWithLabel:@"ARDAMS"];
|
| - RTCVideoTrack* localVideoTrack = [self createLocalVideoTrack];
|
| - if (localVideoTrack) {
|
| - [localStream addVideoTrack:localVideoTrack];
|
| - [_delegate appClient:self didReceiveLocalVideoTrack:localVideoTrack];
|
| - }
|
| - [localStream addAudioTrack:[_factory audioTrackWithID:@"ARDAMSa0"]];
|
| - return localStream;
|
| -}
|
| -
|
| -- (RTCVideoTrack *)createLocalVideoTrack {
|
| - RTCVideoTrack* localVideoTrack = nil;
|
| - // The iOS simulator doesn't provide any sort of camera capture
|
| - // support or emulation (http://goo.gl/rHAnC1) so don't bother
|
| - // trying to open a local stream.
|
| - // TODO(tkchin): local video capture for OSX. See
|
| - // https://code.google.com/p/webrtc/issues/detail?id=3417.
|
| -#if !TARGET_IPHONE_SIMULATOR && TARGET_OS_IPHONE
|
| - RTCMediaConstraints *mediaConstraints = [self defaultMediaStreamConstraints];
|
| - RTCAVFoundationVideoSource *source =
|
| - [[RTCAVFoundationVideoSource alloc] initWithFactory:_factory
|
| - constraints:mediaConstraints];
|
| - localVideoTrack =
|
| - [[RTCVideoTrack alloc] initWithFactory:_factory
|
| - source:source
|
| - trackId:@"ARDAMSv0"];
|
| -#endif
|
| - return localVideoTrack;
|
| -}
|
| -
|
| -#pragma mark - Collider methods
|
| -
|
| -- (void)registerWithColliderIfReady {
|
| - if (!self.hasJoinedRoomServerRoom) {
|
| - return;
|
| - }
|
| - // Open WebSocket connection.
|
| - if (!_channel) {
|
| - _channel =
|
| - [[ARDWebSocketChannel alloc] initWithURL:_websocketURL
|
| - restURL:_websocketRestURL
|
| - delegate:self];
|
| - }
|
| - [_channel registerForRoomId:_roomId clientId:_clientId];
|
| -}
|
| -
|
| -#pragma mark - Defaults
|
| -
|
| -- (RTCMediaConstraints *)defaultMediaStreamConstraints {
|
| - RTCMediaConstraints* constraints =
|
| - [[RTCMediaConstraints alloc]
|
| - initWithMandatoryConstraints:nil
|
| - optionalConstraints:nil];
|
| - return constraints;
|
| -}
|
| -
|
| -- (RTCMediaConstraints *)defaultAnswerConstraints {
|
| - return [self defaultOfferConstraints];
|
| -}
|
| -
|
| -- (RTCMediaConstraints *)defaultOfferConstraints {
|
| - NSArray *mandatoryConstraints = @[
|
| - [[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"],
|
| - [[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" value:@"true"]
|
| - ];
|
| - RTCMediaConstraints* constraints =
|
| - [[RTCMediaConstraints alloc]
|
| - initWithMandatoryConstraints:mandatoryConstraints
|
| - optionalConstraints:nil];
|
| - return constraints;
|
| -}
|
| -
|
| -- (RTCMediaConstraints *)defaultPeerConnectionConstraints {
|
| - if (_defaultPeerConnectionConstraints) {
|
| - return _defaultPeerConnectionConstraints;
|
| - }
|
| - NSArray *optionalConstraints = @[
|
| - [[RTCPair alloc] initWithKey:@"DtlsSrtpKeyAgreement" value:@"true"]
|
| - ];
|
| - RTCMediaConstraints* constraints =
|
| - [[RTCMediaConstraints alloc]
|
| - initWithMandatoryConstraints:nil
|
| - optionalConstraints:optionalConstraints];
|
| - return constraints;
|
| -}
|
| -
|
| -- (RTCICEServer *)defaultSTUNServer {
|
| - NSURL *defaultSTUNServerURL = [NSURL URLWithString:kARDDefaultSTUNServerUrl];
|
| - return [[RTCICEServer alloc] initWithURI:defaultSTUNServerURL
|
| - username:@""
|
| - password:@""];
|
| -}
|
| -
|
| -#pragma mark - Errors
|
| -
|
| -+ (NSError *)errorForJoinResultType:(ARDJoinResultType)resultType {
|
| - NSError *error = nil;
|
| - switch (resultType) {
|
| - case kARDJoinResultTypeSuccess:
|
| - break;
|
| - case kARDJoinResultTypeUnknown: {
|
| - error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
| - code:kARDAppClientErrorUnknown
|
| - userInfo:@{
|
| - NSLocalizedDescriptionKey: @"Unknown error.",
|
| - }];
|
| - break;
|
| - }
|
| - case kARDJoinResultTypeFull: {
|
| - error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
| - code:kARDAppClientErrorRoomFull
|
| - userInfo:@{
|
| - NSLocalizedDescriptionKey: @"Room is full.",
|
| - }];
|
| - break;
|
| - }
|
| - }
|
| - return error;
|
| -}
|
| -
|
| -+ (NSError *)errorForMessageResultType:(ARDMessageResultType)resultType {
|
| - NSError *error = nil;
|
| - switch (resultType) {
|
| - case kARDMessageResultTypeSuccess:
|
| - break;
|
| - case kARDMessageResultTypeUnknown:
|
| - error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
| - code:kARDAppClientErrorUnknown
|
| - userInfo:@{
|
| - NSLocalizedDescriptionKey: @"Unknown error.",
|
| - }];
|
| - break;
|
| - case kARDMessageResultTypeInvalidClient:
|
| - error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
| - code:kARDAppClientErrorInvalidClient
|
| - userInfo:@{
|
| - NSLocalizedDescriptionKey: @"Invalid client.",
|
| - }];
|
| - break;
|
| - case kARDMessageResultTypeInvalidRoom:
|
| - error = [[NSError alloc] initWithDomain:kARDAppClientErrorDomain
|
| - code:kARDAppClientErrorInvalidRoom
|
| - userInfo:@{
|
| - NSLocalizedDescriptionKey: @"Invalid room.",
|
| - }];
|
| - break;
|
| - }
|
| - return error;
|
| -}
|
| -
|
| -@end
|
|
|