blob: df31163a0333eb7b6e317160673a79c131008c61 [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(
Harald Alvestranda33a8602019-05-28 11:33:50 +0200193 description->deprecated_as_data()->Unshim(&should_delete));
Harald Alvestrand5fc28b12019-05-13 13:36:16 +0200194 }
195 }
196 if (description->as_sctp()) {
197 if (description->as_sctp() != description) {
198 content->set_media_description(
Harald Alvestranda33a8602019-05-28 11:33:50 +0200199 description->deprecated_as_data()->Unshim(&should_delete));
Harald Alvestrand5fc28b12019-05-13 13:36:16 +0200200 }
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
Harald Alvestranda33a8602019-05-28 11:33:50 +0200295DataContentDescription* RtpDataContentDescription::deprecated_as_data() {
Harald Alvestrand5fc28b12019-05-13 13:36:16 +0200296 if (!shim_) {
297 shim_.reset(new DataContentDescription(this));
298 }
299 return shim_.get();
300}
301
Harald Alvestranda33a8602019-05-28 11:33:50 +0200302DataContentDescription* RtpDataContentDescription::as_data() {
303 return deprecated_as_data();
304}
305
Harald Alvestrand5fc28b12019-05-13 13:36:16 +0200306const DataContentDescription* RtpDataContentDescription::as_data() const {
307 return const_cast<RtpDataContentDescription*>(this)->as_data();
308}
309
Harald Alvestranda33a8602019-05-28 11:33:50 +0200310DataContentDescription* SctpDataContentDescription::deprecated_as_data() {
Harald Alvestrand5fc28b12019-05-13 13:36:16 +0200311 if (!shim_) {
312 shim_.reset(new DataContentDescription(this));
313 }
314 return shim_.get();
315}
316
Harald Alvestranda33a8602019-05-28 11:33:50 +0200317DataContentDescription* SctpDataContentDescription::as_data() {
318 return deprecated_as_data();
319}
320
Harald Alvestrand5fc28b12019-05-13 13:36:16 +0200321const DataContentDescription* SctpDataContentDescription::as_data() const {
Harald Alvestranda33a8602019-05-28 11:33:50 +0200322 return const_cast<SctpDataContentDescription*>(this)->deprecated_as_data();
Harald Alvestrand5fc28b12019-05-13 13:36:16 +0200323}
324
325DataContentDescription::DataContentDescription() {
326 // In this case, we will initialize |owned_description_| as soon as
327 // we are told what protocol to use via set_protocol or another function
328 // calling CreateShimTarget.
329}
330
331DataContentDescription::DataContentDescription(
332 SctpDataContentDescription* wrapped)
333 : real_description_(wrapped) {
334 // SctpDataContentDescription doesn't contain codecs, but code
335 // using DataContentDescription expects to see one.
336 Super::AddCodec(
337 cricket::DataCodec(kGoogleSctpDataCodecPlType, kGoogleSctpDataCodecName));
338}
339
340DataContentDescription::DataContentDescription(
341 RtpDataContentDescription* wrapped)
342 : real_description_(wrapped) {}
343
344DataContentDescription::DataContentDescription(
345 const DataContentDescription* o) {
346 if (o->real_description_) {
347 owned_description_ = absl::WrapUnique(o->real_description_->Copy());
348 real_description_ = owned_description_.get();
349 } else {
350 // Copy all information collected so far, including codecs.
351 Super::operator=(*o);
352 }
353}
354
355void DataContentDescription::CreateShimTarget(bool is_sctp) {
356 RTC_LOG(LS_INFO) << "Creating shim target, is_sctp is " << is_sctp;
357 RTC_CHECK(!owned_description_.get());
358 if (is_sctp) {
359 owned_description_ = absl::make_unique<SctpDataContentDescription>();
360 // Copy all information collected so far, except codecs.
361 owned_description_->MediaContentDescription::operator=(*this);
362 } else {
363 owned_description_ = absl::make_unique<RtpDataContentDescription>();
364 // Copy all information collected so far, including codecs.
365 owned_description_->as_rtp_data()
366 ->MediaContentDescriptionImpl<RtpDataCodec>::operator=(*this);
367 }
368 real_description_ = owned_description_.get();
369}
370
371MediaContentDescription* DataContentDescription::Unshim(bool* should_delete) {
372 // If protocol isn't decided at this point, we have a problem.
373 RTC_CHECK(real_description_);
374 if (owned_description_) {
375 // Pass ownership to caller, and remove myself.
376 // Since caller can't know if I was owner or owned, tell them.
377 MediaContentDescription* to_return = owned_description_.release();
378 *should_delete = true;
379 return to_return;
380 }
381 // Real object is owner, and presumably referenced from elsewhere.
382 *should_delete = false;
383 return real_description_;
384}
385
386void DataContentDescription::set_protocol(const std::string& protocol) {
387 if (!real_description_) {
388 CreateShimTarget(IsSctpProtocol(protocol));
389 }
390 real_description_->set_protocol(protocol);
391}
392
393bool DataContentDescription::IsSctp() const {
394 return (real_description_ && real_description_->as_sctp());
395}
396
397void DataContentDescription::EnsureIsRtp() {
398 RTC_CHECK(real_description_);
399 RTC_CHECK(real_description_->as_rtp_data());
400}
401
402RtpDataContentDescription* DataContentDescription::as_rtp_data() {
403 if (real_description_) {
404 return real_description_->as_rtp_data();
405 }
406 return nullptr;
407}
408
409SctpDataContentDescription* DataContentDescription::as_sctp() {
410 if (real_description_) {
411 return real_description_->as_sctp();
412 }
413 return nullptr;
414}
415
416// Override all methods defined in MediaContentDescription.
417bool DataContentDescription::has_codecs() const {
418 if (!real_description_) {
419 return Super::has_codecs();
420 }
421 return real_description_->has_codecs();
422}
423std::string DataContentDescription::protocol() const {
424 if (!real_description_) {
425 return Super::protocol();
426 }
427 return real_description_->protocol();
428}
429
430webrtc::RtpTransceiverDirection DataContentDescription::direction() const {
431 if (!real_description_) {
432 return Super::direction();
433 }
434 return real_description_->direction();
435}
436void DataContentDescription::set_direction(
437 webrtc::RtpTransceiverDirection direction) {
438 if (!real_description_) {
439 return Super::set_direction(direction);
440 }
441 return real_description_->set_direction(direction);
442}
443bool DataContentDescription::rtcp_mux() const {
444 if (!real_description_) {
445 return Super::rtcp_mux();
446 }
447 return real_description_->rtcp_mux();
448}
449void DataContentDescription::set_rtcp_mux(bool mux) {
450 if (!real_description_) {
451 Super::set_rtcp_mux(mux);
452 return;
453 }
454 real_description_->set_rtcp_mux(mux);
455}
456bool DataContentDescription::rtcp_reduced_size() const {
457 if (!real_description_) {
458 return Super::rtcp_reduced_size();
459 }
460 return real_description_->rtcp_reduced_size();
461}
462void DataContentDescription::set_rtcp_reduced_size(bool reduced_size) {
463 if (!real_description_) {
464 return Super::set_rtcp_reduced_size(reduced_size);
465 }
466
467 return real_description_->set_rtcp_reduced_size(reduced_size);
468}
469int DataContentDescription::bandwidth() const {
470 if (!real_description_) {
471 return Super::bandwidth();
472 }
473
474 return real_description_->bandwidth();
475}
476void DataContentDescription::set_bandwidth(int bandwidth) {
477 if (!real_description_) {
478 return Super::set_bandwidth(bandwidth);
479 }
480
481 return real_description_->set_bandwidth(bandwidth);
482}
483const std::vector<CryptoParams>& DataContentDescription::cryptos() const {
484 if (!real_description_) {
485 return Super::cryptos();
486 }
487
488 return real_description_->cryptos();
489}
490void DataContentDescription::AddCrypto(const CryptoParams& params) {
491 if (!real_description_) {
492 return Super::AddCrypto(params);
493 }
494
495 return real_description_->AddCrypto(params);
496}
497void DataContentDescription::set_cryptos(
498 const std::vector<CryptoParams>& cryptos) {
499 if (!real_description_) {
500 return Super::set_cryptos(cryptos);
501 }
502
503 return real_description_->set_cryptos(cryptos);
504}
505const RtpHeaderExtensions& DataContentDescription::rtp_header_extensions()
506 const {
507 if (!real_description_) {
508 return Super::rtp_header_extensions();
509 }
510
511 return real_description_->rtp_header_extensions();
512}
513void DataContentDescription::set_rtp_header_extensions(
514 const RtpHeaderExtensions& extensions) {
515 if (!real_description_) {
516 return Super::set_rtp_header_extensions(extensions);
517 }
518
519 return real_description_->set_rtp_header_extensions(extensions);
520}
521void DataContentDescription::AddRtpHeaderExtension(
522 const webrtc::RtpExtension& ext) {
523 if (!real_description_) {
524 return Super::AddRtpHeaderExtension(ext);
525 }
526 return real_description_->AddRtpHeaderExtension(ext);
527}
528void DataContentDescription::AddRtpHeaderExtension(
529 const cricket::RtpHeaderExtension& ext) {
530 if (!real_description_) {
531 return Super::AddRtpHeaderExtension(ext);
532 }
533 return real_description_->AddRtpHeaderExtension(ext);
534}
535void DataContentDescription::ClearRtpHeaderExtensions() {
536 if (!real_description_) {
537 return Super::ClearRtpHeaderExtensions();
538 }
539 return real_description_->ClearRtpHeaderExtensions();
540}
541bool DataContentDescription::rtp_header_extensions_set() const {
542 if (!real_description_) {
543 return Super::rtp_header_extensions_set();
544 }
545 return real_description_->rtp_header_extensions_set();
546}
547const StreamParamsVec& DataContentDescription::streams() const {
548 if (!real_description_) {
549 return Super::streams();
550 }
551 return real_description_->streams();
552}
553StreamParamsVec& DataContentDescription::mutable_streams() {
554 if (!real_description_) {
555 return Super::mutable_streams();
556 }
557 return real_description_->mutable_streams();
558}
559void DataContentDescription::AddStream(const StreamParams& stream) {
560 if (!real_description_) {
561 return Super::AddStream(stream);
562 }
563 return real_description_->AddStream(stream);
564}
565void DataContentDescription::SetCnameIfEmpty(const std::string& cname) {
566 if (!real_description_) {
567 return Super::SetCnameIfEmpty(cname);
568 }
569 return real_description_->SetCnameIfEmpty(cname);
570}
571uint32_t DataContentDescription::first_ssrc() const {
572 if (!real_description_) {
573 return Super::first_ssrc();
574 }
575 return real_description_->first_ssrc();
576}
577bool DataContentDescription::has_ssrcs() const {
578 if (!real_description_) {
579 return Super::has_ssrcs();
580 }
581 return real_description_->has_ssrcs();
582}
583void DataContentDescription::set_conference_mode(bool enable) {
584 if (!real_description_) {
585 return Super::set_conference_mode(enable);
586 }
587 return real_description_->set_conference_mode(enable);
588}
589bool DataContentDescription::conference_mode() const {
590 if (!real_description_) {
591 return Super::conference_mode();
592 }
593 return real_description_->conference_mode();
594}
595void DataContentDescription::set_connection_address(
596 const rtc::SocketAddress& address) {
597 if (!real_description_) {
598 return Super::set_connection_address(address);
599 }
600 return real_description_->set_connection_address(address);
601}
602const rtc::SocketAddress& DataContentDescription::connection_address() const {
603 if (!real_description_) {
604 return Super::connection_address();
605 }
606 return real_description_->connection_address();
607}
608void DataContentDescription::set_extmap_allow_mixed_enum(
609 ExtmapAllowMixed mixed) {
610 if (!real_description_) {
611 return Super::set_extmap_allow_mixed_enum(mixed);
612 }
613 return real_description_->set_extmap_allow_mixed_enum(mixed);
614}
615MediaContentDescription::ExtmapAllowMixed
616DataContentDescription::extmap_allow_mixed_enum() const {
617 if (!real_description_) {
618 return Super::extmap_allow_mixed_enum();
619 }
620 return real_description_->extmap_allow_mixed_enum();
621}
622bool DataContentDescription::HasSimulcast() const {
623 if (!real_description_) {
624 return Super::HasSimulcast();
625 }
626 return real_description_->HasSimulcast();
627}
628SimulcastDescription& DataContentDescription::simulcast_description() {
629 if (!real_description_) {
630 return Super::simulcast_description();
631 }
632 return real_description_->simulcast_description();
633}
634const SimulcastDescription& DataContentDescription::simulcast_description()
635 const {
636 if (!real_description_) {
637 return Super::simulcast_description();
638 }
639 return real_description_->simulcast_description();
640}
641void DataContentDescription::set_simulcast_description(
642 const SimulcastDescription& simulcast) {
643 if (!real_description_) {
644 return Super::set_simulcast_description(simulcast);
645 }
646 return real_description_->set_simulcast_description(simulcast);
647}
648
649// Methods defined in MediaContentDescriptionImpl.
650// For SCTP, we implement codec handling.
651// For RTP, we pass the codecs.
652// In the cases where type hasn't been decided yet, we return dummies.
653
654const std::vector<DataCodec>& DataContentDescription::codecs() const {
655 if (IsSctp() || !real_description_) {
656 return Super::codecs();
657 }
658 return real_description_->as_rtp_data()->codecs();
659}
660
661void DataContentDescription::set_codecs(const std::vector<DataCodec>& codecs) {
662 if (IsSctp() || !real_description_) {
663 Super::set_codecs(codecs);
664 } else {
665 EnsureIsRtp();
666 real_description_->as_rtp_data()->set_codecs(codecs);
667 }
668}
669
670bool DataContentDescription::HasCodec(int id) {
671 if (IsSctp() || !real_description_) {
672 return Super::HasCodec(id);
673 }
674 return real_description_->as_rtp_data()->HasCodec(id);
675}
676
677void DataContentDescription::AddCodec(const DataCodec& codec) {
678 if (IsSctp() || !real_description_) {
679 Super::AddCodec(codec);
680 } else {
681 EnsureIsRtp();
682 real_description_->as_rtp_data()->AddCodec(codec);
683 }
684}
685
686void DataContentDescription::AddOrReplaceCodec(const DataCodec& codec) {
687 if (IsSctp() || real_description_) {
688 Super::AddOrReplaceCodec(codec);
689 } else {
690 EnsureIsRtp();
691 real_description_->as_rtp_data()->AddOrReplaceCodec(codec);
692 }
693}
694
695void DataContentDescription::AddCodecs(const std::vector<DataCodec>& codecs) {
696 if (IsSctp() || !real_description_) {
697 Super::AddCodecs(codecs);
698 } else {
699 EnsureIsRtp();
700 real_description_->as_rtp_data()->AddCodecs(codecs);
701 }
702}
703
henrike@webrtc.org269fb4b2014-10-28 22:20:11 +0000704} // namespace cricket