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 <sstream> |
| 14 #include <vector> |
| 15 #include <utility> // For std::move. |
| 16 |
| 17 #include "webrtc/api/proxy.h" |
| 18 #include "webrtc/api/mediastreamtrackproxy.h" |
| 19 #include "webrtc/api/rtcerror.h" |
| 20 #include "webrtc/api/videosourceproxy.h" |
| 21 #include "webrtc/base/asyncpacketsocket.h" |
| 22 #include "webrtc/base/bind.h" |
| 23 #include "webrtc/base/checks.h" |
| 24 #include "webrtc/base/helpers.h" |
| 25 #include "webrtc/base/logging.h" |
| 26 #include "webrtc/logging/rtc_event_log/rtc_event_log.h" |
| 27 #include "webrtc/media/base/mediaconstants.h" |
| 28 #include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h" |
| 29 #include "webrtc/ortc/ortcrtpreceiveradapter.h" |
| 30 #include "webrtc/ortc/ortcrtpsenderadapter.h" |
| 31 #include "webrtc/ortc/rtpparametersconversion.h" |
| 32 #include "webrtc/ortc/rtptransportadapter.h" |
| 33 #include "webrtc/ortc/rtptransportcontrolleradapter.h" |
| 34 #include "webrtc/p2p/base/basicpacketsocketfactory.h" |
| 35 #include "webrtc/p2p/base/udptransport.h" |
| 36 #include "webrtc/pc/channelmanager.h" |
| 37 #include "webrtc/pc/localaudiosource.h" |
| 38 #include "webrtc/pc/audiotrack.h" |
| 39 #include "webrtc/pc/videocapturertracksource.h" |
| 40 #include "webrtc/pc/videotrack.h" |
| 41 |
| 42 namespace { |
| 43 |
| 44 const int kDefaultRtcpCnameLength = 16; |
| 45 |
| 46 // Asserts that all of the built-in capabilities can be converted to |
| 47 // RtpCapabilities. If they can't, something's wrong (for example, maybe a new |
| 48 // feedback mechanism is supported, but an enum value wasn't added to |
| 49 // rtpparameters.h). |
| 50 template <typename C> |
| 51 webrtc::RtpCapabilities ToRtpCapabilitiesWithAsserts( |
| 52 const std::vector<C>& cricket_codecs, |
| 53 const cricket::RtpHeaderExtensions& cricket_extensions) { |
| 54 webrtc::RtpCapabilities capabilities = |
| 55 webrtc::ToRtpCapabilities(cricket_codecs, cricket_extensions); |
| 56 RTC_DCHECK_EQ(capabilities.codecs.size(), cricket_codecs.size()); |
| 57 for (size_t i = 0; i < capabilities.codecs.size(); ++i) { |
| 58 RTC_DCHECK_EQ(capabilities.codecs[i].rtcp_feedback.size(), |
| 59 cricket_codecs[i].feedback_params.params().size()); |
| 60 } |
| 61 RTC_DCHECK_EQ(capabilities.header_extensions.size(), |
| 62 cricket_extensions.size()); |
| 63 return capabilities; |
| 64 } |
| 65 |
| 66 } // namespace |
| 67 |
| 68 namespace webrtc { |
| 69 |
| 70 // Note that this proxy class uses the network thread as the "worker" thread. |
| 71 BEGIN_OWNED_PROXY_MAP(OrtcFactory) |
| 72 PROXY_SIGNALING_THREAD_DESTRUCTOR() |
| 73 PROXY_METHOD0(RTCErrorOr<std::unique_ptr<RtpTransportControllerInterface>>, |
| 74 CreateRtpTransportController) |
| 75 PROXY_METHOD4(RTCErrorOr<std::unique_ptr<RtpTransportInterface>>, |
| 76 CreateRtpTransport, |
| 77 const RtcpParameters&, |
| 78 PacketTransportInterface*, |
| 79 PacketTransportInterface*, |
| 80 RtpTransportControllerInterface*) |
| 81 PROXY_CONSTMETHOD1(RtpCapabilities, |
| 82 GetRtpSenderCapabilities, |
| 83 cricket::MediaType) |
| 84 PROXY_METHOD2(RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>, |
| 85 CreateRtpSender, |
| 86 rtc::scoped_refptr<MediaStreamTrackInterface>, |
| 87 RtpTransportInterface*) |
| 88 PROXY_METHOD2(RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>, |
| 89 CreateRtpSender, |
| 90 cricket::MediaType, |
| 91 RtpTransportInterface*) |
| 92 PROXY_CONSTMETHOD1(RtpCapabilities, |
| 93 GetRtpReceiverCapabilities, |
| 94 cricket::MediaType) |
| 95 PROXY_METHOD2(RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>>, |
| 96 CreateRtpReceiver, |
| 97 cricket::MediaType, |
| 98 RtpTransportInterface*) |
| 99 PROXY_WORKER_METHOD3(RTCErrorOr<std::unique_ptr<UdpTransportInterface>>, |
| 100 CreateUdpTransport, |
| 101 int, |
| 102 uint16_t, |
| 103 uint16_t) |
| 104 PROXY_METHOD1(rtc::scoped_refptr<AudioSourceInterface>, |
| 105 CreateAudioSource, |
| 106 const cricket::AudioOptions&) |
| 107 PROXY_METHOD2(rtc::scoped_refptr<VideoTrackSourceInterface>, |
| 108 CreateVideoSource, |
| 109 std::unique_ptr<cricket::VideoCapturer>, |
| 110 const MediaConstraintsInterface*) |
| 111 PROXY_METHOD2(rtc::scoped_refptr<VideoTrackInterface>, |
| 112 CreateVideoTrack, |
| 113 const std::string&, |
| 114 VideoTrackSourceInterface*) |
| 115 PROXY_METHOD2(rtc::scoped_refptr<AudioTrackInterface>, |
| 116 CreateAudioTrack, |
| 117 const std::string&, |
| 118 AudioSourceInterface*) |
| 119 END_PROXY_MAP() |
| 120 |
| 121 // static |
| 122 RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> OrtcFactory::Create( |
| 123 rtc::Thread* network_thread, |
| 124 rtc::Thread* signaling_thread, |
| 125 rtc::NetworkManager* network_manager, |
| 126 rtc::PacketSocketFactory* socket_factory, |
| 127 AudioDeviceModule* adm, |
| 128 std::unique_ptr<cricket::MediaEngineInterface> media_engine) { |
| 129 // Hop to signaling thread if needed. |
| 130 if (signaling_thread && !signaling_thread->IsCurrent()) { |
| 131 return signaling_thread |
| 132 ->Invoke<RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>>>( |
| 133 RTC_FROM_HERE, |
| 134 rtc::Bind(&OrtcFactoryInterface::Create, network_thread, |
| 135 signaling_thread, network_manager, socket_factory, adm)); |
| 136 } |
| 137 std::unique_ptr<OrtcFactory> new_factory(new OrtcFactory( |
| 138 network_thread, signaling_thread, network_manager, socket_factory, adm)); |
| 139 RTCError err = new_factory->Initialize(std::move(media_engine)); |
| 140 if (!err.ok()) { |
| 141 return err; |
| 142 } |
| 143 // Return a proxy so that any calls on the returned object (including |
| 144 // destructor) happen on the signaling thread. |
| 145 return OrtcFactoryProxy::Create(new_factory->signaling_thread(), |
| 146 new_factory->network_thread(), |
| 147 new_factory.release()); |
| 148 } |
| 149 |
| 150 RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> OrtcFactoryInterface::Create( |
| 151 rtc::Thread* network_thread, |
| 152 rtc::Thread* signaling_thread, |
| 153 rtc::NetworkManager* network_manager, |
| 154 rtc::PacketSocketFactory* socket_factory, |
| 155 AudioDeviceModule* adm) { |
| 156 return OrtcFactory::Create(network_thread, signaling_thread, network_manager, |
| 157 socket_factory, adm, nullptr); |
| 158 } |
| 159 |
| 160 OrtcFactory::OrtcFactory(rtc::Thread* network_thread, |
| 161 rtc::Thread* signaling_thread, |
| 162 rtc::NetworkManager* network_manager, |
| 163 rtc::PacketSocketFactory* socket_factory, |
| 164 AudioDeviceModule* adm) |
| 165 : network_thread_(network_thread), |
| 166 signaling_thread_(signaling_thread), |
| 167 network_manager_(network_manager), |
| 168 socket_factory_(socket_factory), |
| 169 adm_(adm), |
| 170 null_event_log_(RtcEventLog::CreateNull()), |
| 171 audio_decoder_factory_(CreateBuiltinAudioDecoderFactory()) { |
| 172 if (!rtc::CreateRandomString(kDefaultRtcpCnameLength, &default_cname_)) { |
| 173 LOG(LS_ERROR) << "Failed to generate CNAME?"; |
| 174 RTC_NOTREACHED(); |
| 175 } |
| 176 if (!network_thread_) { |
| 177 owned_network_thread_ = rtc::Thread::CreateWithSocketServer(); |
| 178 owned_network_thread_->Start(); |
| 179 network_thread_ = owned_network_thread_.get(); |
| 180 } |
| 181 |
| 182 // The worker thread is created internally because it's an implementation |
| 183 // detail, and consumers of the API don't need to really know about it. |
| 184 worker_thread_ = rtc::Thread::Create(); |
| 185 worker_thread_->Start(); |
| 186 |
| 187 if (signaling_thread_) { |
| 188 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 189 } else { |
| 190 signaling_thread_ = rtc::Thread::Current(); |
| 191 if (!signaling_thread_) { |
| 192 // If this thread isn't already wrapped by an rtc::Thread, create a |
| 193 // wrapper and own it in this class. |
| 194 signaling_thread_ = rtc::ThreadManager::Instance()->WrapCurrentThread(); |
| 195 wraps_signaling_thread_ = true; |
| 196 } |
| 197 } |
| 198 if (!network_manager_) { |
| 199 owned_network_manager_.reset(new rtc::BasicNetworkManager()); |
| 200 network_manager_ = owned_network_manager_.get(); |
| 201 } |
| 202 if (!socket_factory_) { |
| 203 owned_socket_factory_.reset( |
| 204 new rtc::BasicPacketSocketFactory(network_thread_)); |
| 205 socket_factory_ = owned_socket_factory_.get(); |
| 206 } |
| 207 } |
| 208 |
| 209 OrtcFactory::~OrtcFactory() { |
| 210 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 211 if (wraps_signaling_thread_) { |
| 212 rtc::ThreadManager::Instance()->UnwrapCurrentThread(); |
| 213 } |
| 214 } |
| 215 |
| 216 RTCErrorOr<std::unique_ptr<RtpTransportControllerInterface>> |
| 217 OrtcFactory::CreateRtpTransportController() { |
| 218 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 219 return RtpTransportControllerAdapter::CreateProxied( |
| 220 cricket::MediaConfig(), channel_manager_.get(), null_event_log_.get(), |
| 221 signaling_thread_, worker_thread_.get()); |
| 222 } |
| 223 |
| 224 RTCErrorOr<std::unique_ptr<RtpTransportInterface>> |
| 225 OrtcFactory::CreateRtpTransport( |
| 226 const RtcpParameters& rtcp_parameters, |
| 227 PacketTransportInterface* rtp, |
| 228 PacketTransportInterface* rtcp, |
| 229 RtpTransportControllerInterface* transport_controller) { |
| 230 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 231 RtcpParameters copied_parameters = rtcp_parameters; |
| 232 if (copied_parameters.cname.empty()) { |
| 233 copied_parameters.cname = default_cname_; |
| 234 } |
| 235 if (transport_controller) { |
| 236 return RtpTransportAdapter::CreateProxied(copied_parameters, rtp, rtcp, |
| 237 transport_controller); |
| 238 } else { |
| 239 // If |transport_controller| is null, create one automatically, which the |
| 240 // returned RtpTransport will own. |
| 241 auto result = CreateRtpTransportController(); |
| 242 if (!result.ok()) { |
| 243 return result.MoveError(); |
| 244 } |
| 245 return RtpTransportAdapter::CreateProxied(copied_parameters, rtp, rtcp, |
| 246 result.MoveValue()); |
| 247 } |
| 248 } |
| 249 |
| 250 RtpCapabilities OrtcFactory::GetRtpSenderCapabilities( |
| 251 cricket::MediaType kind) const { |
| 252 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 253 switch (kind) { |
| 254 case cricket::MEDIA_TYPE_AUDIO: { |
| 255 cricket::AudioCodecs cricket_codecs; |
| 256 cricket::RtpHeaderExtensions cricket_extensions; |
| 257 channel_manager_->GetSupportedAudioSendCodecs(&cricket_codecs); |
| 258 channel_manager_->GetSupportedAudioRtpHeaderExtensions( |
| 259 &cricket_extensions); |
| 260 return ToRtpCapabilitiesWithAsserts(cricket_codecs, cricket_extensions); |
| 261 } |
| 262 case cricket::MEDIA_TYPE_VIDEO: { |
| 263 cricket::VideoCodecs cricket_codecs; |
| 264 cricket::RtpHeaderExtensions cricket_extensions; |
| 265 channel_manager_->GetSupportedVideoCodecs(&cricket_codecs); |
| 266 channel_manager_->GetSupportedVideoRtpHeaderExtensions( |
| 267 &cricket_extensions); |
| 268 return ToRtpCapabilitiesWithAsserts(cricket_codecs, cricket_extensions); |
| 269 } |
| 270 case cricket::MEDIA_TYPE_DATA: |
| 271 return RtpCapabilities(); |
| 272 } |
| 273 } |
| 274 |
| 275 RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>> |
| 276 OrtcFactory::CreateRtpSender( |
| 277 rtc::scoped_refptr<MediaStreamTrackInterface> track, |
| 278 RtpTransportInterface* transport) { |
| 279 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 280 if (!track) { |
| 281 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, |
| 282 "Cannot pass null track into CreateRtpSender."); |
| 283 } |
| 284 auto result = |
| 285 CreateRtpSender(cricket::MediaTypeFromString(track->kind()), transport); |
| 286 if (!result.ok()) { |
| 287 return result; |
| 288 } |
| 289 auto err = result.value()->SetTrack(track); |
| 290 if (!err.ok()) { |
| 291 return err; |
| 292 } |
| 293 return result; |
| 294 } |
| 295 |
| 296 RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>> |
| 297 OrtcFactory::CreateRtpSender(cricket::MediaType kind, |
| 298 RtpTransportInterface* transport) { |
| 299 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 300 if (kind == cricket::MEDIA_TYPE_DATA) { |
| 301 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, |
| 302 "Cannot create data RtpSender."); |
| 303 } |
| 304 if (!transport) { |
| 305 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, |
| 306 "Cannot pass null transport into CreateRtpSender."); |
| 307 } |
| 308 return transport->GetInternal() |
| 309 ->rtp_transport_controller() |
| 310 ->CreateProxiedRtpSender(kind, transport); |
| 311 } |
| 312 |
| 313 RtpCapabilities OrtcFactory::GetRtpReceiverCapabilities( |
| 314 cricket::MediaType kind) const { |
| 315 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 316 switch (kind) { |
| 317 case cricket::MEDIA_TYPE_AUDIO: { |
| 318 cricket::AudioCodecs cricket_codecs; |
| 319 cricket::RtpHeaderExtensions cricket_extensions; |
| 320 channel_manager_->GetSupportedAudioReceiveCodecs(&cricket_codecs); |
| 321 channel_manager_->GetSupportedAudioRtpHeaderExtensions( |
| 322 &cricket_extensions); |
| 323 return ToRtpCapabilitiesWithAsserts(cricket_codecs, cricket_extensions); |
| 324 } |
| 325 case cricket::MEDIA_TYPE_VIDEO: { |
| 326 cricket::VideoCodecs cricket_codecs; |
| 327 cricket::RtpHeaderExtensions cricket_extensions; |
| 328 channel_manager_->GetSupportedVideoCodecs(&cricket_codecs); |
| 329 channel_manager_->GetSupportedVideoRtpHeaderExtensions( |
| 330 &cricket_extensions); |
| 331 return ToRtpCapabilitiesWithAsserts(cricket_codecs, cricket_extensions); |
| 332 } |
| 333 case cricket::MEDIA_TYPE_DATA: |
| 334 return RtpCapabilities(); |
| 335 } |
| 336 } |
| 337 |
| 338 RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>> |
| 339 OrtcFactory::CreateRtpReceiver(cricket::MediaType kind, |
| 340 RtpTransportInterface* transport) { |
| 341 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 342 if (kind == cricket::MEDIA_TYPE_DATA) { |
| 343 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, |
| 344 "Cannot create data RtpReceiver."); |
| 345 } |
| 346 if (!transport) { |
| 347 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, |
| 348 "Cannot pass null transport into CreateRtpReceiver."); |
| 349 } |
| 350 return transport->GetInternal() |
| 351 ->rtp_transport_controller() |
| 352 ->CreateProxiedRtpReceiver(kind, transport); |
| 353 } |
| 354 |
| 355 // UdpTransport expects all methods to be called on one thread, which needs to |
| 356 // be the network thread, since that's where its socket can safely be used. So |
| 357 // return a proxy to the created UdpTransport. |
| 358 BEGIN_OWNED_PROXY_MAP(UdpTransport) |
| 359 PROXY_WORKER_THREAD_DESTRUCTOR() |
| 360 PROXY_WORKER_CONSTMETHOD0(rtc::SocketAddress, GetLocalAddress) |
| 361 PROXY_WORKER_METHOD1(bool, SetRemoteAddress, const rtc::SocketAddress&) |
| 362 PROXY_WORKER_CONSTMETHOD0(rtc::SocketAddress, GetRemoteAddress) |
| 363 protected: |
| 364 rtc::PacketTransportInternal* GetInternal() override { |
| 365 return internal(); |
| 366 } |
| 367 END_PROXY_MAP() |
| 368 |
| 369 RTCErrorOr<std::unique_ptr<UdpTransportInterface>> |
| 370 OrtcFactory::CreateUdpTransport(int family, |
| 371 uint16_t min_port, |
| 372 uint16_t max_port) { |
| 373 RTC_DCHECK_RUN_ON(network_thread_); |
| 374 if (family != AF_INET && family != AF_INET6) { |
| 375 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, |
| 376 "Address family must be AF_INET or AF_INET6."); |
| 377 } |
| 378 if (min_port > max_port) { |
| 379 LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, |
| 380 "Port range invalid; minimum port must be less than " |
| 381 "or equal to max port."); |
| 382 } |
| 383 std::unique_ptr<rtc::AsyncPacketSocket> socket( |
| 384 socket_factory_->CreateUdpSocket( |
| 385 rtc::SocketAddress(rtc::GetAnyIP(family), 0), min_port, max_port)); |
| 386 if (!socket) { |
| 387 // Only log at warning level, because this method may be called with |
| 388 // specific port ranges to determine if a port is available, expecting the |
| 389 // possibility of an error. |
| 390 LOG_AND_RETURN_ERROR_EX(RTCErrorType::RESOURCE_EXHAUSTED, |
| 391 "Local socket allocation failure.", LS_WARNING); |
| 392 } |
| 393 LOG(LS_INFO) << "Created UDP socket with address " |
| 394 << socket->GetLocalAddress().ToSensitiveString() << "."; |
| 395 // Make a unique debug name (for logging/diagnostics only). |
| 396 std::ostringstream oss; |
| 397 static int udp_id = 0; |
| 398 oss << "udp" << udp_id++; |
| 399 return UdpTransportProxyWithInternal<cricket::UdpTransport>::Create( |
| 400 signaling_thread_, network_thread_, |
| 401 new cricket::UdpTransport(oss.str(), std::move(socket))); |
| 402 } |
| 403 |
| 404 rtc::scoped_refptr<AudioSourceInterface> OrtcFactory::CreateAudioSource( |
| 405 const cricket::AudioOptions& options) { |
| 406 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 407 return rtc::scoped_refptr<LocalAudioSource>( |
| 408 LocalAudioSource::Create(&options)); |
| 409 } |
| 410 |
| 411 rtc::scoped_refptr<VideoTrackSourceInterface> OrtcFactory::CreateVideoSource( |
| 412 std::unique_ptr<cricket::VideoCapturer> capturer, |
| 413 const MediaConstraintsInterface* constraints) { |
| 414 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 415 rtc::scoped_refptr<VideoTrackSourceInterface> source( |
| 416 VideoCapturerTrackSource::Create( |
| 417 worker_thread_.get(), std::move(capturer), constraints, false)); |
| 418 return VideoTrackSourceProxy::Create(signaling_thread_, worker_thread_.get(), |
| 419 source); |
| 420 } |
| 421 |
| 422 rtc::scoped_refptr<VideoTrackInterface> OrtcFactory::CreateVideoTrack( |
| 423 const std::string& id, |
| 424 VideoTrackSourceInterface* source) { |
| 425 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 426 rtc::scoped_refptr<VideoTrackInterface> track(VideoTrack::Create(id, source)); |
| 427 return VideoTrackProxy::Create(signaling_thread_, worker_thread_.get(), |
| 428 track); |
| 429 } |
| 430 |
| 431 rtc::scoped_refptr<AudioTrackInterface> OrtcFactory::CreateAudioTrack( |
| 432 const std::string& id, |
| 433 AudioSourceInterface* source) { |
| 434 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 435 rtc::scoped_refptr<AudioTrackInterface> track(AudioTrack::Create(id, source)); |
| 436 return AudioTrackProxy::Create(signaling_thread_, track); |
| 437 } |
| 438 |
| 439 RTCError OrtcFactory::Initialize( |
| 440 std::unique_ptr<cricket::MediaEngineInterface> media_engine) { |
| 441 RTC_DCHECK_RUN_ON(signaling_thread_); |
| 442 // TODO(deadbeef): Get rid of requirement to hop to worker thread here. |
| 443 if (!media_engine) { |
| 444 media_engine = |
| 445 worker_thread_->Invoke<std::unique_ptr<cricket::MediaEngineInterface>>( |
| 446 RTC_FROM_HERE, rtc::Bind(&OrtcFactory::CreateMediaEngine_w, this)); |
| 447 } |
| 448 |
| 449 channel_manager_.reset(new cricket::ChannelManager( |
| 450 std::move(media_engine), worker_thread_.get(), network_thread_)); |
| 451 channel_manager_->SetVideoRtxEnabled(true); |
| 452 if (!channel_manager_->Init()) { |
| 453 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR, |
| 454 "Failed to initialize ChannelManager."); |
| 455 } |
| 456 return RTCError::OK(); |
| 457 } |
| 458 |
| 459 std::unique_ptr<cricket::MediaEngineInterface> |
| 460 OrtcFactory::CreateMediaEngine_w() { |
| 461 RTC_DCHECK_RUN_ON(worker_thread_.get()); |
| 462 // The null arguments are optional factories that could be passed into the |
| 463 // OrtcFactory, but aren't yet. |
| 464 // |
| 465 // Note that |adm_| may be null, in which case the platform-specific default |
| 466 // AudioDeviceModule will be used. |
| 467 return std::unique_ptr<cricket::MediaEngineInterface>( |
| 468 cricket::WebRtcMediaEngineFactory::Create(adm_, audio_decoder_factory_, |
| 469 nullptr, nullptr, nullptr)); |
| 470 } |
| 471 |
| 472 } // namespace webrtc |
OLD | NEW |