blob: cf3d147bc98617775eff1ef7663db86a69beb4f9 [file] [log] [blame]
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +00001/*
2 * Copyright 2010 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
Steve Anton10542f22019-01-11 09:11:00 -080011#include "pc/session_description.h"
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000012
Harald Alvestrand4d7160e2019-04-12 07:01:29 +020013#include <algorithm>
Steve Anton5adfafd2017-12-20 16:34:00 -080014#include <utility>
15
Steve Anton64b626b2019-01-28 17:25:26 -080016#include "absl/algorithm/container.h"
Harald Alvestrand4d7160e2019-04-12 07:01:29 +020017#include "absl/memory/memory.h"
Harald Alvestrand5fc28b12019-05-13 13:36:16 +020018#include "pc/media_protocol_names.h"
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "rtc_base/checks.h"
20
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000021namespace cricket {
Steve Anton4ab68ee2017-12-19 14:26:11 -080022namespace {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000023
Steve Anton4ab68ee2017-12-19 14:26:11 -080024ContentInfo* FindContentInfoByName(ContentInfos* contents,
25 const std::string& name) {
26 RTC_DCHECK(contents);
27 for (ContentInfo& content : *contents) {
28 if (content.name == name) {
29 return &content;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000030 }
31 }
Steve Anton4ab68ee2017-12-19 14:26:11 -080032 return nullptr;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000033}
34
Steve Anton4ab68ee2017-12-19 14:26:11 -080035} // namespace
36
37const ContentInfo* FindContentInfoByName(const ContentInfos& contents,
38 const std::string& name) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000039 for (ContentInfos::const_iterator content = contents.begin();
40 content != contents.end(); ++content) {
41 if (content->name == name) {
42 return &(*content);
43 }
44 }
45 return NULL;
46}
47
Steve Anton4ab68ee2017-12-19 14:26:11 -080048const ContentInfo* FindContentInfoByType(const ContentInfos& contents,
Steve Anton5adfafd2017-12-20 16:34:00 -080049 MediaProtocolType type) {
50 for (const auto& content : contents) {
51 if (content.type == type) {
52 return &content;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000053 }
54 }
Steve Anton5adfafd2017-12-20 16:34:00 -080055 return nullptr;
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000056}
57
Steve Antond3ea9992017-10-31 12:38:23 -070058ContentGroup::ContentGroup(const std::string& semantics)
59 : semantics_(semantics) {}
60
61ContentGroup::ContentGroup(const ContentGroup&) = default;
62ContentGroup::ContentGroup(ContentGroup&&) = default;
63ContentGroup& ContentGroup::operator=(const ContentGroup&) = default;
64ContentGroup& ContentGroup::operator=(ContentGroup&&) = default;
65ContentGroup::~ContentGroup() = default;
66
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000067const std::string* ContentGroup::FirstContentName() const {
68 return (!content_names_.empty()) ? &(*content_names_.begin()) : NULL;
69}
70
71bool ContentGroup::HasContentName(const std::string& content_name) const {
Steve Anton64b626b2019-01-28 17:25:26 -080072 return absl::c_linear_search(content_names_, content_name);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000073}
74
75void ContentGroup::AddContentName(const std::string& content_name) {
76 if (!HasContentName(content_name)) {
77 content_names_.push_back(content_name);
78 }
79}
80
81bool ContentGroup::RemoveContentName(const std::string& content_name) {
Steve Anton64b626b2019-01-28 17:25:26 -080082 ContentNames::iterator iter = absl::c_find(content_names_, content_name);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +000083 if (iter == content_names_.end()) {
84 return false;
85 }
86 content_names_.erase(iter);
87 return true;
88}
89
Steve Antond3ea9992017-10-31 12:38:23 -070090SessionDescription::SessionDescription() = default;
Steve Antond3ea9992017-10-31 12:38:23 -070091SessionDescription::SessionDescription(const SessionDescription&) = default;
92
93SessionDescription::~SessionDescription() {
94 for (ContentInfos::iterator content = contents_.begin();
95 content != contents_.end(); ++content) {
96 delete content->description;
97 }
98}
99
Harald Alvestrand4d7160e2019-04-12 07:01:29 +0200100std::unique_ptr<SessionDescription> SessionDescription::Clone() const {
101 // Copy the non-special portions using the private copy constructor.
102 auto copy = absl::WrapUnique(new SessionDescription(*this));
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000103 // Copy all ContentDescriptions.
104 for (ContentInfos::iterator content = copy->contents_.begin();
Steve Anton4ab68ee2017-12-19 14:26:11 -0800105 content != copy->contents().end(); ++content) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000106 content->description = content->description->Copy();
107 }
108 return copy;
109}
110
Harald Alvestrand4d7160e2019-04-12 07:01:29 +0200111SessionDescription* SessionDescription::Copy() const {
112 return Clone().release();
113}
114
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000115const ContentInfo* SessionDescription::GetContentByName(
116 const std::string& name) const {
117 return FindContentInfoByName(contents_, name);
118}
119
Steve Anton4ab68ee2017-12-19 14:26:11 -0800120ContentInfo* SessionDescription::GetContentByName(const std::string& name) {
121 return FindContentInfoByName(&contents_, name);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000122}
123
Steve Antonb1c1de12017-12-21 15:14:30 -0800124const MediaContentDescription* SessionDescription::GetContentDescriptionByName(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000125 const std::string& name) const {
126 const ContentInfo* cinfo = FindContentInfoByName(contents_, name);
127 if (cinfo == NULL) {
128 return NULL;
129 }
130
Steve Antonb1c1de12017-12-21 15:14:30 -0800131 return cinfo->media_description();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000132}
133
Steve Antonb1c1de12017-12-21 15:14:30 -0800134MediaContentDescription* SessionDescription::GetContentDescriptionByName(
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000135 const std::string& name) {
Steve Anton4ab68ee2017-12-19 14:26:11 -0800136 ContentInfo* cinfo = FindContentInfoByName(&contents_, name);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000137 if (cinfo == NULL) {
138 return NULL;
139 }
140
Steve Antonb1c1de12017-12-21 15:14:30 -0800141 return cinfo->media_description();
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000142}
143
144const ContentInfo* SessionDescription::FirstContentByType(
Steve Anton5adfafd2017-12-20 16:34:00 -0800145 MediaProtocolType type) const {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000146 return FindContentInfoByType(contents_, type);
147}
148
149const ContentInfo* SessionDescription::FirstContent() const {
150 return (contents_.empty()) ? NULL : &(*contents_.begin());
151}
152
153void SessionDescription::AddContent(const std::string& name,
Steve Anton5adfafd2017-12-20 16:34:00 -0800154 MediaProtocolType type,
Steve Antonb1c1de12017-12-21 15:14:30 -0800155 MediaContentDescription* description) {
Steve Anton5adfafd2017-12-20 16:34:00 -0800156 ContentInfo content(type);
157 content.name = name;
158 content.description = description;
Johannes Kron9ac3c912018-10-12 10:54:26 +0200159 AddContent(&content);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000160}
161
162void SessionDescription::AddContent(const std::string& name,
Steve Anton5adfafd2017-12-20 16:34:00 -0800163 MediaProtocolType type,
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000164 bool rejected,
Steve Antonb1c1de12017-12-21 15:14:30 -0800165 MediaContentDescription* description) {
Steve Anton5adfafd2017-12-20 16:34:00 -0800166 ContentInfo content(type);
167 content.name = name;
168 content.rejected = rejected;
169 content.description = description;
Johannes Kron9ac3c912018-10-12 10:54:26 +0200170 AddContent(&content);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000171}
172
deadbeef25ed4352016-12-12 18:37:36 -0800173void SessionDescription::AddContent(const std::string& name,
Steve Anton5adfafd2017-12-20 16:34:00 -0800174 MediaProtocolType type,
deadbeef25ed4352016-12-12 18:37:36 -0800175 bool rejected,
176 bool bundle_only,
Steve Antonb1c1de12017-12-21 15:14:30 -0800177 MediaContentDescription* description) {
Steve Anton5adfafd2017-12-20 16:34:00 -0800178 ContentInfo content(type);
179 content.name = name;
180 content.rejected = rejected;
181 content.bundle_only = bundle_only;
182 content.description = description;
Johannes Kron9ac3c912018-10-12 10:54:26 +0200183 AddContent(&content);
184}
185
186void SessionDescription::AddContent(ContentInfo* content) {
Harald Alvestrand5fc28b12019-05-13 13:36:16 +0200187 // Unwrap the as_data shim layer before using.
188 auto* description = content->media_description();
189 bool should_delete = false;
190 if (description->as_rtp_data()) {
191 if (description->as_rtp_data() != description) {
192 content->set_media_description(
193 description->as_data()->Unshim(&should_delete));
194 }
195 }
196 if (description->as_sctp()) {
197 if (description->as_sctp() != description) {
198 content->set_media_description(
199 description->as_data()->Unshim(&should_delete));
200 }
201 }
202 if (should_delete) {
203 delete description;
204 }
Johannes Kron9581bc42018-10-23 10:17:39 +0200205 if (extmap_allow_mixed()) {
Johannes Kron9ac3c912018-10-12 10:54:26 +0200206 // Mixed support on session level overrides setting on media level.
Johannes Kron9581bc42018-10-23 10:17:39 +0200207 content->description->set_extmap_allow_mixed_enum(
Johannes Kron9ac3c912018-10-12 10:54:26 +0200208 MediaContentDescription::kSession);
209 }
210 contents_.push_back(std::move(*content));
deadbeef25ed4352016-12-12 18:37:36 -0800211}
212
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000213bool SessionDescription::RemoveContentByName(const std::string& name) {
214 for (ContentInfos::iterator content = contents_.begin();
215 content != contents_.end(); ++content) {
216 if (content->name == name) {
217 delete content->description;
218 contents_.erase(content);
219 return true;
220 }
221 }
222
223 return false;
224}
225
Steve Anton06817cd2018-12-18 15:55:30 -0800226void SessionDescription::AddTransportInfo(const TransportInfo& transport_info) {
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000227 transport_infos_.push_back(transport_info);
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000228}
229
230bool SessionDescription::RemoveTransportInfoByName(const std::string& name) {
231 for (TransportInfos::iterator transport_info = transport_infos_.begin();
232 transport_info != transport_infos_.end(); ++transport_info) {
233 if (transport_info->content_name == name) {
234 transport_infos_.erase(transport_info);
235 return true;
236 }
237 }
238 return false;
239}
240
241const TransportInfo* SessionDescription::GetTransportInfoByName(
242 const std::string& name) const {
243 for (TransportInfos::const_iterator iter = transport_infos_.begin();
244 iter != transport_infos_.end(); ++iter) {
245 if (iter->content_name == name) {
246 return &(*iter);
247 }
248 }
249 return NULL;
250}
251
252TransportInfo* SessionDescription::GetTransportInfoByName(
253 const std::string& name) {
254 for (TransportInfos::iterator iter = transport_infos_.begin();
255 iter != transport_infos_.end(); ++iter) {
256 if (iter->content_name == name) {
257 return &(*iter);
258 }
259 }
260 return NULL;
261}
262
263void SessionDescription::RemoveGroupByName(const std::string& name) {
264 for (ContentGroups::iterator iter = content_groups_.begin();
265 iter != content_groups_.end(); ++iter) {
266 if (iter->semantics() == name) {
267 content_groups_.erase(iter);
268 break;
269 }
270 }
271}
272
273bool SessionDescription::HasGroup(const std::string& name) const {
274 for (ContentGroups::const_iterator iter = content_groups_.begin();
275 iter != content_groups_.end(); ++iter) {
276 if (iter->semantics() == name) {
277 return true;
278 }
279 }
280 return false;
281}
282
283const ContentGroup* SessionDescription::GetGroupByName(
284 const std::string& name) const {
285 for (ContentGroups::const_iterator iter = content_groups_.begin();
286 iter != content_groups_.end(); ++iter) {
287 if (iter->semantics() == name) {
288 return &(*iter);
289 }
290 }
291 return NULL;
292}
293
Harald Alvestrand5fc28b12019-05-13 13:36:16 +0200294// DataContentDescription shim creation
295DataContentDescription* RtpDataContentDescription::as_data() {
296 if (!shim_) {
297 shim_.reset(new DataContentDescription(this));
298 }
299 return shim_.get();
300}
301
302const DataContentDescription* RtpDataContentDescription::as_data() const {
303 return const_cast<RtpDataContentDescription*>(this)->as_data();
304}
305
306DataContentDescription* SctpDataContentDescription::as_data() {
307 if (!shim_) {
308 shim_.reset(new DataContentDescription(this));
309 }
310 return shim_.get();
311}
312
313const DataContentDescription* SctpDataContentDescription::as_data() const {
314 return const_cast<SctpDataContentDescription*>(this)->as_data();
315}
316
317DataContentDescription::DataContentDescription() {
318 // In this case, we will initialize |owned_description_| as soon as
319 // we are told what protocol to use via set_protocol or another function
320 // calling CreateShimTarget.
321}
322
323DataContentDescription::DataContentDescription(
324 SctpDataContentDescription* wrapped)
325 : real_description_(wrapped) {
326 // SctpDataContentDescription doesn't contain codecs, but code
327 // using DataContentDescription expects to see one.
328 Super::AddCodec(
329 cricket::DataCodec(kGoogleSctpDataCodecPlType, kGoogleSctpDataCodecName));
330}
331
332DataContentDescription::DataContentDescription(
333 RtpDataContentDescription* wrapped)
334 : real_description_(wrapped) {}
335
336DataContentDescription::DataContentDescription(
337 const DataContentDescription* o) {
338 if (o->real_description_) {
339 owned_description_ = absl::WrapUnique(o->real_description_->Copy());
340 real_description_ = owned_description_.get();
341 } else {
342 // Copy all information collected so far, including codecs.
343 Super::operator=(*o);
344 }
345}
346
347void DataContentDescription::CreateShimTarget(bool is_sctp) {
348 RTC_LOG(LS_INFO) << "Creating shim target, is_sctp is " << is_sctp;
349 RTC_CHECK(!owned_description_.get());
350 if (is_sctp) {
351 owned_description_ = absl::make_unique<SctpDataContentDescription>();
352 // Copy all information collected so far, except codecs.
353 owned_description_->MediaContentDescription::operator=(*this);
354 } else {
355 owned_description_ = absl::make_unique<RtpDataContentDescription>();
356 // Copy all information collected so far, including codecs.
357 owned_description_->as_rtp_data()
358 ->MediaContentDescriptionImpl<RtpDataCodec>::operator=(*this);
359 }
360 real_description_ = owned_description_.get();
361}
362
363MediaContentDescription* DataContentDescription::Unshim(bool* should_delete) {
364 // If protocol isn't decided at this point, we have a problem.
365 RTC_CHECK(real_description_);
366 if (owned_description_) {
367 // Pass ownership to caller, and remove myself.
368 // Since caller can't know if I was owner or owned, tell them.
369 MediaContentDescription* to_return = owned_description_.release();
370 *should_delete = true;
371 return to_return;
372 }
373 // Real object is owner, and presumably referenced from elsewhere.
374 *should_delete = false;
375 return real_description_;
376}
377
378void DataContentDescription::set_protocol(const std::string& protocol) {
379 if (!real_description_) {
380 CreateShimTarget(IsSctpProtocol(protocol));
381 }
382 real_description_->set_protocol(protocol);
383}
384
385bool DataContentDescription::IsSctp() const {
386 return (real_description_ && real_description_->as_sctp());
387}
388
389void DataContentDescription::EnsureIsRtp() {
390 RTC_CHECK(real_description_);
391 RTC_CHECK(real_description_->as_rtp_data());
392}
393
394RtpDataContentDescription* DataContentDescription::as_rtp_data() {
395 if (real_description_) {
396 return real_description_->as_rtp_data();
397 }
398 return nullptr;
399}
400
401SctpDataContentDescription* DataContentDescription::as_sctp() {
402 if (real_description_) {
403 return real_description_->as_sctp();
404 }
405 return nullptr;
406}
407
408// Override all methods defined in MediaContentDescription.
409bool DataContentDescription::has_codecs() const {
410 if (!real_description_) {
411 return Super::has_codecs();
412 }
413 return real_description_->has_codecs();
414}
415std::string DataContentDescription::protocol() const {
416 if (!real_description_) {
417 return Super::protocol();
418 }
419 return real_description_->protocol();
420}
421
422webrtc::RtpTransceiverDirection DataContentDescription::direction() const {
423 if (!real_description_) {
424 return Super::direction();
425 }
426 return real_description_->direction();
427}
428void DataContentDescription::set_direction(
429 webrtc::RtpTransceiverDirection direction) {
430 if (!real_description_) {
431 return Super::set_direction(direction);
432 }
433 return real_description_->set_direction(direction);
434}
435bool DataContentDescription::rtcp_mux() const {
436 if (!real_description_) {
437 return Super::rtcp_mux();
438 }
439 return real_description_->rtcp_mux();
440}
441void DataContentDescription::set_rtcp_mux(bool mux) {
442 if (!real_description_) {
443 Super::set_rtcp_mux(mux);
444 return;
445 }
446 real_description_->set_rtcp_mux(mux);
447}
448bool DataContentDescription::rtcp_reduced_size() const {
449 if (!real_description_) {
450 return Super::rtcp_reduced_size();
451 }
452 return real_description_->rtcp_reduced_size();
453}
454void DataContentDescription::set_rtcp_reduced_size(bool reduced_size) {
455 if (!real_description_) {
456 return Super::set_rtcp_reduced_size(reduced_size);
457 }
458
459 return real_description_->set_rtcp_reduced_size(reduced_size);
460}
461int DataContentDescription::bandwidth() const {
462 if (!real_description_) {
463 return Super::bandwidth();
464 }
465
466 return real_description_->bandwidth();
467}
468void DataContentDescription::set_bandwidth(int bandwidth) {
469 if (!real_description_) {
470 return Super::set_bandwidth(bandwidth);
471 }
472
473 return real_description_->set_bandwidth(bandwidth);
474}
475const std::vector<CryptoParams>& DataContentDescription::cryptos() const {
476 if (!real_description_) {
477 return Super::cryptos();
478 }
479
480 return real_description_->cryptos();
481}
482void DataContentDescription::AddCrypto(const CryptoParams& params) {
483 if (!real_description_) {
484 return Super::AddCrypto(params);
485 }
486
487 return real_description_->AddCrypto(params);
488}
489void DataContentDescription::set_cryptos(
490 const std::vector<CryptoParams>& cryptos) {
491 if (!real_description_) {
492 return Super::set_cryptos(cryptos);
493 }
494
495 return real_description_->set_cryptos(cryptos);
496}
497const RtpHeaderExtensions& DataContentDescription::rtp_header_extensions()
498 const {
499 if (!real_description_) {
500 return Super::rtp_header_extensions();
501 }
502
503 return real_description_->rtp_header_extensions();
504}
505void DataContentDescription::set_rtp_header_extensions(
506 const RtpHeaderExtensions& extensions) {
507 if (!real_description_) {
508 return Super::set_rtp_header_extensions(extensions);
509 }
510
511 return real_description_->set_rtp_header_extensions(extensions);
512}
513void DataContentDescription::AddRtpHeaderExtension(
514 const webrtc::RtpExtension& ext) {
515 if (!real_description_) {
516 return Super::AddRtpHeaderExtension(ext);
517 }
518 return real_description_->AddRtpHeaderExtension(ext);
519}
520void DataContentDescription::AddRtpHeaderExtension(
521 const cricket::RtpHeaderExtension& ext) {
522 if (!real_description_) {
523 return Super::AddRtpHeaderExtension(ext);
524 }
525 return real_description_->AddRtpHeaderExtension(ext);
526}
527void DataContentDescription::ClearRtpHeaderExtensions() {
528 if (!real_description_) {
529 return Super::ClearRtpHeaderExtensions();
530 }
531 return real_description_->ClearRtpHeaderExtensions();
532}
533bool DataContentDescription::rtp_header_extensions_set() const {
534 if (!real_description_) {
535 return Super::rtp_header_extensions_set();
536 }
537 return real_description_->rtp_header_extensions_set();
538}
539const StreamParamsVec& DataContentDescription::streams() const {
540 if (!real_description_) {
541 return Super::streams();
542 }
543 return real_description_->streams();
544}
545StreamParamsVec& DataContentDescription::mutable_streams() {
546 if (!real_description_) {
547 return Super::mutable_streams();
548 }
549 return real_description_->mutable_streams();
550}
551void DataContentDescription::AddStream(const StreamParams& stream) {
552 if (!real_description_) {
553 return Super::AddStream(stream);
554 }
555 return real_description_->AddStream(stream);
556}
557void DataContentDescription::SetCnameIfEmpty(const std::string& cname) {
558 if (!real_description_) {
559 return Super::SetCnameIfEmpty(cname);
560 }
561 return real_description_->SetCnameIfEmpty(cname);
562}
563uint32_t DataContentDescription::first_ssrc() const {
564 if (!real_description_) {
565 return Super::first_ssrc();
566 }
567 return real_description_->first_ssrc();
568}
569bool DataContentDescription::has_ssrcs() const {
570 if (!real_description_) {
571 return Super::has_ssrcs();
572 }
573 return real_description_->has_ssrcs();
574}
575void DataContentDescription::set_conference_mode(bool enable) {
576 if (!real_description_) {
577 return Super::set_conference_mode(enable);
578 }
579 return real_description_->set_conference_mode(enable);
580}
581bool DataContentDescription::conference_mode() const {
582 if (!real_description_) {
583 return Super::conference_mode();
584 }
585 return real_description_->conference_mode();
586}
587void DataContentDescription::set_connection_address(
588 const rtc::SocketAddress& address) {
589 if (!real_description_) {
590 return Super::set_connection_address(address);
591 }
592 return real_description_->set_connection_address(address);
593}
594const rtc::SocketAddress& DataContentDescription::connection_address() const {
595 if (!real_description_) {
596 return Super::connection_address();
597 }
598 return real_description_->connection_address();
599}
600void DataContentDescription::set_extmap_allow_mixed_enum(
601 ExtmapAllowMixed mixed) {
602 if (!real_description_) {
603 return Super::set_extmap_allow_mixed_enum(mixed);
604 }
605 return real_description_->set_extmap_allow_mixed_enum(mixed);
606}
607MediaContentDescription::ExtmapAllowMixed
608DataContentDescription::extmap_allow_mixed_enum() const {
609 if (!real_description_) {
610 return Super::extmap_allow_mixed_enum();
611 }
612 return real_description_->extmap_allow_mixed_enum();
613}
614bool DataContentDescription::HasSimulcast() const {
615 if (!real_description_) {
616 return Super::HasSimulcast();
617 }
618 return real_description_->HasSimulcast();
619}
620SimulcastDescription& DataContentDescription::simulcast_description() {
621 if (!real_description_) {
622 return Super::simulcast_description();
623 }
624 return real_description_->simulcast_description();
625}
626const SimulcastDescription& DataContentDescription::simulcast_description()
627 const {
628 if (!real_description_) {
629 return Super::simulcast_description();
630 }
631 return real_description_->simulcast_description();
632}
633void DataContentDescription::set_simulcast_description(
634 const SimulcastDescription& simulcast) {
635 if (!real_description_) {
636 return Super::set_simulcast_description(simulcast);
637 }
638 return real_description_->set_simulcast_description(simulcast);
639}
640
641// Methods defined in MediaContentDescriptionImpl.
642// For SCTP, we implement codec handling.
643// For RTP, we pass the codecs.
644// In the cases where type hasn't been decided yet, we return dummies.
645
646const std::vector<DataCodec>& DataContentDescription::codecs() const {
647 if (IsSctp() || !real_description_) {
648 return Super::codecs();
649 }
650 return real_description_->as_rtp_data()->codecs();
651}
652
653void DataContentDescription::set_codecs(const std::vector<DataCodec>& codecs) {
654 if (IsSctp() || !real_description_) {
655 Super::set_codecs(codecs);
656 } else {
657 EnsureIsRtp();
658 real_description_->as_rtp_data()->set_codecs(codecs);
659 }
660}
661
662bool DataContentDescription::HasCodec(int id) {
663 if (IsSctp() || !real_description_) {
664 return Super::HasCodec(id);
665 }
666 return real_description_->as_rtp_data()->HasCodec(id);
667}
668
669void DataContentDescription::AddCodec(const DataCodec& codec) {
670 if (IsSctp() || !real_description_) {
671 Super::AddCodec(codec);
672 } else {
673 EnsureIsRtp();
674 real_description_->as_rtp_data()->AddCodec(codec);
675 }
676}
677
678void DataContentDescription::AddOrReplaceCodec(const DataCodec& codec) {
679 if (IsSctp() || real_description_) {
680 Super::AddOrReplaceCodec(codec);
681 } else {
682 EnsureIsRtp();
683 real_description_->as_rtp_data()->AddOrReplaceCodec(codec);
684 }
685}
686
687void DataContentDescription::AddCodecs(const std::vector<DataCodec>& codecs) {
688 if (IsSctp() || !real_description_) {
689 Super::AddCodecs(codecs);
690 } else {
691 EnsureIsRtp();
692 real_description_->as_rtp_data()->AddCodecs(codecs);
693 }
694}
695
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000696} // namespace cricket