diff --git a/webrtc/examples/objc/AppRTCDemo/ARDAppClient.m b/webrtc/examples/objc/AppRTCDemo/ARDAppClient.m index 7d060c9e9f..86d18d1333 100644 --- a/webrtc/examples/objc/AppRTCDemo/ARDAppClient.m +++ b/webrtc/examples/objc/AppRTCDemo/ARDAppClient.m @@ -22,6 +22,7 @@ #import "WebRTC/RTCMediaConstraints.h" #import "WebRTC/RTCMediaStream.h" #import "WebRTC/RTCPeerConnectionFactory.h" +#import "WebRTC/RTCRtpSender.h" #import "ARDAppEngineClient.h" #import "ARDCEODTURNClient.h" @@ -48,6 +49,9 @@ static NSInteger const kARDAppClientErrorCreateSDP = -3; static NSInteger const kARDAppClientErrorSetSDP = -4; static NSInteger const kARDAppClientErrorInvalidClient = -5; static NSInteger const kARDAppClientErrorInvalidRoom = -6; +static NSString * const kARDMediaStreamId = @"ARDAMS"; +static NSString * const kARDAudioTrackId = @"ARDAMSa0"; +static NSString * const kARDVideoTrackId = @"ARDAMSv0"; // TODO(tkchin): Remove guard once rtc_sdk_common_objc compiles on Mac. #if defined(WEBRTC_IOS) @@ -505,9 +509,9 @@ static BOOL const kARDAppClientEnableTracing = NO; _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]; + // Create AV senders. + [self createAudioSender]; + [self createVideoSender]; if (_isInitiator) { // Send offer. __weak ARDAppClient *weakSelf = self; @@ -606,17 +610,25 @@ static BOOL const kARDAppClientEnableTracing = NO; } } -- (RTCMediaStream *)createLocalMediaStream { - RTCMediaStream *localStream = [_factory mediaStreamWithStreamId:@"ARDAMS"]; - RTCVideoTrack *localVideoTrack = [self createLocalVideoTrack]; - if (localVideoTrack) { - [localStream addVideoTrack:localVideoTrack]; - [_delegate appClient:self didReceiveLocalVideoTrack:localVideoTrack]; +- (RTCRtpSender *)createVideoSender { + RTCRtpSender *sender = + [_peerConnection senderWithKind:kRTCMediaStreamTrackKindVideo + streamId:kARDMediaStreamId]; + RTCVideoTrack *track = [self createLocalVideoTrack]; + if (track) { + sender.track = track; + [_delegate appClient:self didReceiveLocalVideoTrack:track]; } - RTCAudioTrack *localAudioTrack = - [_factory audioTrackWithTrackId:@"ARDAMSa0"]; - [localStream addAudioTrack:localAudioTrack]; - return localStream; + return sender; +} + +- (RTCRtpSender *)createAudioSender { + RTCRtpSender *sender = + [_peerConnection senderWithKind:kRTCMediaStreamTrackKindAudio + streamId:kARDMediaStreamId]; + RTCAudioTrack *track = [_factory audioTrackWithTrackId:kARDAudioTrackId]; + sender.track = track; + return sender; } - (RTCVideoTrack *)createLocalVideoTrack { @@ -634,7 +646,7 @@ static BOOL const kARDAppClientEnableTracing = NO; [_factory avFoundationVideoSourceWithConstraints:mediaConstraints]; localVideoTrack = [_factory videoTrackWithSource:source - trackId:@"ARDAMSv0"]; + trackId:kARDVideoTrackId]; } #endif return localVideoTrack; diff --git a/webrtc/sdk/objc/Framework/Classes/RTCMediaStreamTrack.mm b/webrtc/sdk/objc/Framework/Classes/RTCMediaStreamTrack.mm index 3d307be507..208550f6c8 100644 --- a/webrtc/sdk/objc/Framework/Classes/RTCMediaStreamTrack.mm +++ b/webrtc/sdk/objc/Framework/Classes/RTCMediaStreamTrack.mm @@ -12,6 +12,11 @@ #import "NSString+StdString.h" +NSString * const kRTCMediaStreamTrackKindAudio = + @(webrtc::MediaStreamTrackInterface::kAudioKind); +NSString * const kRTCMediaStreamTrackKindVideo = + @(webrtc::MediaStreamTrackInterface::kVideoKind); + @implementation RTCMediaStreamTrack { rtc::scoped_refptr _nativeTrack; RTCMediaStreamTrackType _type; diff --git a/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection.mm b/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection.mm index e8fa4c9a56..46ea52a8f6 100644 --- a/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection.mm +++ b/webrtc/sdk/objc/Framework/Classes/RTCPeerConnection.mm @@ -311,6 +311,17 @@ void PeerConnectionDelegateAdapter::OnIceCandidate( _peerConnection->SetRemoteDescription(observer, sdp.nativeDescription); } +- (RTCRtpSender *)senderWithKind:(NSString *)kind + streamId:(NSString *)streamId { + std::string nativeKind = [NSString stdStringForString:kind]; + std::string nativeStreamId = [NSString stdStringForString:streamId]; + rtc::scoped_refptr nativeSender( + _peerConnection->CreateSender(nativeKind, nativeStreamId)); + return nativeSender ? + [[RTCRtpSender alloc] initWithNativeRtpSender:nativeSender] + : nil; +} + - (NSArray *)senders { std::vector> nativeSenders( _peerConnection->GetSenders()); diff --git a/webrtc/sdk/objc/Framework/Classes/RTCRtpSender.mm b/webrtc/sdk/objc/Framework/Classes/RTCRtpSender.mm index 71030029ad..3d413dc160 100644 --- a/webrtc/sdk/objc/Framework/Classes/RTCRtpSender.mm +++ b/webrtc/sdk/objc/Framework/Classes/RTCRtpSender.mm @@ -10,8 +10,10 @@ #import "RTCRtpSender+Private.h" +#import "NSString+StdString.h" #import "RTCMediaStreamTrack+Private.h" #import "RTCRtpParameters+Private.h" +#import "WebRTC/RTCLogging.h" #include "webrtc/api/mediastreaminterface.h" @@ -21,19 +23,28 @@ - (instancetype)initWithNativeRtpSender: (rtc::scoped_refptr)nativeRtpSender { + NSParameterAssert(nativeRtpSender); if (self = [super init]) { _nativeRtpSender = nativeRtpSender; + RTCLogInfo(@"RTCRtpSender(%p): created sender: %@", self, self.description); } return self; } +- (NSString *)senderId { + return [NSString stringForStdString:_nativeRtpSender->id()]; +} + - (RTCRtpParameters *)parameters { return [[RTCRtpParameters alloc] initWithNativeParameters:_nativeRtpSender->GetParameters()]; } -- (BOOL)setParameters:(RTCRtpParameters *)parameters { - return _nativeRtpSender->SetParameters(parameters.nativeParameters); +- (void)setParameters:(RTCRtpParameters *)parameters { + if (!_nativeRtpSender->SetParameters(parameters.nativeParameters)) { + RTCLogError(@"RTCRtpSender(%p): Failed to set parameters: %@", self, + parameters); + } } - (RTCMediaStreamTrack *)track { @@ -45,4 +56,15 @@ return nil; } +- (void)setTrack:(RTCMediaStreamTrack *)track { + if (!_nativeRtpSender->SetTrack(track.nativeTrack)) { + RTCLogError(@"RTCRtpSender(%p): Failed to set track %@", self, track); + } +} + +- (NSString *)description { + return [NSString stringWithFormat:@"RTCRtpSender {\n senderId: %@\n}", + self.senderId]; +} + @end diff --git a/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCMediaStreamTrack.h b/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCMediaStreamTrack.h index 37b80194c2..c42f0cfb1a 100644 --- a/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCMediaStreamTrack.h +++ b/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCMediaStreamTrack.h @@ -22,6 +22,9 @@ typedef NS_ENUM(NSInteger, RTCMediaStreamTrackState) { NS_ASSUME_NONNULL_BEGIN +RTC_EXTERN NSString * const kRTCMediaStreamTrackKindAudio; +RTC_EXTERN NSString * const kRTCMediaStreamTrackKindVideo; + RTC_EXPORT @interface RTCMediaStreamTrack : NSObject diff --git a/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCPeerConnection.h b/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCPeerConnection.h index b89df8ec2d..0db84ac2f9 100644 --- a/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCPeerConnection.h +++ b/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCPeerConnection.h @@ -171,6 +171,16 @@ RTC_EXPORT @end +@interface RTCPeerConnection (Media) + +/** + * Create an RTCRtpSender with the specified kind and media stream ID. + * See RTCMediaStreamTrack.h for available kinds. + */ +- (RTCRtpSender *)senderWithKind:(NSString *)kind streamId:(NSString *)streamId; + +@end + @interface RTCPeerConnection (DataChannel) /** Create a new data channel with the given label and configuration. */ diff --git a/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCRtpSender.h b/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCRtpSender.h index c874b77e6b..d910c6ceb2 100644 --- a/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCRtpSender.h +++ b/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCRtpSender.h @@ -19,22 +19,20 @@ NS_ASSUME_NONNULL_BEGIN RTC_EXPORT @protocol RTCRtpSender +/** A unique identifier for this sender. */ +@property(nonatomic, readonly) NSString *senderId; + /** The currently active RTCRtpParameters, as defined in * https://www.w3.org/TR/webrtc/#idl-def-RTCRtpParameters. */ -@property(nonatomic, readonly) RTCRtpParameters *parameters; +@property(nonatomic, copy) RTCRtpParameters *parameters; /** The RTCMediaStreamTrack associated with the sender. * Note: reading this property returns a new instance of * RTCMediaStreamTrack. Use isEqual: instead of == to compare * RTCMediaStreamTrack instances. */ -@property(nonatomic, readonly) RTCMediaStreamTrack *track; - -/** Set the new RTCRtpParameters to be used by the sender. - * Returns YES if the new parameters were applied, NO otherwise. - */ -- (BOOL)setParameters:(RTCRtpParameters *)parameters; +@property(nonatomic, copy, nullable) RTCMediaStreamTrack *track; @end