This CL adds the following interfaces: * RtpTransportController * RtpTransport * RtpSender * RtpReceiver They're implemented on top of the "BaseChannel" object, which is normally used in a PeerConnection, and roughly corresponds to an SDP "m=" section. As a result of this, there are several limitations: * You can only have one of each type of sender and receiver (audio/video) on top of the same transport controller. * The sender/receiver with the same media type must use the same RTP transport. * You can't change the transport after creating the sender or receiver. * Some of the parameters aren't supported. Later, these "adapter" objects will be gradually replaced by real objects that don't have these limitations, as "BaseChannel", "MediaChannel" and related code is restructured. In this CL, we essentially have: ORTC adapter objects -> BaseChannel -> Media engine PeerConnection -> BaseChannel -> Media engine And later we hope to have simply: PeerConnection -> "Real" ORTC objects -> Media engine See the linked bug for more context. BUG=webrtc:7013 TBR=stefan@webrtc.org Review-Url: https://codereview.webrtc.org/2675173003 Cr-Commit-Position: refs/heads/master@{#16842}
505 lines
20 KiB
C++
505 lines
20 KiB
C++
/*
|
|
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "webrtc/ortc/ortcfactory.h"
|
|
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <utility> // For std::move.
|
|
|
|
#include "webrtc/api/proxy.h"
|
|
#include "webrtc/api/mediastreamtrackproxy.h"
|
|
#include "webrtc/api/rtcerror.h"
|
|
#include "webrtc/api/videosourceproxy.h"
|
|
#include "webrtc/base/asyncpacketsocket.h"
|
|
#include "webrtc/base/bind.h"
|
|
#include "webrtc/base/checks.h"
|
|
#include "webrtc/base/helpers.h"
|
|
#include "webrtc/base/logging.h"
|
|
#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
|
|
#include "webrtc/media/base/mediaconstants.h"
|
|
#include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h"
|
|
#include "webrtc/ortc/ortcrtpreceiveradapter.h"
|
|
#include "webrtc/ortc/ortcrtpsenderadapter.h"
|
|
#include "webrtc/ortc/rtpparametersconversion.h"
|
|
#include "webrtc/ortc/rtptransportadapter.h"
|
|
#include "webrtc/ortc/rtptransportcontrolleradapter.h"
|
|
#include "webrtc/p2p/base/basicpacketsocketfactory.h"
|
|
#include "webrtc/p2p/base/udptransport.h"
|
|
#include "webrtc/pc/channelmanager.h"
|
|
#include "webrtc/pc/localaudiosource.h"
|
|
#include "webrtc/pc/audiotrack.h"
|
|
#include "webrtc/pc/videocapturertracksource.h"
|
|
#include "webrtc/pc/videotrack.h"
|
|
|
|
namespace {
|
|
|
|
const int kDefaultRtcpCnameLength = 16;
|
|
|
|
// Asserts that all of the built-in capabilities can be converted to
|
|
// RtpCapabilities. If they can't, something's wrong (for example, maybe a new
|
|
// feedback mechanism is supported, but an enum value wasn't added to
|
|
// rtpparameters.h).
|
|
template <typename C>
|
|
webrtc::RtpCapabilities ToRtpCapabilitiesWithAsserts(
|
|
const std::vector<C>& cricket_codecs,
|
|
const cricket::RtpHeaderExtensions& cricket_extensions) {
|
|
webrtc::RtpCapabilities capabilities =
|
|
webrtc::ToRtpCapabilities(cricket_codecs, cricket_extensions);
|
|
RTC_DCHECK_EQ(capabilities.codecs.size(), cricket_codecs.size());
|
|
for (size_t i = 0; i < capabilities.codecs.size(); ++i) {
|
|
RTC_DCHECK_EQ(capabilities.codecs[i].rtcp_feedback.size(),
|
|
cricket_codecs[i].feedback_params.params().size());
|
|
}
|
|
RTC_DCHECK_EQ(capabilities.header_extensions.size(),
|
|
cricket_extensions.size());
|
|
return capabilities;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace webrtc {
|
|
|
|
// Note that this proxy class uses the network thread as the "worker" thread.
|
|
BEGIN_OWNED_PROXY_MAP(OrtcFactory)
|
|
PROXY_SIGNALING_THREAD_DESTRUCTOR()
|
|
PROXY_METHOD0(RTCErrorOr<std::unique_ptr<RtpTransportControllerInterface>>,
|
|
CreateRtpTransportController)
|
|
PROXY_METHOD4(RTCErrorOr<std::unique_ptr<RtpTransportInterface>>,
|
|
CreateRtpTransport,
|
|
const RtcpParameters&,
|
|
PacketTransportInterface*,
|
|
PacketTransportInterface*,
|
|
RtpTransportControllerInterface*)
|
|
PROXY_CONSTMETHOD1(RtpCapabilities,
|
|
GetRtpSenderCapabilities,
|
|
cricket::MediaType)
|
|
PROXY_METHOD2(RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>,
|
|
CreateRtpSender,
|
|
rtc::scoped_refptr<MediaStreamTrackInterface>,
|
|
RtpTransportInterface*)
|
|
PROXY_METHOD2(RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>,
|
|
CreateRtpSender,
|
|
cricket::MediaType,
|
|
RtpTransportInterface*)
|
|
PROXY_CONSTMETHOD1(RtpCapabilities,
|
|
GetRtpReceiverCapabilities,
|
|
cricket::MediaType)
|
|
PROXY_METHOD2(RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>>,
|
|
CreateRtpReceiver,
|
|
cricket::MediaType,
|
|
RtpTransportInterface*)
|
|
PROXY_WORKER_METHOD3(RTCErrorOr<std::unique_ptr<UdpTransportInterface>>,
|
|
CreateUdpTransport,
|
|
int,
|
|
uint16_t,
|
|
uint16_t)
|
|
PROXY_METHOD1(rtc::scoped_refptr<AudioSourceInterface>,
|
|
CreateAudioSource,
|
|
const cricket::AudioOptions&)
|
|
PROXY_METHOD2(rtc::scoped_refptr<VideoTrackSourceInterface>,
|
|
CreateVideoSource,
|
|
std::unique_ptr<cricket::VideoCapturer>,
|
|
const MediaConstraintsInterface*)
|
|
PROXY_METHOD2(rtc::scoped_refptr<VideoTrackInterface>,
|
|
CreateVideoTrack,
|
|
const std::string&,
|
|
VideoTrackSourceInterface*)
|
|
PROXY_METHOD2(rtc::scoped_refptr<AudioTrackInterface>,
|
|
CreateAudioTrack,
|
|
const std::string&,
|
|
AudioSourceInterface*)
|
|
END_PROXY_MAP()
|
|
|
|
// static
|
|
RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> OrtcFactory::Create(
|
|
rtc::Thread* network_thread,
|
|
rtc::Thread* signaling_thread,
|
|
rtc::NetworkManager* network_manager,
|
|
rtc::PacketSocketFactory* socket_factory,
|
|
AudioDeviceModule* adm,
|
|
std::unique_ptr<cricket::MediaEngineInterface> media_engine) {
|
|
// Hop to signaling thread if needed.
|
|
if (signaling_thread && !signaling_thread->IsCurrent()) {
|
|
return signaling_thread
|
|
->Invoke<RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>>>(
|
|
RTC_FROM_HERE,
|
|
rtc::Bind(&OrtcFactory::Create_s, network_thread, signaling_thread,
|
|
network_manager, socket_factory, adm,
|
|
media_engine.release()));
|
|
}
|
|
return Create_s(network_thread, signaling_thread, network_manager,
|
|
socket_factory, adm, media_engine.release());
|
|
}
|
|
|
|
RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> OrtcFactoryInterface::Create(
|
|
rtc::Thread* network_thread,
|
|
rtc::Thread* signaling_thread,
|
|
rtc::NetworkManager* network_manager,
|
|
rtc::PacketSocketFactory* socket_factory,
|
|
AudioDeviceModule* adm) {
|
|
return OrtcFactory::Create(network_thread, signaling_thread, network_manager,
|
|
socket_factory, adm, nullptr);
|
|
}
|
|
|
|
OrtcFactory::OrtcFactory(rtc::Thread* network_thread,
|
|
rtc::Thread* signaling_thread,
|
|
rtc::NetworkManager* network_manager,
|
|
rtc::PacketSocketFactory* socket_factory,
|
|
AudioDeviceModule* adm)
|
|
: network_thread_(network_thread),
|
|
signaling_thread_(signaling_thread),
|
|
network_manager_(network_manager),
|
|
socket_factory_(socket_factory),
|
|
adm_(adm),
|
|
null_event_log_(RtcEventLog::CreateNull()),
|
|
audio_decoder_factory_(CreateBuiltinAudioDecoderFactory()) {
|
|
if (!rtc::CreateRandomString(kDefaultRtcpCnameLength, &default_cname_)) {
|
|
LOG(LS_ERROR) << "Failed to generate CNAME?";
|
|
RTC_NOTREACHED();
|
|
}
|
|
if (!network_thread_) {
|
|
owned_network_thread_ = rtc::Thread::CreateWithSocketServer();
|
|
owned_network_thread_->Start();
|
|
network_thread_ = owned_network_thread_.get();
|
|
}
|
|
|
|
// The worker thread is created internally because it's an implementation
|
|
// detail, and consumers of the API don't need to really know about it.
|
|
worker_thread_ = rtc::Thread::Create();
|
|
worker_thread_->Start();
|
|
|
|
if (signaling_thread_) {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
} else {
|
|
signaling_thread_ = rtc::Thread::Current();
|
|
if (!signaling_thread_) {
|
|
// If this thread isn't already wrapped by an rtc::Thread, create a
|
|
// wrapper and own it in this class.
|
|
signaling_thread_ = rtc::ThreadManager::Instance()->WrapCurrentThread();
|
|
wraps_signaling_thread_ = true;
|
|
}
|
|
}
|
|
if (!network_manager_) {
|
|
owned_network_manager_.reset(new rtc::BasicNetworkManager());
|
|
network_manager_ = owned_network_manager_.get();
|
|
}
|
|
if (!socket_factory_) {
|
|
owned_socket_factory_.reset(
|
|
new rtc::BasicPacketSocketFactory(network_thread_));
|
|
socket_factory_ = owned_socket_factory_.get();
|
|
}
|
|
}
|
|
|
|
OrtcFactory::~OrtcFactory() {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
if (wraps_signaling_thread_) {
|
|
rtc::ThreadManager::Instance()->UnwrapCurrentThread();
|
|
}
|
|
}
|
|
|
|
RTCErrorOr<std::unique_ptr<RtpTransportControllerInterface>>
|
|
OrtcFactory::CreateRtpTransportController() {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
return RtpTransportControllerAdapter::CreateProxied(
|
|
cricket::MediaConfig(), channel_manager_.get(), null_event_log_.get(),
|
|
signaling_thread_, worker_thread_.get());
|
|
}
|
|
|
|
RTCErrorOr<std::unique_ptr<RtpTransportInterface>>
|
|
OrtcFactory::CreateRtpTransport(
|
|
const RtcpParameters& rtcp_parameters,
|
|
PacketTransportInterface* rtp,
|
|
PacketTransportInterface* rtcp,
|
|
RtpTransportControllerInterface* transport_controller) {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
RtcpParameters copied_parameters = rtcp_parameters;
|
|
if (copied_parameters.cname.empty()) {
|
|
copied_parameters.cname = default_cname_;
|
|
}
|
|
if (transport_controller) {
|
|
return transport_controller->GetInternal()->CreateProxiedRtpTransport(
|
|
copied_parameters, rtp, rtcp);
|
|
} else {
|
|
// If |transport_controller| is null, create one automatically, which the
|
|
// returned RtpTransport will own.
|
|
auto controller_result = CreateRtpTransportController();
|
|
if (!controller_result.ok()) {
|
|
return controller_result.MoveError();
|
|
}
|
|
auto controller = controller_result.MoveValue();
|
|
auto transport_result =
|
|
controller->GetInternal()->CreateProxiedRtpTransport(copied_parameters,
|
|
rtp, rtcp);
|
|
// If RtpTransport was successfully created, transfer ownership of
|
|
// |rtp_transport_controller|. Otherwise it will go out of scope and be
|
|
// deleted automatically.
|
|
if (transport_result.ok()) {
|
|
transport_result.value()
|
|
->GetInternal()
|
|
->TakeOwnershipOfRtpTransportController(std::move(controller));
|
|
}
|
|
return transport_result;
|
|
}
|
|
}
|
|
|
|
RtpCapabilities OrtcFactory::GetRtpSenderCapabilities(
|
|
cricket::MediaType kind) const {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
switch (kind) {
|
|
case cricket::MEDIA_TYPE_AUDIO: {
|
|
cricket::AudioCodecs cricket_codecs;
|
|
cricket::RtpHeaderExtensions cricket_extensions;
|
|
channel_manager_->GetSupportedAudioSendCodecs(&cricket_codecs);
|
|
channel_manager_->GetSupportedAudioRtpHeaderExtensions(
|
|
&cricket_extensions);
|
|
return ToRtpCapabilitiesWithAsserts(cricket_codecs, cricket_extensions);
|
|
}
|
|
case cricket::MEDIA_TYPE_VIDEO: {
|
|
cricket::VideoCodecs cricket_codecs;
|
|
cricket::RtpHeaderExtensions cricket_extensions;
|
|
channel_manager_->GetSupportedVideoCodecs(&cricket_codecs);
|
|
channel_manager_->GetSupportedVideoRtpHeaderExtensions(
|
|
&cricket_extensions);
|
|
return ToRtpCapabilitiesWithAsserts(cricket_codecs, cricket_extensions);
|
|
}
|
|
case cricket::MEDIA_TYPE_DATA:
|
|
return RtpCapabilities();
|
|
}
|
|
// Not reached; avoids compile warning.
|
|
FATAL();
|
|
}
|
|
|
|
RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>
|
|
OrtcFactory::CreateRtpSender(
|
|
rtc::scoped_refptr<MediaStreamTrackInterface> track,
|
|
RtpTransportInterface* transport) {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
if (!track) {
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
"Cannot pass null track into CreateRtpSender.");
|
|
}
|
|
auto result =
|
|
CreateRtpSender(cricket::MediaTypeFromString(track->kind()), transport);
|
|
if (!result.ok()) {
|
|
return result;
|
|
}
|
|
auto err = result.value()->SetTrack(track);
|
|
if (!err.ok()) {
|
|
return std::move(err);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>
|
|
OrtcFactory::CreateRtpSender(cricket::MediaType kind,
|
|
RtpTransportInterface* transport) {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
if (kind == cricket::MEDIA_TYPE_DATA) {
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
"Cannot create data RtpSender.");
|
|
}
|
|
if (!transport) {
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
"Cannot pass null transport into CreateRtpSender.");
|
|
}
|
|
return transport->GetInternal()
|
|
->rtp_transport_controller()
|
|
->CreateProxiedRtpSender(kind, transport);
|
|
}
|
|
|
|
RtpCapabilities OrtcFactory::GetRtpReceiverCapabilities(
|
|
cricket::MediaType kind) const {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
switch (kind) {
|
|
case cricket::MEDIA_TYPE_AUDIO: {
|
|
cricket::AudioCodecs cricket_codecs;
|
|
cricket::RtpHeaderExtensions cricket_extensions;
|
|
channel_manager_->GetSupportedAudioReceiveCodecs(&cricket_codecs);
|
|
channel_manager_->GetSupportedAudioRtpHeaderExtensions(
|
|
&cricket_extensions);
|
|
return ToRtpCapabilitiesWithAsserts(cricket_codecs, cricket_extensions);
|
|
}
|
|
case cricket::MEDIA_TYPE_VIDEO: {
|
|
cricket::VideoCodecs cricket_codecs;
|
|
cricket::RtpHeaderExtensions cricket_extensions;
|
|
channel_manager_->GetSupportedVideoCodecs(&cricket_codecs);
|
|
channel_manager_->GetSupportedVideoRtpHeaderExtensions(
|
|
&cricket_extensions);
|
|
return ToRtpCapabilitiesWithAsserts(cricket_codecs, cricket_extensions);
|
|
}
|
|
case cricket::MEDIA_TYPE_DATA:
|
|
return RtpCapabilities();
|
|
}
|
|
// Not reached; avoids compile warning.
|
|
FATAL();
|
|
}
|
|
|
|
RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>>
|
|
OrtcFactory::CreateRtpReceiver(cricket::MediaType kind,
|
|
RtpTransportInterface* transport) {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
if (kind == cricket::MEDIA_TYPE_DATA) {
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
"Cannot create data RtpReceiver.");
|
|
}
|
|
if (!transport) {
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
"Cannot pass null transport into CreateRtpReceiver.");
|
|
}
|
|
return transport->GetInternal()
|
|
->rtp_transport_controller()
|
|
->CreateProxiedRtpReceiver(kind, transport);
|
|
}
|
|
|
|
// UdpTransport expects all methods to be called on one thread, which needs to
|
|
// be the network thread, since that's where its socket can safely be used. So
|
|
// return a proxy to the created UdpTransport.
|
|
BEGIN_OWNED_PROXY_MAP(UdpTransport)
|
|
PROXY_WORKER_THREAD_DESTRUCTOR()
|
|
PROXY_WORKER_CONSTMETHOD0(rtc::SocketAddress, GetLocalAddress)
|
|
PROXY_WORKER_METHOD1(bool, SetRemoteAddress, const rtc::SocketAddress&)
|
|
PROXY_WORKER_CONSTMETHOD0(rtc::SocketAddress, GetRemoteAddress)
|
|
protected:
|
|
rtc::PacketTransportInternal* GetInternal() override {
|
|
return internal();
|
|
}
|
|
END_PROXY_MAP()
|
|
|
|
RTCErrorOr<std::unique_ptr<UdpTransportInterface>>
|
|
OrtcFactory::CreateUdpTransport(int family,
|
|
uint16_t min_port,
|
|
uint16_t max_port) {
|
|
RTC_DCHECK_RUN_ON(network_thread_);
|
|
if (family != AF_INET && family != AF_INET6) {
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
|
|
"Address family must be AF_INET or AF_INET6.");
|
|
}
|
|
if (min_port > max_port) {
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
|
|
"Port range invalid; minimum port must be less than "
|
|
"or equal to max port.");
|
|
}
|
|
std::unique_ptr<rtc::AsyncPacketSocket> socket(
|
|
socket_factory_->CreateUdpSocket(
|
|
rtc::SocketAddress(rtc::GetAnyIP(family), 0), min_port, max_port));
|
|
if (!socket) {
|
|
// Only log at warning level, because this method may be called with
|
|
// specific port ranges to determine if a port is available, expecting the
|
|
// possibility of an error.
|
|
LOG_AND_RETURN_ERROR_EX(RTCErrorType::RESOURCE_EXHAUSTED,
|
|
"Local socket allocation failure.", LS_WARNING);
|
|
}
|
|
LOG(LS_INFO) << "Created UDP socket with address "
|
|
<< socket->GetLocalAddress().ToSensitiveString() << ".";
|
|
// Make a unique debug name (for logging/diagnostics only).
|
|
std::ostringstream oss;
|
|
static int udp_id = 0;
|
|
oss << "udp" << udp_id++;
|
|
return UdpTransportProxyWithInternal<cricket::UdpTransport>::Create(
|
|
signaling_thread_, network_thread_,
|
|
std::unique_ptr<cricket::UdpTransport>(
|
|
new cricket::UdpTransport(oss.str(), std::move(socket))));
|
|
}
|
|
|
|
rtc::scoped_refptr<AudioSourceInterface> OrtcFactory::CreateAudioSource(
|
|
const cricket::AudioOptions& options) {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
return rtc::scoped_refptr<LocalAudioSource>(
|
|
LocalAudioSource::Create(&options));
|
|
}
|
|
|
|
rtc::scoped_refptr<VideoTrackSourceInterface> OrtcFactory::CreateVideoSource(
|
|
std::unique_ptr<cricket::VideoCapturer> capturer,
|
|
const MediaConstraintsInterface* constraints) {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
rtc::scoped_refptr<VideoTrackSourceInterface> source(
|
|
VideoCapturerTrackSource::Create(
|
|
worker_thread_.get(), std::move(capturer), constraints, false));
|
|
return VideoTrackSourceProxy::Create(signaling_thread_, worker_thread_.get(),
|
|
source);
|
|
}
|
|
|
|
rtc::scoped_refptr<VideoTrackInterface> OrtcFactory::CreateVideoTrack(
|
|
const std::string& id,
|
|
VideoTrackSourceInterface* source) {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
rtc::scoped_refptr<VideoTrackInterface> track(VideoTrack::Create(id, source));
|
|
return VideoTrackProxy::Create(signaling_thread_, worker_thread_.get(),
|
|
track);
|
|
}
|
|
|
|
rtc::scoped_refptr<AudioTrackInterface> OrtcFactory::CreateAudioTrack(
|
|
const std::string& id,
|
|
AudioSourceInterface* source) {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
rtc::scoped_refptr<AudioTrackInterface> track(AudioTrack::Create(id, source));
|
|
return AudioTrackProxy::Create(signaling_thread_, track);
|
|
}
|
|
|
|
// static
|
|
RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> OrtcFactory::Create_s(
|
|
rtc::Thread* network_thread,
|
|
rtc::Thread* signaling_thread,
|
|
rtc::NetworkManager* network_manager,
|
|
rtc::PacketSocketFactory* socket_factory,
|
|
AudioDeviceModule* adm,
|
|
cricket::MediaEngineInterface* media_engine) {
|
|
// Add the unique_ptr wrapper back.
|
|
std::unique_ptr<cricket::MediaEngineInterface> owned_media_engine(
|
|
media_engine);
|
|
std::unique_ptr<OrtcFactory> new_factory(new OrtcFactory(
|
|
network_thread, signaling_thread, network_manager, socket_factory, adm));
|
|
RTCError err = new_factory->Initialize(std::move(owned_media_engine));
|
|
if (!err.ok()) {
|
|
return std::move(err);
|
|
}
|
|
// Return a proxy so that any calls on the returned object (including
|
|
// destructor) happen on the signaling thread.
|
|
rtc::Thread* signaling = new_factory->signaling_thread();
|
|
rtc::Thread* network = new_factory->network_thread();
|
|
return OrtcFactoryProxy::Create(signaling, network, std::move(new_factory));
|
|
}
|
|
|
|
RTCError OrtcFactory::Initialize(
|
|
std::unique_ptr<cricket::MediaEngineInterface> media_engine) {
|
|
RTC_DCHECK_RUN_ON(signaling_thread_);
|
|
// TODO(deadbeef): Get rid of requirement to hop to worker thread here.
|
|
if (!media_engine) {
|
|
media_engine =
|
|
worker_thread_->Invoke<std::unique_ptr<cricket::MediaEngineInterface>>(
|
|
RTC_FROM_HERE, rtc::Bind(&OrtcFactory::CreateMediaEngine_w, this));
|
|
}
|
|
|
|
channel_manager_.reset(new cricket::ChannelManager(
|
|
std::move(media_engine), worker_thread_.get(), network_thread_));
|
|
channel_manager_->SetVideoRtxEnabled(true);
|
|
if (!channel_manager_->Init()) {
|
|
LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
|
|
"Failed to initialize ChannelManager.");
|
|
}
|
|
return RTCError::OK();
|
|
}
|
|
|
|
std::unique_ptr<cricket::MediaEngineInterface>
|
|
OrtcFactory::CreateMediaEngine_w() {
|
|
RTC_DCHECK_RUN_ON(worker_thread_.get());
|
|
// The null arguments are optional factories that could be passed into the
|
|
// OrtcFactory, but aren't yet.
|
|
//
|
|
// Note that |adm_| may be null, in which case the platform-specific default
|
|
// AudioDeviceModule will be used.
|
|
return std::unique_ptr<cricket::MediaEngineInterface>(
|
|
cricket::WebRtcMediaEngineFactory::Create(adm_, audio_decoder_factory_,
|
|
nullptr, nullptr, nullptr));
|
|
}
|
|
|
|
} // namespace webrtc
|