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

Powered by Google App Engine
This is Rietveld 408576698