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