1/* 2 * Copyright 2015 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#import "RTCMediaStream+Private.h" 12 13#import "RTCAudioTrack+Private.h" 14#import "RTCMediaStreamTrack+Private.h" 15#import "RTCPeerConnectionFactory+Private.h" 16#import "RTCVideoTrack+Private.h" 17#import "helpers/NSString+StdString.h" 18 19@implementation RTC_OBJC_TYPE (RTCMediaStream) { 20 RTC_OBJC_TYPE(RTCPeerConnectionFactory) * _factory; 21 rtc::Thread *_signalingThread; 22 NSMutableArray *_audioTracks /* accessed on _signalingThread */; 23 NSMutableArray *_videoTracks /* accessed on _signalingThread */; 24 rtc::scoped_refptr<webrtc::MediaStreamInterface> _nativeMediaStream; 25} 26 27- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory 28 streamId:(NSString *)streamId { 29 NSParameterAssert(factory); 30 NSParameterAssert(streamId.length); 31 std::string nativeId = [NSString stdStringForString:streamId]; 32 rtc::scoped_refptr<webrtc::MediaStreamInterface> stream = 33 factory.nativeFactory->CreateLocalMediaStream(nativeId); 34 return [self initWithFactory:factory nativeMediaStream:stream]; 35} 36 37- (NSArray<RTC_OBJC_TYPE(RTCAudioTrack) *> *)audioTracks { 38 if (!_signalingThread->IsCurrent()) { 39 return _signalingThread->BlockingCall([self]() { return self.audioTracks; }); 40 } 41 return [_audioTracks copy]; 42} 43 44- (NSArray<RTC_OBJC_TYPE(RTCVideoTrack) *> *)videoTracks { 45 if (!_signalingThread->IsCurrent()) { 46 return _signalingThread->BlockingCall([self]() { return self.videoTracks; }); 47 } 48 return [_videoTracks copy]; 49} 50 51- (NSString *)streamId { 52 return [NSString stringForStdString:_nativeMediaStream->id()]; 53} 54 55- (void)addAudioTrack:(RTC_OBJC_TYPE(RTCAudioTrack) *)audioTrack { 56 if (!_signalingThread->IsCurrent()) { 57 return _signalingThread->BlockingCall( 58 [audioTrack, self]() { return [self addAudioTrack:audioTrack]; }); 59 } 60 if (_nativeMediaStream->AddTrack(audioTrack.nativeAudioTrack)) { 61 [_audioTracks addObject:audioTrack]; 62 } 63} 64 65- (void)addVideoTrack:(RTC_OBJC_TYPE(RTCVideoTrack) *)videoTrack { 66 if (!_signalingThread->IsCurrent()) { 67 return _signalingThread->BlockingCall( 68 [videoTrack, self]() { return [self addVideoTrack:videoTrack]; }); 69 } 70 if (_nativeMediaStream->AddTrack(videoTrack.nativeVideoTrack)) { 71 [_videoTracks addObject:videoTrack]; 72 } 73} 74 75- (void)removeAudioTrack:(RTC_OBJC_TYPE(RTCAudioTrack) *)audioTrack { 76 if (!_signalingThread->IsCurrent()) { 77 return _signalingThread->BlockingCall( 78 [audioTrack, self]() { return [self removeAudioTrack:audioTrack]; }); 79 } 80 NSUInteger index = [_audioTracks indexOfObjectIdenticalTo:audioTrack]; 81 if (index == NSNotFound) { 82 RTC_LOG(LS_INFO) << "|removeAudioTrack| called on unexpected RTC_OBJC_TYPE(RTCAudioTrack)"; 83 return; 84 } 85 if (_nativeMediaStream->RemoveTrack(audioTrack.nativeAudioTrack)) { 86 [_audioTracks removeObjectAtIndex:index]; 87 } 88} 89 90- (void)removeVideoTrack:(RTC_OBJC_TYPE(RTCVideoTrack) *)videoTrack { 91 if (!_signalingThread->IsCurrent()) { 92 return _signalingThread->BlockingCall( 93 [videoTrack, self]() { return [self removeVideoTrack:videoTrack]; }); 94 } 95 NSUInteger index = [_videoTracks indexOfObjectIdenticalTo:videoTrack]; 96 if (index == NSNotFound) { 97 RTC_LOG(LS_INFO) << "|removeVideoTrack| called on unexpected RTC_OBJC_TYPE(RTCVideoTrack)"; 98 return; 99 } 100 101 if (_nativeMediaStream->RemoveTrack(videoTrack.nativeVideoTrack)) { 102 [_videoTracks removeObjectAtIndex:index]; 103 } 104} 105 106- (NSString *)description { 107 return [NSString stringWithFormat:@"RTC_OBJC_TYPE(RTCMediaStream):\n%@\nA=%lu\nV=%lu", 108 self.streamId, 109 (unsigned long)self.audioTracks.count, 110 (unsigned long)self.videoTracks.count]; 111} 112 113#pragma mark - Private 114 115- (rtc::scoped_refptr<webrtc::MediaStreamInterface>)nativeMediaStream { 116 return _nativeMediaStream; 117} 118 119- (instancetype)initWithFactory:(RTC_OBJC_TYPE(RTCPeerConnectionFactory) *)factory 120 nativeMediaStream: 121 (rtc::scoped_refptr<webrtc::MediaStreamInterface>)nativeMediaStream { 122 NSParameterAssert(nativeMediaStream); 123 if (self = [super init]) { 124 _factory = factory; 125 _signalingThread = factory.signalingThread; 126 127 webrtc::AudioTrackVector audioTracks = nativeMediaStream->GetAudioTracks(); 128 webrtc::VideoTrackVector videoTracks = nativeMediaStream->GetVideoTracks(); 129 130 _audioTracks = [NSMutableArray arrayWithCapacity:audioTracks.size()]; 131 _videoTracks = [NSMutableArray arrayWithCapacity:videoTracks.size()]; 132 _nativeMediaStream = nativeMediaStream; 133 134 for (auto &track : audioTracks) { 135 RTCMediaStreamTrackType type = RTCMediaStreamTrackTypeAudio; 136 RTC_OBJC_TYPE(RTCAudioTrack) *audioTrack = 137 [[RTC_OBJC_TYPE(RTCAudioTrack) alloc] initWithFactory:_factory 138 nativeTrack:track 139 type:type]; 140 [_audioTracks addObject:audioTrack]; 141 } 142 143 for (auto &track : videoTracks) { 144 RTCMediaStreamTrackType type = RTCMediaStreamTrackTypeVideo; 145 RTC_OBJC_TYPE(RTCVideoTrack) *videoTrack = 146 [[RTC_OBJC_TYPE(RTCVideoTrack) alloc] initWithFactory:_factory 147 nativeTrack:track 148 type:type]; 149 [_videoTracks addObject:videoTrack]; 150 } 151 } 152 return self; 153} 154 155@end 156