Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: webrtc/ortc/ortcfactory.cc

Issue 2675173003: Adding "adapter" ORTC objects on top of ChannelManager/BaseChannel/etc. (Closed)
Patch Set: Rebase onto split-off RtcError CL Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/ortc/ortcfactory.h ('k') | webrtc/ortc/ortcfactory_integrationtest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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) {
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") {
44 if (cricket_feedback.param() == "fir") {
45 codec->rtcp_feedback.emplace_back(webrtc::RtcpFeedbackType::CCM,
46 webrtc::RtcpFeedbackMessageType::FIR);
47 } else {
48 RTC_NOTREACHED();
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 }
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) {
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") {
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.MoveValue());
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
OLDNEW
« no previous file with comments | « webrtc/ortc/ortcfactory.h ('k') | webrtc/ortc/ortcfactory_integrationtest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698