OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2017 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 "webrtc/ortc/ortcfactory.h" | |
12 | |
13 #include <vector> | |
14 #include <utility> // For std::move. | |
15 | |
16 #include "webrtc/api/proxy.h" | |
17 #include "webrtc/api/mediastreamtrackproxy.h" | |
18 #include "webrtc/api/videosourceproxy.h" | |
19 #include "webrtc/base/bind.h" | |
20 #include "webrtc/base/asyncpacketsocket.h" | |
21 #include "webrtc/base/logging.h" | |
22 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" | |
23 #include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h" | |
24 #include "webrtc/ortc/rtpreceivershim.h" | |
25 #include "webrtc/ortc/rtpsendershim.h" | |
26 #include "webrtc/ortc/rtptransportcontrollershim.h" | |
27 #include "webrtc/ortc/rtptransportshim.h" | |
28 #include "webrtc/p2p/base/basicpacketsocketfactory.h" | |
29 #include "webrtc/p2p/base/udptransport.h" | |
30 #include "webrtc/pc/channelmanager.h" | |
31 #include "webrtc/pc/localaudiosource.h" | |
32 #include "webrtc/pc/audiotrack.h" | |
33 #include "webrtc/pc/videocapturertracksource.h" | |
34 #include "webrtc/pc/videotrack.h" | |
35 | |
36 namespace { | |
37 | |
38 void ConvertFeedbackParam(const cricket::FeedbackParam& cricket_feedback, | |
39 webrtc::RtpCodecCapability* codec) { | |
pthatcher1
2017/02/10 22:36:52
Would a better name be AddCodecCapabilityFeedbackP
Taylor Brandstetter
2017/02/14 06:55:05
As long as we're renaming it, AddRtcpFeedbackFromF
pthatcher1
2017/02/17 23:10:22
I like it
| |
40 if (cricket_feedback.id() == "ack") { | |
41 RTC_DCHECK(cricket_feedback.param().empty()); | |
42 codec->rtcp_feedback.emplace_back(webrtc::RtcpFeedbackType::ACK); | |
43 } else if (cricket_feedback.id() == "ccm") { | |
pthatcher1
2017/02/10 22:36:52
Why not use kRtcpFbParamCcm, kRtcpFbCcmParamFir, a
Taylor Brandstetter
2017/02/14 06:55:04
Done.
| |
44 if (cricket_feedback.param() == "fir") { | |
45 codec->rtcp_feedback.emplace_back(webrtc::RtcpFeedbackType::CCM, | |
46 webrtc::RtcpFeedbackMessageType::FIR); | |
47 } else { | |
48 RTC_NOTREACHED(); | |
pthatcher1
2017/02/10 22:36:52
Wouldn't an RTC_DCHECK be more reasonable?
Here
Taylor Brandstetter
2017/02/14 06:55:05
How would that work?
pthatcher1
2017/02/17 23:10:22
I went through and read other uses of RTC_NOTREACH
| |
49 } | |
50 } else if (cricket_feedback.id() == "nack") { | |
51 if (cricket_feedback.param().empty()) { | |
52 codec->rtcp_feedback.emplace_back( | |
53 webrtc::RtcpFeedbackType::NACK, | |
54 webrtc::RtcpFeedbackMessageType::GENERIC_NACK); | |
55 } else if (cricket_feedback.param() == "pli") { | |
56 codec->rtcp_feedback.emplace_back(webrtc::RtcpFeedbackType::NACK, | |
57 webrtc::RtcpFeedbackMessageType::PLI); | |
58 } else { | |
59 RTC_NOTREACHED(); | |
60 } | |
61 } else if (cricket_feedback.id() == "goog-remb") { | |
62 RTC_DCHECK(cricket_feedback.param().empty()); | |
63 codec->rtcp_feedback.emplace_back(webrtc::RtcpFeedbackType::REMB); | |
64 } else if (cricket_feedback.id() == "transport-cc") { | |
65 RTC_DCHECK(cricket_feedback.param().empty()); | |
66 codec->rtcp_feedback.emplace_back(webrtc::RtcpFeedbackType::TRANSPORT_CC); | |
67 } else { | |
68 RTC_NOTREACHED(); | |
69 } | |
70 } | |
71 | |
72 template <typename C> | |
73 void CodecSpecificConversion(const C& cricket_codec, | |
74 webrtc::RtpCodecCapability* codec) {} | |
75 | |
76 template <> | |
77 void CodecSpecificConversion<cricket::AudioCodec>( | |
78 const cricket::AudioCodec& cricket_codec, | |
79 webrtc::RtpCodecCapability* codec) { | |
80 codec->num_channels = rtc::Optional<int>(cricket_codec.channels); | |
81 } | |
pthatcher1
2017/02/10 22:36:52
Would FromCricketCodec be a better name? Or ToCod
Taylor Brandstetter
2017/02/14 06:55:04
This is only converting the audio or video specifi
| |
82 | |
83 template <class C> | |
84 webrtc::RtpCapabilities ConvertCapabilities( | |
85 cricket::MediaType kind, | |
86 const std::vector<C> cricket_codecs, | |
87 const cricket::RtpHeaderExtensions& cricket_extensions) { | |
pthatcher1
2017/02/10 22:36:52
Would ToRtpCapabilites or FromCricketCapabilities
Taylor Brandstetter
2017/02/14 06:55:05
Done.
| |
88 webrtc::RtpCapabilities capabilities; | |
89 bool have_red = false; | |
90 bool have_ulpfec = false; | |
91 bool have_flexfec = false; | |
92 for (const C& cricket_codec : cricket_codecs) { | |
93 if (cricket_codec.name == "red") { | |
pthatcher1
2017/02/10 22:36:52
Why not use kRedCodecName, kUlpfecCodecName, and o
Taylor Brandstetter
2017/02/14 06:55:04
Done.
| |
94 have_red = true; | |
95 } else if (cricket_codec.name == "ulpfec") { | |
96 have_ulpfec = true; | |
97 } else if (cricket_codec.name == "flexfec") { | |
98 have_flexfec = true; | |
99 } | |
100 webrtc::RtpCodecCapability codec; | |
101 codec.name = cricket_codec.name; | |
102 codec.kind = kind; | |
103 codec.clock_rate = rtc::Optional<int>(cricket_codec.clockrate); | |
104 codec.preferred_payload_type = rtc::Optional<int>(cricket_codec.id); | |
105 for (const cricket::FeedbackParam& cricket_feedback : | |
106 cricket_codec.feedback_params.params()) { | |
107 ConvertFeedbackParam(cricket_feedback, &codec); | |
108 } | |
109 CodecSpecificConversion(cricket_codec, &codec); | |
110 codec.parameters.insert(cricket_codec.params.begin(), | |
111 cricket_codec.params.end()); | |
112 capabilities.codecs.push_back(std::move(codec)); | |
113 } | |
114 for (const webrtc::RtpExtension& cricket_extension : cricket_extensions) { | |
115 capabilities.header_extensions.emplace_back(cricket_extension.uri, | |
116 cricket_extension.id); | |
117 } | |
118 if (have_red) { | |
119 capabilities.fec.push_back(webrtc::FecMechanism::RED); | |
120 } | |
121 if (have_red && have_ulpfec) { | |
122 capabilities.fec.push_back(webrtc::FecMechanism::RED_AND_ULPFEC); | |
123 } | |
124 if (have_flexfec) { | |
125 capabilities.fec.push_back(webrtc::FecMechanism::FLEXFEC); | |
126 } | |
127 return capabilities; | |
128 } | |
129 | |
130 } // namespace | |
131 | |
132 namespace webrtc { | |
133 | |
134 // Note that this proxy class uses the network thread as the "worker" thread. | |
135 BEGIN_OWNED_PROXY_MAP(OrtcFactory) | |
136 PROXY_SIGNALING_THREAD_DESTRUCTOR() | |
137 PROXY_METHOD0(RTCErrorOr<std::unique_ptr<RtpTransportControllerInterface>>, | |
138 CreateRtpTransportController) | |
139 PROXY_METHOD4(RTCErrorOr<std::unique_ptr<RtpTransportInterface>>, | |
140 CreateRtpTransport, | |
141 const RtcpParameters&, | |
142 PacketTransportInterface*, | |
143 PacketTransportInterface*, | |
144 RtpTransportControllerInterface*) | |
145 PROXY_CONSTMETHOD1(RtpCapabilities, | |
146 GetRtpSenderCapabilities, | |
147 cricket::MediaType) | |
148 PROXY_METHOD2(RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>, | |
149 CreateRtpSender, | |
150 rtc::scoped_refptr<MediaStreamTrackInterface>, | |
151 RtpTransportInterface*) | |
152 PROXY_METHOD2(RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>, | |
153 CreateRtpSender, | |
154 cricket::MediaType, | |
155 RtpTransportInterface*) | |
156 PROXY_CONSTMETHOD1(RtpCapabilities, | |
157 GetRtpReceiverCapabilities, | |
158 cricket::MediaType) | |
159 PROXY_METHOD2(RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>>, | |
160 CreateRtpReceiver, | |
161 cricket::MediaType, | |
162 RtpTransportInterface*) | |
163 PROXY_WORKER_METHOD3(RTCErrorOr<std::unique_ptr<UdpTransportInterface>>, | |
164 CreateUdpTransport, | |
165 int, | |
166 uint16_t, | |
167 uint16_t) | |
168 PROXY_METHOD1(rtc::scoped_refptr<AudioSourceInterface>, | |
169 CreateAudioSource, | |
170 const cricket::AudioOptions&) | |
171 PROXY_METHOD2(rtc::scoped_refptr<VideoTrackSourceInterface>, | |
172 CreateVideoSource, | |
173 std::unique_ptr<cricket::VideoCapturer>, | |
174 const MediaConstraintsInterface*) | |
175 PROXY_METHOD2(rtc::scoped_refptr<VideoTrackInterface>, | |
176 CreateVideoTrack, | |
177 const std::string&, | |
178 VideoTrackSourceInterface*) | |
179 PROXY_METHOD2(rtc::scoped_refptr<AudioTrackInterface>, | |
180 CreateAudioTrack, | |
181 const std::string&, | |
182 AudioSourceInterface*) | |
183 END_PROXY_MAP() | |
184 | |
185 // static | |
186 RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> OrtcFactoryInterface::Create( | |
187 rtc::Thread* network_thread, | |
188 rtc::Thread* signaling_thread, | |
189 rtc::NetworkManager* network_manager, | |
190 rtc::PacketSocketFactory* socket_factory, | |
191 AudioDeviceModule* adm) { | |
192 // Hop to signaling thread if needed. | |
193 if (signaling_thread && !signaling_thread->IsCurrent()) { | |
194 return signaling_thread | |
195 ->Invoke<RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>>>( | |
196 RTC_FROM_HERE, | |
197 rtc::Bind(&OrtcFactoryInterface::Create, network_thread, | |
198 signaling_thread, network_manager, socket_factory, adm)); | |
199 } | |
200 std::unique_ptr<OrtcFactory> new_factory(new OrtcFactory( | |
201 network_thread, signaling_thread, network_manager, socket_factory, adm)); | |
202 RTCError err = new_factory->Initialize(); | |
203 if (!err.ok()) { | |
204 return err; | |
205 } | |
206 // Return a proxy so that any calls on the returned object (including | |
207 // destructor) happen on the signaling thread. | |
208 return OrtcFactoryProxy::Create(new_factory->signaling_thread(), | |
209 new_factory->network_thread(), | |
210 new_factory.release()); | |
211 } | |
212 | |
213 OrtcFactory::OrtcFactory(rtc::Thread* network_thread, | |
214 rtc::Thread* signaling_thread, | |
215 rtc::NetworkManager* network_manager, | |
216 rtc::PacketSocketFactory* socket_factory, | |
217 AudioDeviceModule* adm) | |
218 : network_thread_(network_thread), | |
219 signaling_thread_(signaling_thread), | |
220 network_manager_(network_manager), | |
221 socket_factory_(socket_factory), | |
222 adm_(adm), | |
223 null_event_log_(RtcEventLog::CreateNull()), | |
224 audio_decoder_factory_(CreateBuiltinAudioDecoderFactory()) { | |
225 if (!network_thread_) { | |
226 owned_network_thread_ = rtc::Thread::CreateWithSocketServer(); | |
227 owned_network_thread_->Start(); | |
228 network_thread_ = owned_network_thread_.get(); | |
229 } | |
230 | |
231 // The worker thread is created internally because it's an implementation | |
232 // detail, and consumers of the API don't need to really know about it. | |
233 worker_thread_ = rtc::Thread::Create(); | |
234 worker_thread_->Start(); | |
235 | |
236 if (signaling_thread_) { | |
237 RTC_DCHECK_RUN_ON(signaling_thread_); | |
238 } else { | |
239 signaling_thread_ = rtc::Thread::Current(); | |
240 if (!signaling_thread_) { | |
241 // If this thread isn't already wrapped by an rtc::Thread, create a | |
242 // wrapper and own it in this class. | |
243 signaling_thread_ = rtc::ThreadManager::Instance()->WrapCurrentThread(); | |
244 wraps_signaling_thread_ = true; | |
245 } | |
246 } | |
247 if (!network_manager_) { | |
248 owned_network_manager_.reset(new rtc::BasicNetworkManager()); | |
249 network_manager_ = owned_network_manager_.get(); | |
250 } | |
251 if (!socket_factory_) { | |
252 owned_socket_factory_.reset( | |
253 new rtc::BasicPacketSocketFactory(network_thread_)); | |
254 socket_factory_ = owned_socket_factory_.get(); | |
255 } | |
256 } | |
257 | |
258 OrtcFactory::~OrtcFactory() { | |
259 RTC_DCHECK_RUN_ON(signaling_thread_); | |
260 if (wraps_signaling_thread_) { | |
261 rtc::ThreadManager::Instance()->UnwrapCurrentThread(); | |
262 } | |
263 } | |
264 | |
265 RTCErrorOr<std::unique_ptr<RtpTransportControllerInterface>> | |
266 OrtcFactory::CreateRtpTransportController() { | |
267 return RtpTransportControllerShim::CreateProxied( | |
268 cricket::MediaConfig(), channel_manager_.get(), null_event_log_.get(), | |
269 signaling_thread_, worker_thread_.get()); | |
270 } | |
271 | |
272 RTCErrorOr<std::unique_ptr<RtpTransportInterface>> | |
273 OrtcFactory::CreateRtpTransport( | |
274 const RtcpParameters& rtcp_parameters, | |
275 PacketTransportInterface* rtp, | |
276 PacketTransportInterface* rtcp, | |
277 RtpTransportControllerInterface* transport_controller) { | |
278 if (transport_controller) { | |
279 return RtpTransportShim::CreateProxied(rtcp_parameters, rtp, rtcp, | |
280 transport_controller); | |
281 } else { | |
282 // If |transport_controller| is null, create one automatically, which the | |
283 // returned RtpTransport will own. | |
284 auto result = CreateRtpTransportController(); | |
285 if (!result.ok()) { | |
286 return result.error(); | |
287 } | |
288 return RtpTransportShim::CreateProxied(rtcp_parameters, rtp, rtcp, | |
289 result.ConsumeValue()); | |
290 } | |
291 } | |
292 | |
293 RtpCapabilities OrtcFactory::GetRtpSenderCapabilities( | |
294 cricket::MediaType kind) const { | |
295 switch (kind) { | |
296 case cricket::MEDIA_TYPE_AUDIO: { | |
297 cricket::AudioCodecs cricket_codecs; | |
298 cricket::RtpHeaderExtensions cricket_extensions; | |
299 channel_manager_->GetSupportedAudioSendCodecs(&cricket_codecs); | |
300 channel_manager_->GetSupportedAudioRtpHeaderExtensions( | |
301 &cricket_extensions); | |
302 return ConvertCapabilities(kind, cricket_codecs, cricket_extensions); | |
303 } | |
304 case cricket::MEDIA_TYPE_VIDEO: { | |
305 cricket::VideoCodecs cricket_codecs; | |
306 cricket::RtpHeaderExtensions cricket_extensions; | |
307 channel_manager_->GetSupportedVideoCodecs(&cricket_codecs); | |
308 channel_manager_->GetSupportedVideoRtpHeaderExtensions( | |
309 &cricket_extensions); | |
310 return ConvertCapabilities(kind, cricket_codecs, cricket_extensions); | |
311 } | |
312 case cricket::MEDIA_TYPE_DATA: | |
313 return RtpCapabilities(); | |
314 } | |
315 } | |
316 | |
317 RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>> | |
318 OrtcFactory::CreateRtpSender( | |
319 rtc::scoped_refptr<MediaStreamTrackInterface> track, | |
320 RtpTransportInterface* transport) { | |
321 if (!track) { | |
322 return CreateAndLogError(RTCErrorType::INVALID_PARAMETER, | |
323 "Cannot pass null track into CreateRtpSender."); | |
324 } | |
325 auto result = | |
326 CreateRtpSender(cricket::MediaTypeFromString(track->kind()), transport); | |
327 if (!result.ok()) { | |
328 return result; | |
329 } | |
330 auto err = result.value()->SetTrack(track); | |
331 if (!err.ok()) { | |
332 return err; | |
333 } | |
334 return result; | |
335 } | |
336 | |
337 RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>> | |
338 OrtcFactory::CreateRtpSender(cricket::MediaType kind, | |
339 RtpTransportInterface* transport) { | |
340 if (kind == cricket::MEDIA_TYPE_DATA) { | |
341 return CreateAndLogError(RTCErrorType::INVALID_PARAMETER, | |
342 "Cannot create data RtpSender."); | |
343 } | |
344 if (!transport) { | |
345 return CreateAndLogError( | |
346 RTCErrorType::INVALID_PARAMETER, | |
347 "Cannot pass null transport into CreateRtpSender."); | |
348 } | |
349 return RtpSenderShim::CreateProxied(kind, transport->GetInternal()); | |
350 } | |
351 | |
352 RtpCapabilities OrtcFactory::GetRtpReceiverCapabilities( | |
353 cricket::MediaType kind) const { | |
354 switch (kind) { | |
355 case cricket::MEDIA_TYPE_AUDIO: { | |
356 cricket::AudioCodecs cricket_codecs; | |
357 cricket::RtpHeaderExtensions cricket_extensions; | |
358 channel_manager_->GetSupportedAudioReceiveCodecs(&cricket_codecs); | |
359 channel_manager_->GetSupportedAudioRtpHeaderExtensions( | |
360 &cricket_extensions); | |
361 return ConvertCapabilities(kind, cricket_codecs, cricket_extensions); | |
362 } | |
363 case cricket::MEDIA_TYPE_VIDEO: { | |
364 cricket::VideoCodecs cricket_codecs; | |
365 cricket::RtpHeaderExtensions cricket_extensions; | |
366 channel_manager_->GetSupportedVideoCodecs(&cricket_codecs); | |
367 channel_manager_->GetSupportedVideoRtpHeaderExtensions( | |
368 &cricket_extensions); | |
369 return ConvertCapabilities(kind, cricket_codecs, cricket_extensions); | |
370 } | |
371 case cricket::MEDIA_TYPE_DATA: | |
372 return RtpCapabilities(); | |
373 } | |
374 } | |
375 | |
376 RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>> | |
377 OrtcFactory::CreateRtpReceiver(cricket::MediaType kind, | |
378 RtpTransportInterface* transport) { | |
379 if (kind == cricket::MEDIA_TYPE_DATA) { | |
380 return CreateAndLogError(RTCErrorType::INVALID_PARAMETER, | |
381 "Cannot create data RtpReceiver."); | |
382 } | |
383 if (!transport) { | |
384 return CreateAndLogError( | |
385 RTCErrorType::INVALID_PARAMETER, | |
386 "Cannot pass null transport into CreateRtpReceiver."); | |
387 } | |
388 return RtpReceiverShim::CreateProxied(kind, transport->GetInternal()); | |
389 } | |
390 | |
391 BEGIN_OWNED_PROXY_MAP(UdpTransport) | |
392 PROXY_WORKER_THREAD_DESTRUCTOR() | |
393 PROXY_WORKER_CONSTMETHOD0(rtc::SocketAddress, GetLocalAddress) | |
394 PROXY_WORKER_METHOD1(bool, SetRemoteAddress, const rtc::SocketAddress&) | |
395 PROXY_WORKER_CONSTMETHOD0(rtc::SocketAddress, GetRemoteAddress) | |
396 protected: | |
397 rtc::PacketTransportInternal* GetInternal() override { | |
398 return internal(); | |
399 } | |
400 END_PROXY_MAP() | |
401 | |
402 RTCErrorOr<std::unique_ptr<UdpTransportInterface>> | |
403 OrtcFactory::CreateUdpTransport(int family, | |
404 uint16_t min_port, | |
405 uint16_t max_port) { | |
406 RTC_DCHECK_RUN_ON(network_thread_); | |
407 std::unique_ptr<rtc::AsyncPacketSocket> socket( | |
408 socket_factory_->CreateUdpSocket( | |
409 rtc::SocketAddress(rtc::GetAnyIP(family), 0), min_port, max_port)); | |
410 if (!socket) { | |
411 // Only log at warning level, because this method may be called with | |
412 // specific port ranges to determine if a port is available, expecting the | |
413 // possibility of an error. | |
414 return CreateAndLogError(RTCErrorType::RESOURCE_EXHAUSTED, | |
415 "Local socket allocation failure.", | |
416 rtc::LS_WARNING); | |
417 } | |
418 LOG(LS_INFO) << "Created UDP socket with address " | |
419 << socket->GetLocalAddress().ToSensitiveString() << "."; | |
420 // Use proxy so that calls to the returned object are invoked on the network | |
421 // thread. | |
422 return UdpTransportProxyWithInternal<cricket::UdpTransport>::Create( | |
423 signaling_thread_, network_thread_, | |
424 new cricket::UdpTransport(std::string(), std::move(socket))); | |
425 } | |
426 | |
427 rtc::scoped_refptr<AudioSourceInterface> OrtcFactory::CreateAudioSource( | |
428 const cricket::AudioOptions& options) { | |
429 RTC_DCHECK_RUN_ON(signaling_thread_); | |
430 return rtc::scoped_refptr<LocalAudioSource>( | |
431 LocalAudioSource::Create(&options)); | |
432 } | |
433 | |
434 rtc::scoped_refptr<VideoTrackSourceInterface> OrtcFactory::CreateVideoSource( | |
435 std::unique_ptr<cricket::VideoCapturer> capturer, | |
436 const MediaConstraintsInterface* constraints) { | |
437 RTC_DCHECK_RUN_ON(signaling_thread_); | |
438 rtc::scoped_refptr<VideoTrackSourceInterface> source( | |
439 VideoCapturerTrackSource::Create( | |
440 worker_thread_.get(), std::move(capturer), constraints, false)); | |
441 return VideoTrackSourceProxy::Create(signaling_thread_, worker_thread_.get(), | |
442 source); | |
443 } | |
444 | |
445 rtc::scoped_refptr<VideoTrackInterface> OrtcFactory::CreateVideoTrack( | |
446 const std::string& id, | |
447 VideoTrackSourceInterface* source) { | |
448 RTC_DCHECK_RUN_ON(signaling_thread_); | |
449 rtc::scoped_refptr<VideoTrackInterface> track(VideoTrack::Create(id, source)); | |
450 return VideoTrackProxy::Create(signaling_thread_, worker_thread_.get(), | |
451 track); | |
452 } | |
453 | |
454 rtc::scoped_refptr<AudioTrackInterface> OrtcFactory::CreateAudioTrack( | |
455 const std::string& id, | |
456 AudioSourceInterface* source) { | |
457 RTC_DCHECK_RUN_ON(signaling_thread_); | |
458 rtc::scoped_refptr<AudioTrackInterface> track(AudioTrack::Create(id, source)); | |
459 return AudioTrackProxy::Create(signaling_thread_, track); | |
460 } | |
461 | |
462 RTCError OrtcFactory::Initialize() { | |
463 // TODO(deadbeef): Get rid of requirement to hop to worker thread here. | |
464 std::unique_ptr<cricket::MediaEngineInterface> media_engine = | |
465 worker_thread_->Invoke<std::unique_ptr<cricket::MediaEngineInterface>>( | |
466 RTC_FROM_HERE, rtc::Bind(&OrtcFactory::CreateMediaEngine_w, this)); | |
467 | |
468 channel_manager_.reset(new cricket::ChannelManager( | |
469 std::move(media_engine), worker_thread_.get(), network_thread_)); | |
470 channel_manager_->SetVideoRtxEnabled(true); | |
471 if (!channel_manager_->Init()) { | |
472 return CreateAndLogError(RTCErrorType::INTERNAL_ERROR, | |
473 "Failed to initialize ChannelManager."); | |
474 } | |
475 return RTCError(); | |
476 } | |
477 | |
478 std::unique_ptr<cricket::MediaEngineInterface> | |
479 OrtcFactory::CreateMediaEngine_w() { | |
480 RTC_DCHECK_RUN_ON(worker_thread_.get()); | |
481 // The nullptr arguments are optional factories that could be passed into the | |
482 // OrtcFactory, but aren't yet. | |
483 // Note that |adm_| may be null. | |
484 return std::unique_ptr<cricket::MediaEngineInterface>( | |
485 cricket::WebRtcMediaEngineFactory::Create(adm_, audio_decoder_factory_, | |
486 nullptr, nullptr, nullptr)); | |
487 } | |
488 | |
489 } // namespace webrtc | |
OLD | NEW |