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

Side by Side Diff: webrtc/ortc/rtptransportcontrollershim.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/rtptransportcontrollershim.h ('k') | webrtc/ortc/rtptransportshim.h » ('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/rtptransportcontrollershim.h"
12
13 #include <algorithm> // For "remove", "find".
14 #include <set>
15 #include <utility> // For std::move.
16
17 #include "webrtc/api/proxy.h"
18 #include "webrtc/base/checks.h"
19 #include "webrtc/media/base/mediaconstants.h"
20 #include "webrtc/ortc/rtptransportshim.h"
21
22 namespace {
23
24 static const int kVideoClockrate = 90000;
25
26 // Returns false on invalid input. Certain message types are only valid for
27 // certain feedback types.
28 webrtc::RTCError ValidateAndConvertRtcpFeedback(
29 const webrtc::RtcpFeedback& feedback,
30 cricket::Codec* codec) {
31 switch (feedback.type) {
32 case webrtc::RtcpFeedbackType::ACK:
33 if (feedback.message_type) {
34 return CreateAndLogError(
35 webrtc::RTCErrorType::INVALID_PARAMETER,
36 "Didn't expect message type in ACK RtcpFeedback.");
37 }
38 codec->AddFeedbackParam(cricket::FeedbackParam("ack"));
39 return webrtc::RTCError();
40 case webrtc::RtcpFeedbackType::CCM:
41 if (!feedback.message_type) {
42 return CreateAndLogError(webrtc::RTCErrorType::INVALID_PARAMETER,
43 "Missing message type in CCM RtcpFeedback.");
44 } else if (*feedback.message_type !=
45 webrtc::RtcpFeedbackMessageType::FIR) {
46 return CreateAndLogError(webrtc::RTCErrorType::INVALID_PARAMETER,
47 "Invalid message type in CCM RtcpFeedback.");
48 }
49 codec->AddFeedbackParam(cricket::FeedbackParam("ccm", "fir"));
50 return webrtc::RTCError();
51 case webrtc::RtcpFeedbackType::NACK:
52 if (!feedback.message_type) {
53 return CreateAndLogError(webrtc::RTCErrorType::INVALID_PARAMETER,
54 "Missing message type in NACK RtcpFeedback.");
55 }
56 switch (*feedback.message_type) {
57 case webrtc::RtcpFeedbackMessageType::GENERIC_NACK:
58 codec->AddFeedbackParam(cricket::FeedbackParam("nack"));
59 return webrtc::RTCError();
60 case webrtc::RtcpFeedbackMessageType::PLI:
61 codec->AddFeedbackParam(cricket::FeedbackParam("nack", "pli"));
62 return webrtc::RTCError();
63 default:
64 return CreateAndLogError(
65 webrtc::RTCErrorType::INVALID_PARAMETER,
66 "Invalid message type in NACK RtcpFeedback.");
67 }
68 case webrtc::RtcpFeedbackType::REMB:
69 if (feedback.message_type) {
70 return CreateAndLogError(
71 webrtc::RTCErrorType::INVALID_PARAMETER,
72 "Didn't expect message type in REMB RtcpFeedback.");
73 }
74 codec->AddFeedbackParam(cricket::FeedbackParam("goog-remb"));
75 return webrtc::RTCError();
76 case webrtc::RtcpFeedbackType::TRANSPORT_CC:
77 if (feedback.message_type) {
78 return CreateAndLogError(
79 webrtc::RTCErrorType::INVALID_PARAMETER,
80 "Didn't expect message type in transport-cc RtcpFeedback.");
81 }
82 codec->AddFeedbackParam(cricket::FeedbackParam("transport-cc"));
83 return webrtc::RTCError();
84 }
85 }
86
87 template <typename C>
88 webrtc::RTCError CodecSpecificConversion(
89 const webrtc::RtpCodecParameters& codec,
90 C* cricket_codec) {}
91
92 template <>
93 webrtc::RTCError CodecSpecificConversion<cricket::AudioCodec>(
94 const webrtc::RtpCodecParameters& codec,
95 cricket::AudioCodec* cricket_codec) {
96 if (codec.kind != cricket::MEDIA_TYPE_AUDIO) {
97 return CreateAndLogError(
98 webrtc::RTCErrorType::INVALID_PARAMETER,
99 "Can't use video codec with audio sender or receiver.");
100 }
101 if (!codec.num_channels) {
102 // A default value for number of channels should have been filled already.
103 RTC_NOTREACHED();
104 return CreateAndLogError(webrtc::RTCErrorType::INVALID_PARAMETER,
105 "Missing number of channels for audio codec.");
106 }
107 if (*codec.num_channels <= 0) {
108 return CreateAndLogError(webrtc::RTCErrorType::INVALID_RANGE,
109 "Number of channels must be positive.");
110 }
111 cricket_codec->channels = *codec.num_channels;
112 if (!codec.clock_rate) {
113 return CreateAndLogError(webrtc::RTCErrorType::INVALID_PARAMETER,
114 "Missing codec clock rate.");
115 }
116 if (*codec.clock_rate <= 0) {
117 return CreateAndLogError(webrtc::RTCErrorType::INVALID_RANGE,
118 "Clock rate must be positive.");
119 }
120 cricket_codec->clockrate = *codec.clock_rate;
121 return webrtc::RTCError();
122 }
123
124 // Video codec doesn't use num_channels or clock_rate, but they should at least
125 // be validated.
126 template <>
127 webrtc::RTCError CodecSpecificConversion<cricket::VideoCodec>(
128 const webrtc::RtpCodecParameters& codec,
129 cricket::VideoCodec*) {
130 if (codec.kind != cricket::MEDIA_TYPE_VIDEO) {
131 return CreateAndLogError(
132 webrtc::RTCErrorType::INVALID_PARAMETER,
133 "Can't use video codec with video sender or receiver.");
134 }
135 if (codec.num_channels) {
136 return CreateAndLogError(webrtc::RTCErrorType::INVALID_PARAMETER,
137 "Video codec shouldn't have num_channels.");
138 }
139 if (!codec.clock_rate) {
140 // A default value should have been filled already.
141 RTC_NOTREACHED();
142 return CreateAndLogError(webrtc::RTCErrorType::INVALID_PARAMETER,
143 "Missing codec clock rate.");
144 }
145 if (*codec.clock_rate != kVideoClockrate) {
146 return CreateAndLogError(webrtc::RTCErrorType::INVALID_PARAMETER,
147 "Video clock rate must be 90000.");
148 }
149 return webrtc::RTCError();
150 }
151
152 template <typename C>
153 webrtc::RTCError ValidateAndConvertCodecs(
154 const std::vector<webrtc::RtpCodecParameters>& codecs,
155 std::vector<C>* cricket_codecs) {
156 std::ostringstream err_writer;
157 std::set<int> seen_payload_types;
158 for (const webrtc::RtpCodecParameters& codec : codecs) {
159 C cricket_codec;
160 // Start with audio/video specific conversion.
161 webrtc::RTCError err = CodecSpecificConversion(codec, &cricket_codec);
162 if (!err.ok()) {
163 return err;
164 }
165 cricket_codec.name = codec.name;
166 if (codec.payload_type < 0 || codec.payload_type > 127) {
167 err_writer << "Invalid payload type: " << codec.payload_type;
168 return CreateAndLogError(webrtc::RTCErrorType::INVALID_RANGE,
169 err_writer.str());
170 }
171 if (!seen_payload_types.insert(codec.payload_type).second) {
172 err_writer << "Duplicate payload type: " << codec.payload_type;
173 return CreateAndLogError(webrtc::RTCErrorType::INVALID_PARAMETER,
174 err_writer.str());
175 }
176 cricket_codec.id = codec.payload_type;
177 for (const webrtc::RtcpFeedback& feedback : codec.rtcp_feedback) {
178 webrtc::RTCError err =
179 ValidateAndConvertRtcpFeedback(feedback, &cricket_codec);
180 if (!err.ok()) {
181 return err;
182 }
183 }
184 cricket_codec.params.insert(codec.parameters.begin(),
185 codec.parameters.end());
186 cricket_codecs->push_back(std::move(cricket_codec));
187 }
188 return webrtc::RTCError();
189 }
190
191 webrtc::RTCError ValidateAndConvertHeaderExtensions(
192 const std::vector<webrtc::RtpHeaderExtensionParameters>& extensions,
193 cricket::RtpHeaderExtensions* cricket_extensions) {
194 std::ostringstream err_writer;
195 std::set<int> seen_header_extension_ids;
196 for (const webrtc::RtpHeaderExtensionParameters& extension : extensions) {
197 if (extension.id < 1 || extension.id > 14) {
198 err_writer << "Invalid header extension id: " << extension.id;
199 return CreateAndLogError(webrtc::RTCErrorType::INVALID_RANGE,
200 err_writer.str());
201 }
202 if (!seen_header_extension_ids.insert(extension.id).second) {
203 err_writer << "Duplicate header extension id: " << extension.id;
204 return CreateAndLogError(webrtc::RTCErrorType::INVALID_PARAMETER,
205 err_writer.str());
206 }
207 cricket_extensions->emplace_back(extension.uri, extension.id);
208 }
209 return webrtc::RTCError();
210 }
211
212 // Missing SSRC is treated differently for receiver encodings; this means
213 // SSRCs are unsignaled.
214 webrtc::RTCError ValidateAndConvertReceiverEncodings(
215 const std::vector<webrtc::RtpEncodingParameters> encodings,
216 cricket::StreamParamsVec* cricket_streams,
217 bool* receiving) {
218 if (encodings.size() > 1u) {
219 return CreateAndLogError(webrtc::RTCErrorType::UNSUPPORTED_PARAMETER,
220 "ORTC API implementation doesn't currently "
221 "support simulcast or layered encodings.");
222 }
223 if (encodings.size() == 1u) {
224 const webrtc::RtpEncodingParameters& encoding = encodings[0];
225 *receiving = encoding.active;
226 if (encoding.ssrc) {
227 cricket::StreamParams stream_params;
228 stream_params.add_ssrc(*encoding.ssrc);
229 if (encoding.rtx && encoding.rtx->ssrc) {
230 stream_params.AddFidSsrc(*encoding.ssrc, *encoding.rtx->ssrc);
231 }
232 cricket_streams->push_back(std::move(stream_params));
233 }
234 } else {
235 *receiving = false;
236 }
237 return webrtc::RTCError();
238 }
239
240 // Codecs that will never be used, but will at least not be rejected by
241 // BaseChannel/MediaChannel classes.
242 void AddDefaultAudioCodec(cricket::AudioContentDescription* description) {
243 description->AddCodec(
244 cricket::AudioCodec(0, cricket::kPcmuCodecName, 8000, 0, 1));
245 }
246
247 void AddDefaultVideoCodec(cricket::VideoContentDescription* description) {
248 description->AddCodec(cricket::VideoCodec(96, cricket::kVp8CodecName));
249 }
250
251 } // namespace
252
253 namespace webrtc {
254
255 BEGIN_OWNED_PROXY_MAP(RtpTransportController)
256 PROXY_SIGNALING_THREAD_DESTRUCTOR()
257 PROXY_CONSTMETHOD0(std::vector<RtpTransportInterface*>, GetTransports)
258 protected:
259 RtpTransportControllerShim* GetInternal() override {
260 return internal();
261 }
262 END_PROXY_MAP()
263
264 // static
265 std::unique_ptr<RtpTransportControllerInterface>
266 RtpTransportControllerShim::CreateProxied(
267 const cricket::MediaConfig& config,
268 cricket::ChannelManager* channel_manager,
269 webrtc::RtcEventLog* event_log,
270 rtc::Thread* signaling_thread,
271 rtc::Thread* worker_thread) {
272 return RtpTransportControllerProxyWithInternal<
273 RtpTransportControllerShim>::Create(signaling_thread, worker_thread,
274 new RtpTransportControllerShim(
275 config, channel_manager,
276 event_log, signaling_thread,
277 worker_thread));
278 }
279
280 RtpTransportControllerShim::~RtpTransportControllerShim() {
281 RTC_DCHECK_RUN_ON(signaling_thread_);
282 if (!transport_proxies_.empty()) {
283 LOG(LS_ERROR)
284 << "Destroying RtpTransportControllerShim while RtpTransports "
285 "are still using it; this is unsafe.";
286 }
287 if (voice_channel_) {
288 // This would mean audio RTP senders/receivers are still using us.
289 DestroyVoiceChannel();
290 }
291 if (voice_channel_) {
292 // This would mean video RTP senders/receivers are still using us.
293 DestroyVideoChannel();
294 }
295 }
296
297 std::vector<RtpTransportInterface*> RtpTransportControllerShim::GetTransports()
298 const {
299 RTC_DCHECK_RUN_ON(signaling_thread_);
300 return transport_proxies_;
301 }
302
303 void RtpTransportControllerShim::AddTransport(
304 RtpTransportInterface* transport_proxy) {
305 RTC_DCHECK_RUN_ON(signaling_thread_);
306 transport_proxies_.push_back(transport_proxy);
307 }
308
309 void RtpTransportControllerShim::RemoveTransport(
310 RtpTransportInterface* inner_transport) {
311 RTC_DCHECK_RUN_ON(signaling_thread_);
312 auto it = std::find_if(transport_proxies_.begin(), transport_proxies_.end(),
313 [inner_transport](RtpTransportInterface* proxy) {
314 return proxy->GetInternal() == inner_transport;
315 });
316 if (it == transport_proxies_.end()) {
317 RTC_NOTREACHED();
318 return;
319 }
320 transport_proxies_.erase(it);
321 }
322
323 RTCError RtpTransportControllerShim::SetRtcpParameters(
324 const RtcpParameters& parameters,
325 RtpTransportInterface* inner_transport) {
326 if (inner_transport == inner_audio_transport_) {
327 CopyRtcpParametersToDescriptions(parameters, &local_audio_description_,
328 &remote_audio_description_);
329 if (!voice_channel_->SetLocalContent(&local_audio_description_,
330 cricket::CA_OFFER, nullptr)) {
331 return CreateAndLogError(RTCErrorType::INTERNAL_ERROR,
332 "Failed to apply new RTCP parameters.");
333 }
334 if (!voice_channel_->SetRemoteContent(&remote_audio_description_,
335 cricket::CA_ANSWER, nullptr)) {
336 return CreateAndLogError(RTCErrorType::INTERNAL_ERROR,
337 "Failed to apply new RTCP parameters.");
338 }
339 } else if (inner_transport == inner_video_transport_) {
340 CopyRtcpParametersToDescriptions(parameters, &local_video_description_,
341 &remote_video_description_);
342 if (!video_channel_->SetLocalContent(&local_video_description_,
343 cricket::CA_OFFER, nullptr)) {
344 return CreateAndLogError(RTCErrorType::INTERNAL_ERROR,
345 "Failed to apply new RTCP parameters.");
346 }
347 if (!video_channel_->SetRemoteContent(&remote_video_description_,
348 cricket::CA_ANSWER, nullptr)) {
349 return CreateAndLogError(RTCErrorType::INTERNAL_ERROR,
350 "Failed to apply new RTCP parameters.");
351 }
352 }
353 return RTCError();
354 }
355
356 RTCError RtpTransportControllerShim::AttachAudioSender(
357 RtpTransportInterface* inner_transport) {
358 if (have_audio_sender_) {
359 return CreateAndLogError(RTCErrorType::UNSUPPORTED_OPERATION,
360 "Using two RtpSenders with the same "
361 "RtpTransportControllerShim is not currently "
362 "supported.");
363 }
364 if (inner_audio_transport_ && inner_audio_transport_ != inner_transport) {
365 return CreateAndLogError(RTCErrorType::UNSUPPORTED_PARAMETER,
366 "Using different transports for the audio "
367 "RtpSender and RtpReceiver is not currently "
368 "supported.");
369 }
370 // If setting new transport, extract its RTCP parameters and create voice
371 // channel.
372 if (!inner_audio_transport_) {
373 CopyRtcpParametersToDescriptions(inner_transport->GetRtcpParameters(),
374 &local_audio_description_,
375 &remote_audio_description_);
376 inner_audio_transport_ = inner_transport;
377 CreateVoiceChannel();
378 }
379 have_audio_sender_ = true;
380 return RTCError();
381 }
382
383 RTCError RtpTransportControllerShim::AttachVideoSender(
384 RtpTransportInterface* inner_transport) {
385 if (have_video_sender_) {
386 return CreateAndLogError(RTCErrorType::UNSUPPORTED_OPERATION,
387 "Using two RtpSenders with the same "
388 "RtpTransportControllerShim is not currently "
389 "supported.");
390 }
391 if (inner_video_transport_ && inner_video_transport_ != inner_transport) {
392 return CreateAndLogError(RTCErrorType::UNSUPPORTED_PARAMETER,
393 "Using different transports for the video "
394 "RtpSender and RtpReceiver is not currently "
395 "supported.");
396 }
397 // If setting new transport, extract its RTCP parameters and create video
398 // channel.
399 if (!inner_video_transport_) {
400 CopyRtcpParametersToDescriptions(inner_transport->GetRtcpParameters(),
401 &local_video_description_,
402 &remote_video_description_);
403 inner_video_transport_ = inner_transport;
404 CreateVideoChannel();
405 }
406 have_video_sender_ = true;
407 return RTCError();
408 }
409
410 RTCError RtpTransportControllerShim::AttachAudioReceiver(
411 RtpTransportInterface* inner_transport) {
412 if (have_audio_receiver_) {
413 return CreateAndLogError(RTCErrorType::UNSUPPORTED_OPERATION,
414 "Using two RtpReceivers with the same "
415 "RtpTransportControllerShim is not currently "
416 "supported.");
417 }
418 if (inner_audio_transport_ && inner_audio_transport_ != inner_transport) {
419 return CreateAndLogError(RTCErrorType::UNSUPPORTED_PARAMETER,
420 "Using different transports for the audio "
421 "RtpReceiver and RtpReceiver is not currently "
422 "supported.");
423 }
424 // If setting new transport, extract its RTCP parameters and create voice
425 // channel.
426 if (!inner_audio_transport_) {
427 CopyRtcpParametersToDescriptions(inner_transport->GetRtcpParameters(),
428 &local_audio_description_,
429 &remote_audio_description_);
430 inner_audio_transport_ = inner_transport;
431 CreateVoiceChannel();
432 }
433 have_audio_receiver_ = true;
434 return RTCError();
435 }
436
437 RTCError RtpTransportControllerShim::AttachVideoReceiver(
438 RtpTransportInterface* inner_transport) {
439 if (have_video_receiver_) {
440 return CreateAndLogError(RTCErrorType::UNSUPPORTED_OPERATION,
441 "Using two RtpReceivers with the same "
442 "RtpTransportControllerShim is not currently "
443 "supported.");
444 }
445 if (inner_video_transport_ && inner_video_transport_ != inner_transport) {
446 return CreateAndLogError(RTCErrorType::UNSUPPORTED_PARAMETER,
447 "Using different transports for the video "
448 "RtpReceiver and RtpReceiver is not currently "
449 "supported.");
450 }
451 // If setting new transport, extract its RTCP parameters and create video
452 // channel.
453 if (!inner_video_transport_) {
454 CopyRtcpParametersToDescriptions(inner_transport->GetRtcpParameters(),
455 &local_video_description_,
456 &remote_video_description_);
457 inner_video_transport_ = inner_transport;
458 CreateVideoChannel();
459 }
460 have_video_receiver_ = true;
461 return RTCError();
462 }
463
464 void RtpTransportControllerShim::DetachAudioSender() {
465 if (!have_audio_sender_) {
466 // Should be impossible unless RtpSenderShim is doing something wrong.
467 RTC_NOTREACHED();
468 return;
469 }
470 // Empty parameters should result in sending being stopped.
471 RTCError err =
472 ValidateAndApplyAudioSenderParameters(RtpParameters(), nullptr);
473 RTC_DCHECK(err.ok());
474 have_audio_sender_ = false;
475 if (!have_audio_receiver_) {
476 DestroyVoiceChannel();
477 }
478 }
479
480 void RtpTransportControllerShim::DetachVideoSender() {
481 if (!have_video_sender_) {
482 // Should be impossible unless RtpSenderShim is doing something wrong.
483 RTC_NOTREACHED();
484 return;
485 }
486 // Empty parameters should result in sending being stopped.
487 RTCError err =
488 ValidateAndApplyVideoSenderParameters(RtpParameters(), nullptr);
489 RTC_DCHECK(err.ok());
490 have_video_sender_ = false;
491 if (!have_video_receiver_) {
492 DestroyVideoChannel();
493 }
494 }
495
496 void RtpTransportControllerShim::DetachAudioReceiver() {
497 if (!have_audio_receiver_) {
498 // Should be impossible unless RtpReceiverShim is doing something wrong.
499 RTC_NOTREACHED();
500 return;
501 }
502 // Empty parameters should result in receiving being stopped.
503 RTCError err = ValidateAndApplyAudioReceiverParameters(RtpParameters());
504 RTC_DCHECK(err.ok());
505 have_audio_receiver_ = false;
506 if (!have_audio_sender_) {
507 DestroyVoiceChannel();
508 }
509 }
510
511 void RtpTransportControllerShim::DetachVideoReceiver() {
512 if (!have_video_receiver_) {
513 // Should be impossible unless RtpReceiverShim is doing something wrong.
514 RTC_NOTREACHED();
515 return;
516 }
517 // Empty parameters should result in receiving being stopped.
518 RTCError err = ValidateAndApplyVideoReceiverParameters(RtpParameters());
519 RTC_DCHECK(err.ok());
520 have_video_receiver_ = false;
521 if (!have_video_sender_) {
522 DestroyVideoChannel();
523 }
524 }
525
526 RTCError RtpTransportControllerShim::ValidateAndApplyAudioSenderParameters(
527 const RtpParameters& parameters,
528 uint32_t* primary_ssrc) {
529 RTC_DCHECK(voice_channel_);
530 RTC_DCHECK(have_audio_sender_);
531
532 std::vector<cricket::AudioCodec> cricket_codecs;
533 RTCError err = ValidateAndConvertCodecs(parameters.codecs, &cricket_codecs);
534 if (!err.ok()) {
535 return err;
536 }
537
538 cricket::RtpHeaderExtensions cricket_extensions;
539 err = ValidateAndConvertHeaderExtensions(parameters.header_extensions,
540 &cricket_extensions);
541 if (!err.ok()) {
542 return err;
543 }
544
545 cricket::StreamParamsVec cricket_streams;
546 cricket::RtpTransceiverDirection local_direction =
547 cricket::RtpTransceiverDirection::FromMediaContentDirection(
548 local_audio_description_.direction());
549 int bandwidth = cricket::kAutoBandwidth;
550 err = ValidateAndConvertSenderEncodings(
551 parameters.encodings, inner_audio_transport_->GetRtcpParameters().cname,
552 local_audio_description_, &cricket_streams, &local_direction.send,
553 &bandwidth);
554 if (!err.ok()) {
555 return err;
556 }
557 if (primary_ssrc && !cricket_streams.empty()) {
558 *primary_ssrc = cricket_streams[0].first_ssrc();
559 }
560
561 // Validation is done, so we can attempt applying the descriptions. Sent
562 // codecs and header extensions go in remote description, streams go in
563 // local.
564 remote_audio_description_.set_codecs(cricket_codecs);
565 remote_audio_description_.set_rtp_header_extensions(cricket_extensions);
566 remote_audio_description_.set_bandwidth(bandwidth);
567 local_audio_description_.mutable_streams() = cricket_streams;
568 // Direction set based on encoding "active" flag.
569 local_audio_description_.set_direction(
570 local_direction.ToMediaContentDirection());
571 remote_audio_description_.set_direction(
572 local_direction.MakeReversed().ToMediaContentDirection());
573 // Add default codec if there are no encodings; no codec and no encodings
574 // should be legal, but the media engine code doesn't support that.
575 if (local_audio_description_.streams().empty() &&
576 remote_audio_description_.codecs().empty()) {
577 AddDefaultAudioCodec(&remote_audio_description_);
578 }
579
580 // Set remote content first, to ensure the stream is created with the correct
581 // codec.
582 if (!voice_channel_->SetRemoteContent(&remote_audio_description_,
583 cricket::CA_OFFER, nullptr)) {
584 return CreateAndLogError(
585 RTCErrorType::INTERNAL_ERROR,
586 "Failed to apply remote parameters to media channel.");
587 }
588 if (!voice_channel_->SetLocalContent(&local_audio_description_,
589 cricket::CA_ANSWER, nullptr)) {
590 return CreateAndLogError(
591 RTCErrorType::INTERNAL_ERROR,
592 "Failed to apply local parameters to media channel.");
593 }
594 return RTCError();
595 }
596
597 RTCError RtpTransportControllerShim::ValidateAndApplyVideoSenderParameters(
598 const RtpParameters& parameters,
599 uint32_t* primary_ssrc) {
600 RTC_DCHECK(video_channel_);
601 RTC_DCHECK(have_video_sender_);
602
603 std::vector<cricket::VideoCodec> cricket_codecs;
604 RTCError err = ValidateAndConvertCodecs(parameters.codecs, &cricket_codecs);
605 if (!err.ok()) {
606 return err;
607 }
608
609 cricket::RtpHeaderExtensions cricket_extensions;
610 err = ValidateAndConvertHeaderExtensions(parameters.header_extensions,
611 &cricket_extensions);
612 if (!err.ok()) {
613 return err;
614 }
615
616 cricket::StreamParamsVec cricket_streams;
617 cricket::RtpTransceiverDirection local_direction =
618 cricket::RtpTransceiverDirection::FromMediaContentDirection(
619 local_video_description_.direction());
620 int bandwidth = cricket::kAutoBandwidth;
621 err = ValidateAndConvertSenderEncodings(
622 parameters.encodings, inner_video_transport_->GetRtcpParameters().cname,
623 local_video_description_, &cricket_streams, &local_direction.send,
624 &bandwidth);
625 if (!err.ok()) {
626 return err;
627 }
628 if (primary_ssrc && !cricket_streams.empty()) {
629 *primary_ssrc = cricket_streams[0].first_ssrc();
630 }
631
632 // Validation is done, so we can attempt applying the descriptions. Sent
633 // codecs and header extensions go in remote description, streams go in
634 // local.
635 remote_video_description_.set_codecs(cricket_codecs);
636 remote_video_description_.set_rtp_header_extensions(cricket_extensions);
637 remote_video_description_.set_bandwidth(bandwidth);
638 local_video_description_.mutable_streams() = cricket_streams;
639 // Direction set based on encoding "active" flag.
640 local_video_description_.set_direction(
641 local_direction.ToMediaContentDirection());
642 remote_video_description_.set_direction(
643 local_direction.MakeReversed().ToMediaContentDirection());
644 // Add default codec if there are no encodings; no codec and no encodings
645 // should be legal, but the media engine code doesn't support that.
646 if (local_video_description_.streams().empty() &&
647 remote_video_description_.codecs().empty()) {
648 AddDefaultVideoCodec(&remote_video_description_);
649 }
650
651 // Set remote content first, to ensure the stream is created with the correct
652 // codec.
653 if (!video_channel_->SetRemoteContent(&remote_video_description_,
654 cricket::CA_OFFER, nullptr)) {
655 return CreateAndLogError(
656 RTCErrorType::INTERNAL_ERROR,
657 "Failed to apply remote parameters to media channel.");
658 }
659 if (!video_channel_->SetLocalContent(&local_video_description_,
660 cricket::CA_ANSWER, nullptr)) {
661 return CreateAndLogError(
662 RTCErrorType::INTERNAL_ERROR,
663 "Failed to apply local parameters to media channel.");
664 }
665 return RTCError();
666 }
667
668 RTCError RtpTransportControllerShim::ValidateAndApplyAudioReceiverParameters(
669 const RtpParameters& parameters) {
670 RTC_DCHECK(voice_channel_);
671 RTC_DCHECK(have_audio_receiver_);
672
673 std::vector<cricket::AudioCodec> cricket_codecs;
674 RTCError err = ValidateAndConvertCodecs(parameters.codecs, &cricket_codecs);
675 if (!err.ok()) {
676 return err;
677 }
678
679 cricket::RtpHeaderExtensions cricket_extensions;
680 err = ValidateAndConvertHeaderExtensions(parameters.header_extensions,
681 &cricket_extensions);
682 if (!err.ok()) {
683 return err;
684 }
685
686 cricket::StreamParamsVec cricket_streams;
687 cricket::RtpTransceiverDirection local_direction =
688 cricket::RtpTransceiverDirection::FromMediaContentDirection(
689 local_audio_description_.direction());
690 int bandwidth = cricket::kAutoBandwidth;
691 err = ValidateAndConvertReceiverEncodings(
692 parameters.encodings, &cricket_streams, &local_direction.recv);
693 if (!err.ok()) {
694 return err;
695 }
696
697 // Validation is done, so we can attempt applying the descriptions. Received
698 // codecs and header extensions go in local description, streams go in
699 // remote.
700 local_audio_description_.set_codecs(cricket_codecs);
701 local_audio_description_.set_rtp_header_extensions(cricket_extensions);
702 local_audio_description_.set_bandwidth(bandwidth);
703 remote_audio_description_.mutable_streams() = cricket_streams;
704 // Direction set based on encoding "active" flag.
705 local_audio_description_.set_direction(
706 local_direction.ToMediaContentDirection());
707 remote_audio_description_.set_direction(
708 local_direction.MakeReversed().ToMediaContentDirection());
709 // Add default codec if there are no encodings; no codec and no encodings
710 // should be legal, but the media engine code doesn't support that.
711 if (remote_audio_description_.streams().empty() &&
712 local_audio_description_.codecs().empty()) {
713 AddDefaultAudioCodec(&local_audio_description_);
714 }
715
716 if (!voice_channel_->SetLocalContent(&local_audio_description_,
717 cricket::CA_OFFER, nullptr)) {
718 return CreateAndLogError(
719 RTCErrorType::INTERNAL_ERROR,
720 "Failed to apply local parameters to media channel.");
721 }
722 if (!voice_channel_->SetRemoteContent(&remote_audio_description_,
723 cricket::CA_ANSWER, nullptr)) {
724 return CreateAndLogError(
725 RTCErrorType::INTERNAL_ERROR,
726 "Failed to apply remote parameters to media channel.");
727 }
728 return RTCError();
729 }
730
731 RTCError RtpTransportControllerShim::ValidateAndApplyVideoReceiverParameters(
732 const RtpParameters& parameters) {
733 RTC_DCHECK(video_channel_);
734 RTC_DCHECK(have_video_receiver_);
735
736 std::vector<cricket::VideoCodec> cricket_codecs;
737 RTCError err = ValidateAndConvertCodecs(parameters.codecs, &cricket_codecs);
738 if (!err.ok()) {
739 return err;
740 }
741
742 cricket::RtpHeaderExtensions cricket_extensions;
743 err = ValidateAndConvertHeaderExtensions(parameters.header_extensions,
744 &cricket_extensions);
745 if (!err.ok()) {
746 return err;
747 }
748
749 cricket::StreamParamsVec cricket_streams;
750 cricket::RtpTransceiverDirection local_direction =
751 cricket::RtpTransceiverDirection::FromMediaContentDirection(
752 local_video_description_.direction());
753 int bandwidth = cricket::kAutoBandwidth;
754 err = ValidateAndConvertReceiverEncodings(
755 parameters.encodings, &cricket_streams, &local_direction.recv);
756 if (!err.ok()) {
757 return err;
758 }
759
760 // Validation is done, so we can attempt applying the descriptions. Received
761 // codecs and header extensions go in local description, streams go in
762 // remote.
763 local_video_description_.set_codecs(cricket_codecs);
764 local_video_description_.set_rtp_header_extensions(cricket_extensions);
765 local_video_description_.set_bandwidth(bandwidth);
766 remote_video_description_.mutable_streams() = cricket_streams;
767 // Direction set based on encoding "active" flag.
768 local_video_description_.set_direction(
769 local_direction.ToMediaContentDirection());
770 remote_video_description_.set_direction(
771 local_direction.MakeReversed().ToMediaContentDirection());
772 // Add default codec if there are no encodings; no codec and no encodings
773 // should be legal, but the media engine code doesn't support that.
774 if (remote_video_description_.streams().empty() &&
775 local_video_description_.codecs().empty()) {
776 AddDefaultVideoCodec(&local_video_description_);
777 }
778
779 if (!video_channel_->SetLocalContent(&local_video_description_,
780 cricket::CA_OFFER, nullptr)) {
781 return CreateAndLogError(
782 RTCErrorType::INTERNAL_ERROR,
783 "Failed to apply local parameters to media channel.");
784 }
785 if (!video_channel_->SetRemoteContent(&remote_video_description_,
786 cricket::CA_ANSWER, nullptr)) {
787 return CreateAndLogError(
788 RTCErrorType::INTERNAL_ERROR,
789 "Failed to apply remote parameters to media channel.");
790 }
791 return RTCError();
792 }
793
794 RtpTransportControllerShim::RtpTransportControllerShim(
795 const cricket::MediaConfig& config,
796 cricket::ChannelManager* channel_manager,
797 webrtc::RtcEventLog* event_log,
798 rtc::Thread* signaling_thread,
799 rtc::Thread* worker_thread)
800 : signaling_thread_(signaling_thread),
801 worker_thread_(worker_thread),
802 media_controller_(MediaControllerInterface::Create(config,
803 worker_thread,
804 channel_manager,
805 event_log)) {
806 RTC_DCHECK_RUN_ON(signaling_thread_);
807 RTC_DCHECK(channel_manager);
808 // MediaControllerInterface::Create should never fail.
809 RTC_DCHECK(media_controller_);
810 AddDefaultAudioCodec(&local_audio_description_);
811 AddDefaultAudioCodec(&remote_audio_description_);
812 AddDefaultVideoCodec(&local_video_description_);
813 AddDefaultVideoCodec(&remote_video_description_);
814 }
815
816 void RtpTransportControllerShim::CreateVoiceChannel() {
817 voice_channel_ = media_controller_->channel_manager()->CreateVoiceChannel(
818 media_controller_.get(),
819 inner_audio_transport_->GetRtpPacketTransport()->GetInternal(),
820 inner_audio_transport_->GetRtcpPacketTransport()
821 ? inner_audio_transport_->GetRtcpPacketTransport()->GetInternal()
822 : nullptr,
823 signaling_thread_, "audio", false, cricket::AudioOptions());
824 RTC_DCHECK(voice_channel_);
825 voice_channel_->Enable(true);
826 }
827
828 void RtpTransportControllerShim::CreateVideoChannel() {
829 video_channel_ = media_controller_->channel_manager()->CreateVideoChannel(
830 media_controller_.get(),
831 inner_video_transport_->GetRtpPacketTransport()->GetInternal(),
832 inner_video_transport_->GetRtcpPacketTransport()
833 ? inner_video_transport_->GetRtcpPacketTransport()->GetInternal()
834 : nullptr,
835 signaling_thread_, "audio", false, cricket::VideoOptions());
836 RTC_DCHECK(video_channel_);
837 video_channel_->Enable(true);
838 }
839
840 void RtpTransportControllerShim::DestroyVoiceChannel() {
841 RTC_DCHECK(voice_channel_);
842 media_controller_->channel_manager()->DestroyVoiceChannel(voice_channel_);
843 voice_channel_ = nullptr;
844 }
845
846 void RtpTransportControllerShim::DestroyVideoChannel() {
847 RTC_DCHECK(video_channel_);
848 media_controller_->channel_manager()->DestroyVideoChannel(video_channel_);
849 video_channel_ = nullptr;
850 }
851
852 void RtpTransportControllerShim::CopyRtcpParametersToDescriptions(
853 const RtcpParameters& params,
854 cricket::MediaContentDescription* local,
855 cricket::MediaContentDescription* remote) {
856 local->set_rtcp_mux(params.mux);
857 remote->set_rtcp_mux(params.mux);
858 local->set_rtcp_reduced_size(params.reduced_size);
859 remote->set_rtcp_reduced_size(params.reduced_size);
860 for (cricket::StreamParams& stream_params : local->mutable_streams()) {
861 stream_params.cname = params.cname;
862 }
863 }
864
865 uint32_t RtpTransportControllerShim::GenerateUnusedSsrc(
866 const cricket::StreamParams& new_params) const {
867 uint32_t ssrc;
868 do {
869 ssrc = rtc::CreateRandomNonZeroId();
870 } while (
871 cricket::GetStreamBySsrc(local_audio_description_.streams(), ssrc) ||
872 cricket::GetStreamBySsrc(remote_audio_description_.streams(), ssrc) ||
873 cricket::GetStreamBySsrc(local_video_description_.streams(), ssrc) ||
874 cricket::GetStreamBySsrc(remote_video_description_.streams(), ssrc) ||
875 new_params.has_ssrc(ssrc));
876 return ssrc;
877 }
878
879 RTCError RtpTransportControllerShim::ValidateAndConvertSenderEncodings(
880 const std::vector<RtpEncodingParameters> encodings,
881 const std::string& cname,
882 const cricket::MediaContentDescription& description,
883 cricket::StreamParamsVec* cricket_streams,
884 bool* sending,
885 int* bandwidth) const {
886 if (encodings.size() > 1u) {
887 return CreateAndLogError(RTCErrorType::UNSUPPORTED_PARAMETER,
888 "ORTC API implementation doesn't currently "
889 "support simulcast or layered encodings.");
890 }
891 if (encodings.size() == 1u) {
892 const RtpEncodingParameters& encoding = encodings[0];
893 cricket::StreamParams stream_params;
894 stream_params.cname = cname;
895 if (encoding.ssrc) {
896 stream_params.add_ssrc(*encoding.ssrc);
897 } else {
898 // SSRC not provided; generate it or use the existing one.
899 if (!description.streams().empty()) {
900 stream_params.add_ssrc(description.streams()[0].first_ssrc());
901 } else {
902 stream_params.add_ssrc(GenerateUnusedSsrc(stream_params));
903 }
904 }
905 if (encoding.rtx) {
906 if (encoding.rtx->ssrc) {
907 stream_params.AddFidSsrc(stream_params.first_ssrc(),
908 *encoding.rtx->ssrc);
909 } else {
910 // SSRC not provided; generate it or use the existing one.
911 if (!description.streams().empty() &&
912 description.streams()[0].has_ssrc_group(
913 cricket::kFidSsrcGroupSemantics)) {
914 stream_params.AddFidSsrc(
915 stream_params.first_ssrc(),
916 description.streams()[0]
917 .get_ssrc_group(cricket::kFidSsrcGroupSemantics)
918 ->ssrcs[1]);
919 } else {
920 stream_params.AddFidSsrc(stream_params.first_ssrc(),
921 GenerateUnusedSsrc(stream_params));
922 }
923 }
924 }
925 cricket_streams->push_back(std::move(stream_params));
926 if (encoding.max_bitrate_bps) {
927 *bandwidth = *encoding.max_bitrate_bps;
928 }
929 *sending = encoding.active;
930 } else {
931 *sending = false;
932 }
933 return RTCError();
934 }
935
936 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/ortc/rtptransportcontrollershim.h ('k') | webrtc/ortc/rtptransportshim.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698