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

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

Issue 2675173003: Adding "adapter" ORTC objects on top of ChannelManager/BaseChannel/etc. (Closed)
Patch Set: Move ORTC files to different subdirectories 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
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_METHOD3(RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>,
149 CreateRtpSender,
150 rtc::scoped_refptr<MediaStreamTrackInterface>,
151 const RtpParameters&,
152 RtpTransportInterface*)
153 PROXY_METHOD3(RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>,
154 CreateRtpSender,
155 cricket::MediaType,
156 const RtpParameters&,
157 RtpTransportInterface*)
158 PROXY_CONSTMETHOD1(RtpCapabilities,
159 GetRtpReceiverCapabilities,
160 cricket::MediaType)
161 PROXY_METHOD3(RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>>,
162 CreateRtpReceiver,
163 cricket::MediaType,
164 const RtpParameters&,
165 RtpTransportInterface*)
166 PROXY_WORKER_METHOD3(RTCErrorOr<std::unique_ptr<UdpTransportInterface>>,
167 CreateUdpTransport,
168 int,
169 uint16_t,
170 uint16_t)
171 PROXY_METHOD1(rtc::scoped_refptr<AudioSourceInterface>,
172 CreateAudioSource,
173 const cricket::AudioOptions&)
174 PROXY_METHOD2(rtc::scoped_refptr<VideoTrackSourceInterface>,
175 CreateVideoSource,
176 std::unique_ptr<cricket::VideoCapturer>,
177 const MediaConstraintsInterface*)
178 PROXY_METHOD2(rtc::scoped_refptr<VideoTrackInterface>,
179 CreateVideoTrack,
180 const std::string&,
181 VideoTrackSourceInterface*)
182 PROXY_METHOD2(rtc::scoped_refptr<AudioTrackInterface>,
183 CreateAudioTrack,
184 const std::string&,
185 AudioSourceInterface*)
186 END_PROXY_MAP()
187
188 // static
189 RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> OrtcFactoryInterface::Create(
190 rtc::Thread* network_thread,
191 rtc::Thread* signaling_thread,
192 rtc::NetworkManager* network_manager,
193 rtc::PacketSocketFactory* socket_factory,
194 AudioDeviceModule* adm) {
195 // Hop to signaling thread if needed.
196 if (signaling_thread && !signaling_thread->IsCurrent()) {
197 return signaling_thread
198 ->Invoke<RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>>>(
199 RTC_FROM_HERE,
200 rtc::Bind(&OrtcFactoryInterface::Create, network_thread,
201 signaling_thread, network_manager, socket_factory, adm));
202 }
203 std::unique_ptr<OrtcFactory> new_factory(new OrtcFactory(
204 network_thread, signaling_thread, network_manager, socket_factory, adm));
205 RTCError err = new_factory->Initialize();
206 if (!err.ok()) {
207 return err;
208 }
209 // Return a proxy so that any calls on the returned object (including
210 // destructor) happen on the signaling thread.
211 return OrtcFactoryProxy::Create(new_factory->signaling_thread(),
212 new_factory->network_thread(),
213 new_factory.release());
214 }
215
216 OrtcFactory::OrtcFactory(rtc::Thread* network_thread,
217 rtc::Thread* signaling_thread,
218 rtc::NetworkManager* network_manager,
219 rtc::PacketSocketFactory* socket_factory,
220 AudioDeviceModule* adm)
221 : network_thread_(network_thread),
222 signaling_thread_(signaling_thread),
223 network_manager_(network_manager),
224 socket_factory_(socket_factory),
225 adm_(adm),
226 null_event_log_(RtcEventLog::CreateNull()),
227 audio_decoder_factory_(CreateBuiltinAudioDecoderFactory()) {
228 if (!network_thread_) {
229 owned_network_thread_ = rtc::Thread::CreateWithSocketServer();
230 owned_network_thread_->Start();
231 network_thread_ = owned_network_thread_.get();
232 }
233
234 // The worker thread is created internally because it's an implementation
235 // detail, and consumers of the API don't need to really know about it.
236 worker_thread_ = rtc::Thread::Create();
237 worker_thread_->Start();
238
239 if (signaling_thread_) {
240 RTC_DCHECK_RUN_ON(signaling_thread_);
241 } else {
242 signaling_thread_ = rtc::Thread::Current();
243 if (!signaling_thread_) {
244 // If this thread isn't already wrapped by an rtc::Thread, create a
245 // wrapper and own it in this class.
246 signaling_thread_ = rtc::ThreadManager::Instance()->WrapCurrentThread();
247 wraps_signaling_thread_ = true;
248 }
249 }
250 if (!network_manager_) {
251 owned_network_manager_.reset(new rtc::BasicNetworkManager());
252 network_manager_ = owned_network_manager_.get();
253 }
254 if (!socket_factory_) {
255 owned_socket_factory_.reset(
256 new rtc::BasicPacketSocketFactory(network_thread_));
257 socket_factory_ = owned_socket_factory_.get();
258 }
259 }
260
261 OrtcFactory::~OrtcFactory() {
262 RTC_DCHECK_RUN_ON(signaling_thread_);
263 if (wraps_signaling_thread_) {
264 rtc::ThreadManager::Instance()->UnwrapCurrentThread();
265 }
266 }
267
268 RTCErrorOr<std::unique_ptr<RtpTransportControllerInterface>>
269 OrtcFactory::CreateRtpTransportController() {
270 return RtpTransportControllerShim::CreateProxied(
271 cricket::MediaConfig(), channel_manager_.get(), null_event_log_.get(),
272 signaling_thread_, worker_thread_.get());
273 }
274
275 RTCErrorOr<std::unique_ptr<RtpTransportInterface>>
276 OrtcFactory::CreateRtpTransport(
277 const RtcpParameters& rtcp_parameters,
278 PacketTransportInterface* rtp,
279 PacketTransportInterface* rtcp,
280 RtpTransportControllerInterface* transport_controller) {
281 return RtpTransportShim::CreateProxied(rtcp_parameters, rtp, rtcp,
282 transport_controller);
283 }
284
285 RtpCapabilities OrtcFactory::GetRtpSenderCapabilities(
286 cricket::MediaType kind) const {
287 switch (kind) {
288 case cricket::MEDIA_TYPE_AUDIO: {
289 cricket::AudioCodecs cricket_codecs;
290 cricket::RtpHeaderExtensions cricket_extensions;
291 channel_manager_->GetSupportedAudioSendCodecs(&cricket_codecs);
292 channel_manager_->GetSupportedAudioRtpHeaderExtensions(
293 &cricket_extensions);
294 return ConvertCapabilities(kind, cricket_codecs, cricket_extensions);
295 }
296 case cricket::MEDIA_TYPE_VIDEO: {
297 cricket::VideoCodecs cricket_codecs;
298 cricket::RtpHeaderExtensions cricket_extensions;
299 channel_manager_->GetSupportedVideoCodecs(&cricket_codecs);
300 channel_manager_->GetSupportedVideoRtpHeaderExtensions(
301 &cricket_extensions);
302 return ConvertCapabilities(kind, cricket_codecs, cricket_extensions);
303 }
304 case cricket::MEDIA_TYPE_DATA:
305 return RtpCapabilities();
306 }
307 }
308
309 RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>
310 OrtcFactory::CreateRtpSender(
311 rtc::scoped_refptr<MediaStreamTrackInterface> track,
312 const RtpParameters& rtp_parameters,
313 RtpTransportInterface* transport) {
314 if (!track) {
315 return CreateAndLogError(RTCErrorType::INVALID_PARAMETER,
316 "Cannot pass null track into CreateRtpSender.");
317 }
318 auto result = CreateRtpSender(cricket::MediaTypeFromString(track->kind()),
319 rtp_parameters, transport);
320 if (!result.ok()) {
321 return result;
322 }
323 auto err = result.value()->SetTrack(track);
324 if (!err.ok()) {
325 return err;
326 }
327 return result;
328 }
329
330 RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>
331 OrtcFactory::CreateRtpSender(cricket::MediaType kind,
332 const RtpParameters& rtp_parameters,
333 RtpTransportInterface* transport) {
334 if (kind == cricket::MEDIA_TYPE_DATA) {
335 return CreateAndLogError(RTCErrorType::INVALID_PARAMETER,
336 "Cannot create data RtpSender.");
337 }
338 if (!transport) {
339 return CreateAndLogError(
340 RTCErrorType::INVALID_PARAMETER,
341 "Cannot pass null transport into CreateRtpSender.");
342 }
343 return RtpSenderShim::CreateProxied(kind, rtp_parameters,
344 transport->GetInternal());
345 }
346
347 RtpCapabilities OrtcFactory::GetRtpReceiverCapabilities(
348 cricket::MediaType kind) const {
349 switch (kind) {
350 case cricket::MEDIA_TYPE_AUDIO: {
351 cricket::AudioCodecs cricket_codecs;
352 cricket::RtpHeaderExtensions cricket_extensions;
353 channel_manager_->GetSupportedAudioReceiveCodecs(&cricket_codecs);
354 channel_manager_->GetSupportedAudioRtpHeaderExtensions(
355 &cricket_extensions);
356 return ConvertCapabilities(kind, cricket_codecs, cricket_extensions);
357 }
358 case cricket::MEDIA_TYPE_VIDEO: {
359 cricket::VideoCodecs cricket_codecs;
360 cricket::RtpHeaderExtensions cricket_extensions;
361 channel_manager_->GetSupportedVideoCodecs(&cricket_codecs);
362 channel_manager_->GetSupportedVideoRtpHeaderExtensions(
363 &cricket_extensions);
364 return ConvertCapabilities(kind, cricket_codecs, cricket_extensions);
365 }
366 case cricket::MEDIA_TYPE_DATA:
367 return RtpCapabilities();
368 }
369 }
370
371 RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>>
372 OrtcFactory::CreateRtpReceiver(cricket::MediaType kind,
373 const RtpParameters& rtp_parameters,
374 RtpTransportInterface* transport) {
375 if (kind == cricket::MEDIA_TYPE_DATA) {
376 return CreateAndLogError(RTCErrorType::INVALID_PARAMETER,
377 "Cannot create data RtpReceiver.");
378 }
379 if (!transport) {
380 return CreateAndLogError(
381 RTCErrorType::INVALID_PARAMETER,
382 "Cannot pass null transport into CreateRtpReceiver.");
383 }
384 return RtpReceiverShim::CreateProxied(kind, rtp_parameters,
385 transport->GetInternal());
386 }
387
388 BEGIN_OWNED_PROXY_MAP(UdpTransport)
389 PROXY_WORKER_THREAD_DESTRUCTOR()
390 PROXY_WORKER_CONSTMETHOD0(rtc::SocketAddress, GetLocalAddress)
391 PROXY_WORKER_METHOD1(bool, SetRemoteAddress, const rtc::SocketAddress&)
392 PROXY_WORKER_CONSTMETHOD0(rtc::SocketAddress, GetRemoteAddress)
393 protected:
394 rtc::PacketTransportInternal* GetInternal() override {
395 return internal();
396 }
397 END_PROXY_MAP()
398
399 RTCErrorOr<std::unique_ptr<UdpTransportInterface>>
400 OrtcFactory::CreateUdpTransport(int family,
401 uint16_t min_port,
402 uint16_t max_port) {
403 RTC_DCHECK_RUN_ON(network_thread_);
404 std::unique_ptr<rtc::AsyncPacketSocket> socket(
405 socket_factory_->CreateUdpSocket(
406 rtc::SocketAddress(rtc::GetAnyIP(family), 0), min_port, max_port));
407 if (!socket) {
408 // Only log at warning level, because this method may be called with
409 // specific port ranges to determine if a port is available, expecting the
410 // possibility of an error.
411 return CreateAndLogError(RTCErrorType::RESOURCE_EXHAUSTED,
412 "Local socket allocation failure.",
413 rtc::LS_WARNING);
414 }
415 LOG(LS_INFO) << "Created UDP socket with address "
416 << socket->GetLocalAddress().ToSensitiveString() << ".";
417 // Use proxy so that calls to the returned object are invoked on the network
418 // thread.
419 return UdpTransportProxyWithInternal<cricket::UdpTransport>::Create(
420 signaling_thread_, network_thread_,
421 new cricket::UdpTransport(std::string(), std::move(socket)));
422 }
423
424 rtc::scoped_refptr<AudioSourceInterface> OrtcFactory::CreateAudioSource(
425 const cricket::AudioOptions& options) {
426 RTC_DCHECK_RUN_ON(signaling_thread_);
427 return rtc::scoped_refptr<LocalAudioSource>(
428 LocalAudioSource::Create(&options));
429 }
430
431 rtc::scoped_refptr<VideoTrackSourceInterface> OrtcFactory::CreateVideoSource(
432 std::unique_ptr<cricket::VideoCapturer> capturer,
433 const MediaConstraintsInterface* constraints) {
434 RTC_DCHECK_RUN_ON(signaling_thread_);
435 rtc::scoped_refptr<VideoTrackSourceInterface> source(
436 VideoCapturerTrackSource::Create(
437 worker_thread_.get(), std::move(capturer), constraints, false));
438 return VideoTrackSourceProxy::Create(signaling_thread_, worker_thread_.get(),
439 source);
440 }
441
442 rtc::scoped_refptr<VideoTrackInterface> OrtcFactory::CreateVideoTrack(
443 const std::string& id,
444 VideoTrackSourceInterface* source) {
445 RTC_DCHECK_RUN_ON(signaling_thread_);
446 rtc::scoped_refptr<VideoTrackInterface> track(VideoTrack::Create(id, source));
447 return VideoTrackProxy::Create(signaling_thread_, worker_thread_.get(),
448 track);
449 }
450
451 rtc::scoped_refptr<AudioTrackInterface> OrtcFactory::CreateAudioTrack(
452 const std::string& id,
453 AudioSourceInterface* source) {
454 RTC_DCHECK_RUN_ON(signaling_thread_);
455 rtc::scoped_refptr<AudioTrackInterface> track(AudioTrack::Create(id, source));
456 return AudioTrackProxy::Create(signaling_thread_, track);
457 }
458
459 RTCError OrtcFactory::Initialize() {
460 // TODO(deadbeef): Get rid of requirement to hop to worker thread here.
461 std::unique_ptr<cricket::MediaEngineInterface> media_engine =
462 worker_thread_->Invoke<std::unique_ptr<cricket::MediaEngineInterface>>(
463 RTC_FROM_HERE, rtc::Bind(&OrtcFactory::CreateMediaEngine_w, this));
464
465 channel_manager_.reset(new cricket::ChannelManager(
466 std::move(media_engine), worker_thread_.get(), network_thread_));
467 channel_manager_->SetVideoRtxEnabled(true);
468 if (!channel_manager_->Init()) {
469 return CreateAndLogError(RTCErrorType::INTERNAL_ERROR,
470 "Failed to initialize ChannelManager.");
471 }
472 return RTCError();
473 }
474
475 std::unique_ptr<cricket::MediaEngineInterface>
476 OrtcFactory::CreateMediaEngine_w() {
477 RTC_DCHECK_RUN_ON(worker_thread_.get());
478 // The nullptr arguments are optional factories that could be passed into the
479 // OrtcFactory, but aren't yet.
480 // Note that |adm_| may be null.
481 return cricket::WebRtcMediaEngineFactory::Create(adm_, audio_decoder_factory_,
482 nullptr, nullptr, nullptr);
483 }
484
485 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698