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#include <memory> 12 13#import "RTCPeerConnectionFactory+Native.h" 14#import "RTCPeerConnectionFactory+Private.h" 15#import "RTCPeerConnectionFactoryOptions+Private.h" 16 17#import "RTCAudioSource+Private.h" 18#import "RTCAudioTrack+Private.h" 19#import "RTCMediaConstraints+Private.h" 20#import "RTCMediaStream+Private.h" 21#import "RTCPeerConnection+Private.h" 22#import "RTCVideoSource+Private.h" 23#import "RTCVideoTrack+Private.h" 24#import "base/RTCLogging.h" 25#import "base/RTCVideoDecoderFactory.h" 26#import "base/RTCVideoEncoderFactory.h" 27#import "helpers/NSString+StdString.h" 28#ifndef HAVE_NO_MEDIA 29#import "components/video_codec/RTCVideoDecoderFactoryH264.h" 30#import "components/video_codec/RTCVideoEncoderFactoryH264.h" 31// The no-media version PeerConnectionFactory doesn't depend on these files, but the gn check tool 32// is not smart enough to take the #ifdef into account. 33#include "api/audio_codecs/builtin_audio_decoder_factory.h" // nogncheck 34#include "api/audio_codecs/builtin_audio_encoder_factory.h" // nogncheck 35#include "api/rtc_event_log/rtc_event_log_factory.h" 36#include "api/task_queue/default_task_queue_factory.h" 37#include "modules/audio_device/include/audio_device.h" // nogncheck 38#include "modules/audio_processing/include/audio_processing.h" // nogncheck 39 40#include "sdk/objc/native/api/video_decoder_factory.h" 41#include "sdk/objc/native/api/video_encoder_factory.h" 42#include "sdk/objc/native/src/objc_video_decoder_factory.h" 43#include "sdk/objc/native/src/objc_video_encoder_factory.h" 44#endif 45 46#if defined(WEBRTC_IOS) 47#import "sdk/objc/native/api/audio_device_module.h" 48#endif 49 50// Adding the nogncheck to disable the including header check. 51// The no-media version PeerConnectionFactory doesn't depend on media related 52// C++ target. 53// TODO(zhihuang): Remove nogncheck once MediaEngineInterface is moved to C++ 54// API layer. 55#include "media/engine/webrtc_media_engine.h" // nogncheck 56 57@implementation RTC_OBJC_TYPE (RTCPeerConnectionFactory) { 58 std::unique_ptr<rtc::Thread> _networkThread; 59 std::unique_ptr<rtc::Thread> _workerThread; 60 std::unique_ptr<rtc::Thread> _signalingThread; 61 BOOL _hasStartedAecDump; 62} 63 64@synthesize nativeFactory = _nativeFactory; 65 66- (rtc::scoped_refptr<webrtc::AudioDeviceModule>)audioDeviceModule { 67#if defined(WEBRTC_IOS) 68 return webrtc::CreateAudioDeviceModule(); 69#else 70 return nullptr; 71#endif 72} 73 74- (instancetype)init { 75#ifdef HAVE_NO_MEDIA 76 return [self initWithNoMedia]; 77#else 78 return [self 79 initWithNativeAudioEncoderFactory:webrtc::CreateBuiltinAudioEncoderFactory() 80 nativeAudioDecoderFactory:webrtc::CreateBuiltinAudioDecoderFactory() 81 nativeVideoEncoderFactory:webrtc::ObjCToNativeVideoEncoderFactory([[RTC_OBJC_TYPE( 82 RTCVideoEncoderFactoryH264) alloc] init]) 83 nativeVideoDecoderFactory:webrtc::ObjCToNativeVideoDecoderFactory([[RTC_OBJC_TYPE( 84 RTCVideoDecoderFactoryH264) alloc] init]) 85 audioDeviceModule:[self audioDeviceModule] 86 audioProcessingModule:nullptr]; 87#endif 88} 89 90- (instancetype) 91 initWithEncoderFactory:(nullable id<RTC_OBJC_TYPE(RTCVideoEncoderFactory)>)encoderFactory 92 decoderFactory:(nullable id<RTC_OBJC_TYPE(RTCVideoDecoderFactory)>)decoderFactory { 93#ifdef HAVE_NO_MEDIA 94 return [self initWithNoMedia]; 95#else 96 std::unique_ptr<webrtc::VideoEncoderFactory> native_encoder_factory; 97 std::unique_ptr<webrtc::VideoDecoderFactory> native_decoder_factory; 98 if (encoderFactory) { 99 native_encoder_factory = webrtc::ObjCToNativeVideoEncoderFactory(encoderFactory); 100 } 101 if (decoderFactory) { 102 native_decoder_factory = webrtc::ObjCToNativeVideoDecoderFactory(decoderFactory); 103 } 104 return [self initWithNativeAudioEncoderFactory:webrtc::CreateBuiltinAudioEncoderFactory() 105 nativeAudioDecoderFactory:webrtc::CreateBuiltinAudioDecoderFactory() 106 nativeVideoEncoderFactory:std::move(native_encoder_factory) 107 nativeVideoDecoderFactory:std::move(native_decoder_factory) 108 audioDeviceModule:[self audioDeviceModule] 109 audioProcessingModule:nullptr]; 110#endif 111} 112- (instancetype)initNative { 113 if (self = [super init]) { 114 _networkThread = rtc::Thread::CreateWithSocketServer(); 115 _networkThread->SetName("network_thread", _networkThread.get()); 116 BOOL result = _networkThread->Start(); 117 NSAssert(result, @"Failed to start network thread."); 118 119 _workerThread = rtc::Thread::Create(); 120 _workerThread->SetName("worker_thread", _workerThread.get()); 121 result = _workerThread->Start(); 122 NSAssert(result, @"Failed to start worker thread."); 123 124 _signalingThread = rtc::Thread::Create(); 125 _signalingThread->SetName("signaling_thread", _signalingThread.get()); 126 result = _signalingThread->Start(); 127 NSAssert(result, @"Failed to start signaling thread."); 128 } 129 return self; 130} 131 132- (instancetype)initWithNoMedia { 133 if (self = [self initNative]) { 134 webrtc::PeerConnectionFactoryDependencies dependencies; 135 dependencies.network_thread = _networkThread.get(); 136 dependencies.worker_thread = _workerThread.get(); 137 dependencies.signaling_thread = _signalingThread.get(); 138 _nativeFactory = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies)); 139 NSAssert(_nativeFactory, @"Failed to initialize PeerConnectionFactory!"); 140 } 141 return self; 142} 143 144- (instancetype)initWithNativeAudioEncoderFactory: 145 (rtc::scoped_refptr<webrtc::AudioEncoderFactory>)audioEncoderFactory 146 nativeAudioDecoderFactory: 147 (rtc::scoped_refptr<webrtc::AudioDecoderFactory>)audioDecoderFactory 148 nativeVideoEncoderFactory: 149 (std::unique_ptr<webrtc::VideoEncoderFactory>)videoEncoderFactory 150 nativeVideoDecoderFactory: 151 (std::unique_ptr<webrtc::VideoDecoderFactory>)videoDecoderFactory 152 audioDeviceModule:(webrtc::AudioDeviceModule *)audioDeviceModule 153 audioProcessingModule: 154 (rtc::scoped_refptr<webrtc::AudioProcessing>)audioProcessingModule { 155 return [self initWithNativeAudioEncoderFactory:audioEncoderFactory 156 nativeAudioDecoderFactory:audioDecoderFactory 157 nativeVideoEncoderFactory:std::move(videoEncoderFactory) 158 nativeVideoDecoderFactory:std::move(videoDecoderFactory) 159 audioDeviceModule:audioDeviceModule 160 audioProcessingModule:audioProcessingModule 161 networkControllerFactory:nullptr]; 162} 163- (instancetype)initWithNativeAudioEncoderFactory: 164 (rtc::scoped_refptr<webrtc::AudioEncoderFactory>)audioEncoderFactory 165 nativeAudioDecoderFactory: 166 (rtc::scoped_refptr<webrtc::AudioDecoderFactory>)audioDecoderFactory 167 nativeVideoEncoderFactory: 168 (std::unique_ptr<webrtc::VideoEncoderFactory>)videoEncoderFactory 169 nativeVideoDecoderFactory: 170 (std::unique_ptr<webrtc::VideoDecoderFactory>)videoDecoderFactory 171 audioDeviceModule:(webrtc::AudioDeviceModule *)audioDeviceModule 172 audioProcessingModule: 173 (rtc::scoped_refptr<webrtc::AudioProcessing>)audioProcessingModule 174 networkControllerFactory: 175 (std::unique_ptr<webrtc::NetworkControllerFactoryInterface>) 176 networkControllerFactory { 177 if (self = [self initNative]) { 178 webrtc::PeerConnectionFactoryDependencies dependencies; 179 dependencies.network_thread = _networkThread.get(); 180 dependencies.worker_thread = _workerThread.get(); 181 dependencies.signaling_thread = _signalingThread.get(); 182#ifndef HAVE_NO_MEDIA 183 dependencies.task_queue_factory = webrtc::CreateDefaultTaskQueueFactory(); 184 cricket::MediaEngineDependencies media_deps; 185 media_deps.adm = std::move(audioDeviceModule); 186 media_deps.task_queue_factory = dependencies.task_queue_factory.get(); 187 media_deps.audio_encoder_factory = std::move(audioEncoderFactory); 188 media_deps.audio_decoder_factory = std::move(audioDecoderFactory); 189 media_deps.video_encoder_factory = std::move(videoEncoderFactory); 190 media_deps.video_decoder_factory = std::move(videoDecoderFactory); 191 if (audioProcessingModule) { 192 media_deps.audio_processing = std::move(audioProcessingModule); 193 } else { 194 media_deps.audio_processing = webrtc::AudioProcessingBuilder().Create(); 195 } 196 dependencies.media_engine = cricket::CreateMediaEngine(std::move(media_deps)); 197 dependencies.call_factory = webrtc::CreateCallFactory(); 198 dependencies.event_log_factory = 199 std::make_unique<webrtc::RtcEventLogFactory>(dependencies.task_queue_factory.get()); 200 dependencies.network_controller_factory = std::move(networkControllerFactory); 201#endif 202 _nativeFactory = webrtc::CreateModularPeerConnectionFactory(std::move(dependencies)); 203 NSAssert(_nativeFactory, @"Failed to initialize PeerConnectionFactory!"); 204 } 205 return self; 206} 207 208- (RTC_OBJC_TYPE(RTCAudioSource) *)audioSourceWithConstraints: 209 (nullable RTC_OBJC_TYPE(RTCMediaConstraints) *)constraints { 210 std::unique_ptr<webrtc::MediaConstraints> nativeConstraints; 211 if (constraints) { 212 nativeConstraints = constraints.nativeConstraints; 213 } 214 cricket::AudioOptions options; 215 CopyConstraintsIntoAudioOptions(nativeConstraints.get(), &options); 216 217 rtc::scoped_refptr<webrtc::AudioSourceInterface> source = 218 _nativeFactory->CreateAudioSource(options); 219 return [[RTC_OBJC_TYPE(RTCAudioSource) alloc] initWithFactory:self nativeAudioSource:source]; 220} 221 222- (RTC_OBJC_TYPE(RTCAudioTrack) *)audioTrackWithTrackId:(NSString *)trackId { 223 RTC_OBJC_TYPE(RTCAudioSource) *audioSource = [self audioSourceWithConstraints:nil]; 224 return [self audioTrackWithSource:audioSource trackId:trackId]; 225} 226 227- (RTC_OBJC_TYPE(RTCAudioTrack) *)audioTrackWithSource:(RTC_OBJC_TYPE(RTCAudioSource) *)source 228 trackId:(NSString *)trackId { 229 return [[RTC_OBJC_TYPE(RTCAudioTrack) alloc] initWithFactory:self source:source trackId:trackId]; 230} 231 232- (RTC_OBJC_TYPE(RTCVideoSource) *)videoSource { 233 return [[RTC_OBJC_TYPE(RTCVideoSource) alloc] initWithFactory:self 234 signalingThread:_signalingThread.get() 235 workerThread:_workerThread.get()]; 236} 237 238- (RTC_OBJC_TYPE(RTCVideoTrack) *)videoTrackWithSource:(RTC_OBJC_TYPE(RTCVideoSource) *)source 239 trackId:(NSString *)trackId { 240 return [[RTC_OBJC_TYPE(RTCVideoTrack) alloc] initWithFactory:self source:source trackId:trackId]; 241} 242 243- (RTC_OBJC_TYPE(RTCMediaStream) *)mediaStreamWithStreamId:(NSString *)streamId { 244 return [[RTC_OBJC_TYPE(RTCMediaStream) alloc] initWithFactory:self streamId:streamId]; 245} 246 247- (RTC_OBJC_TYPE(RTCPeerConnection) *) 248 peerConnectionWithConfiguration:(RTC_OBJC_TYPE(RTCConfiguration) *)configuration 249 constraints:(RTC_OBJC_TYPE(RTCMediaConstraints) *)constraints 250 delegate: 251 (nullable id<RTC_OBJC_TYPE(RTCPeerConnectionDelegate)>)delegate { 252 return [[RTC_OBJC_TYPE(RTCPeerConnection) alloc] initWithFactory:self 253 configuration:configuration 254 constraints:constraints 255 delegate:delegate]; 256} 257 258- (RTC_OBJC_TYPE(RTCPeerConnection) *) 259 peerConnectionWithDependencies:(RTC_OBJC_TYPE(RTCConfiguration) *)configuration 260 constraints:(RTC_OBJC_TYPE(RTCMediaConstraints) *)constraints 261 dependencies:(std::unique_ptr<webrtc::PeerConnectionDependencies>)dependencies 262 delegate:(id<RTC_OBJC_TYPE(RTCPeerConnectionDelegate)>)delegate { 263 return [[RTC_OBJC_TYPE(RTCPeerConnection) alloc] initWithDependencies:self 264 configuration:configuration 265 constraints:constraints 266 dependencies:std::move(dependencies) 267 delegate:delegate]; 268} 269 270- (void)setOptions:(nonnull RTC_OBJC_TYPE(RTCPeerConnectionFactoryOptions) *)options { 271 RTC_DCHECK(options != nil); 272 _nativeFactory->SetOptions(options.nativeOptions); 273} 274 275- (BOOL)startAecDumpWithFilePath:(NSString *)filePath 276 maxSizeInBytes:(int64_t)maxSizeInBytes { 277 RTC_DCHECK(filePath.length); 278 RTC_DCHECK_GT(maxSizeInBytes, 0); 279 280 if (_hasStartedAecDump) { 281 RTCLogError(@"Aec dump already started."); 282 return NO; 283 } 284 FILE *f = fopen(filePath.UTF8String, "wb"); 285 if (!f) { 286 RTCLogError(@"Error opening file: %@. Error: %s", filePath, strerror(errno)); 287 return NO; 288 } 289 _hasStartedAecDump = _nativeFactory->StartAecDump(f, maxSizeInBytes); 290 return _hasStartedAecDump; 291} 292 293- (void)stopAecDump { 294 _nativeFactory->StopAecDump(); 295 _hasStartedAecDump = NO; 296} 297 298@end 299