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

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

Issue 2675173003: Adding "adapter" ORTC objects on top of ChannelManager/BaseChannel/etc. (Closed)
Patch Set: More sender/receiver 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/rtptransportcontrolleradapter.h"
12
13 #include <algorithm> // For "remove", "find".
14 #include <utility> // For std::move.
15
16 #include "webrtc/api/proxy.h"
17 #include "webrtc/base/checks.h"
18 #include "webrtc/media/base/mediaconstants.h"
19 #include "webrtc/ortc/ortcrtpreceiveradapter.h"
20 #include "webrtc/ortc/ortcrtpsenderadapter.h"
21 #include "webrtc/ortc/rtpparametersconversion.h"
22 #include "webrtc/ortc/rtptransportadapter.h"
23
24 namespace webrtc {
25
26 BEGIN_OWNED_PROXY_MAP(RtpTransportController)
27 PROXY_SIGNALING_THREAD_DESTRUCTOR()
28 PROXY_CONSTMETHOD0(std::vector<RtpTransportInterface*>, GetTransports)
29 protected:
30 RtpTransportControllerAdapter* GetInternal() override {
31 return internal();
32 }
33 END_PROXY_MAP()
34
35 // static
36 std::unique_ptr<RtpTransportControllerInterface>
37 RtpTransportControllerAdapter::CreateProxied(
38 const cricket::MediaConfig& config,
39 cricket::ChannelManager* channel_manager,
40 webrtc::RtcEventLog* event_log,
41 rtc::Thread* signaling_thread,
42 rtc::Thread* worker_thread) {
43 RtpTransportControllerAdapter* wrapped = new RtpTransportControllerAdapter(
44 config, channel_manager, event_log, signaling_thread, worker_thread);
45 return RtpTransportControllerProxyWithInternal<
46 RtpTransportControllerAdapter>::Create(signaling_thread, worker_thread,
47 wrapped);
48 }
49
50 RtpTransportControllerAdapter::~RtpTransportControllerAdapter() {
51 RTC_DCHECK_RUN_ON(signaling_thread_);
52 if (!transport_proxies_.empty()) {
53 LOG(LS_ERROR)
54 << "Destroying RtpTransportControllerAdapter while RtpTransports "
55 "are still using it; this is unsafe.";
56 }
57 if (voice_channel_) {
58 // This would mean audio RTP senders/receivers that are using us haven't
59 // been destroyed. This isn't safe (see error log above).
60 DestroyVoiceChannel();
61 }
62 if (voice_channel_) {
63 // This would mean video RTP senders/receivers that are using us haven't
64 // been destroyed. This isn't safe (see error log above).
65 DestroyVideoChannel();
66 }
67 }
68
69 RTCErrorOr<std::unique_ptr<OrtcRtpSenderInterface>>
70 RtpTransportControllerAdapter::CreateProxiedRtpSender(
71 cricket::MediaType kind,
72 RtpTransportInterface* transport_proxy) {
73 RTC_DCHECK(transport_proxy);
74 RTC_DCHECK(std::find(transport_proxies_.begin(), transport_proxies_.end(),
75 transport_proxy) != transport_proxies_.end());
76 std::unique_ptr<OrtcRtpSenderAdapter> new_sender(
77 new OrtcRtpSenderAdapter(kind, transport_proxy, this));
78 RTCError err;
79 switch (kind) {
80 case cricket::MEDIA_TYPE_AUDIO:
81 err = AttachAudioSender(new_sender.get(), transport_proxy->GetInternal());
82 break;
83 case cricket::MEDIA_TYPE_VIDEO:
84 err = AttachVideoSender(new_sender.get(), transport_proxy->GetInternal());
85 break;
86 case cricket::MEDIA_TYPE_DATA:
87 RTC_NOTREACHED();
88 }
89 if (!err.ok()) {
90 return err;
91 }
92
93 return OrtcRtpSenderAdapter::CreateProxy(std::move(new_sender));
94 }
95
96 RTCErrorOr<std::unique_ptr<OrtcRtpReceiverInterface>>
97 RtpTransportControllerAdapter::CreateProxiedRtpReceiver(
98 cricket::MediaType kind,
99 RtpTransportInterface* transport_proxy) {
100 RTC_DCHECK(transport_proxy);
101 RTC_DCHECK(std::find(transport_proxies_.begin(), transport_proxies_.end(),
102 transport_proxy) != transport_proxies_.end());
103 std::unique_ptr<OrtcRtpReceiverAdapter> new_receiver(
104 new OrtcRtpReceiverAdapter(kind, transport_proxy, this));
105 RTCError err;
106 switch (kind) {
107 case cricket::MEDIA_TYPE_AUDIO:
108 err = AttachAudioReceiver(new_receiver.get(),
109 transport_proxy->GetInternal());
110 break;
111 case cricket::MEDIA_TYPE_VIDEO:
112 err = AttachVideoReceiver(new_receiver.get(),
113 transport_proxy->GetInternal());
114 break;
115 case cricket::MEDIA_TYPE_DATA:
116 RTC_NOTREACHED();
117 }
118 if (!err.ok()) {
119 return err;
120 }
121
122 return OrtcRtpReceiverAdapter::CreateProxy(std::move(new_receiver));
123 }
124
125 std::vector<RtpTransportInterface*>
126 RtpTransportControllerAdapter::GetTransports() const {
127 RTC_DCHECK_RUN_ON(signaling_thread_);
128 return transport_proxies_;
129 }
130
131 void RtpTransportControllerAdapter::AddTransport(
132 RtpTransportInterface* transport_proxy) {
133 RTC_DCHECK_RUN_ON(signaling_thread_);
134 transport_proxies_.push_back(transport_proxy);
135 }
136
137 void RtpTransportControllerAdapter::RemoveTransport(
138 RtpTransportAdapter* inner_transport) {
139 RTC_DCHECK_RUN_ON(signaling_thread_);
140 auto it = std::find_if(transport_proxies_.begin(), transport_proxies_.end(),
141 [inner_transport](RtpTransportInterface* proxy) {
142 return proxy->GetInternal() == inner_transport;
143 });
144 if (it == transport_proxies_.end()) {
145 RTC_NOTREACHED();
146 return;
147 }
148 transport_proxies_.erase(it);
149 }
150
151 RTCError RtpTransportControllerAdapter::SetRtcpParameters(
152 const RtcpParameters& parameters,
153 RtpTransportInterface* inner_transport) {
154 if (inner_transport == inner_audio_transport_) {
155 CopyRtcpParametersToDescriptions(parameters, &local_audio_description_,
156 &remote_audio_description_);
157 if (!voice_channel_->SetLocalContent(&local_audio_description_,
158 cricket::CA_OFFER, nullptr)) {
159 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
160 "Failed to apply new RTCP parameters.");
161 }
162 if (!voice_channel_->SetRemoteContent(&remote_audio_description_,
163 cricket::CA_ANSWER, nullptr)) {
164 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
165 "Failed to apply new RTCP parameters.");
166 }
167 } else if (inner_transport == inner_video_transport_) {
168 CopyRtcpParametersToDescriptions(parameters, &local_video_description_,
169 &remote_video_description_);
170 if (!video_channel_->SetLocalContent(&local_video_description_,
171 cricket::CA_OFFER, nullptr)) {
172 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
173 "Failed to apply new RTCP parameters.");
174 }
175 if (!video_channel_->SetRemoteContent(&remote_video_description_,
176 cricket::CA_ANSWER, nullptr)) {
177 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
178 "Failed to apply new RTCP parameters.");
179 }
180 }
181 return RTCError::OK();
182 }
183
184 RTCError RtpTransportControllerAdapter::ValidateAndApplyAudioSenderParameters(
185 const RtpParameters& parameters,
186 uint32_t* primary_ssrc) {
187 RTC_DCHECK(voice_channel_);
188 RTC_DCHECK(have_audio_sender_);
189
190 auto codecs_result = ToCricketCodecs<cricket::AudioCodec>(parameters.codecs);
191 if (!codecs_result.ok()) {
192 return codecs_result.MoveError();
193 }
194
195 auto extensions_result = ToRtpHeaderExtensions(parameters.header_extensions);
196 if (!extensions_result.ok()) {
197 return extensions_result.MoveError();
198 }
199
200 auto stream_params_result = MakeSendStreamParamsVec(
201 parameters.encodings, inner_audio_transport_->GetRtcpParameters().cname,
202 local_audio_description_);
203 if (!stream_params_result.ok()) {
204 return stream_params_result.MoveError();
205 }
206
207 cricket::RtpTransceiverDirection local_direction =
208 cricket::RtpTransceiverDirection::FromMediaContentDirection(
209 local_audio_description_.direction());
210 int bandwidth = cricket::kAutoBandwidth;
211 if (parameters.encodings.size() == 1u) {
212 if (parameters.encodings[0].max_bitrate_bps) {
213 bandwidth = *parameters.encodings[0].max_bitrate_bps;
214 }
215 local_direction.send = parameters.encodings[0].active;
216 } else {
217 local_direction.send = false;
218 }
219 if (primary_ssrc && !stream_params_result.value().empty()) {
220 *primary_ssrc = stream_params_result.value()[0].first_ssrc();
221 }
222
223 // Validation is done, so we can attempt applying the descriptions. Sent
224 // codecs and header extensions go in remote description, streams go in
225 // local.
226 //
227 // If there are no codecs or encodings, just leave the previous set of
228 // codecs. The media engine doesn't like an empty set of codecs.
229 if (local_audio_description_.streams().empty() &&
230 remote_audio_description_.codecs().empty()) {
231 } else {
232 remote_audio_description_.set_codecs(codecs_result.MoveValue());
233 }
234 remote_audio_description_.set_rtp_header_extensions(
235 extensions_result.MoveValue());
236 remote_audio_description_.set_bandwidth(bandwidth);
237 local_audio_description_.mutable_streams() = stream_params_result.MoveValue();
238 // Direction set based on encoding "active" flag.
239 local_audio_description_.set_direction(
240 local_direction.ToMediaContentDirection());
241 remote_audio_description_.set_direction(
242 local_direction.Reversed().ToMediaContentDirection());
243
244 // Set remote content first, to ensure the stream is created with the correct
245 // codec.
246 if (!voice_channel_->SetRemoteContent(&remote_audio_description_,
247 cricket::CA_OFFER, nullptr)) {
248 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
249 "Failed to apply remote parameters to media channel.");
250 }
251 if (!voice_channel_->SetLocalContent(&local_audio_description_,
252 cricket::CA_ANSWER, nullptr)) {
253 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
254 "Failed to apply local parameters to media channel.");
255 }
256 return RTCError::OK();
257 }
258
259 RTCError RtpTransportControllerAdapter::ValidateAndApplyVideoSenderParameters(
260 const RtpParameters& parameters,
261 uint32_t* primary_ssrc) {
262 RTC_DCHECK(video_channel_);
263 RTC_DCHECK(have_video_sender_);
264
265 auto codecs_result = ToCricketCodecs<cricket::VideoCodec>(parameters.codecs);
266 if (!codecs_result.ok()) {
267 return codecs_result.MoveError();
268 }
269
270 auto extensions_result = ToRtpHeaderExtensions(parameters.header_extensions);
271 if (!extensions_result.ok()) {
272 return extensions_result.MoveError();
273 }
274
275 auto stream_params_result = MakeSendStreamParamsVec(
276 parameters.encodings, inner_video_transport_->GetRtcpParameters().cname,
277 local_video_description_);
278 if (!stream_params_result.ok()) {
279 return stream_params_result.MoveError();
280 }
281
282 cricket::RtpTransceiverDirection local_direction =
283 cricket::RtpTransceiverDirection::FromMediaContentDirection(
284 local_video_description_.direction());
285 int bandwidth = cricket::kAutoBandwidth;
286 if (parameters.encodings.size() == 1u) {
287 if (parameters.encodings[0].max_bitrate_bps) {
288 bandwidth = *parameters.encodings[0].max_bitrate_bps;
289 }
290 local_direction.send = parameters.encodings[0].active;
291 } else {
292 local_direction.send = false;
293 }
294 if (primary_ssrc && !stream_params_result.value().empty()) {
295 *primary_ssrc = stream_params_result.value()[0].first_ssrc();
296 }
297
298 // Validation is done, so we can attempt applying the descriptions. Sent
299 // codecs and header extensions go in remote description, streams go in
300 // local.
301 //
302 // If there are no codecs or encodings, just leave the previous set of
303 // codecs. The media engine doesn't like an empty set of codecs.
304 if (local_video_description_.streams().empty() &&
305 remote_video_description_.codecs().empty()) {
306 } else {
307 remote_video_description_.set_codecs(codecs_result.MoveValue());
308 }
309 remote_video_description_.set_rtp_header_extensions(
310 extensions_result.MoveValue());
311 remote_video_description_.set_bandwidth(bandwidth);
312 local_video_description_.mutable_streams() = stream_params_result.MoveValue();
313 // Direction set based on encoding "active" flag.
314 local_video_description_.set_direction(
315 local_direction.ToMediaContentDirection());
316 remote_video_description_.set_direction(
317 local_direction.Reversed().ToMediaContentDirection());
318
319 // Set remote content first, to ensure the stream is created with the correct
320 // codec.
321 if (!video_channel_->SetRemoteContent(&remote_video_description_,
322 cricket::CA_OFFER, nullptr)) {
323 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
324 "Failed to apply remote parameters to media channel.");
325 }
326 if (!video_channel_->SetLocalContent(&local_video_description_,
327 cricket::CA_ANSWER, nullptr)) {
328 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
329 "Failed to apply local parameters to media channel.");
330 }
331 return RTCError::OK();
332 }
333
334 RTCError RtpTransportControllerAdapter::ValidateAndApplyAudioReceiverParameters(
335 const RtpParameters& parameters) {
336 RTC_DCHECK(voice_channel_);
337 RTC_DCHECK(have_audio_receiver_);
338
339 auto codecs_result = ToCricketCodecs<cricket::AudioCodec>(parameters.codecs);
340 if (!codecs_result.ok()) {
341 return codecs_result.MoveError();
342 }
343
344 auto extensions_result = ToRtpHeaderExtensions(parameters.header_extensions);
345 if (!extensions_result.ok()) {
346 return extensions_result.MoveError();
347 }
348
349 cricket::RtpTransceiverDirection local_direction =
350 cricket::RtpTransceiverDirection::FromMediaContentDirection(
351 local_audio_description_.direction());
352 auto stream_params_result = ToStreamParamsVec(parameters.encodings);
353 if (!stream_params_result.ok()) {
354 return stream_params_result.MoveError();
355 }
356 local_direction.recv =
357 !parameters.encodings.empty() && parameters.encodings[0].active;
358
359 // Validation is done, so we can attempt applying the descriptions. Received
360 // codecs and header extensions go in local description, streams go in
361 // remote.
362 //
363 // If there are no codecs or encodings, just leave the previous set of
364 // codecs. The media engine doesn't like an empty set of codecs.
365 if (remote_audio_description_.streams().empty() &&
366 local_audio_description_.codecs().empty()) {
367 } else {
368 local_audio_description_.set_codecs(codecs_result.MoveValue());
369 }
370 local_audio_description_.set_rtp_header_extensions(
371 extensions_result.MoveValue());
372 remote_audio_description_.mutable_streams() =
373 stream_params_result.MoveValue();
374 // Direction set based on encoding "active" flag.
375 local_audio_description_.set_direction(
376 local_direction.ToMediaContentDirection());
377 remote_audio_description_.set_direction(
378 local_direction.Reversed().ToMediaContentDirection());
379
380 if (!voice_channel_->SetLocalContent(&local_audio_description_,
381 cricket::CA_OFFER, nullptr)) {
382 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
383 "Failed to apply local parameters to media channel.");
384 }
385 if (!voice_channel_->SetRemoteContent(&remote_audio_description_,
386 cricket::CA_ANSWER, nullptr)) {
387 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
388 "Failed to apply remote parameters to media channel.");
389 }
390 return RTCError::OK();
391 }
392
393 RTCError RtpTransportControllerAdapter::ValidateAndApplyVideoReceiverParameters(
394 const RtpParameters& parameters) {
395 RTC_DCHECK(video_channel_);
396 RTC_DCHECK(have_video_receiver_);
397
398 auto codecs_result = ToCricketCodecs<cricket::VideoCodec>(parameters.codecs);
399 if (!codecs_result.ok()) {
400 return codecs_result.MoveError();
401 }
402
403 auto extensions_result = ToRtpHeaderExtensions(parameters.header_extensions);
404 if (!extensions_result.ok()) {
405 return extensions_result.MoveError();
406 }
407
408 cricket::RtpTransceiverDirection local_direction =
409 cricket::RtpTransceiverDirection::FromMediaContentDirection(
410 local_video_description_.direction());
411 int bandwidth = cricket::kAutoBandwidth;
412 auto stream_params_result = ToStreamParamsVec(parameters.encodings);
413 if (!stream_params_result.ok()) {
414 return stream_params_result.MoveError();
415 }
416 local_direction.recv =
417 !parameters.encodings.empty() && parameters.encodings[0].active;
418
419 // Validation is done, so we can attempt applying the descriptions. Received
420 // codecs and header extensions go in local description, streams go in
421 // remote.
422 //
423 // If there are no codecs or encodings, just leave the previous set of
424 // codecs. The media engine doesn't like an empty set of codecs.
425 if (remote_video_description_.streams().empty() &&
426 local_video_description_.codecs().empty()) {
427 } else {
428 local_video_description_.set_codecs(codecs_result.MoveValue());
429 }
430 local_video_description_.set_rtp_header_extensions(
431 extensions_result.MoveValue());
432 local_video_description_.set_bandwidth(bandwidth);
433 remote_video_description_.mutable_streams() =
434 stream_params_result.MoveValue();
435 // Direction set based on encoding "active" flag.
436 local_video_description_.set_direction(
437 local_direction.ToMediaContentDirection());
438 remote_video_description_.set_direction(
439 local_direction.Reversed().ToMediaContentDirection());
440
441 if (!video_channel_->SetLocalContent(&local_video_description_,
442 cricket::CA_OFFER, nullptr)) {
443 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
444 "Failed to apply local parameters to media channel.");
445 }
446 if (!video_channel_->SetRemoteContent(&remote_video_description_,
447 cricket::CA_ANSWER, nullptr)) {
448 LOG_AND_RETURN_ERROR(RTCErrorType::INTERNAL_ERROR,
449 "Failed to apply remote parameters to media channel.");
450 }
451 return RTCError::OK();
452 }
453
454 RtpTransportControllerAdapter::RtpTransportControllerAdapter(
455 const cricket::MediaConfig& config,
456 cricket::ChannelManager* channel_manager,
457 webrtc::RtcEventLog* event_log,
458 rtc::Thread* signaling_thread,
459 rtc::Thread* worker_thread)
460 : signaling_thread_(signaling_thread),
461 worker_thread_(worker_thread),
462 media_controller_(MediaControllerInterface::Create(config,
463 worker_thread,
464 channel_manager,
465 event_log)) {
466 RTC_DCHECK_RUN_ON(signaling_thread_);
467 RTC_DCHECK(channel_manager);
468 // MediaControllerInterface::Create should never fail.
469 RTC_DCHECK(media_controller_);
470 static const cricket::AudioCodec dummy_audio(0, cricket::kPcmuCodecName, 8000,
471 0, 1);
472 static const cricket::VideoCodec dummy_video(96, cricket::kVp8CodecName);
473 local_audio_description_.AddCodec(dummy_audio);
474 remote_audio_description_.AddCodec(dummy_audio);
475 local_video_description_.AddCodec(dummy_video);
476 remote_video_description_.AddCodec(dummy_video);
477 }
478
479 void RtpTransportControllerAdapter::OnAudioSenderDestroyed() {
480 if (!have_audio_sender_) {
481 RTC_NOTREACHED();
482 return;
483 }
484 // Empty parameters should result in sending being stopped.
485 RTCError err =
486 ValidateAndApplyAudioSenderParameters(RtpParameters(), nullptr);
487 RTC_DCHECK(err.ok());
488 have_audio_sender_ = false;
489 if (!have_audio_receiver_) {
490 DestroyVoiceChannel();
491 }
492 }
493
494 void RtpTransportControllerAdapter::OnVideoSenderDestroyed() {
495 if (!have_video_sender_) {
496 RTC_NOTREACHED();
497 return;
498 }
499 // Empty parameters should result in sending being stopped.
500 RTCError err =
501 ValidateAndApplyVideoSenderParameters(RtpParameters(), nullptr);
502 RTC_DCHECK(err.ok());
503 have_video_sender_ = false;
504 if (!have_video_receiver_) {
505 DestroyVideoChannel();
506 }
507 }
508
509 RTCError RtpTransportControllerAdapter::AttachAudioSender(
510 OrtcRtpSenderAdapter* sender,
511 RtpTransportInterface* inner_transport) {
512 if (have_audio_sender_) {
513 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
514 "Using two audio RtpSenders with the same "
515 "RtpTransportControllerAdapter is not currently "
516 "supported.");
517 }
518 if (inner_audio_transport_ && inner_audio_transport_ != inner_transport) {
519 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
520 "Using different transports for the audio "
521 "RtpSender and RtpReceiver is not currently "
522 "supported.");
523 }
524 // If setting new transport, extract its RTCP parameters and create voice
525 // channel.
526 if (!inner_audio_transport_) {
527 CopyRtcpParametersToDescriptions(inner_transport->GetRtcpParameters(),
528 &local_audio_description_,
529 &remote_audio_description_);
530 inner_audio_transport_ = inner_transport;
531 CreateVoiceChannel();
532 }
533 have_audio_sender_ = true;
534 sender->SignalDestroyed.connect(
535 this, &RtpTransportControllerAdapter::OnAudioSenderDestroyed);
536 return RTCError::OK();
537 }
538
539 RTCError RtpTransportControllerAdapter::AttachVideoSender(
540 OrtcRtpSenderAdapter* sender,
541 RtpTransportInterface* inner_transport) {
542 if (have_video_sender_) {
543 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
544 "Using two video RtpSenders with the same "
545 "RtpTransportControllerAdapter is not currently "
546 "supported.");
547 }
548 if (inner_video_transport_ && inner_video_transport_ != inner_transport) {
549 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
550 "Using different transports for the video "
551 "RtpSender and RtpReceiver is not currently "
552 "supported.");
553 }
554 // If setting new transport, extract its RTCP parameters and create video
555 // channel.
556 if (!inner_video_transport_) {
557 CopyRtcpParametersToDescriptions(inner_transport->GetRtcpParameters(),
558 &local_video_description_,
559 &remote_video_description_);
560 inner_video_transport_ = inner_transport;
561 CreateVideoChannel();
562 }
563 have_video_sender_ = true;
564 sender->SignalDestroyed.connect(
565 this, &RtpTransportControllerAdapter::OnVideoSenderDestroyed);
566 return RTCError::OK();
567 }
568
569 RTCError RtpTransportControllerAdapter::AttachAudioReceiver(
570 OrtcRtpReceiverAdapter* receiver,
571 RtpTransportInterface* inner_transport) {
572 if (have_audio_receiver_) {
573 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
574 "Using two audio RtpReceivers with the same "
575 "RtpTransportControllerAdapter is not currently "
576 "supported.");
577 }
578 if (inner_audio_transport_ && inner_audio_transport_ != inner_transport) {
579 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
580 "Using different transports for the audio "
581 "RtpReceiver and RtpReceiver is not currently "
582 "supported.");
583 }
584 // If setting new transport, extract its RTCP parameters and create voice
585 // channel.
586 if (!inner_audio_transport_) {
587 CopyRtcpParametersToDescriptions(inner_transport->GetRtcpParameters(),
588 &local_audio_description_,
589 &remote_audio_description_);
590 inner_audio_transport_ = inner_transport;
591 CreateVoiceChannel();
592 }
593 have_audio_receiver_ = true;
594 receiver->SignalDestroyed.connect(
595 this, &RtpTransportControllerAdapter::OnAudioReceiverDestroyed);
596 return RTCError::OK();
597 }
598
599 RTCError RtpTransportControllerAdapter::AttachVideoReceiver(
600 OrtcRtpReceiverAdapter* receiver,
601 RtpTransportInterface* inner_transport) {
602 if (have_video_receiver_) {
603 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
604 "Using two video RtpReceivers with the same "
605 "RtpTransportControllerAdapter is not currently "
606 "supported.");
607 }
608 if (inner_video_transport_ && inner_video_transport_ != inner_transport) {
609 LOG_AND_RETURN_ERROR(RTCErrorType::UNSUPPORTED_OPERATION,
610 "Using different transports for the video "
611 "RtpReceiver and RtpReceiver is not currently "
612 "supported.");
613 }
614 // If setting new transport, extract its RTCP parameters and create video
615 // channel.
616 if (!inner_video_transport_) {
617 CopyRtcpParametersToDescriptions(inner_transport->GetRtcpParameters(),
618 &local_video_description_,
619 &remote_video_description_);
620 inner_video_transport_ = inner_transport;
621 CreateVideoChannel();
622 }
623 have_video_receiver_ = true;
624 receiver->SignalDestroyed.connect(
625 this, &RtpTransportControllerAdapter::OnVideoReceiverDestroyed);
626 return RTCError::OK();
627 }
628
629 void RtpTransportControllerAdapter::OnAudioReceiverDestroyed() {
630 if (!have_audio_receiver_) {
631 RTC_NOTREACHED();
632 return;
633 }
634 // Empty parameters should result in receiving being stopped.
635 RTCError err = ValidateAndApplyAudioReceiverParameters(RtpParameters());
636 RTC_DCHECK(err.ok());
637 have_audio_receiver_ = false;
638 if (!have_audio_sender_) {
639 DestroyVoiceChannel();
640 }
641 }
642
643 void RtpTransportControllerAdapter::OnVideoReceiverDestroyed() {
644 if (!have_video_receiver_) {
645 RTC_NOTREACHED();
646 return;
647 }
648 // Empty parameters should result in receiving being stopped.
649 RTCError err = ValidateAndApplyVideoReceiverParameters(RtpParameters());
650 RTC_DCHECK(err.ok());
651 have_video_receiver_ = false;
652 if (!have_video_sender_) {
653 DestroyVideoChannel();
654 }
655 }
656
657 void RtpTransportControllerAdapter::CreateVoiceChannel() {
658 voice_channel_ = media_controller_->channel_manager()->CreateVoiceChannel(
659 media_controller_.get(),
660 inner_audio_transport_->GetRtpPacketTransport()->GetInternal(),
661 inner_audio_transport_->GetRtcpPacketTransport()
662 ? inner_audio_transport_->GetRtcpPacketTransport()->GetInternal()
663 : nullptr,
664 signaling_thread_, "audio", false, cricket::AudioOptions());
665 RTC_DCHECK(voice_channel_);
666 voice_channel_->Enable(true);
667 }
668
669 void RtpTransportControllerAdapter::CreateVideoChannel() {
670 video_channel_ = media_controller_->channel_manager()->CreateVideoChannel(
671 media_controller_.get(),
672 inner_video_transport_->GetRtpPacketTransport()->GetInternal(),
673 inner_video_transport_->GetRtcpPacketTransport()
674 ? inner_video_transport_->GetRtcpPacketTransport()->GetInternal()
675 : nullptr,
676 signaling_thread_, "video", false, cricket::VideoOptions());
677 RTC_DCHECK(video_channel_);
678 video_channel_->Enable(true);
679 }
680
681 void RtpTransportControllerAdapter::DestroyVoiceChannel() {
682 RTC_DCHECK(voice_channel_);
683 media_controller_->channel_manager()->DestroyVoiceChannel(voice_channel_);
684 voice_channel_ = nullptr;
685 inner_audio_transport_ = nullptr;
686 }
687
688 void RtpTransportControllerAdapter::DestroyVideoChannel() {
689 RTC_DCHECK(video_channel_);
690 media_controller_->channel_manager()->DestroyVideoChannel(video_channel_);
691 video_channel_ = nullptr;
692 inner_video_transport_ = nullptr;
693 }
694
695 void RtpTransportControllerAdapter::CopyRtcpParametersToDescriptions(
696 const RtcpParameters& params,
697 cricket::MediaContentDescription* local,
698 cricket::MediaContentDescription* remote) {
699 local->set_rtcp_mux(params.mux);
700 remote->set_rtcp_mux(params.mux);
701 local->set_rtcp_reduced_size(params.reduced_size);
702 remote->set_rtcp_reduced_size(params.reduced_size);
703 for (cricket::StreamParams& stream_params : local->mutable_streams()) {
704 stream_params.cname = params.cname;
705 }
706 }
707
708 uint32_t RtpTransportControllerAdapter::GenerateUnusedSsrc(
709 std::set<uint32_t>* new_ssrcs) const {
710 uint32_t ssrc;
711 do {
712 ssrc = rtc::CreateRandomNonZeroId();
713 } while (
714 cricket::GetStreamBySsrc(local_audio_description_.streams(), ssrc) ||
715 cricket::GetStreamBySsrc(remote_audio_description_.streams(), ssrc) ||
716 cricket::GetStreamBySsrc(local_video_description_.streams(), ssrc) ||
717 cricket::GetStreamBySsrc(remote_video_description_.streams(), ssrc) ||
718 !new_ssrcs->insert(ssrc).second);
719 return ssrc;
720 }
721
722 RTCErrorOr<cricket::StreamParamsVec>
723 RtpTransportControllerAdapter::MakeSendStreamParamsVec(
724 std::vector<RtpEncodingParameters> encodings,
725 const std::string& cname,
726 const cricket::MediaContentDescription& description) const {
727 if (encodings.size() > 1u) {
728 LOG_AND_RETURN_ERROR(webrtc::RTCErrorType::UNSUPPORTED_PARAMETER,
729 "ORTC API implementation doesn't currently "
730 "support simulcast or layered encodings.");
731 } else if (encodings.empty()) {
732 return cricket::StreamParamsVec();
733 }
734 RtpEncodingParameters& encoding = encodings[0];
735 std::set<uint32_t> new_ssrcs;
736 if (encoding.ssrc) {
737 new_ssrcs.insert(*encoding.ssrc);
738 }
739 if (encoding.rtx && encoding.rtx->ssrc) {
740 new_ssrcs.insert(*encoding.rtx->ssrc);
741 }
742 // May need to fill missing SSRCs with generated ones.
743 if (!encoding.ssrc) {
744 if (!description.streams().empty()) {
745 encoding.ssrc.emplace(description.streams()[0].first_ssrc());
746 } else {
747 encoding.ssrc.emplace(GenerateUnusedSsrc(&new_ssrcs));
748 }
749 }
750 if (encoding.rtx && !encoding.rtx->ssrc) {
751 uint32_t existing_rtx_ssrc;
752 if (!description.streams().empty() &&
753 description.streams()[0].GetFidSsrc(
754 description.streams()[0].first_ssrc(), &existing_rtx_ssrc)) {
755 encoding.rtx->ssrc.emplace(existing_rtx_ssrc);
756 } else {
757 encoding.rtx->ssrc.emplace(GenerateUnusedSsrc(&new_ssrcs));
758 }
759 }
760
761 auto result = ToStreamParamsVec(encodings);
762 if (!result.ok()) {
763 return result.MoveError();
764 }
765 // If conversion was successful, there should be one StreamParams.
766 RTC_DCHECK_EQ(1u, result.value().size());
767 result.value()[0].cname = cname;
768 return result;
769 }
770
771 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698