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

Side by Side Diff: webrtc/pc/mediasession.cc

Issue 2600153004: Adding support for Unified Plan offer/answer negotiation.
Patch Set: Got tests working (aside from ones that need to be completely rewritten) Created 3 years, 11 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/pc/mediasession.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2004 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2004 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 it != crypto_suites.end(); ++it) { 152 it != crypto_suites.end(); ++it) {
153 if (!AddCryptoParams(*it, &cryptos)) { 153 if (!AddCryptoParams(*it, &cryptos)) {
154 return false; 154 return false;
155 } 155 }
156 } 156 }
157 AddMediaCryptos(cryptos, media); 157 AddMediaCryptos(cryptos, media);
158 return true; 158 return true;
159 } 159 }
160 #endif 160 #endif
161 161
162 const CryptoParamsVec* GetCryptos(const MediaContentDescription* media) { 162 const CryptoParamsVec* GetCryptos(const ContentInfo* content) {
163 if (!media) { 163 if (!content) {
164 return NULL; 164 return nullptr;
165 } 165 }
166 return &media->cryptos(); 166 return &(static_cast<const MediaContentDescription*>(content->description)
167 ->cryptos());
167 } 168 }
168 169
169 bool FindMatchingCrypto(const CryptoParamsVec& cryptos, 170 bool FindMatchingCrypto(const CryptoParamsVec& cryptos,
170 const CryptoParams& crypto, 171 const CryptoParams& crypto,
171 CryptoParams* out) { 172 CryptoParams* out) {
172 for (CryptoParamsVec::const_iterator it = cryptos.begin(); 173 for (CryptoParamsVec::const_iterator it = cryptos.begin();
173 it != cryptos.end(); ++it) { 174 it != cryptos.end(); ++it) {
174 if (crypto.Matches(*it)) { 175 if (crypto.Matches(*it)) {
175 *out = *it; 176 *out = *it;
176 return true; 177 return true;
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 } 326 }
326 327
327 // Loops through all Id in |ids| and changes its id if it is 328 // Loops through all Id in |ids| and changes its id if it is
328 // already in use by another IdStruct. Call this methods with all Id 329 // already in use by another IdStruct. Call this methods with all Id
329 // in a session description to make sure no duplicate ids exists. 330 // in a session description to make sure no duplicate ids exists.
330 // Note that typename Id must be a type of IdStruct. 331 // Note that typename Id must be a type of IdStruct.
331 template <typename Id> 332 template <typename Id>
332 void FindAndSetIdUsed(std::vector<Id>* ids) { 333 void FindAndSetIdUsed(std::vector<Id>* ids) {
333 for (typename std::vector<Id>::iterator it = ids->begin(); 334 for (typename std::vector<Id>::iterator it = ids->begin();
334 it != ids->end(); ++it) { 335 it != ids->end(); ++it) {
335 FindAndSetIdUsed(&*it); 336 FindAndSetIdUsed(&*it, true);
336 } 337 }
337 } 338 }
338 339
339 // Finds and sets an unused id if the |idstruct| id is already in use. 340 // Finds and sets an unused id if the |idstruct| id is already in use.
340 void FindAndSetIdUsed(IdStruct* idstruct) { 341 // If |can_reassign_id| is false, the ID of |idstruct| won't be reassigned,
342 // and ID conflicts will simply result in false being returned.
343 bool FindAndSetIdUsed(IdStruct* idstruct, bool can_reassign_id) {
341 const int original_id = idstruct->id; 344 const int original_id = idstruct->id;
342 int new_id = idstruct->id; 345 int new_id = idstruct->id;
343 346
344 if (original_id > max_allowed_id_ || original_id < min_allowed_id_) { 347 if (original_id > max_allowed_id_ || original_id < min_allowed_id_) {
345 // If the original id is not in range - this is an id that can't be 348 // If the original id is not in range - this is an id that can't be
346 // dynamically changed. 349 // dynamically changed.
347 return; 350 return true;
348 } 351 }
349 352
350 if (IsIdUsed(original_id)) { 353 if (IsIdUsed(original_id)) {
354 if (!can_reassign_id) {
355 return false;
356 }
351 new_id = FindUnusedId(); 357 new_id = FindUnusedId();
352 LOG(LS_WARNING) << "Duplicate id found. Reassigning from " << original_id 358 LOG(LS_WARNING) << "Duplicate id found. Reassigning from " << original_id
353 << " to " << new_id; 359 << " to " << new_id;
354 idstruct->id = new_id; 360 idstruct->id = new_id;
355 } 361 }
356 SetIdUsed(new_id); 362 SetIdUsed(new_id);
363 return true;
357 } 364 }
358 365
359 private: 366 private:
360 // Returns the first unused id in reverse order. 367 // Returns the first unused id in reverse order.
361 // This hopefully reduce the risk of more collisions. We want to change the 368 // This hopefully reduce the risk of more collisions. We want to change the
362 // default ids as little as possible. 369 // default ids as little as possible.
363 int FindUnusedId() { 370 int FindUnusedId() {
364 while (IsIdUsed(next_id_) && next_id_ >= min_allowed_id_) { 371 while (IsIdUsed(next_id_) && next_id_ >= min_allowed_id_) {
365 --next_id_; 372 --next_id_;
366 } 373 }
(...skipping 16 matching lines...) Expand all
383 }; 390 };
384 391
385 // Helper class used for finding duplicate RTP payload types among audio, video 392 // Helper class used for finding duplicate RTP payload types among audio, video
386 // and data codecs. When bundle is used the payload types may not collide. 393 // and data codecs. When bundle is used the payload types may not collide.
387 class UsedPayloadTypes : public UsedIds<Codec> { 394 class UsedPayloadTypes : public UsedIds<Codec> {
388 public: 395 public:
389 UsedPayloadTypes() 396 UsedPayloadTypes()
390 : UsedIds<Codec>(kDynamicPayloadTypeMin, kDynamicPayloadTypeMax) { 397 : UsedIds<Codec>(kDynamicPayloadTypeMin, kDynamicPayloadTypeMax) {
391 } 398 }
392 399
393
394 private: 400 private:
395 static const int kDynamicPayloadTypeMin = 96; 401 static const int kDynamicPayloadTypeMin = 96;
396 static const int kDynamicPayloadTypeMax = 127; 402 static const int kDynamicPayloadTypeMax = 127;
397 }; 403 };
398 404
399 // Helper class used for finding duplicate RTP Header extension ids among 405 // Helper class used for finding duplicate RTP Header extension ids among
400 // audio and video extensions. 406 // audio and video extensions.
401 class UsedRtpHeaderExtensionIds : public UsedIds<webrtc::RtpExtension> { 407 class UsedRtpHeaderExtensionIds : public UsedIds<webrtc::RtpExtension> {
402 public: 408 public:
403 UsedRtpHeaderExtensionIds() 409 UsedRtpHeaderExtensionIds()
404 : UsedIds<webrtc::RtpExtension>(kLocalIdMin, kLocalIdMax) {} 410 : UsedIds<webrtc::RtpExtension>(kLocalIdMin, kLocalIdMax) {}
405 411
406 private: 412 private:
407 // Min and Max local identifier for one-byte header extensions, per RFC5285. 413 // Min and Max local identifier for one-byte header extensions, per RFC5285.
408 static const int kLocalIdMin = 1; 414 static const int kLocalIdMin = 1;
409 static const int kLocalIdMax = 14; 415 static const int kLocalIdMax = 14;
410 }; 416 };
411 417
412 static bool IsSctp(const MediaContentDescription* desc) { 418 static bool IsSctp(const MediaContentDescription* desc) {
413 return ((desc->protocol() == kMediaProtocolSctp) || 419 return ((desc->protocol() == kMediaProtocolSctp) ||
414 (desc->protocol() == kMediaProtocolDtlsSctp)); 420 (desc->protocol() == kMediaProtocolDtlsSctp));
415 } 421 }
416 422
417 // Adds a StreamParams for each Stream in Streams with media type 423 // Adds a StreamParams for each SenderOptions in |sender_options| to
418 // media_type to content_description. 424 // content_description.
419 // |current_params| - All currently known StreamParams of any media type. 425 // |current_params| - All currently known StreamParams.
420 template <class C> 426 template <class C>
421 static bool AddStreamParams(MediaType media_type, 427 static bool AddStreamParams(
422 const MediaSessionOptions& options, 428 const std::vector<SenderOptions>& sender_options,
423 StreamParamsVec* current_streams, 429 const std::string& rtcp_cname,
424 MediaContentDescriptionImpl<C>* content_description, 430 StreamParamsVec* current_streams,
425 const bool add_legacy_stream) { 431 MediaContentDescriptionImpl<C>* content_description) {
426 // SCTP streams are not negotiated using SDP/ContentDescriptions. 432 // SCTP streams are not negotiated using SDP/ContentDescriptions.
427 if (IsSctp(content_description)) { 433 if (IsSctp(content_description)) {
428 return true; 434 return true;
429 } 435 }
430 436
431 const bool include_rtx_streams = 437 const bool include_rtx_streams =
432 ContainsRtxCodec(content_description->codecs()); 438 ContainsRtxCodec(content_description->codecs());
433 439
434 const MediaSessionOptions::Streams& streams = options.streams;
435 if (streams.empty() && add_legacy_stream) {
436 // TODO(perkj): Remove this legacy stream when all apps use StreamParams.
437 std::vector<uint32_t> ssrcs;
438 int num_ssrcs = include_rtx_streams ? 2 : 1;
439 GenerateSsrcs(*current_streams, num_ssrcs, &ssrcs);
440 if (include_rtx_streams) {
441 content_description->AddLegacyStream(ssrcs[0], ssrcs[1]);
442 content_description->set_multistream(true);
443 } else {
444 content_description->AddLegacyStream(ssrcs[0]);
445 }
446 return true;
447 }
448
449 const bool include_flexfec_stream = 440 const bool include_flexfec_stream =
450 ContainsFlexfecCodec(content_description->codecs()); 441 ContainsFlexfecCodec(content_description->codecs());
451 442
452 MediaSessionOptions::Streams::const_iterator stream_it; 443 for (const SenderOptions& sender : sender_options) {
453 for (stream_it = streams.begin();
454 stream_it != streams.end(); ++stream_it) {
455 if (stream_it->type != media_type)
456 continue; // Wrong media type.
457
458 const StreamParams* param =
459 GetStreamByIds(*current_streams, "", stream_it->id);
460 // groupid is empty for StreamParams generated using 444 // groupid is empty for StreamParams generated using
461 // MediaSessionDescriptionFactory. 445 // MediaSessionDescriptionFactory.
446 const StreamParams* param =
447 GetStreamByIds(*current_streams, "", sender.track_id);
462 if (!param) { 448 if (!param) {
463 // This is a new stream. 449 // This is a new sender.
464 std::vector<uint32_t> ssrcs; 450 std::vector<uint32_t> ssrcs;
465 GenerateSsrcs(*current_streams, stream_it->num_sim_layers, &ssrcs); 451 GenerateSsrcs(*current_streams, sender.num_sim_layers, &ssrcs);
466 StreamParams stream_param; 452 StreamParams stream_param;
467 stream_param.id = stream_it->id; 453 stream_param.id = sender.track_id;
468 // Add the generated ssrc. 454 // Add the generated ssrc.
469 for (size_t i = 0; i < ssrcs.size(); ++i) { 455 for (size_t i = 0; i < ssrcs.size(); ++i) {
470 stream_param.ssrcs.push_back(ssrcs[i]); 456 stream_param.ssrcs.push_back(ssrcs[i]);
471 } 457 }
472 if (stream_it->num_sim_layers > 1) { 458 if (sender.num_sim_layers > 1) {
473 SsrcGroup group(kSimSsrcGroupSemantics, stream_param.ssrcs); 459 SsrcGroup group(kSimSsrcGroupSemantics, stream_param.ssrcs);
474 stream_param.ssrc_groups.push_back(group); 460 stream_param.ssrc_groups.push_back(group);
475 } 461 }
476 // Generate extra ssrcs for include_rtx_streams case. 462 // Generate extra ssrcs for include_rtx_streams case.
477 if (include_rtx_streams) { 463 if (include_rtx_streams) {
478 // Generate an RTX ssrc for every ssrc in the group. 464 // Generate an RTX ssrc for every ssrc in the group.
479 std::vector<uint32_t> rtx_ssrcs; 465 std::vector<uint32_t> rtx_ssrcs;
480 GenerateSsrcs(*current_streams, static_cast<int>(ssrcs.size()), 466 GenerateSsrcs(*current_streams, static_cast<int>(ssrcs.size()),
481 &rtx_ssrcs); 467 &rtx_ssrcs);
482 for (size_t i = 0; i < ssrcs.size(); ++i) { 468 for (size_t i = 0; i < ssrcs.size(); ++i) {
483 stream_param.AddFidSsrc(ssrcs[i], rtx_ssrcs[i]); 469 stream_param.AddFidSsrc(ssrcs[i], rtx_ssrcs[i]);
484 } 470 }
485 content_description->set_multistream(true); 471 content_description->set_multistream(true);
486 } 472 }
487 // Generate extra ssrc for include_flexfec_stream case. 473 // Generate extra ssrc for include_flexfec_stream case.
488 if (include_flexfec_stream) { 474 if (include_flexfec_stream) {
489 // TODO(brandtr): Update when we support multistream protection. 475 // TODO(brandtr): Update when we support multistream protection.
490 if (ssrcs.size() == 1) { 476 if (ssrcs.size() == 1) {
491 std::vector<uint32_t> flexfec_ssrcs; 477 std::vector<uint32_t> flexfec_ssrcs;
492 GenerateSsrcs(*current_streams, 1, &flexfec_ssrcs); 478 GenerateSsrcs(*current_streams, 1, &flexfec_ssrcs);
493 stream_param.AddFecFrSsrc(ssrcs[0], flexfec_ssrcs[0]); 479 stream_param.AddFecFrSsrc(ssrcs[0], flexfec_ssrcs[0]);
494 content_description->set_multistream(true); 480 content_description->set_multistream(true);
495 } else if (!ssrcs.empty()) { 481 } else if (!ssrcs.empty()) {
496 LOG(LS_WARNING) 482 LOG(LS_WARNING)
497 << "Our FlexFEC implementation only supports protecting " 483 << "Our FlexFEC implementation only supports protecting "
498 << "a single media streams. This session has multiple " 484 << "a single media streams. This session has multiple "
499 << "media streams however, so no FlexFEC SSRC will be generated."; 485 << "media streams however, so no FlexFEC SSRC will be generated.";
500 } 486 }
501 } 487 }
502 stream_param.cname = options.rtcp_cname; 488 stream_param.cname = rtcp_cname;
503 stream_param.sync_label = stream_it->sync_label; 489 stream_param.sync_label = sender.stream_id;
504 content_description->AddStream(stream_param); 490 content_description->AddStream(stream_param);
505 491
506 // Store the new StreamParams in current_streams. 492 // Store the new StreamParams in current_streams.
507 // This is necessary so that we can use the CNAME for other media types. 493 // This is necessary so that we can use the CNAME for other media types.
508 current_streams->push_back(stream_param); 494 current_streams->push_back(stream_param);
509 } else { 495 } else {
510 content_description->AddStream(*param); 496 content_description->AddStream(*param);
511 } 497 }
512 } 498 }
513 return true; 499 return true;
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 } 697 }
712 } 698 }
713 return false; 699 return false;
714 } 700 }
715 701
716 template <class C> 702 template <class C>
717 static bool IsFlexfecCodec(const C& codec) { 703 static bool IsFlexfecCodec(const C& codec) {
718 return stricmp(codec.name.c_str(), kFlexfecCodecName) == 0; 704 return stricmp(codec.name.c_str(), kFlexfecCodecName) == 0;
719 } 705 }
720 706
721 static TransportOptions GetTransportOptions(const MediaSessionOptions& options, 707 // Create a media content to be offered in a session-initiate for the
722 const std::string& content_name) { 708 // given |sender_options|, according to the given options.rtcp_mux,
723 TransportOptions transport_options; 709 // session_options.is_muc,
724 auto it = options.transport_options.find(content_name); 710 // codecs, secure_transport, crypto, and current_streams. If we don't
725 if (it != options.transport_options.end()) {
726 transport_options = it->second;
727 }
728 transport_options.enable_ice_renomination = options.enable_ice_renomination;
729 return transport_options;
730 }
731
732 // Create a media content to be offered in a session-initiate,
733 // according to the given options.rtcp_mux, options.is_muc,
734 // options.streams, codecs, secure_transport, crypto, and streams. If we don't
735 // currently have crypto (in current_cryptos) and it is enabled (in 711 // currently have crypto (in current_cryptos) and it is enabled (in
736 // secure_policy), crypto is created (according to crypto_suites). If 712 // secure_policy), crypto is created (according to crypto_suites). The created
737 // add_legacy_stream is true, and current_streams is empty, a legacy 713 // content is added to the offer.
738 // stream is created. The created content is added to the offer.
739 template <class C> 714 template <class C>
740 static bool CreateMediaContentOffer( 715 static bool CreateMediaContentOffer(
741 const MediaSessionOptions& options, 716 const std::vector<SenderOptions>& sender_options,
717 const MediaSessionOptions& session_options,
742 const std::vector<C>& codecs, 718 const std::vector<C>& codecs,
743 const SecurePolicy& secure_policy, 719 const SecurePolicy& secure_policy,
744 const CryptoParamsVec* current_cryptos, 720 const CryptoParamsVec* current_cryptos,
745 const std::vector<std::string>& crypto_suites, 721 const std::vector<std::string>& crypto_suites,
746 const RtpHeaderExtensions& rtp_extensions, 722 const RtpHeaderExtensions& rtp_extensions,
747 bool add_legacy_stream,
748 StreamParamsVec* current_streams, 723 StreamParamsVec* current_streams,
749 MediaContentDescriptionImpl<C>* offer) { 724 MediaContentDescriptionImpl<C>* offer) {
750 offer->AddCodecs(codecs); 725 offer->AddCodecs(codecs);
751 726
752 offer->set_rtcp_mux(options.rtcp_mux_enabled); 727 offer->set_rtcp_mux(session_options.rtcp_mux_enabled);
753 if (offer->type() == cricket::MEDIA_TYPE_VIDEO) { 728 if (offer->type() == cricket::MEDIA_TYPE_VIDEO) {
754 offer->set_rtcp_reduced_size(true); 729 offer->set_rtcp_reduced_size(true);
755 } 730 }
756 offer->set_multistream(options.is_muc); 731 offer->set_multistream(session_options.is_muc);
757 offer->set_rtp_header_extensions(rtp_extensions); 732 offer->set_rtp_header_extensions(rtp_extensions);
758 733
759 if (!AddStreamParams(offer->type(), options, current_streams, offer, 734 if (!AddStreamParams(sender_options, session_options.rtcp_cname,
760 add_legacy_stream)) { 735 current_streams, offer)) {
761 return false; 736 return false;
762 } 737 }
763 738
764 #ifdef HAVE_SRTP 739 #ifdef HAVE_SRTP
765 if (secure_policy != SEC_DISABLED) { 740 if (secure_policy != SEC_DISABLED) {
766 if (current_cryptos) { 741 if (current_cryptos) {
767 AddMediaCryptos(*current_cryptos, offer); 742 AddMediaCryptos(*current_cryptos, offer);
768 } 743 }
769 if (offer->cryptos().empty()) { 744 if (offer->cryptos().empty()) {
770 if (!CreateMediaCryptos(crypto_suites, offer)) { 745 if (!CreateMediaCryptos(crypto_suites, offer)) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 } 835 }
861 if (found_codec) { 836 if (found_codec) {
862 *found_codec = potential_match; 837 *found_codec = potential_match;
863 } 838 }
864 return true; 839 return true;
865 } 840 }
866 } 841 }
867 return false; 842 return false;
868 } 843 }
869 844
870 // Adds all codecs from |reference_codecs| to |offered_codecs| that dont' 845 // Find the codec in |codec_list| that |rtx_codec| is associated with.
846 template <class C>
847 static const C* GetAssociatedCodec(const std::vector<C>& codec_list,
848 const C& rtx_codec) {
849 std::string associated_pt_str;
850 if (!rtx_codec.GetParam(kCodecParamAssociatedPayloadType,
851 &associated_pt_str)) {
852 LOG(LS_WARNING) << "RTX codec " << rtx_codec.name
853 << " is missing an associated payload type.";
854 return nullptr;
855 }
856
857 int associated_pt;
858 if (!rtc::FromString(associated_pt_str, &associated_pt)) {
859 LOG(LS_WARNING) << "Couldn't convert payload type " << associated_pt_str
860 << " of RTX codec " << rtx_codec.name << " to an integer.";
861 return nullptr;
862 }
863
864 // Find the associated reference codec for the reference RTX codec.
865 const C* associated_codec = FindCodecById(codec_list, associated_pt);
866 if (!associated_codec) {
867 LOG(LS_WARNING) << "Couldn't find associated codec with payload type "
868 << associated_pt << " for RTX codec " << rtx_codec.name
869 << ".";
870 }
871 return associated_codec;
872 }
873
874 // Adds all codecs from |reference_codecs| to |offered_codecs| that don't
871 // already exist in |offered_codecs| and ensure the payload types don't 875 // already exist in |offered_codecs| and ensure the payload types don't
872 // collide. 876 // collide. If |can_modify_codecs| is false, a codec is only added if it
877 // can be added without changing any parameters (namely payload type,
878 // associated payload type).
873 template <class C> 879 template <class C>
874 static void FindCodecsToOffer( 880 static void MergeCodecs(const std::vector<C>& reference_codecs,
875 const std::vector<C>& reference_codecs, 881 bool can_modify_codecs,
876 std::vector<C>* offered_codecs, 882 std::vector<C>* offered_codecs,
877 UsedPayloadTypes* used_pltypes) { 883 UsedPayloadTypes* used_pltypes) {
878
879 // Add all new codecs that are not RTX codecs. 884 // Add all new codecs that are not RTX codecs.
880 for (const C& reference_codec : reference_codecs) { 885 for (const C& reference_codec : reference_codecs) {
881 if (!IsRtxCodec(reference_codec) && 886 if (!IsRtxCodec(reference_codec) &&
882 !FindMatchingCodec<C>(reference_codecs, *offered_codecs, 887 !FindMatchingCodec<C>(reference_codecs, *offered_codecs,
883 reference_codec, nullptr)) { 888 reference_codec, nullptr)) {
884 C codec = reference_codec; 889 C codec = reference_codec;
885 used_pltypes->FindAndSetIdUsed(&codec); 890 if (used_pltypes->FindAndSetIdUsed(&codec, can_modify_codecs)) {
886 offered_codecs->push_back(codec); 891 offered_codecs->push_back(codec);
892 }
887 } 893 }
888 } 894 }
889 895
890 // Add all new RTX codecs. 896 // Add all new RTX codecs.
891 for (const C& reference_codec : reference_codecs) { 897 for (const C& reference_codec : reference_codecs) {
892 if (IsRtxCodec(reference_codec) && 898 if (IsRtxCodec(reference_codec) &&
893 !FindMatchingCodec<C>(reference_codecs, *offered_codecs, 899 !FindMatchingCodec<C>(reference_codecs, *offered_codecs,
894 reference_codec, nullptr)) { 900 reference_codec, nullptr)) {
895 C rtx_codec = reference_codec; 901 C rtx_codec = reference_codec;
896 902 const C* associated_codec =
897 std::string associated_pt_str; 903 GetAssociatedCodec(reference_codecs, rtx_codec);
898 if (!rtx_codec.GetParam(kCodecParamAssociatedPayloadType, 904 if (!associated_codec) {
899 &associated_pt_str)) {
900 LOG(LS_WARNING) << "RTX codec " << rtx_codec.name
901 << " is missing an associated payload type.";
902 continue; 905 continue;
903 } 906 }
904 907
905 int associated_pt;
906 if (!rtc::FromString(associated_pt_str, &associated_pt)) {
907 LOG(LS_WARNING) << "Couldn't convert payload type " << associated_pt_str
908 << " of RTX codec " << rtx_codec.name
909 << " to an integer.";
910 continue;
911 }
912
913 // Find the associated reference codec for the reference RTX codec.
914 const C* associated_codec =
915 FindCodecById(reference_codecs, associated_pt);
916 if (!associated_codec) {
917 LOG(LS_WARNING) << "Couldn't find associated codec with payload type "
918 << associated_pt << " for RTX codec " << rtx_codec.name
919 << ".";
920 continue;
921 }
922
923 // Find a codec in the offered list that matches the reference codec. 908 // Find a codec in the offered list that matches the reference codec.
924 // Its payload type may be different than the reference codec. 909 // Its payload type may be different than the reference codec.
925 C matching_codec; 910 C matching_codec;
926 if (!FindMatchingCodec<C>(reference_codecs, *offered_codecs, 911 if (!FindMatchingCodec<C>(reference_codecs, *offered_codecs,
927 *associated_codec, &matching_codec)) { 912 *associated_codec, &matching_codec)) {
928 LOG(LS_WARNING) << "Couldn't find matching " << associated_codec->name 913 LOG(LS_WARNING) << "Couldn't find matching " << associated_codec->name
929 << " codec."; 914 << " codec.";
930 continue; 915 continue;
931 } 916 }
932 917
918 if (!can_modify_codecs && matching_codec.id != associated_codec->id) {
919 continue;
920 }
921
933 rtx_codec.params[kCodecParamAssociatedPayloadType] = 922 rtx_codec.params[kCodecParamAssociatedPayloadType] =
934 rtc::ToString(matching_codec.id); 923 rtc::ToString(matching_codec.id);
935 used_pltypes->FindAndSetIdUsed(&rtx_codec); 924 if (used_pltypes->FindAndSetIdUsed(&rtx_codec, can_modify_codecs)) {
936 offered_codecs->push_back(rtx_codec); 925 offered_codecs->push_back(rtx_codec);
926 }
937 } 927 }
938 } 928 }
939 } 929 }
940 930
941 static bool FindByUri(const RtpHeaderExtensions& extensions, 931 static bool FindByUri(const RtpHeaderExtensions& extensions,
942 const webrtc::RtpExtension& ext_to_match, 932 const webrtc::RtpExtension& ext_to_match,
943 webrtc::RtpExtension* found_extension) { 933 webrtc::RtpExtension* found_extension) {
944 for (RtpHeaderExtensions::const_iterator it = extensions.begin(); 934 for (RtpHeaderExtensions::const_iterator it = extensions.begin();
945 it != extensions.end(); ++it) { 935 it != extensions.end(); ++it) {
946 // We assume that all URIs are given in a canonical format. 936 // We assume that all URIs are given in a canonical format.
947 if (it->uri == ext_to_match.uri) { 937 if (it->uri == ext_to_match.uri) {
948 if (found_extension != NULL) { 938 if (found_extension != NULL) {
949 *found_extension = *it; 939 *found_extension = *it;
950 } 940 }
951 return true; 941 return true;
952 } 942 }
953 } 943 }
954 return false; 944 return false;
955 } 945 }
956 946
957 // Iterates through |offered_extensions|, adding each one to |all_extensions| 947 // Adds all extensions from |reference_extensions| to |offered_extensions| that
958 // and |used_ids|, and resolving ID conflicts. If an offered extension has the 948 // don't already exist in |offered_extensions| and ensure the IDs don't
959 // same URI as one in |all_extensions|, it will re-use the same ID and won't be 949 // collide. If an extension is added, it's also added to |all_extensions|, and
960 // treated as a conflict. 950 // if the extension is in |all_extensions| its ID is used. If
961 static void FindAndSetRtpHdrExtUsed(RtpHeaderExtensions* offered_extensions, 951 // |can_modify_extensions| is false, a extension is only added if it can be
962 RtpHeaderExtensions* all_extensions, 952 // added without changing the ID.
963 UsedRtpHeaderExtensionIds* used_ids) { 953 static void MergeRtpHdrExts(const RtpHeaderExtensions& reference_extensions,
964 for (auto& extension : *offered_extensions) { 954 bool can_modify_extension,
965 webrtc::RtpExtension existing; 955 RtpHeaderExtensions* offered_extensions,
966 if (FindByUri(*all_extensions, extension, &existing)) { 956 RtpHeaderExtensions* all_extensions,
967 extension.id = existing.id; 957 UsedRtpHeaderExtensionIds* used_ids) {
968 } else {
969 used_ids->FindAndSetIdUsed(&extension);
970 all_extensions->push_back(extension);
971 }
972 }
973 }
974
975 // Adds |reference_extensions| to |offered_extensions|, while updating
976 // |all_extensions| and |used_ids|.
977 static void FindRtpHdrExtsToOffer(
978 const RtpHeaderExtensions& reference_extensions,
979 RtpHeaderExtensions* offered_extensions,
980 RtpHeaderExtensions* all_extensions,
981 UsedRtpHeaderExtensionIds* used_ids) {
982 for (auto reference_extension : reference_extensions) { 958 for (auto reference_extension : reference_extensions) {
983 if (!FindByUri(*offered_extensions, reference_extension, NULL)) { 959 if (!FindByUri(*offered_extensions, reference_extension, NULL)) {
984 webrtc::RtpExtension existing; 960 webrtc::RtpExtension existing;
985 if (FindByUri(*all_extensions, reference_extension, &existing)) { 961 if (FindByUri(*all_extensions, reference_extension, &existing)) {
986 offered_extensions->push_back(existing); 962 offered_extensions->push_back(existing);
987 } else { 963 } else {
988 used_ids->FindAndSetIdUsed(&reference_extension); 964 webrtc::RtpExtension extension = reference_extension;
989 all_extensions->push_back(reference_extension); 965 if (used_ids->FindAndSetIdUsed(&extension, can_modify_extension)) {
990 offered_extensions->push_back(reference_extension); 966 all_extensions->push_back(extension);
967 offered_extensions->push_back(extension);
968 }
991 } 969 }
992 } 970 }
993 } 971 }
994 } 972 }
995 973
996 static void NegotiateRtpHeaderExtensions( 974 static void NegotiateRtpHeaderExtensions(
997 const RtpHeaderExtensions& local_extensions, 975 const RtpHeaderExtensions& local_extensions,
998 const RtpHeaderExtensions& offered_extensions, 976 const RtpHeaderExtensions& offered_extensions,
999 RtpHeaderExtensions* negotiated_extenstions) { 977 RtpHeaderExtensions* negotiated_extenstions) {
1000 RtpHeaderExtensions::const_iterator ours; 978 RtpHeaderExtensions::const_iterator ours;
(...skipping 11 matching lines...) Expand all
1012 AudioCodecs::iterator iter = audio_codecs->begin(); 990 AudioCodecs::iterator iter = audio_codecs->begin();
1013 while (iter != audio_codecs->end()) { 991 while (iter != audio_codecs->end()) {
1014 if (stricmp(iter->name.c_str(), kComfortNoiseCodecName) == 0) { 992 if (stricmp(iter->name.c_str(), kComfortNoiseCodecName) == 0) {
1015 iter = audio_codecs->erase(iter); 993 iter = audio_codecs->erase(iter);
1016 } else { 994 } else {
1017 ++iter; 995 ++iter;
1018 } 996 }
1019 } 997 }
1020 } 998 }
1021 999
1022 // Create a media content to be answered in a session-accept, 1000 // Create a media content to be answered in a session-accept for
1023 // according to the given options.rtcp_mux, options.streams, codecs, 1001 // the given |sender_options|, according to the given session_options.rtcp_mux,
1024 // crypto, and streams. If we don't currently have crypto (in 1002 // session_options.streams, codecs, crypto, and current_streams. If we don't
1025 // current_cryptos) and it is enabled (in secure_policy), crypto is 1003 // currently
1026 // created (according to crypto_suites). If add_legacy_stream is 1004 // have crypto (in current_cryptos) and it is enabled (in secure_policy),
1027 // true, and current_streams is empty, a legacy stream is created. 1005 // crypto is created (according to crypto_suites). The codecs, rtcp_mux, and
1028 // The codecs, rtcp_mux, and crypto are all negotiated with the offer 1006 // crypto are all negotiated with the offer from the incoming session-initiate.
1029 // from the incoming session-initiate. If the negotiation fails, this 1007 // If the negotiation fails, this method returns false. The created content is
1030 // method returns false. The created content is added to the offer. 1008 // added to the offer.
1031 template <class C> 1009 template <class C>
1032 static bool CreateMediaContentAnswer( 1010 static bool CreateMediaContentAnswer(
1033 const MediaContentDescriptionImpl<C>* offer, 1011 const MediaContentDescriptionImpl<C>* offer,
1034 const MediaSessionOptions& options, 1012 const std::vector<SenderOptions>& sender_options,
1013 // TODO: combine these two params into mediadescriptionoptions
1014 RtpTransceiverDirection desired_direction,
1015 const MediaSessionOptions& session_options,
1035 const std::vector<C>& local_codecs, 1016 const std::vector<C>& local_codecs,
1036 const SecurePolicy& sdes_policy, 1017 const SecurePolicy& sdes_policy,
1037 const CryptoParamsVec* current_cryptos, 1018 const CryptoParamsVec* current_cryptos,
1038 const RtpHeaderExtensions& local_rtp_extenstions, 1019 const RtpHeaderExtensions& local_rtp_extenstions,
1039 StreamParamsVec* current_streams, 1020 StreamParamsVec* current_streams,
1040 bool add_legacy_stream,
1041 bool bundle_enabled, 1021 bool bundle_enabled,
1042 MediaContentDescriptionImpl<C>* answer) { 1022 MediaContentDescriptionImpl<C>* answer) {
1043 std::vector<C> negotiated_codecs; 1023 std::vector<C> negotiated_codecs;
1044 NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs); 1024 NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs);
1045 answer->AddCodecs(negotiated_codecs); 1025 answer->AddCodecs(negotiated_codecs);
1046 answer->set_protocol(offer->protocol()); 1026 answer->set_protocol(offer->protocol());
1047 RtpHeaderExtensions negotiated_rtp_extensions; 1027 RtpHeaderExtensions negotiated_rtp_extensions;
1048 NegotiateRtpHeaderExtensions(local_rtp_extenstions, 1028 NegotiateRtpHeaderExtensions(local_rtp_extenstions,
1049 offer->rtp_header_extensions(), 1029 offer->rtp_header_extensions(),
1050 &negotiated_rtp_extensions); 1030 &negotiated_rtp_extensions);
1051 answer->set_rtp_header_extensions(negotiated_rtp_extensions); 1031 answer->set_rtp_header_extensions(negotiated_rtp_extensions);
1052 1032
1053 answer->set_rtcp_mux(options.rtcp_mux_enabled && offer->rtcp_mux()); 1033 answer->set_rtcp_mux(session_options.rtcp_mux_enabled && offer->rtcp_mux());
1054 if (answer->type() == cricket::MEDIA_TYPE_VIDEO) { 1034 if (answer->type() == cricket::MEDIA_TYPE_VIDEO) {
1055 answer->set_rtcp_reduced_size(offer->rtcp_reduced_size()); 1035 answer->set_rtcp_reduced_size(offer->rtcp_reduced_size());
1056 } 1036 }
1057 1037
1058 if (sdes_policy != SEC_DISABLED) { 1038 if (sdes_policy != SEC_DISABLED) {
1059 CryptoParams crypto; 1039 CryptoParams crypto;
1060 if (SelectCrypto(offer, bundle_enabled, options.crypto_options, &crypto)) { 1040 if (SelectCrypto(offer, bundle_enabled, session_options.crypto_options,
1041 &crypto)) {
1061 if (current_cryptos) { 1042 if (current_cryptos) {
1062 FindMatchingCrypto(*current_cryptos, crypto, &crypto); 1043 FindMatchingCrypto(*current_cryptos, crypto, &crypto);
1063 } 1044 }
1064 answer->AddCrypto(crypto); 1045 answer->AddCrypto(crypto);
1065 } 1046 }
1066 } 1047 }
1067 1048
1068 if (answer->cryptos().empty() && sdes_policy == SEC_REQUIRED) { 1049 if (answer->cryptos().empty() && sdes_policy == SEC_REQUIRED) {
1069 return false; 1050 return false;
1070 } 1051 }
1071 1052
1072 if (!AddStreamParams(answer->type(), options, current_streams, answer, 1053 if (!AddStreamParams(sender_options, session_options.rtcp_cname,
1073 add_legacy_stream)) { 1054 current_streams, answer)) {
1074 return false; // Something went seriously wrong. 1055 return false; // Something went seriously wrong.
1075 } 1056 }
1076 1057
1077 // Make sure the answer media content direction is per default set as
1078 // described in RFC3264 section 6.1.
1079 const bool is_data = !IsRtpProtocol(answer->protocol());
1080 const bool has_send_streams = !answer->streams().empty();
1081 const bool wants_send = has_send_streams || is_data;
1082 const bool recv_audio =
1083 answer->type() == cricket::MEDIA_TYPE_AUDIO && options.recv_audio;
1084 const bool recv_video =
1085 answer->type() == cricket::MEDIA_TYPE_VIDEO && options.recv_video;
1086 const bool recv_data =
1087 answer->type() == cricket::MEDIA_TYPE_DATA;
1088 const bool wants_receive = recv_audio || recv_video || recv_data;
1089
1090 auto offer_rtd = 1058 auto offer_rtd =
1091 RtpTransceiverDirection::FromMediaContentDirection(offer->direction()); 1059 RtpTransceiverDirection::FromMediaContentDirection(offer->direction());
1092 auto wants_rtd = RtpTransceiverDirection(wants_send, wants_receive); 1060 answer->set_direction(
1093 answer->set_direction(NegotiateRtpTransceiverDirection(offer_rtd, wants_rtd) 1061 NegotiateRtpTransceiverDirection(offer_rtd, desired_direction)
1094 .ToMediaContentDirection()); 1062 .ToMediaContentDirection());
1095 return true; 1063 return true;
1096 } 1064 }
1097 1065
1098 static bool IsDtlsRtp(const std::string& protocol) { 1066 static bool IsDtlsRtp(const std::string& protocol) {
1099 // Most-likely values first. 1067 // Most-likely values first.
1100 return protocol == "UDP/TLS/RTP/SAVPF" || protocol == "TCP/TLS/RTP/SAVPF" || 1068 return protocol == "UDP/TLS/RTP/SAVPF" || protocol == "TCP/TLS/RTP/SAVPF" ||
1101 protocol == "UDP/TLS/RTP/SAVP" || protocol == "TCP/TLS/RTP/SAVP"; 1069 protocol == "UDP/TLS/RTP/SAVP" || protocol == "TCP/TLS/RTP/SAVP";
1102 } 1070 }
1103 1071
1104 static bool IsPlainRtp(const std::string& protocol) { 1072 static bool IsPlainRtp(const std::string& protocol) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1166 const TransportInfo* info = 1134 const TransportInfo* info =
1167 current_description->GetTransportInfoByName(content_name); 1135 current_description->GetTransportInfoByName(content_name);
1168 if (info) { 1136 if (info) {
1169 desc = &info->description; 1137 desc = &info->description;
1170 } 1138 }
1171 } 1139 }
1172 return desc; 1140 return desc;
1173 } 1141 }
1174 1142
1175 // Gets the current DTLS state from the transport description. 1143 // Gets the current DTLS state from the transport description.
1176 static bool IsDtlsActive( 1144 static bool IsDtlsActive(const ContentInfo* content,
1177 const std::string& content_name, 1145 const SessionDescription* current_description) {
1178 const SessionDescription* current_description) { 1146 if (!content) {
1179 if (!current_description)
1180 return false; 1147 return false;
1181 1148 }
1182 const ContentInfo* content =
1183 current_description->GetContentByName(content_name);
1184 if (!content)
1185 return false;
1186 1149
1187 const TransportDescription* current_tdesc = 1150 const TransportDescription* current_tdesc =
1188 GetTransportDescription(content_name, current_description); 1151 GetTransportDescription(content->name, current_description);
1189 if (!current_tdesc) 1152 if (!current_tdesc) {
1190 return false; 1153 return false;
1154 }
1191 1155
1192 return current_tdesc->secure(); 1156 return current_tdesc->secure();
1193 } 1157 }
1194 1158
1195 std::string MediaTypeToString(MediaType type) { 1159 std::string MediaTypeToString(MediaType type) {
1196 std::string type_str; 1160 std::string type_str;
1197 switch (type) { 1161 switch (type) {
1198 case MEDIA_TYPE_AUDIO: 1162 case MEDIA_TYPE_AUDIO:
1199 type_str = "audio"; 1163 type_str = "audio";
1200 break; 1164 break;
(...skipping 26 matching lines...) Expand all
1227 dir_str = "sendrecv"; 1191 dir_str = "sendrecv";
1228 break; 1192 break;
1229 default: 1193 default:
1230 ASSERT(false); 1194 ASSERT(false);
1231 break; 1195 break;
1232 } 1196 }
1233 1197
1234 return dir_str; 1198 return dir_str;
1235 } 1199 }
1236 1200
1237 void MediaSessionOptions::AddSendStream(MediaType type, 1201 void MediaDescriptionOptions::AddAudioSender(const std::string& track_id,
1238 const std::string& id, 1202 const std::string& stream_id) {
1239 const std::string& sync_label) { 1203 RTC_DCHECK(type == MEDIA_TYPE_AUDIO);
1240 AddSendStreamInternal(type, id, sync_label, 1); 1204 AddSenderInternal(track_id, stream_id, 1);
1241 } 1205 }
1242 1206
1243 void MediaSessionOptions::AddSendVideoStream( 1207 void MediaDescriptionOptions::AddVideoSender(const std::string& track_id,
1244 const std::string& id, 1208 const std::string& stream_id,
1245 const std::string& sync_label, 1209 int num_sim_layers) {
1246 int num_sim_layers) { 1210 RTC_DCHECK(type == MEDIA_TYPE_VIDEO);
1247 AddSendStreamInternal(MEDIA_TYPE_VIDEO, id, sync_label, num_sim_layers); 1211 AddSenderInternal(track_id, stream_id, num_sim_layers);
1248 } 1212 }
1249 1213
1250 void MediaSessionOptions::AddSendStreamInternal( 1214 void MediaDescriptionOptions::AddRtpDataChannel(const std::string& track_id,
1251 MediaType type, 1215 const std::string& stream_id) {
1252 const std::string& id, 1216 RTC_DCHECK(type == MEDIA_TYPE_DATA);
1253 const std::string& sync_label, 1217 AddSenderInternal(track_id, stream_id, 1);
1254 int num_sim_layers) {
1255 streams.push_back(Stream(type, id, sync_label, num_sim_layers));
1256
1257 // If we haven't already set the data_channel_type, and we add a
1258 // stream, we assume it's an RTP data stream.
1259 if (type == MEDIA_TYPE_DATA && data_channel_type == DCT_NONE)
1260 data_channel_type = DCT_RTP;
1261 } 1218 }
1262 1219
1263 void MediaSessionOptions::RemoveSendStream(MediaType type, 1220 void MediaDescriptionOptions::AddSenderInternal(const std::string& track_id,
1264 const std::string& id) { 1221 const std::string& stream_id,
1265 Streams::iterator stream_it = streams.begin(); 1222 int num_sim_layers) {
1266 for (; stream_it != streams.end(); ++stream_it) { 1223 sender_options.push_back(SenderOptions{track_id, stream_id, num_sim_layers});
1267 if (stream_it->type == type && stream_it->id == id) {
1268 streams.erase(stream_it);
1269 return;
1270 }
1271 }
1272 ASSERT(false);
1273 } 1224 }
1274 1225
1275 bool MediaSessionOptions::HasSendMediaStream(MediaType type) const { 1226 bool MediaSessionOptions::HasMediaDescription(MediaType type) const {
1276 Streams::const_iterator stream_it = streams.begin(); 1227 return std::find_if(media_description_options.begin(),
1277 for (; stream_it != streams.end(); ++stream_it) { 1228 media_description_options.end(),
1278 if (stream_it->type == type) { 1229 [type](const MediaDescriptionOptions& t) {
1279 return true; 1230 return t.type == type;
1280 } 1231 }) != media_description_options.end();
1281 } 1232 }
1282 return false; 1233
1234 std::vector<MediaDescriptionOptions>::iterator
1235 MediaSessionOptions::FindMediaDescription(const std::string& mid) {
1236 return std::find_if(
1237 media_description_options.begin(), media_description_options.end(),
1238 [mid](const MediaDescriptionOptions& t) { return t.mid == mid; });
1283 } 1239 }
1284 1240
1285 MediaSessionDescriptionFactory::MediaSessionDescriptionFactory( 1241 MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
1286 const TransportDescriptionFactory* transport_desc_factory) 1242 const TransportDescriptionFactory* transport_desc_factory)
1287 : secure_(SEC_DISABLED), 1243 : transport_desc_factory_(transport_desc_factory) {}
1288 add_legacy_(true),
1289 transport_desc_factory_(transport_desc_factory) {
1290 }
1291 1244
1292 MediaSessionDescriptionFactory::MediaSessionDescriptionFactory( 1245 MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
1293 ChannelManager* channel_manager, 1246 ChannelManager* channel_manager,
1294 const TransportDescriptionFactory* transport_desc_factory) 1247 const TransportDescriptionFactory* transport_desc_factory)
1295 : secure_(SEC_DISABLED), 1248 : transport_desc_factory_(transport_desc_factory) {
1296 add_legacy_(true),
1297 transport_desc_factory_(transport_desc_factory) {
1298 channel_manager->GetSupportedAudioSendCodecs(&audio_send_codecs_); 1249 channel_manager->GetSupportedAudioSendCodecs(&audio_send_codecs_);
1299 channel_manager->GetSupportedAudioReceiveCodecs(&audio_recv_codecs_); 1250 channel_manager->GetSupportedAudioReceiveCodecs(&audio_recv_codecs_);
1300 channel_manager->GetSupportedAudioSendCodecs(&audio_send_codecs_); 1251 channel_manager->GetSupportedAudioSendCodecs(&audio_send_codecs_);
1301 channel_manager->GetSupportedAudioRtpHeaderExtensions(&audio_rtp_extensions_); 1252 channel_manager->GetSupportedAudioRtpHeaderExtensions(&audio_rtp_extensions_);
1302 channel_manager->GetSupportedVideoCodecs(&video_codecs_); 1253 channel_manager->GetSupportedVideoCodecs(&video_codecs_);
1303 channel_manager->GetSupportedVideoRtpHeaderExtensions(&video_rtp_extensions_); 1254 channel_manager->GetSupportedVideoRtpHeaderExtensions(&video_rtp_extensions_);
1304 channel_manager->GetSupportedDataCodecs(&data_codecs_); 1255 channel_manager->GetSupportedDataCodecs(&data_codecs_);
1305 NegotiateCodecs(audio_recv_codecs_, audio_send_codecs_, 1256 // Precompute the intersection and union of audio send/recv codecs.
1306 &audio_sendrecv_codecs_); 1257 for (const AudioCodec& recv : audio_recv_codecs_) {
1258 all_audio_codecs_.push_back(recv);
1259 if (FindMatchingCodec<AudioCodec>(audio_recv_codecs_, audio_send_codecs_,
1260 recv, nullptr)) {
1261 audio_sendrecv_codecs_.push_back(recv);
1262 }
1263 }
1264 for (const AudioCodec& send : audio_send_codecs_) {
1265 if (!FindMatchingCodec<AudioCodec>(audio_send_codecs_, audio_recv_codecs_,
1266 send, nullptr)) {
1267 // It doesn't make sense to have an RTX codec we support sending but not
1268 // receiving.
1269 RTC_DCHECK(!IsRtxCodec(send));
1270 all_audio_codecs_.push_back(send);
1271 }
1272 }
1307 } 1273 }
1308 1274
1309 const AudioCodecs& MediaSessionDescriptionFactory::audio_sendrecv_codecs() 1275 const AudioCodecs& MediaSessionDescriptionFactory::audio_sendrecv_codecs()
1310 const { 1276 const {
1311 return audio_sendrecv_codecs_; 1277 return audio_sendrecv_codecs_;
1312 } 1278 }
1313 1279
1314 const AudioCodecs& MediaSessionDescriptionFactory::audio_send_codecs() const { 1280 const AudioCodecs& MediaSessionDescriptionFactory::audio_send_codecs() const {
1315 return audio_send_codecs_; 1281 return audio_send_codecs_;
1316 } 1282 }
1317 1283
1318 const AudioCodecs& MediaSessionDescriptionFactory::audio_recv_codecs() const { 1284 const AudioCodecs& MediaSessionDescriptionFactory::audio_recv_codecs() const {
1319 return audio_recv_codecs_; 1285 return audio_recv_codecs_;
1320 } 1286 }
1321 1287
1322 void MediaSessionDescriptionFactory::set_audio_codecs( 1288 void MediaSessionDescriptionFactory::set_audio_codecs(
1323 const AudioCodecs& send_codecs, const AudioCodecs& recv_codecs) { 1289 const AudioCodecs& send_codecs, const AudioCodecs& recv_codecs) {
1324 audio_send_codecs_ = send_codecs; 1290 audio_send_codecs_ = send_codecs;
1325 audio_recv_codecs_ = recv_codecs; 1291 audio_recv_codecs_ = recv_codecs;
1326 audio_sendrecv_codecs_.clear(); 1292 audio_sendrecv_codecs_.clear();
1327 // Use NegotiateCodecs to merge our codec lists, since the operation is 1293 // Use NegotiateCodecs to merge our codec lists, since the operation is
1328 // essentially the same. Put send_codecs as the offered_codecs, which is the 1294 // essentially the same. Put send_codecs as the offered_codecs, which is the
1329 // order we'd like to follow. The reasoning is that encoding is usually more 1295 // order we'd like to follow. The reasoning is that encoding is usually more
1330 // expensive than decoding, and prioritizing a codec in the send list probably 1296 // expensive than decoding, and prioritizing a codec in the send list probably
1331 // means it's a codec we can handle efficiently. 1297 // means it's a codec we can handle efficiently.
1332 NegotiateCodecs(recv_codecs, send_codecs, &audio_sendrecv_codecs_); 1298 NegotiateCodecs(recv_codecs, send_codecs, &audio_sendrecv_codecs_);
1333 } 1299 }
1334 1300
1335 SessionDescription* MediaSessionDescriptionFactory::CreateOffer( 1301 SessionDescription* MediaSessionDescriptionFactory::CreateOffer(
1336 const MediaSessionOptions& options, 1302 const MediaSessionOptions& session_options,
1337 const SessionDescription* current_description) const { 1303 const SessionDescription* current_description) const {
1338 std::unique_ptr<SessionDescription> offer(new SessionDescription()); 1304 std::unique_ptr<SessionDescription> offer(new SessionDescription());
1339 1305
1340 StreamParamsVec current_streams; 1306 StreamParamsVec current_streams;
1341 GetCurrentStreamParams(current_description, &current_streams); 1307 GetCurrentStreamParams(current_description, &current_streams);
1342 1308
1343 const bool wants_send = 1309 AudioCodecs offer_audio_codecs;
1344 options.HasSendMediaStream(MEDIA_TYPE_AUDIO) || add_legacy_; 1310 VideoCodecs offer_video_codecs;
1345 const AudioCodecs& supported_audio_codecs = 1311 DataCodecs offer_data_codecs;
1346 GetAudioCodecsForOffer({wants_send, options.recv_audio}); 1312 GetCodecsForOffer(current_description, &offer_audio_codecs,
1313 &offer_video_codecs, &offer_data_codecs);
1347 1314
1348 AudioCodecs audio_codecs; 1315 if (!session_options.vad_enabled) {
1349 VideoCodecs video_codecs;
1350 DataCodecs data_codecs;
1351 GetCodecsToOffer(current_description, supported_audio_codecs,
1352 video_codecs_, data_codecs_,
1353 &audio_codecs, &video_codecs, &data_codecs);
1354
1355 if (!options.vad_enabled) {
1356 // If application doesn't want CN codecs in offer. 1316 // If application doesn't want CN codecs in offer.
1357 StripCNCodecs(&audio_codecs); 1317 StripCNCodecs(&offer_audio_codecs);
1358 } 1318 }
1319 FilterDataCodecs(&offer_data_codecs,
1320 session_options.data_channel_type == DCT_SCTP);
1359 1321
1360 RtpHeaderExtensions audio_rtp_extensions; 1322 RtpHeaderExtensions audio_rtp_extensions;
1361 RtpHeaderExtensions video_rtp_extensions; 1323 RtpHeaderExtensions video_rtp_extensions;
1362 GetRtpHdrExtsToOffer(current_description, &audio_rtp_extensions, 1324 GetRtpHdrExtsToOffer(current_description, &audio_rtp_extensions,
1363 &video_rtp_extensions); 1325 &video_rtp_extensions);
1364 1326
1365 bool audio_added = false; 1327 // Must have options for each existing section.
1366 bool video_added = false;
1367 bool data_added = false;
1368
1369 // Iterate through the contents of |current_description| to maintain the order
1370 // of the m-lines in the new offer.
1371 if (current_description) { 1328 if (current_description) {
1372 ContentInfos::const_iterator it = current_description->contents().begin(); 1329 RTC_DCHECK(current_description->contents().size() <=
1373 for (; it != current_description->contents().end(); ++it) { 1330 session_options.media_description_options.size());
1374 if (IsMediaContentOfType(&*it, MEDIA_TYPE_AUDIO)) { 1331 }
1375 if (!AddAudioContentForOffer(options, current_description, 1332 // Iterate through the media description options, matching with existing
1376 audio_rtp_extensions, audio_codecs, 1333 // media descriptions in |current_description|.
1334 int msection_index = 0;
1335 for (const MediaDescriptionOptions& media_description_options :
1336 session_options.media_description_options) {
1337 const ContentInfo* current_content = nullptr;
1338 if (current_description &&
1339 msection_index <
1340 static_cast<int>(current_description->contents().size())) {
1341 current_content = &current_description->contents()[msection_index];
1342 // Media types and mids must match.
1343 RTC_DCHECK(IsMediaContentOfType(current_content,
1344 media_description_options.type));
1345 RTC_DCHECK(media_description_options.mid == current_content->name);
1346 }
1347 switch (media_description_options.type) {
1348 case MEDIA_TYPE_AUDIO:
1349 if (!AddAudioContentForOffer(media_description_options, session_options,
1350 current_content, current_description,
1351 audio_rtp_extensions, offer_audio_codecs,
1377 &current_streams, offer.get())) { 1352 &current_streams, offer.get())) {
1378 return NULL; 1353 return nullptr;
1379 } 1354 }
1380 audio_added = true; 1355 break;
1381 } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_VIDEO)) { 1356 case MEDIA_TYPE_VIDEO:
1382 if (!AddVideoContentForOffer(options, current_description, 1357 if (!AddVideoContentForOffer(media_description_options, session_options,
1383 video_rtp_extensions, video_codecs, 1358 current_content, current_description,
1359 video_rtp_extensions, offer_video_codecs,
1384 &current_streams, offer.get())) { 1360 &current_streams, offer.get())) {
1385 return NULL; 1361 return nullptr;
1386 } 1362 }
1387 video_added = true; 1363 break;
1388 } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_DATA)) { 1364 case MEDIA_TYPE_DATA:
1389 MediaSessionOptions options_copy(options); 1365 if (!AddDataContentForOffer(media_description_options, session_options,
1390 if (IsSctp(static_cast<const MediaContentDescription*>( 1366 current_content, current_description,
1391 it->description))) { 1367 offer_data_codecs, &current_streams,
1392 options_copy.data_channel_type = DCT_SCTP; 1368 offer.get())) {
1369 return nullptr;
1393 } 1370 }
1394 if (!AddDataContentForOffer(options_copy, current_description, 1371 break;
1395 &data_codecs, &current_streams, 1372 default:
1396 offer.get())) { 1373 RTC_NOTREACHED();
1397 return NULL;
1398 }
1399 data_added = true;
1400 } else {
1401 ASSERT(false);
1402 }
1403 } 1374 }
1404 } 1375 ++msection_index;
1405
1406 // Append contents that are not in |current_description|.
1407 if (!audio_added && options.has_audio() &&
1408 !AddAudioContentForOffer(options, current_description,
1409 audio_rtp_extensions, audio_codecs,
1410 &current_streams, offer.get())) {
1411 return NULL;
1412 }
1413 if (!video_added && options.has_video() &&
1414 !AddVideoContentForOffer(options, current_description,
1415 video_rtp_extensions, video_codecs,
1416 &current_streams, offer.get())) {
1417 return NULL;
1418 }
1419 if (!data_added && options.has_data() &&
1420 !AddDataContentForOffer(options, current_description, &data_codecs,
1421 &current_streams, offer.get())) {
1422 return NULL;
1423 } 1376 }
1424 1377
1425 // Bundle the contents together, if we've been asked to do so, and update any 1378 // Bundle the contents together, if we've been asked to do so, and update any
1426 // parameters that need to be tweaked for BUNDLE. 1379 // parameters that need to be tweaked for BUNDLE.
1427 if (options.bundle_enabled) { 1380 if (session_options.bundle_enabled && offer->contents().size() > 0u) {
1428 ContentGroup offer_bundle(GROUP_TYPE_BUNDLE); 1381 ContentGroup offer_bundle(GROUP_TYPE_BUNDLE);
1429 for (ContentInfos::const_iterator content = offer->contents().begin(); 1382 for (const ContentInfo& content : offer->contents()) {
1430 content != offer->contents().end(); ++content) { 1383 // TODO(deadbeef): There are conditions that make bundling two media
1431 offer_bundle.AddContentName(content->name); 1384 // descriptions together illegal. For example, they use the same payload
1385 // type to represent different codecs, or same IDs for different header
1386 // extensions. We need to detect this and not try to bundle those media
1387 // descriptions together.
1388 offer_bundle.AddContentName(content.name);
1432 } 1389 }
1433 offer->AddGroup(offer_bundle); 1390 offer->AddGroup(offer_bundle);
1434 if (!UpdateTransportInfoForBundle(offer_bundle, offer.get())) { 1391 if (!UpdateTransportInfoForBundle(offer_bundle, offer.get())) {
1435 LOG(LS_ERROR) << "CreateOffer failed to UpdateTransportInfoForBundle."; 1392 LOG(LS_ERROR) << "CreateOffer failed to UpdateTransportInfoForBundle.";
1436 return NULL; 1393 return NULL;
1437 } 1394 }
1438 if (!UpdateCryptoParamsForBundle(offer_bundle, offer.get())) { 1395 if (!UpdateCryptoParamsForBundle(offer_bundle, offer.get())) {
1439 LOG(LS_ERROR) << "CreateOffer failed to UpdateCryptoParamsForBundle."; 1396 LOG(LS_ERROR) << "CreateOffer failed to UpdateCryptoParamsForBundle.";
1440 return NULL; 1397 return NULL;
1441 } 1398 }
1442 } 1399 }
1443 1400
1444 return offer.release(); 1401 return offer.release();
1445 } 1402 }
1446 1403
1447 SessionDescription* MediaSessionDescriptionFactory::CreateAnswer( 1404 SessionDescription* MediaSessionDescriptionFactory::CreateAnswer(
1448 const SessionDescription* offer, const MediaSessionOptions& options, 1405 const SessionDescription* offer,
1406 const MediaSessionOptions& session_options,
1449 const SessionDescription* current_description) const { 1407 const SessionDescription* current_description) const {
1408 RTC_DCHECK(offer);
1450 // The answer contains the intersection of the codecs in the offer with the 1409 // The answer contains the intersection of the codecs in the offer with the
1451 // codecs we support. As indicated by XEP-0167, we retain the same payload ids 1410 // codecs we support. As indicated by XEP-0167, we retain the same payload ids
1452 // from the offer in the answer. 1411 // from the offer in the answer.
1453 std::unique_ptr<SessionDescription> answer(new SessionDescription()); 1412 std::unique_ptr<SessionDescription> answer(new SessionDescription());
1454 1413
1455 StreamParamsVec current_streams; 1414 StreamParamsVec current_streams;
1456 GetCurrentStreamParams(current_description, &current_streams); 1415 GetCurrentStreamParams(current_description, &current_streams);
1457 1416
1458 if (offer) { 1417 // Get list of all possible codecs that respects existing payload type
1459 ContentInfos::const_iterator it = offer->contents().begin(); 1418 // mappings and uses a single payload type space.
1460 for (; it != offer->contents().end(); ++it) { 1419 //
1461 if (IsMediaContentOfType(&*it, MEDIA_TYPE_AUDIO)) { 1420 // Note that these lists may be further filtered for each m= section; this
1462 if (!AddAudioContentForAnswer(offer, options, current_description, 1421 // step is done just to establish the payload type mappings shared by all
1463 &current_streams, answer.get())) { 1422 // sections.
1464 return NULL; 1423 AudioCodecs answer_audio_codecs;
1424 VideoCodecs answer_video_codecs;
1425 DataCodecs answer_data_codecs;
1426 GetCodecsForAnswer(current_description, offer, &answer_audio_codecs,
1427 &answer_video_codecs, &answer_data_codecs);
1428
1429 if (!session_options.vad_enabled) {
1430 // If application doesn't want CN codecs in answer.
1431 StripCNCodecs(&answer_audio_codecs);
1432 }
1433 FilterDataCodecs(&answer_data_codecs,
1434 session_options.data_channel_type == DCT_SCTP);
1435
1436 // Must have options for exactly as many sections as in the offer.
1437 RTC_DCHECK(offer->contents().size() ==
1438 session_options.media_description_options.size());
1439 // Iterate through the media description options, matching with existing
1440 // media descriptions in |current_description|.
1441 int msection_index = 0;
1442 for (const MediaDescriptionOptions& media_description_options :
1443 session_options.media_description_options) {
1444 const ContentInfo* offer_content = &offer->contents()[msection_index];
1445 // Media types and mids must match.
1446 RTC_DCHECK(
1447 IsMediaContentOfType(offer_content, media_description_options.type));
1448 RTC_DCHECK(media_description_options.mid == offer_content->name);
1449 const ContentInfo* current_content = nullptr;
1450 if (current_description &&
1451 msection_index <
1452 static_cast<int>(current_description->contents().size())) {
1453 current_content = &current_description->contents()[msection_index];
1454 // Media types and mids must match.
1455 RTC_DCHECK(IsMediaContentOfType(current_content,
1456 media_description_options.type));
1457 RTC_DCHECK(media_description_options.mid == current_content->name);
1458 }
1459 switch (media_description_options.type) {
1460 case MEDIA_TYPE_AUDIO:
1461 if (!AddAudioContentForAnswer(
1462 media_description_options, session_options, offer_content,
1463 offer, current_content, current_description,
1464 answer_audio_codecs, &current_streams, answer.get())) {
1465 return nullptr;
1465 } 1466 }
1466 } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_VIDEO)) { 1467 break;
1467 if (!AddVideoContentForAnswer(offer, options, current_description, 1468 case MEDIA_TYPE_VIDEO:
1468 &current_streams, answer.get())) { 1469 if (!AddVideoContentForAnswer(
1469 return NULL; 1470 media_description_options, session_options, offer_content,
1471 offer, current_content, current_description,
1472 answer_video_codecs, &current_streams, answer.get())) {
1473 return nullptr;
1470 } 1474 }
1471 } else { 1475 break;
1472 ASSERT(IsMediaContentOfType(&*it, MEDIA_TYPE_DATA)); 1476 case MEDIA_TYPE_DATA:
1473 if (!AddDataContentForAnswer(offer, options, current_description, 1477 if (!AddDataContentForAnswer(media_description_options, session_options,
1478 offer_content, offer, current_content,
1479 current_description, answer_data_codecs,
1474 &current_streams, answer.get())) { 1480 &current_streams, answer.get())) {
1475 return NULL; 1481 return nullptr;
1476 } 1482 }
1477 } 1483 break;
1484 default:
1485 RTC_NOTREACHED();
1478 } 1486 }
1487 ++msection_index;
1479 } 1488 }
1480 1489
1481 // If the offer supports BUNDLE, and we want to use it too, create a BUNDLE 1490 // If the offer supports BUNDLE, and we want to use it too, create a BUNDLE
1482 // group in the answer with the appropriate content names. 1491 // group in the answer with the appropriate content names.
1483 if (offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled) { 1492 if (offer->HasGroup(GROUP_TYPE_BUNDLE) && session_options.bundle_enabled) {
1484 const ContentGroup* offer_bundle = offer->GetGroupByName(GROUP_TYPE_BUNDLE); 1493 const ContentGroup* offer_bundle = offer->GetGroupByName(GROUP_TYPE_BUNDLE);
1485 ContentGroup answer_bundle(GROUP_TYPE_BUNDLE); 1494 ContentGroup answer_bundle(GROUP_TYPE_BUNDLE);
1486 for (ContentInfos::const_iterator content = answer->contents().begin(); 1495 for (ContentInfos::const_iterator content = answer->contents().begin();
1487 content != answer->contents().end(); ++content) { 1496 content != answer->contents().end(); ++content) {
1488 if (!content->rejected && offer_bundle->HasContentName(content->name)) { 1497 if (!content->rejected && offer_bundle->HasContentName(content->name)) {
1489 answer_bundle.AddContentName(content->name); 1498 answer_bundle.AddContentName(content->name);
1490 } 1499 }
1491 } 1500 }
1492 if (answer_bundle.FirstContentName()) { 1501 if (answer_bundle.FirstContentName()) {
1493 answer->AddGroup(answer_bundle); 1502 answer->AddGroup(answer_bundle);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1534 } else { 1543 } else {
1535 return audio_send_codecs_; 1544 return audio_send_codecs_;
1536 } 1545 }
1537 } else if (answer.send) { 1546 } else if (answer.send) {
1538 return audio_send_codecs_; 1547 return audio_send_codecs_;
1539 } else { 1548 } else {
1540 return audio_recv_codecs_; 1549 return audio_recv_codecs_;
1541 } 1550 }
1542 } 1551 }
1543 1552
1544 void MediaSessionDescriptionFactory::GetCodecsToOffer( 1553 void MergeCodecsFromDescription(const SessionDescription* description,
1554 bool can_modify_codecs,
1555 AudioCodecs* audio_codecs,
1556 VideoCodecs* video_codecs,
1557 DataCodecs* data_codecs,
1558 UsedPayloadTypes* used_pltypes) {
1559 for (const ContentInfo& content : description->contents()) {
1560 if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) {
1561 const AudioContentDescription* audio =
1562 static_cast<AudioContentDescription*>(content.description);
1563 MergeCodecs<AudioCodec>(audio->codecs(), can_modify_codecs, audio_codecs,
1564 used_pltypes);
1565 } else if (IsMediaContentOfType(&content, MEDIA_TYPE_VIDEO)) {
1566 const VideoContentDescription* video =
1567 static_cast<VideoContentDescription*>(content.description);
1568 MergeCodecs<VideoCodec>(video->codecs(), can_modify_codecs, video_codecs,
1569 used_pltypes);
1570 } else if (IsMediaContentOfType(&content, MEDIA_TYPE_DATA)) {
1571 const DataContentDescription* data =
1572 static_cast<DataContentDescription*>(content.description);
1573 MergeCodecs<DataCodec>(data->codecs(), can_modify_codecs, data_codecs,
1574 used_pltypes);
1575 }
1576 }
1577 }
1578
1579 // Getting codecs for an offer involves these steps:
1580 //
1581 // 1. Construct payload type -> codec mappings for current description.
1582 // 2. Add any reference codecs that weren't already present
1583 // 3. For each individual media description (m= section), filter codecs based
1584 // on the directional attribute (happens in another method).
1585 void MediaSessionDescriptionFactory::GetCodecsForOffer(
1545 const SessionDescription* current_description, 1586 const SessionDescription* current_description,
1546 const AudioCodecs& supported_audio_codecs,
1547 const VideoCodecs& supported_video_codecs,
1548 const DataCodecs& supported_data_codecs,
1549 AudioCodecs* audio_codecs, 1587 AudioCodecs* audio_codecs,
1550 VideoCodecs* video_codecs, 1588 VideoCodecs* video_codecs,
1551 DataCodecs* data_codecs) const { 1589 DataCodecs* data_codecs) const {
1552 UsedPayloadTypes used_pltypes; 1590 UsedPayloadTypes used_pltypes;
1553 audio_codecs->clear(); 1591 audio_codecs->clear();
1554 video_codecs->clear(); 1592 video_codecs->clear();
1555 data_codecs->clear(); 1593 data_codecs->clear();
1556 1594
1595 // First - get all codecs from the current description if the media type
1596 // is used. Add them to |used_pltypes| so the payload type is not reused if a
1597 // new media type is added.
1598 bool can_modify_codecs = false;
1599 if (current_description) {
1600 MergeCodecsFromDescription(current_description, can_modify_codecs,
1601 audio_codecs, video_codecs, data_codecs,
1602 &used_pltypes);
1603 }
1604
1605 // Add our codecs that are not in |current_description|.
1606 // We can modify our reference codecs (payload type, associated payload type,
1607 // etc.) since they're not part of a negotiated session description.
1608 can_modify_codecs = true;
1609 MergeCodecs<AudioCodec>(all_audio_codecs_, can_modify_codecs, audio_codecs,
1610 &used_pltypes);
1611 MergeCodecs<VideoCodec>(video_codecs_, can_modify_codecs, video_codecs,
1612 &used_pltypes);
1613 MergeCodecs<DataCodec>(data_codecs_, can_modify_codecs, data_codecs,
1614 &used_pltypes);
1615 }
1616
1617 // Getting codecs for an answer involves these steps:
1618 //
1619 // 1. Construct payload type -> codec mappings for current description.
1620 // 2. Add any codecs from the offer that weren't already present.
1621 // 3. Add any remaining codecs that weren't already present.
1622 // 4. For each individual media description (m= section), filter codecs based
1623 // on the directional attribute (happens in another method).
1624 void MediaSessionDescriptionFactory::GetCodecsForAnswer(
1625 const SessionDescription* current_description,
1626 const SessionDescription* remote_offer,
1627 AudioCodecs* audio_codecs,
1628 VideoCodecs* video_codecs,
1629 DataCodecs* data_codecs) const {
1630 UsedPayloadTypes used_pltypes;
1631 audio_codecs->clear();
1632 video_codecs->clear();
1633 data_codecs->clear();
1557 1634
1558 // First - get all codecs from the current description if the media type 1635 // First - get all codecs from the current description if the media type
1559 // is used. 1636 // is used. Add them to |used_pltypes| so the payload type is not reused if a
1560 // Add them to |used_pltypes| so the payloadtype is not reused if a new media 1637 // new media type is added.
1561 // type is added. 1638 bool can_modify_codecs = false;
1562 if (current_description) { 1639 if (current_description) {
1563 const AudioContentDescription* audio = 1640 MergeCodecsFromDescription(current_description, can_modify_codecs,
1564 GetFirstAudioContentDescription(current_description); 1641 audio_codecs, video_codecs, data_codecs,
1565 if (audio) { 1642 &used_pltypes);
1566 *audio_codecs = audio->codecs(); 1643 }
1567 used_pltypes.FindAndSetIdUsed<AudioCodec>(audio_codecs); 1644
1568 } 1645 // First, filter out codecs that we don't support at all and should ignore.
1569 const VideoContentDescription* video = 1646 AudioCodecs filtered_offered_audio_codecs;
1570 GetFirstVideoContentDescription(current_description); 1647 VideoCodecs filtered_offered_video_codecs;
1571 if (video) { 1648 DataCodecs filtered_offered_data_codecs;
1572 *video_codecs = video->codecs(); 1649 for (const ContentInfo& content : remote_offer->contents()) {
1573 used_pltypes.FindAndSetIdUsed<VideoCodec>(video_codecs); 1650 if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) {
1574 } 1651 const AudioContentDescription* audio =
1575 const DataContentDescription* data = 1652 static_cast<AudioContentDescription*>(content.description);
1576 GetFirstDataContentDescription(current_description); 1653 for (const AudioCodec& offered_audio_codec : audio->codecs()) {
1577 if (data) { 1654 if (!FindMatchingCodec<AudioCodec>(audio->codecs(),
1578 *data_codecs = data->codecs(); 1655 filtered_offered_audio_codecs,
1579 used_pltypes.FindAndSetIdUsed<DataCodec>(data_codecs); 1656 offered_audio_codec, nullptr) &&
1657 FindMatchingCodec<AudioCodec>(audio->codecs(), all_audio_codecs_,
1658 offered_audio_codec, nullptr)) {
1659 filtered_offered_audio_codecs.push_back(offered_audio_codec);
1660 }
1661 }
1662 } else if (IsMediaContentOfType(&content, MEDIA_TYPE_VIDEO)) {
1663 const VideoContentDescription* video =
1664 static_cast<VideoContentDescription*>(content.description);
1665 for (const VideoCodec& offered_video_codec : video->codecs()) {
1666 if (!FindMatchingCodec<VideoCodec>(video->codecs(),
1667 filtered_offered_video_codecs,
1668 offered_video_codec, nullptr) &&
1669 FindMatchingCodec<VideoCodec>(video->codecs(), video_codecs_,
1670 offered_video_codec, nullptr)) {
1671 filtered_offered_video_codecs.push_back(offered_video_codec);
1672 }
1673 }
1674 } else if (IsMediaContentOfType(&content, MEDIA_TYPE_DATA)) {
1675 const DataContentDescription* data =
1676 static_cast<DataContentDescription*>(content.description);
1677 for (const DataCodec& offered_data_codec : data->codecs()) {
1678 if (!FindMatchingCodec<DataCodec>(data->codecs(),
1679 filtered_offered_data_codecs,
1680 offered_data_codec, nullptr) &&
1681 FindMatchingCodec<DataCodec>(data->codecs(), data_codecs_,
1682 offered_data_codec, nullptr)) {
1683 filtered_offered_data_codecs.push_back(offered_data_codec);
1684 }
1685 }
1580 } 1686 }
1581 } 1687 }
1582 1688
1583 // Add our codecs that are not in |current_description|. 1689 // Add codecs that are not in |current_description| but were in
1584 FindCodecsToOffer<AudioCodec>(supported_audio_codecs, audio_codecs, 1690 // |remote_offer|. Do two passes, first adding codecs with payload types that
1585 &used_pltypes); 1691 // match the offer, then adding remaining codecs with remapped payload types.
1586 FindCodecsToOffer<VideoCodec>(supported_video_codecs, video_codecs, 1692 //
1587 &used_pltypes); 1693 // The two passes are needed so that a payload type isn't remapped to
1588 FindCodecsToOffer<DataCodec>(supported_data_codecs, data_codecs, 1694 // conflict with another codec. For example, PT "96" is in current
1589 &used_pltypes); 1695 // description, and a remote offer has "96" and "97". If "96" were remapped
1696 // in the first pass (to "97", since that's the next number), that's now not
1697 // available for "97", causing "97" to be remapped to "98" and a payload type
1698 // to be wasted.
1699 MergeCodecs<AudioCodec>(filtered_offered_audio_codecs, can_modify_codecs,
1700 audio_codecs, &used_pltypes);
1701 MergeCodecs<VideoCodec>(filtered_offered_video_codecs, can_modify_codecs,
1702 video_codecs, &used_pltypes);
1703 MergeCodecs<DataCodec>(filtered_offered_data_codecs, can_modify_codecs,
1704 data_codecs, &used_pltypes);
1705 can_modify_codecs = true;
1706 MergeCodecs<AudioCodec>(filtered_offered_audio_codecs, can_modify_codecs,
1707 audio_codecs, &used_pltypes);
1708 MergeCodecs<VideoCodec>(filtered_offered_video_codecs, can_modify_codecs,
1709 video_codecs, &used_pltypes);
1710 MergeCodecs<DataCodec>(filtered_offered_data_codecs, can_modify_codecs,
1711 data_codecs, &used_pltypes);
1590 } 1712 }
1591 1713
1592 void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer( 1714 void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer(
1593 const SessionDescription* current_description, 1715 const SessionDescription* current_description,
1594 RtpHeaderExtensions* audio_extensions, 1716 RtpHeaderExtensions* offer_audio_extensions,
1595 RtpHeaderExtensions* video_extensions) const { 1717 RtpHeaderExtensions* offer_video_extensions) const {
1596 // All header extensions allocated from the same range to avoid potential 1718 // All header extensions allocated from the same range to avoid potential
1597 // issues when using BUNDLE. 1719 // issues when using BUNDLE.
1598 UsedRtpHeaderExtensionIds used_ids; 1720 UsedRtpHeaderExtensionIds used_ids;
1599 RtpHeaderExtensions all_extensions; 1721 RtpHeaderExtensions all_extensions;
1600 audio_extensions->clear(); 1722 offer_audio_extensions->clear();
1601 video_extensions->clear(); 1723 offer_video_extensions->clear();
1602 1724
1603 // First - get all extensions from the current description if the media type 1725 // First - get all extensions from the current description if the media type
1604 // is used. 1726 // is used. Add them to |used_ids| so the local ids are not reused if a new
1605 // Add them to |used_ids| so the local ids are not reused if a new media 1727 // media type is added.
1606 // type is added. 1728 bool can_modify_extensions = false;
1607 if (current_description) { 1729 if (current_description) {
1608 const AudioContentDescription* audio = 1730 for (const ContentInfo& content : current_description->contents()) {
1609 GetFirstAudioContentDescription(current_description); 1731 if (IsMediaContentOfType(&content, MEDIA_TYPE_DATA)) {
1610 if (audio) { 1732 continue;
1611 *audio_extensions = audio->rtp_header_extensions(); 1733 }
1612 FindAndSetRtpHdrExtUsed(audio_extensions, &all_extensions, &used_ids); 1734 if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) {
1613 } 1735 const AudioContentDescription* audio =
1614 const VideoContentDescription* video = 1736 static_cast<const AudioContentDescription*>(content.description);
1615 GetFirstVideoContentDescription(current_description); 1737 MergeRtpHdrExts(audio->rtp_header_extensions(), can_modify_extensions,
1616 if (video) { 1738 offer_audio_extensions, &all_extensions, &used_ids);
1617 *video_extensions = video->rtp_header_extensions(); 1739 } else if (IsMediaContentOfType(&content, MEDIA_TYPE_VIDEO)) {
1618 FindAndSetRtpHdrExtUsed(video_extensions, &all_extensions, &used_ids); 1740 const VideoContentDescription* video =
1741 static_cast<const VideoContentDescription*>(content.description);
1742 MergeRtpHdrExts(video->rtp_header_extensions(), can_modify_extensions,
1743 offer_video_extensions, &all_extensions, &used_ids);
1744 }
1619 } 1745 }
1620 } 1746 }
1747 // TODO: Do this for answer too?
1621 1748
1622 // Add our default RTP header extensions that are not in 1749 // Add our default RTP header extensions that are not in
1623 // |current_description|. 1750 // |current_description|.
1624 FindRtpHdrExtsToOffer(audio_rtp_header_extensions(), audio_extensions, 1751 can_modify_extensions = true;
1625 &all_extensions, &used_ids); 1752 MergeRtpHdrExts(audio_rtp_header_extensions(), can_modify_extensions,
1626 FindRtpHdrExtsToOffer(video_rtp_header_extensions(), video_extensions, 1753 offer_audio_extensions, &all_extensions, &used_ids);
1627 &all_extensions, &used_ids); 1754 MergeRtpHdrExts(video_rtp_header_extensions(), can_modify_extensions,
1755 offer_video_extensions, &all_extensions, &used_ids);
1628 } 1756 }
1629 1757
1630 bool MediaSessionDescriptionFactory::AddTransportOffer( 1758 bool MediaSessionDescriptionFactory::AddTransportOffer(
1631 const std::string& content_name, 1759 const std::string& content_name,
1632 const TransportOptions& transport_options, 1760 const TransportOptions& transport_options,
1633 const SessionDescription* current_desc, 1761 const SessionDescription* current_desc,
1634 SessionDescription* offer_desc) const { 1762 SessionDescription* offer_desc) const {
1635 if (!transport_desc_factory_) 1763 if (!transport_desc_factory_)
1636 return false; 1764 return false;
1637 const TransportDescription* current_tdesc = 1765 const TransportDescription* current_tdesc =
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1670 if (!answer_desc->AddTransportInfo(TransportInfo(content_name, 1798 if (!answer_desc->AddTransportInfo(TransportInfo(content_name,
1671 transport_desc))) { 1799 transport_desc))) {
1672 LOG(LS_ERROR) 1800 LOG(LS_ERROR)
1673 << "Failed to AddTransportAnswer, content name=" << content_name; 1801 << "Failed to AddTransportAnswer, content name=" << content_name;
1674 return false; 1802 return false;
1675 } 1803 }
1676 return true; 1804 return true;
1677 } 1805 }
1678 1806
1679 bool MediaSessionDescriptionFactory::AddAudioContentForOffer( 1807 bool MediaSessionDescriptionFactory::AddAudioContentForOffer(
1680 const MediaSessionOptions& options, 1808 const MediaDescriptionOptions& media_description_options,
1809 const MediaSessionOptions& session_options,
1810 const ContentInfo* current_content,
1681 const SessionDescription* current_description, 1811 const SessionDescription* current_description,
1682 const RtpHeaderExtensions& audio_rtp_extensions, 1812 const RtpHeaderExtensions& audio_rtp_extensions,
1683 const AudioCodecs& audio_codecs, 1813 const AudioCodecs& audio_codecs,
1684 StreamParamsVec* current_streams, 1814 StreamParamsVec* current_streams,
1685 SessionDescription* desc) const { 1815 SessionDescription* desc) const {
1686 const ContentInfo* current_audio_content = 1816 // Filter audio_codecs (which includes all codecs, with correctly remapped
1687 GetFirstAudioContent(current_description); 1817 // payload types) based on transceiver direction.
1688 std::string content_name = 1818 const AudioCodecs& supported_audio_codecs =
1689 current_audio_content ? current_audio_content->name : CN_AUDIO; 1819 GetAudioCodecsForOffer(media_description_options.direction);
1820 AudioCodecs filtered_codecs;
1821 for (const AudioCodec& codec : audio_codecs) {
1822 if (FindMatchingCodec<AudioCodec>(audio_codecs, supported_audio_codecs,
1823 codec, nullptr)) {
1824 filtered_codecs.push_back(codec);
1825 }
1826 }
1690 1827
1691 cricket::SecurePolicy sdes_policy = 1828 cricket::SecurePolicy sdes_policy =
1692 IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED 1829 IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
1693 : secure(); 1830 : secure();
1694 1831
1695 std::unique_ptr<AudioContentDescription> audio(new AudioContentDescription()); 1832 std::unique_ptr<AudioContentDescription> audio(new AudioContentDescription());
1696 std::vector<std::string> crypto_suites; 1833 std::vector<std::string> crypto_suites;
1697 GetSupportedAudioCryptoSuiteNames(options.crypto_options, &crypto_suites); 1834 GetSupportedAudioCryptoSuiteNames(session_options.crypto_options,
1835 &crypto_suites);
1698 if (!CreateMediaContentOffer( 1836 if (!CreateMediaContentOffer(
1699 options, 1837 media_description_options.sender_options, session_options,
1700 audio_codecs, 1838 filtered_codecs, sdes_policy, GetCryptos(current_content),
1701 sdes_policy, 1839 crypto_suites, audio_rtp_extensions, current_streams, audio.get())) {
1702 GetCryptos(GetFirstAudioContentDescription(current_description)),
1703 crypto_suites,
1704 audio_rtp_extensions,
1705 add_legacy_,
1706 current_streams,
1707 audio.get())) {
1708 return false; 1840 return false;
1709 } 1841 }
1710 audio->set_lang(lang_); 1842 audio->set_lang(lang_);
1711 1843
1712 bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED); 1844 bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
1713 SetMediaProtocol(secure_transport, audio.get()); 1845 SetMediaProtocol(secure_transport, audio.get());
1714 1846
1715 auto offer_rtd = 1847 audio->set_direction(
1716 RtpTransceiverDirection(!audio->streams().empty(), options.recv_audio); 1848 media_description_options.direction.ToMediaContentDirection());
1717 audio->set_direction(offer_rtd.ToMediaContentDirection());
1718 1849
1719 desc->AddContent(content_name, NS_JINGLE_RTP, audio.release()); 1850 desc->AddContent(media_description_options.mid, NS_JINGLE_RTP,
1720 if (!AddTransportOffer(content_name, 1851 audio.release());
1721 GetTransportOptions(options, content_name), 1852 if (!AddTransportOffer(media_description_options.mid,
1853 media_description_options.transport_options,
1722 current_description, desc)) { 1854 current_description, desc)) {
1723 return false; 1855 return false;
1724 } 1856 }
1725 1857
1726 return true; 1858 return true;
1727 } 1859 }
1728 1860
1729 bool MediaSessionDescriptionFactory::AddVideoContentForOffer( 1861 bool MediaSessionDescriptionFactory::AddVideoContentForOffer(
1730 const MediaSessionOptions& options, 1862 const MediaDescriptionOptions& media_description_options,
1863 const MediaSessionOptions& session_options,
1864 const ContentInfo* current_content,
1731 const SessionDescription* current_description, 1865 const SessionDescription* current_description,
1732 const RtpHeaderExtensions& video_rtp_extensions, 1866 const RtpHeaderExtensions& video_rtp_extensions,
1733 const VideoCodecs& video_codecs, 1867 const VideoCodecs& video_codecs,
1734 StreamParamsVec* current_streams, 1868 StreamParamsVec* current_streams,
1735 SessionDescription* desc) const { 1869 SessionDescription* desc) const {
1736 const ContentInfo* current_video_content = 1870 // Filter video_codecs (which includes all codecs, with correctly remapped
1737 GetFirstVideoContent(current_description); 1871 // payload types).
1738 std::string content_name = 1872 VideoCodecs filtered_codecs;
1739 current_video_content ? current_video_content->name : CN_VIDEO; 1873 for (const VideoCodec& codec : video_codecs) {
1874 if (FindMatchingCodec<VideoCodec>(video_codecs, video_codecs_, codec,
1875 nullptr)) {
1876 filtered_codecs.push_back(codec);
1877 }
1878 }
1740 1879
1741 cricket::SecurePolicy sdes_policy = 1880 cricket::SecurePolicy sdes_policy =
1742 IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED 1881 IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
1743 : secure(); 1882 : secure();
1744 1883
1745 std::unique_ptr<VideoContentDescription> video(new VideoContentDescription()); 1884 std::unique_ptr<VideoContentDescription> video(new VideoContentDescription());
1746 std::vector<std::string> crypto_suites; 1885 std::vector<std::string> crypto_suites;
1747 GetSupportedVideoCryptoSuiteNames(options.crypto_options, &crypto_suites); 1886 GetSupportedVideoCryptoSuiteNames(session_options.crypto_options,
1887 &crypto_suites);
1748 if (!CreateMediaContentOffer( 1888 if (!CreateMediaContentOffer(
1749 options, 1889 media_description_options.sender_options, session_options,
1750 video_codecs, 1890 filtered_codecs, sdes_policy, GetCryptos(current_content),
1751 sdes_policy, 1891 crypto_suites, video_rtp_extensions, current_streams, video.get())) {
1752 GetCryptos(GetFirstVideoContentDescription(current_description)),
1753 crypto_suites,
1754 video_rtp_extensions,
1755 add_legacy_,
1756 current_streams,
1757 video.get())) {
1758 return false; 1892 return false;
1759 } 1893 }
1760 1894 video->set_bandwidth(kAutoBandwidth);
1761 video->set_bandwidth(options.video_bandwidth);
1762 1895
1763 bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED); 1896 bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
1764 SetMediaProtocol(secure_transport, video.get()); 1897 SetMediaProtocol(secure_transport, video.get());
1765 1898
1766 if (!video->streams().empty()) { 1899 video->set_direction(
1767 if (options.recv_video) { 1900 media_description_options.direction.ToMediaContentDirection());
1768 video->set_direction(MD_SENDRECV);
1769 } else {
1770 video->set_direction(MD_SENDONLY);
1771 }
1772 } else {
1773 if (options.recv_video) {
1774 video->set_direction(MD_RECVONLY);
1775 } else {
1776 video->set_direction(MD_INACTIVE);
1777 }
1778 }
1779 1901
1780 desc->AddContent(content_name, NS_JINGLE_RTP, video.release()); 1902 desc->AddContent(media_description_options.mid, NS_JINGLE_RTP,
1781 if (!AddTransportOffer(content_name, 1903 video.release());
1782 GetTransportOptions(options, content_name), 1904 if (!AddTransportOffer(media_description_options.mid,
1905 media_description_options.transport_options,
1783 current_description, desc)) { 1906 current_description, desc)) {
1784 return false; 1907 return false;
1785 } 1908 }
1786
1787 return true; 1909 return true;
1788 } 1910 }
1789 1911
1790 bool MediaSessionDescriptionFactory::AddDataContentForOffer( 1912 bool MediaSessionDescriptionFactory::AddDataContentForOffer(
1791 const MediaSessionOptions& options, 1913 const MediaDescriptionOptions& media_description_options,
1914 const MediaSessionOptions& session_options,
1915 const ContentInfo* current_content,
1792 const SessionDescription* current_description, 1916 const SessionDescription* current_description,
1793 DataCodecs* data_codecs, 1917 const DataCodecs& data_codecs,
1794 StreamParamsVec* current_streams, 1918 StreamParamsVec* current_streams,
1795 SessionDescription* desc) const { 1919 SessionDescription* desc) const {
1796 bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED); 1920 bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
1797 1921
1798 std::unique_ptr<DataContentDescription> data(new DataContentDescription()); 1922 std::unique_ptr<DataContentDescription> data(new DataContentDescription());
1799 bool is_sctp = (options.data_channel_type == DCT_SCTP); 1923 bool is_sctp = (session_options.data_channel_type == DCT_SCTP);
1800
1801 FilterDataCodecs(data_codecs, is_sctp);
1802
1803 const ContentInfo* current_data_content =
1804 GetFirstDataContent(current_description);
1805 std::string content_name =
1806 current_data_content ? current_data_content->name : CN_DATA;
1807 1924
1808 cricket::SecurePolicy sdes_policy = 1925 cricket::SecurePolicy sdes_policy =
1809 IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED 1926 IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
1810 : secure(); 1927 : secure();
1811 std::vector<std::string> crypto_suites; 1928 std::vector<std::string> crypto_suites;
1812 if (is_sctp) { 1929 if (is_sctp) {
1813 // SDES doesn't make sense for SCTP, so we disable it, and we only 1930 // SDES doesn't make sense for SCTP, so we disable it, and we only
1814 // get SDES crypto suites for RTP-based data channels. 1931 // get SDES crypto suites for RTP-based data channels.
1815 sdes_policy = cricket::SEC_DISABLED; 1932 sdes_policy = cricket::SEC_DISABLED;
1816 // Unlike SetMediaProtocol below, we need to set the protocol 1933 // Unlike SetMediaProtocol below, we need to set the protocol
1817 // before we call CreateMediaContentOffer. Otherwise, 1934 // before we call CreateMediaContentOffer. Otherwise,
1818 // CreateMediaContentOffer won't know this is SCTP and will 1935 // CreateMediaContentOffer won't know this is SCTP and will
1819 // generate SSRCs rather than SIDs. 1936 // generate SSRCs rather than SIDs.
1820 data->set_protocol( 1937 data->set_protocol(
1821 secure_transport ? kMediaProtocolDtlsSctp : kMediaProtocolSctp); 1938 secure_transport ? kMediaProtocolDtlsSctp : kMediaProtocolSctp);
1822 } else { 1939 } else {
1823 GetSupportedDataCryptoSuiteNames(options.crypto_options, &crypto_suites); 1940 GetSupportedDataCryptoSuiteNames(session_options.crypto_options,
1941 &crypto_suites);
1824 } 1942 }
1825 1943
1944 // Even SCTP uses a "codec".
1826 if (!CreateMediaContentOffer( 1945 if (!CreateMediaContentOffer(
1827 options, 1946 media_description_options.sender_options, session_options,
1828 *data_codecs, 1947 data_codecs, sdes_policy, GetCryptos(current_content), crypto_suites,
1829 sdes_policy, 1948 RtpHeaderExtensions(), current_streams, data.get())) {
1830 GetCryptos(GetFirstDataContentDescription(current_description)),
1831 crypto_suites,
1832 RtpHeaderExtensions(),
1833 add_legacy_,
1834 current_streams,
1835 data.get())) {
1836 return false; 1949 return false;
1837 } 1950 }
1838 1951
1839 if (is_sctp) { 1952 if (is_sctp) {
1840 desc->AddContent(content_name, NS_JINGLE_DRAFT_SCTP, data.release()); 1953 desc->AddContent(media_description_options.mid, NS_JINGLE_DRAFT_SCTP,
1954 data.release());
1841 } else { 1955 } else {
1842 data->set_bandwidth(options.data_bandwidth); 1956 data->set_bandwidth(kDataMaxBandwidth);
1843 SetMediaProtocol(secure_transport, data.get()); 1957 SetMediaProtocol(secure_transport, data.get());
1844 desc->AddContent(content_name, NS_JINGLE_RTP, data.release()); 1958 desc->AddContent(media_description_options.mid, NS_JINGLE_RTP,
1959 data.release());
1845 } 1960 }
1846 if (!AddTransportOffer(content_name, 1961 if (!AddTransportOffer(media_description_options.mid,
1847 GetTransportOptions(options, content_name), 1962 media_description_options.transport_options,
1848 current_description, desc)) { 1963 current_description, desc)) {
1849 return false; 1964 return false;
1850 } 1965 }
1851 return true; 1966 return true;
1852 } 1967 }
1853 1968
1854 bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( 1969 bool MediaSessionDescriptionFactory::AddAudioContentForAnswer(
1855 const SessionDescription* offer, 1970 const MediaDescriptionOptions& media_description_options,
1856 const MediaSessionOptions& options, 1971 const MediaSessionOptions& session_options,
1972 const ContentInfo* offer_content,
1973 const SessionDescription* offer_description,
1974 const ContentInfo* current_content,
1857 const SessionDescription* current_description, 1975 const SessionDescription* current_description,
1976 const AudioCodecs& audio_codecs,
1858 StreamParamsVec* current_streams, 1977 StreamParamsVec* current_streams,
1859 SessionDescription* answer) const { 1978 SessionDescription* answer) const {
1860 const ContentInfo* audio_content = GetFirstAudioContent(offer); 1979 const AudioContentDescription* offer_audio_description =
1861 const AudioContentDescription* offer_audio = 1980 static_cast<const AudioContentDescription*>(offer_content->description);
1862 static_cast<const AudioContentDescription*>(audio_content->description);
1863 1981
1864 std::unique_ptr<TransportDescription> audio_transport(CreateTransportAnswer( 1982 std::unique_ptr<TransportDescription> audio_transport(CreateTransportAnswer(
1865 audio_content->name, offer, 1983 media_description_options.mid, offer_description,
1866 GetTransportOptions(options, audio_content->name), current_description)); 1984 media_description_options.transport_options, current_description));
1867 if (!audio_transport) { 1985 if (!audio_transport) {
1868 return false; 1986 return false;
1869 } 1987 }
1870 1988
1871 // Pick codecs based on the requested communications direction in the offer. 1989 // Pick codecs based on the requested communications direction in the offer
1872 const bool wants_send = 1990 // and the selected direction in the answer.
1873 options.HasSendMediaStream(MEDIA_TYPE_AUDIO) || add_legacy_; 1991 // Note these will be filtered one final time in CreateMediaContentAnswer.
1874 auto wants_rtd = RtpTransceiverDirection(wants_send, options.recv_audio); 1992 auto wants_rtd = media_description_options.direction;
1875 auto offer_rtd = 1993 auto offer_rtd = RtpTransceiverDirection::FromMediaContentDirection(
1876 RtpTransceiverDirection::FromMediaContentDirection( 1994 offer_audio_description->direction());
1877 offer_audio->direction());
1878 auto answer_rtd = NegotiateRtpTransceiverDirection(offer_rtd, wants_rtd); 1995 auto answer_rtd = NegotiateRtpTransceiverDirection(offer_rtd, wants_rtd);
1879 AudioCodecs audio_codecs = GetAudioCodecsForAnswer(offer_rtd, answer_rtd); 1996 const AudioCodecs& supported_audio_codecs =
1880 if (!options.vad_enabled) { 1997 GetAudioCodecsForAnswer(offer_rtd, answer_rtd);
1881 StripCNCodecs(&audio_codecs); 1998 AudioCodecs filtered_codecs;
1999 for (const AudioCodec& codec : audio_codecs) {
2000 if (FindMatchingCodec<AudioCodec>(audio_codecs, supported_audio_codecs,
2001 codec, nullptr) &&
2002 FindMatchingCodec<AudioCodec>(audio_codecs, supported_audio_codecs,
2003 codec, nullptr)) {
2004 filtered_codecs.push_back(codec);
2005 }
1882 } 2006 }
1883 2007
1884 bool bundle_enabled = 2008 bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
1885 offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled; 2009 session_options.bundle_enabled;
1886 std::unique_ptr<AudioContentDescription> audio_answer( 2010 std::unique_ptr<AudioContentDescription> audio_answer(
1887 new AudioContentDescription()); 2011 new AudioContentDescription());
1888 // Do not require or create SDES cryptos if DTLS is used. 2012 // Do not require or create SDES cryptos if DTLS is used.
1889 cricket::SecurePolicy sdes_policy = 2013 cricket::SecurePolicy sdes_policy =
1890 audio_transport->secure() ? cricket::SEC_DISABLED : secure(); 2014 audio_transport->secure() ? cricket::SEC_DISABLED : secure();
1891 if (!CreateMediaContentAnswer( 2015 if (!CreateMediaContentAnswer(
1892 offer_audio, 2016 offer_audio_description, media_description_options.sender_options,
1893 options, 2017 media_description_options.direction, session_options, filtered_codecs,
1894 audio_codecs, 2018 sdes_policy, GetCryptos(current_content), audio_rtp_extensions_,
1895 sdes_policy, 2019 current_streams, bundle_enabled, audio_answer.get())) {
1896 GetCryptos(GetFirstAudioContentDescription(current_description)),
1897 audio_rtp_extensions_,
1898 current_streams,
1899 add_legacy_,
1900 bundle_enabled,
1901 audio_answer.get())) {
1902 return false; // Fails the session setup. 2020 return false; // Fails the session setup.
1903 } 2021 }
1904 2022
1905 bool rejected = !options.has_audio() || audio_content->rejected || 2023 bool rejected =
1906 !IsMediaProtocolSupported(MEDIA_TYPE_AUDIO, 2024 media_description_options.stopped || offer_content->rejected ||
1907 audio_answer->protocol(), 2025 !IsMediaProtocolSupported(MEDIA_TYPE_AUDIO, audio_answer->protocol(),
1908 audio_transport->secure()); 2026 audio_transport->secure());
1909 if (!rejected) { 2027 if (!rejected) {
1910 AddTransportAnswer(audio_content->name, *(audio_transport.get()), answer); 2028 AddTransportAnswer(media_description_options.mid, *(audio_transport.get()),
2029 answer);
1911 } else { 2030 } else {
1912 // RFC 3264 2031 LOG(LS_INFO) << "Audio m= section '" << media_description_options.mid
1913 // The answer MUST contain the same number of m-lines as the offer. 2032 << "' being rejected in answer.";
1914 LOG(LS_INFO) << "Audio is not supported in the answer.";
1915 } 2033 }
1916 2034
1917 answer->AddContent(audio_content->name, audio_content->type, rejected, 2035 answer->AddContent(media_description_options.mid, offer_content->type,
1918 audio_answer.release()); 2036 rejected, audio_answer.release());
1919 return true; 2037 return true;
1920 } 2038 }
1921 2039
1922 bool MediaSessionDescriptionFactory::AddVideoContentForAnswer( 2040 bool MediaSessionDescriptionFactory::AddVideoContentForAnswer(
1923 const SessionDescription* offer, 2041 const MediaDescriptionOptions& media_description_options,
1924 const MediaSessionOptions& options, 2042 const MediaSessionOptions& session_options,
2043 const ContentInfo* offer_content,
2044 const SessionDescription* offer_description,
2045 const ContentInfo* current_content,
1925 const SessionDescription* current_description, 2046 const SessionDescription* current_description,
2047 const VideoCodecs& video_codecs,
1926 StreamParamsVec* current_streams, 2048 StreamParamsVec* current_streams,
1927 SessionDescription* answer) const { 2049 SessionDescription* answer) const {
1928 const ContentInfo* video_content = GetFirstVideoContent(offer); 2050 const VideoContentDescription* offer_video_description =
2051 static_cast<const VideoContentDescription*>(offer_content->description);
2052
1929 std::unique_ptr<TransportDescription> video_transport(CreateTransportAnswer( 2053 std::unique_ptr<TransportDescription> video_transport(CreateTransportAnswer(
1930 video_content->name, offer, 2054 media_description_options.mid, offer_description,
1931 GetTransportOptions(options, video_content->name), current_description)); 2055 media_description_options.transport_options, current_description));
1932 if (!video_transport) { 2056 if (!video_transport) {
1933 return false; 2057 return false;
1934 } 2058 }
1935 2059
2060 bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
2061 session_options.bundle_enabled;
1936 std::unique_ptr<VideoContentDescription> video_answer( 2062 std::unique_ptr<VideoContentDescription> video_answer(
1937 new VideoContentDescription()); 2063 new VideoContentDescription());
1938 // Do not require or create SDES cryptos if DTLS is used. 2064 // Do not require or create SDES cryptos if DTLS is used.
1939 cricket::SecurePolicy sdes_policy = 2065 cricket::SecurePolicy sdes_policy =
1940 video_transport->secure() ? cricket::SEC_DISABLED : secure(); 2066 video_transport->secure() ? cricket::SEC_DISABLED : secure();
1941 bool bundle_enabled =
1942 offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled;
1943 if (!CreateMediaContentAnswer( 2067 if (!CreateMediaContentAnswer(
1944 static_cast<const VideoContentDescription*>( 2068 offer_video_description, media_description_options.sender_options,
1945 video_content->description), 2069 media_description_options.direction, session_options, video_codecs,
1946 options, 2070 sdes_policy, GetCryptos(current_content), video_rtp_extensions_,
1947 video_codecs_, 2071 current_streams, bundle_enabled, video_answer.get())) {
1948 sdes_policy, 2072 return false; // Fails the session setup.
1949 GetCryptos(GetFirstVideoContentDescription(current_description)),
1950 video_rtp_extensions_,
1951 current_streams,
1952 add_legacy_,
1953 bundle_enabled,
1954 video_answer.get())) {
1955 return false;
1956 } 2073 }
1957 bool rejected = !options.has_video() || video_content->rejected || 2074
1958 !IsMediaProtocolSupported(MEDIA_TYPE_VIDEO, 2075 bool rejected =
1959 video_answer->protocol(), 2076 media_description_options.stopped || offer_content->rejected ||
2077 !IsMediaProtocolSupported(MEDIA_TYPE_VIDEO, video_answer->protocol(),
1960 video_transport->secure()); 2078 video_transport->secure());
1961 if (!rejected) { 2079 if (!rejected) {
1962 if (!AddTransportAnswer(video_content->name, *(video_transport.get()), 2080 if (!AddTransportAnswer(media_description_options.mid,
1963 answer)) { 2081 *(video_transport.get()), answer)) {
1964 return false; 2082 return false;
1965 } 2083 }
1966 video_answer->set_bandwidth(options.video_bandwidth); 2084 video_answer->set_bandwidth(kAutoBandwidth);
1967 } else { 2085 } else {
1968 // RFC 3264 2086 LOG(LS_INFO) << "Video m= section '" << media_description_options.mid
1969 // The answer MUST contain the same number of m-lines as the offer. 2087 << "' being rejected in answer.";
1970 LOG(LS_INFO) << "Video is not supported in the answer.";
1971 } 2088 }
1972 answer->AddContent(video_content->name, video_content->type, rejected, 2089
1973 video_answer.release()); 2090 answer->AddContent(media_description_options.mid, offer_content->type,
2091 rejected, video_answer.release());
1974 return true; 2092 return true;
1975 } 2093 }
1976 2094
1977 bool MediaSessionDescriptionFactory::AddDataContentForAnswer( 2095 bool MediaSessionDescriptionFactory::AddDataContentForAnswer(
1978 const SessionDescription* offer, 2096 const MediaDescriptionOptions& media_description_options,
1979 const MediaSessionOptions& options, 2097 const MediaSessionOptions& session_options,
2098 const ContentInfo* offer_content,
2099 const SessionDescription* offer_description,
2100 const ContentInfo* current_content,
1980 const SessionDescription* current_description, 2101 const SessionDescription* current_description,
2102 const DataCodecs& data_codecs,
1981 StreamParamsVec* current_streams, 2103 StreamParamsVec* current_streams,
1982 SessionDescription* answer) const { 2104 SessionDescription* answer) const {
1983 const ContentInfo* data_content = GetFirstDataContent(offer);
1984 std::unique_ptr<TransportDescription> data_transport(CreateTransportAnswer( 2105 std::unique_ptr<TransportDescription> data_transport(CreateTransportAnswer(
1985 data_content->name, offer, 2106 media_description_options.mid, offer_description,
1986 GetTransportOptions(options, data_content->name), current_description)); 2107 media_description_options.transport_options, current_description));
1987 if (!data_transport) { 2108 if (!data_transport) {
1988 return false; 2109 return false;
1989 } 2110 }
1990 bool is_sctp = (options.data_channel_type == DCT_SCTP);
1991 std::vector<DataCodec> data_codecs(data_codecs_);
1992 FilterDataCodecs(&data_codecs, is_sctp);
1993 2111
1994 std::unique_ptr<DataContentDescription> data_answer( 2112 std::unique_ptr<DataContentDescription> data_answer(
1995 new DataContentDescription()); 2113 new DataContentDescription());
1996 // Do not require or create SDES cryptos if DTLS is used. 2114 // Do not require or create SDES cryptos if DTLS is used.
1997 cricket::SecurePolicy sdes_policy = 2115 cricket::SecurePolicy sdes_policy =
1998 data_transport->secure() ? cricket::SEC_DISABLED : secure(); 2116 data_transport->secure() ? cricket::SEC_DISABLED : secure();
1999 bool bundle_enabled = 2117 bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
2000 offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled; 2118 session_options.bundle_enabled;
2001 if (!CreateMediaContentAnswer( 2119 if (!CreateMediaContentAnswer(
2002 static_cast<const DataContentDescription*>( 2120 static_cast<const DataContentDescription*>(
2003 data_content->description), 2121 offer_content->description),
2004 options, 2122 media_description_options.sender_options,
2005 data_codecs_, 2123 media_description_options.direction, session_options, data_codecs,
2006 sdes_policy, 2124 sdes_policy, GetCryptos(current_content), RtpHeaderExtensions(),
2007 GetCryptos(GetFirstDataContentDescription(current_description)), 2125 current_streams, bundle_enabled, data_answer.get())) {
2008 RtpHeaderExtensions(),
2009 current_streams,
2010 add_legacy_,
2011 bundle_enabled,
2012 data_answer.get())) {
2013 return false; // Fails the session setup. 2126 return false; // Fails the session setup.
2014 } 2127 }
2015 2128
2016 bool rejected = !options.has_data() || data_content->rejected || 2129 bool rejected =
2017 !IsMediaProtocolSupported(MEDIA_TYPE_DATA, 2130 media_description_options.stopped || offer_content->rejected ||
2018 data_answer->protocol(), 2131 !IsMediaProtocolSupported(MEDIA_TYPE_DATA, data_answer->protocol(),
2019 data_transport->secure()); 2132 data_transport->secure());
2020 if (!rejected) { 2133 if (!rejected) {
2021 data_answer->set_bandwidth(options.data_bandwidth); 2134 data_answer->set_bandwidth(kDataMaxBandwidth);
2022 if (!AddTransportAnswer(data_content->name, *(data_transport.get()), 2135 if (!AddTransportAnswer(media_description_options.mid,
2023 answer)) { 2136 *(data_transport.get()), answer)) {
2024 return false; 2137 return false;
2025 } 2138 }
2026 } else { 2139 } else {
2027 // RFC 3264 2140 // RFC 3264
2028 // The answer MUST contain the same number of m-lines as the offer. 2141 // The answer MUST contain the same number of m-lines as the offer.
2029 LOG(LS_INFO) << "Data is not supported in the answer."; 2142 LOG(LS_INFO) << "Data is not supported in the answer.";
2030 } 2143 }
2031 answer->AddContent(data_content->name, data_content->type, rejected, 2144 answer->AddContent(media_description_options.mid, offer_content->type,
2032 data_answer.release()); 2145 rejected, data_answer.release());
2033 return true; 2146 return true;
2034 } 2147 }
2035 2148
2036 bool IsMediaContent(const ContentInfo* content) { 2149 bool IsMediaContent(const ContentInfo* content) {
2037 return (content && 2150 return (content &&
2038 (content->type == NS_JINGLE_RTP || 2151 (content->type == NS_JINGLE_RTP ||
2039 content->type == NS_JINGLE_DRAFT_SCTP)); 2152 content->type == NS_JINGLE_DRAFT_SCTP));
2040 } 2153 }
2041 2154
2042 bool IsAudioContent(const ContentInfo* content) { 2155 bool IsAudioContent(const ContentInfo* content) {
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
2186 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO)); 2299 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO));
2187 } 2300 }
2188 2301
2189 DataContentDescription* GetFirstDataContentDescription( 2302 DataContentDescription* GetFirstDataContentDescription(
2190 SessionDescription* sdesc) { 2303 SessionDescription* sdesc) {
2191 return static_cast<DataContentDescription*>( 2304 return static_cast<DataContentDescription*>(
2192 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA)); 2305 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA));
2193 } 2306 }
2194 2307
2195 } // namespace cricket 2308 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/pc/mediasession.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698