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

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

Issue 3001083002: Revert of Adding support for Unified Plan offer/answer negotiation. (Closed)
Patch Set: Created 3 years, 4 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') | webrtc/pc/mediasession_unittest.cc » ('j') | 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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 for (std::vector<std::string>::const_iterator it = crypto_suites.begin(); 181 for (std::vector<std::string>::const_iterator it = crypto_suites.begin();
182 it != crypto_suites.end(); ++it) { 182 it != crypto_suites.end(); ++it) {
183 if (!AddCryptoParams(*it, &cryptos)) { 183 if (!AddCryptoParams(*it, &cryptos)) {
184 return false; 184 return false;
185 } 185 }
186 } 186 }
187 AddMediaCryptos(cryptos, media); 187 AddMediaCryptos(cryptos, media);
188 return true; 188 return true;
189 } 189 }
190 190
191 const CryptoParamsVec* GetCryptos(const ContentInfo* content) { 191 const CryptoParamsVec* GetCryptos(const MediaContentDescription* media) {
192 if (!content) { 192 if (!media) {
193 return nullptr; 193 return NULL;
194 } 194 }
195 195 return &media->cryptos();
196 RTC_DCHECK(IsMediaContent(content));
197 return &(static_cast<const MediaContentDescription*>(content->description)
198 ->cryptos());
199 } 196 }
200 197
201 bool FindMatchingCrypto(const CryptoParamsVec& cryptos, 198 bool FindMatchingCrypto(const CryptoParamsVec& cryptos,
202 const CryptoParams& crypto, 199 const CryptoParams& crypto,
203 CryptoParams* out) { 200 CryptoParams* out) {
204 for (CryptoParamsVec::const_iterator it = cryptos.begin(); 201 for (CryptoParamsVec::const_iterator it = cryptos.begin();
205 it != cryptos.end(); ++it) { 202 it != cryptos.end(); ++it) {
206 if (crypto.Matches(*it)) { 203 if (crypto.Matches(*it)) {
207 *out = *it; 204 *out = *it;
208 return true; 205 return true;
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 // audio and video extensions. 421 // audio and video extensions.
425 class UsedRtpHeaderExtensionIds : public UsedIds<webrtc::RtpExtension> { 422 class UsedRtpHeaderExtensionIds : public UsedIds<webrtc::RtpExtension> {
426 public: 423 public:
427 UsedRtpHeaderExtensionIds() 424 UsedRtpHeaderExtensionIds()
428 : UsedIds<webrtc::RtpExtension>(webrtc::RtpExtension::kMinId, 425 : UsedIds<webrtc::RtpExtension>(webrtc::RtpExtension::kMinId,
429 webrtc::RtpExtension::kMaxId) {} 426 webrtc::RtpExtension::kMaxId) {}
430 427
431 private: 428 private:
432 }; 429 };
433 430
434 // Adds a StreamParams for each SenderOptions in |sender_options| to 431 // Adds a StreamParams for each Stream in Streams with media type
435 // content_description. 432 // media_type to content_description.
436 // |current_params| - All currently known StreamParams of any media type. 433 // |current_params| - All currently known StreamParams of any media type.
437 template <class C> 434 template <class C>
438 static bool AddStreamParams( 435 static bool AddStreamParams(MediaType media_type,
439 const std::vector<SenderOptions>& sender_options, 436 const MediaSessionOptions& options,
440 const std::string& rtcp_cname, 437 StreamParamsVec* current_streams,
441 StreamParamsVec* current_streams, 438 MediaContentDescriptionImpl<C>* content_description,
442 MediaContentDescriptionImpl<C>* content_description) { 439 const bool add_legacy_stream) {
443 // SCTP streams are not negotiated using SDP/ContentDescriptions. 440 // SCTP streams are not negotiated using SDP/ContentDescriptions.
444 if (IsSctp(content_description->protocol())) { 441 if (IsSctp(content_description->protocol())) {
445 return true; 442 return true;
446 } 443 }
447 444
448 const bool include_rtx_streams = 445 const bool include_rtx_streams =
449 ContainsRtxCodec(content_description->codecs()); 446 ContainsRtxCodec(content_description->codecs());
450 447
448 const MediaSessionOptions::Streams& streams = options.streams;
449 if (streams.empty() && add_legacy_stream) {
450 // TODO(perkj): Remove this legacy stream when all apps use StreamParams.
451 std::vector<uint32_t> ssrcs;
452 int num_ssrcs = include_rtx_streams ? 2 : 1;
453 GenerateSsrcs(*current_streams, num_ssrcs, &ssrcs);
454 if (include_rtx_streams) {
455 content_description->AddLegacyStream(ssrcs[0], ssrcs[1]);
456 content_description->set_multistream(true);
457 } else {
458 content_description->AddLegacyStream(ssrcs[0]);
459 }
460 return true;
461 }
451 462
452 const bool include_flexfec_stream = 463 const bool include_flexfec_stream =
453 ContainsFlexfecCodec(content_description->codecs()); 464 ContainsFlexfecCodec(content_description->codecs());
454 465
455 for (const SenderOptions& sender : sender_options) { 466 MediaSessionOptions::Streams::const_iterator stream_it;
467 for (stream_it = streams.begin();
468 stream_it != streams.end(); ++stream_it) {
469 if (stream_it->type != media_type)
470 continue; // Wrong media type.
471
472 StreamParams* param = GetStreamByIds(*current_streams, "", stream_it->id);
456 // groupid is empty for StreamParams generated using 473 // groupid is empty for StreamParams generated using
457 // MediaSessionDescriptionFactory. 474 // MediaSessionDescriptionFactory.
458 StreamParams* param =
459 GetStreamByIds(*current_streams, "" /*group_id*/, sender.track_id);
460 if (!param) { 475 if (!param) {
461 // This is a new sender. 476 // This is a new stream.
462 std::vector<uint32_t> ssrcs; 477 std::vector<uint32_t> ssrcs;
463 GenerateSsrcs(*current_streams, sender.num_sim_layers, &ssrcs); 478 GenerateSsrcs(*current_streams, stream_it->num_sim_layers, &ssrcs);
464 StreamParams stream_param; 479 StreamParams stream_param;
465 stream_param.id = sender.track_id; 480 stream_param.id = stream_it->id;
466 // Add the generated ssrc. 481 // Add the generated ssrc.
467 for (size_t i = 0; i < ssrcs.size(); ++i) { 482 for (size_t i = 0; i < ssrcs.size(); ++i) {
468 stream_param.ssrcs.push_back(ssrcs[i]); 483 stream_param.ssrcs.push_back(ssrcs[i]);
469 } 484 }
470 if (sender.num_sim_layers > 1) { 485 if (stream_it->num_sim_layers > 1) {
471 SsrcGroup group(kSimSsrcGroupSemantics, stream_param.ssrcs); 486 SsrcGroup group(kSimSsrcGroupSemantics, stream_param.ssrcs);
472 stream_param.ssrc_groups.push_back(group); 487 stream_param.ssrc_groups.push_back(group);
473 } 488 }
474 // Generate extra ssrcs for include_rtx_streams case. 489 // Generate extra ssrcs for include_rtx_streams case.
475 if (include_rtx_streams) { 490 if (include_rtx_streams) {
476 // Generate an RTX ssrc for every ssrc in the group. 491 // Generate an RTX ssrc for every ssrc in the group.
477 std::vector<uint32_t> rtx_ssrcs; 492 std::vector<uint32_t> rtx_ssrcs;
478 GenerateSsrcs(*current_streams, static_cast<int>(ssrcs.size()), 493 GenerateSsrcs(*current_streams, static_cast<int>(ssrcs.size()),
479 &rtx_ssrcs); 494 &rtx_ssrcs);
480 for (size_t i = 0; i < ssrcs.size(); ++i) { 495 for (size_t i = 0; i < ssrcs.size(); ++i) {
481 stream_param.AddFidSsrc(ssrcs[i], rtx_ssrcs[i]); 496 stream_param.AddFidSsrc(ssrcs[i], rtx_ssrcs[i]);
482 } 497 }
483 content_description->set_multistream(true); 498 content_description->set_multistream(true);
484 } 499 }
485 // Generate extra ssrc for include_flexfec_stream case. 500 // Generate extra ssrc for include_flexfec_stream case.
486 if (include_flexfec_stream) { 501 if (include_flexfec_stream) {
487 // TODO(brandtr): Update when we support multistream protection. 502 // TODO(brandtr): Update when we support multistream protection.
488 if (ssrcs.size() == 1) { 503 if (ssrcs.size() == 1) {
489 std::vector<uint32_t> flexfec_ssrcs; 504 std::vector<uint32_t> flexfec_ssrcs;
490 GenerateSsrcs(*current_streams, 1, &flexfec_ssrcs); 505 GenerateSsrcs(*current_streams, 1, &flexfec_ssrcs);
491 stream_param.AddFecFrSsrc(ssrcs[0], flexfec_ssrcs[0]); 506 stream_param.AddFecFrSsrc(ssrcs[0], flexfec_ssrcs[0]);
492 content_description->set_multistream(true); 507 content_description->set_multistream(true);
493 } else if (!ssrcs.empty()) { 508 } else if (!ssrcs.empty()) {
494 LOG(LS_WARNING) 509 LOG(LS_WARNING)
495 << "Our FlexFEC implementation only supports protecting " 510 << "Our FlexFEC implementation only supports protecting "
496 << "a single media streams. This session has multiple " 511 << "a single media streams. This session has multiple "
497 << "media streams however, so no FlexFEC SSRC will be generated."; 512 << "media streams however, so no FlexFEC SSRC will be generated.";
498 } 513 }
499 } 514 }
500 stream_param.cname = rtcp_cname; 515 stream_param.cname = options.rtcp_cname;
501 stream_param.sync_label = sender.stream_id; 516 stream_param.sync_label = stream_it->sync_label;
502 content_description->AddStream(stream_param); 517 content_description->AddStream(stream_param);
503 518
504 // Store the new StreamParams in current_streams. 519 // Store the new StreamParams in current_streams.
505 // This is necessary so that we can use the CNAME for other media types. 520 // This is necessary so that we can use the CNAME for other media types.
506 current_streams->push_back(stream_param); 521 current_streams->push_back(stream_param);
507 } else { 522 } else {
508 // Use existing generated SSRCs/groups, but update the sync_label if 523 // Use existing generated SSRCs/groups, but update the sync_label if
509 // necessary. This may be needed if a MediaStreamTrack was moved from one 524 // necessary. This may be needed if a MediaStreamTrack was moved from one
510 // MediaStream to another. 525 // MediaStream to another.
511 param->sync_label = sender.stream_id; 526 param->sync_label = stream_it->sync_label;
512 content_description->AddStream(*param); 527 content_description->AddStream(*param);
513 } 528 }
514 } 529 }
515 return true; 530 return true;
516 } 531 }
517 532
518 // Updates the transport infos of the |sdesc| according to the given 533 // Updates the transport infos of the |sdesc| according to the given
519 // |bundle_group|. The transport infos of the content names within the 534 // |bundle_group|. The transport infos of the content names within the
520 // |bundle_group| should be updated to use the ufrag, pwd and DTLS role of the 535 // |bundle_group| should be updated to use the ufrag, pwd and DTLS role of the
521 // first content within the |bundle_group|. 536 // first content within the |bundle_group|.
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 } 728 }
714 } 729 }
715 return false; 730 return false;
716 } 731 }
717 732
718 template <class C> 733 template <class C>
719 static bool IsFlexfecCodec(const C& codec) { 734 static bool IsFlexfecCodec(const C& codec) {
720 return STR_CASE_CMP(codec.name.c_str(), kFlexfecCodecName) == 0; 735 return STR_CASE_CMP(codec.name.c_str(), kFlexfecCodecName) == 0;
721 } 736 }
722 737
723 // Create a media content to be offered for the given |sender_options|, 738 static TransportOptions GetTransportOptions(const MediaSessionOptions& options,
724 // according to the given options.rtcp_mux, session_options.is_muc, codecs, 739 const std::string& content_name) {
725 // secure_transport, crypto, and current_streams. If we don't currently have 740 TransportOptions transport_options;
726 // crypto (in current_cryptos) and it is enabled (in secure_policy), crypto is 741 auto it = options.transport_options.find(content_name);
727 // created (according to crypto_suites). The created content is added to the 742 if (it != options.transport_options.end()) {
728 // offer. 743 transport_options = it->second;
744 }
745 transport_options.enable_ice_renomination = options.enable_ice_renomination;
746 return transport_options;
747 }
748
749 // Create a media content to be offered in a session-initiate,
750 // according to the given options.rtcp_mux, options.is_muc,
751 // options.streams, codecs, secure_transport, crypto, and streams. If we don't
752 // currently have crypto (in current_cryptos) and it is enabled (in
753 // secure_policy), crypto is created (according to crypto_suites). If
754 // add_legacy_stream is true, and current_streams is empty, a legacy
755 // stream is created. The created content is added to the offer.
729 template <class C> 756 template <class C>
730 static bool CreateMediaContentOffer( 757 static bool CreateMediaContentOffer(
731 const std::vector<SenderOptions>& sender_options, 758 const MediaSessionOptions& options,
732 const MediaSessionOptions& session_options,
733 const std::vector<C>& codecs, 759 const std::vector<C>& codecs,
734 const SecurePolicy& secure_policy, 760 const SecurePolicy& secure_policy,
735 const CryptoParamsVec* current_cryptos, 761 const CryptoParamsVec* current_cryptos,
736 const std::vector<std::string>& crypto_suites, 762 const std::vector<std::string>& crypto_suites,
737 const RtpHeaderExtensions& rtp_extensions, 763 const RtpHeaderExtensions& rtp_extensions,
764 bool add_legacy_stream,
738 StreamParamsVec* current_streams, 765 StreamParamsVec* current_streams,
739 MediaContentDescriptionImpl<C>* offer) { 766 MediaContentDescriptionImpl<C>* offer) {
740 offer->AddCodecs(codecs); 767 offer->AddCodecs(codecs);
741 768
742 offer->set_rtcp_mux(session_options.rtcp_mux_enabled); 769 offer->set_rtcp_mux(options.rtcp_mux_enabled);
743 if (offer->type() == cricket::MEDIA_TYPE_VIDEO) { 770 if (offer->type() == cricket::MEDIA_TYPE_VIDEO) {
744 offer->set_rtcp_reduced_size(true); 771 offer->set_rtcp_reduced_size(true);
745 } 772 }
746 offer->set_multistream(session_options.is_muc); 773 offer->set_multistream(options.is_muc);
747 offer->set_rtp_header_extensions(rtp_extensions); 774 offer->set_rtp_header_extensions(rtp_extensions);
748 775
749 if (!AddStreamParams(sender_options, session_options.rtcp_cname, 776 if (!AddStreamParams(offer->type(), options, current_streams, offer,
750 current_streams, offer)) { 777 add_legacy_stream)) {
751 return false; 778 return false;
752 } 779 }
753 780
754 if (secure_policy != SEC_DISABLED) { 781 if (secure_policy != SEC_DISABLED) {
755 if (current_cryptos) { 782 if (current_cryptos) {
756 AddMediaCryptos(*current_cryptos, offer); 783 AddMediaCryptos(*current_cryptos, offer);
757 } 784 }
758 if (offer->cryptos().empty()) { 785 if (offer->cryptos().empty()) {
759 if (!CreateMediaCryptos(crypto_suites, offer)) { 786 if (!CreateMediaCryptos(crypto_suites, offer)) {
760 return false; 787 return false;
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 } 875 }
849 if (found_codec) { 876 if (found_codec) {
850 *found_codec = potential_match; 877 *found_codec = potential_match;
851 } 878 }
852 return true; 879 return true;
853 } 880 }
854 } 881 }
855 return false; 882 return false;
856 } 883 }
857 884
858 // Find the codec in |codec_list| that |rtx_codec| is associated with. 885 // Adds all codecs from |reference_codecs| to |offered_codecs| that dont'
859 template <class C>
860 static const C* GetAssociatedCodec(const std::vector<C>& codec_list,
861 const C& rtx_codec) {
862 std::string associated_pt_str;
863 if (!rtx_codec.GetParam(kCodecParamAssociatedPayloadType,
864 &associated_pt_str)) {
865 LOG(LS_WARNING) << "RTX codec " << rtx_codec.name
866 << " is missing an associated payload type.";
867 return nullptr;
868 }
869
870 int associated_pt;
871 if (!rtc::FromString(associated_pt_str, &associated_pt)) {
872 LOG(LS_WARNING) << "Couldn't convert payload type " << associated_pt_str
873 << " of RTX codec " << rtx_codec.name << " to an integer.";
874 return nullptr;
875 }
876
877 // Find the associated reference codec for the reference RTX codec.
878 const C* associated_codec = FindCodecById(codec_list, associated_pt);
879 if (!associated_codec) {
880 LOG(LS_WARNING) << "Couldn't find associated codec with payload type "
881 << associated_pt << " for RTX codec " << rtx_codec.name
882 << ".";
883 }
884 return associated_codec;
885 }
886
887 // Adds all codecs from |reference_codecs| to |offered_codecs| that don't
888 // already exist in |offered_codecs| and ensure the payload types don't 886 // already exist in |offered_codecs| and ensure the payload types don't
889 // collide. 887 // collide.
890 template <class C> 888 template <class C>
891 static void MergeCodecs(const std::vector<C>& reference_codecs, 889 static void FindCodecsToOffer(
892 std::vector<C>* offered_codecs, 890 const std::vector<C>& reference_codecs,
893 UsedPayloadTypes* used_pltypes) { 891 std::vector<C>* offered_codecs,
892 UsedPayloadTypes* used_pltypes) {
893
894 // Add all new codecs that are not RTX codecs. 894 // Add all new codecs that are not RTX codecs.
895 for (const C& reference_codec : reference_codecs) { 895 for (const C& reference_codec : reference_codecs) {
896 if (!IsRtxCodec(reference_codec) && 896 if (!IsRtxCodec(reference_codec) &&
897 !FindMatchingCodec<C>(reference_codecs, *offered_codecs, 897 !FindMatchingCodec<C>(reference_codecs, *offered_codecs,
898 reference_codec, nullptr)) { 898 reference_codec, nullptr)) {
899 C codec = reference_codec; 899 C codec = reference_codec;
900 used_pltypes->FindAndSetIdUsed(&codec); 900 used_pltypes->FindAndSetIdUsed(&codec);
901 offered_codecs->push_back(codec); 901 offered_codecs->push_back(codec);
902 } 902 }
903 } 903 }
904 904
905 // Add all new RTX codecs. 905 // Add all new RTX codecs.
906 for (const C& reference_codec : reference_codecs) { 906 for (const C& reference_codec : reference_codecs) {
907 if (IsRtxCodec(reference_codec) && 907 if (IsRtxCodec(reference_codec) &&
908 !FindMatchingCodec<C>(reference_codecs, *offered_codecs, 908 !FindMatchingCodec<C>(reference_codecs, *offered_codecs,
909 reference_codec, nullptr)) { 909 reference_codec, nullptr)) {
910 C rtx_codec = reference_codec; 910 C rtx_codec = reference_codec;
911 const C* associated_codec = 911
912 GetAssociatedCodec(reference_codecs, rtx_codec); 912 std::string associated_pt_str;
913 if (!associated_codec) { 913 if (!rtx_codec.GetParam(kCodecParamAssociatedPayloadType,
914 &associated_pt_str)) {
915 LOG(LS_WARNING) << "RTX codec " << rtx_codec.name
916 << " is missing an associated payload type.";
914 continue; 917 continue;
915 } 918 }
919
920 int associated_pt;
921 if (!rtc::FromString(associated_pt_str, &associated_pt)) {
922 LOG(LS_WARNING) << "Couldn't convert payload type " << associated_pt_str
923 << " of RTX codec " << rtx_codec.name
924 << " to an integer.";
925 continue;
926 }
927
928 // Find the associated reference codec for the reference RTX codec.
929 const C* associated_codec =
930 FindCodecById(reference_codecs, associated_pt);
931 if (!associated_codec) {
932 LOG(LS_WARNING) << "Couldn't find associated codec with payload type "
933 << associated_pt << " for RTX codec " << rtx_codec.name
934 << ".";
935 continue;
936 }
937
916 // Find a codec in the offered list that matches the reference codec. 938 // Find a codec in the offered list that matches the reference codec.
917 // Its payload type may be different than the reference codec. 939 // Its payload type may be different than the reference codec.
918 C matching_codec; 940 C matching_codec;
919 if (!FindMatchingCodec<C>(reference_codecs, *offered_codecs, 941 if (!FindMatchingCodec<C>(reference_codecs, *offered_codecs,
920 *associated_codec, &matching_codec)) { 942 *associated_codec, &matching_codec)) {
921 LOG(LS_WARNING) << "Couldn't find matching " << associated_codec->name 943 LOG(LS_WARNING) << "Couldn't find matching " << associated_codec->name
922 << " codec."; 944 << " codec.";
923 continue; 945 continue;
924 } 946 }
925 947
926 rtx_codec.params[kCodecParamAssociatedPayloadType] = 948 rtx_codec.params[kCodecParamAssociatedPayloadType] =
927 rtc::ToString(matching_codec.id); 949 rtc::ToString(matching_codec.id);
928 used_pltypes->FindAndSetIdUsed(&rtx_codec); 950 used_pltypes->FindAndSetIdUsed(&rtx_codec);
929 offered_codecs->push_back(rtx_codec); 951 offered_codecs->push_back(rtx_codec);
930 } 952 }
931 } 953 }
932 } 954 }
933 955
934 static bool FindByUriAndEncryption(const RtpHeaderExtensions& extensions,
935 const webrtc::RtpExtension& ext_to_match,
936 webrtc::RtpExtension* found_extension) {
937 for (RtpHeaderExtensions::const_iterator it = extensions.begin();
938 it != extensions.end(); ++it) {
939 // We assume that all URIs are given in a canonical format.
940 if (it->uri == ext_to_match.uri && it->encrypt == ext_to_match.encrypt) {
941 if (found_extension) {
942 *found_extension = *it;
943 }
944 return true;
945 }
946 }
947 return false;
948 }
949
950 static bool FindByUri(const RtpHeaderExtensions& extensions, 956 static bool FindByUri(const RtpHeaderExtensions& extensions,
951 const webrtc::RtpExtension& ext_to_match, 957 const webrtc::RtpExtension& ext_to_match,
952 webrtc::RtpExtension* found_extension) { 958 webrtc::RtpExtension* found_extension) {
953 // We assume that all URIs are given in a canonical format. 959 // We assume that all URIs are given in a canonical format.
954 const webrtc::RtpExtension* found = 960 const webrtc::RtpExtension* found =
955 webrtc::RtpExtension::FindHeaderExtensionByUri(extensions, 961 webrtc::RtpExtension::FindHeaderExtensionByUri(extensions,
956 ext_to_match.uri); 962 ext_to_match.uri);
957 if (!found) { 963 if (!found) {
958 return false; 964 return false;
959 } 965 }
(...skipping 23 matching lines...) Expand all
983 } 989 }
984 if (unencrypted_extension) { 990 if (unencrypted_extension) {
985 if (found_extension) { 991 if (found_extension) {
986 *found_extension = *unencrypted_extension; 992 *found_extension = *unencrypted_extension;
987 } 993 }
988 return true; 994 return true;
989 } 995 }
990 return false; 996 return false;
991 } 997 }
992 998
993 // Adds all extensions from |reference_extensions| to |offered_extensions| that 999 // Iterates through |offered_extensions|, adding each one to
994 // don't already exist in |offered_extensions| and ensure the IDs don't 1000 // |regular_extensions| (or |encrypted_extensions| if encrypted) and |used_ids|,
995 // collide. If an extension is added, it's also added to |regular_extensions| or 1001 // and resolving ID conflicts.
996 // |encrypted_extensions|, and if the extension is in |regular_extensions| or 1002 // If an offered extension has the same URI as one in |regular_extensions| or
997 // |encrypted_extensions|, its ID is marked as used in |used_ids|. 1003 // |encrypted_extensions|, it will re-use the same ID and won't be treated as
998 // |offered_extensions| is for either audio or video while |regular_extensions| 1004 // a conflict.
999 // and |encrypted_extensions| are used for both audio and video. There could be 1005 static void FindAndSetRtpHdrExtUsed(RtpHeaderExtensions* offered_extensions,
1000 // overlap between audio extensions and video extensions. 1006 RtpHeaderExtensions* regular_extensions,
1001 static void MergeRtpHdrExts(const RtpHeaderExtensions& reference_extensions, 1007 RtpHeaderExtensions* encrypted_extensions,
1002 RtpHeaderExtensions* offered_extensions, 1008 UsedRtpHeaderExtensionIds* used_ids) {
1003 RtpHeaderExtensions* regular_extensions, 1009 for (auto& extension : *offered_extensions) {
1004 RtpHeaderExtensions* encrypted_extensions, 1010 webrtc::RtpExtension existing;
1005 UsedRtpHeaderExtensionIds* used_ids) { 1011 if ((extension.encrypt &&
1006 for (auto reference_extension : reference_extensions) { 1012 FindByUri(*encrypted_extensions, extension, &existing)) ||
1007 if (!FindByUriAndEncryption(*offered_extensions, reference_extension, 1013 (!extension.encrypt &&
1008 nullptr)) { 1014 FindByUri(*regular_extensions, extension, &existing))) {
1009 webrtc::RtpExtension existing; 1015 extension.id = existing.id;
1010 if (reference_extension.encrypt) { 1016 } else {
1011 if (FindByUriAndEncryption(*encrypted_extensions, reference_extension, 1017 used_ids->FindAndSetIdUsed(&extension);
1012 &existing)) { 1018 if (extension.encrypt) {
1013 offered_extensions->push_back(existing); 1019 encrypted_extensions->push_back(extension);
1014 } else {
1015 used_ids->FindAndSetIdUsed(&reference_extension);
1016 encrypted_extensions->push_back(reference_extension);
1017 offered_extensions->push_back(reference_extension);
1018 }
1019 } else { 1020 } else {
1020 if (FindByUriAndEncryption(*regular_extensions, reference_extension, 1021 regular_extensions->push_back(extension);
1021 &existing)) {
1022 offered_extensions->push_back(existing);
1023 } else {
1024 used_ids->FindAndSetIdUsed(&reference_extension);
1025 regular_extensions->push_back(reference_extension);
1026 offered_extensions->push_back(reference_extension);
1027 }
1028 } 1022 }
1029 } 1023 }
1030 } 1024 }
1025 }
1026
1027 // Adds |reference_extensions| to |offered_extensions|, while updating
1028 // |all_extensions| and |used_ids|.
1029 static void FindRtpHdrExtsToOffer(
1030 const RtpHeaderExtensions& reference_extensions,
1031 RtpHeaderExtensions* offered_extensions,
1032 RtpHeaderExtensions* all_extensions,
1033 UsedRtpHeaderExtensionIds* used_ids) {
1034 for (auto reference_extension : reference_extensions) {
1035 if (!FindByUri(*offered_extensions, reference_extension, NULL)) {
1036 webrtc::RtpExtension existing;
1037 if (FindByUri(*all_extensions, reference_extension, &existing)) {
1038 offered_extensions->push_back(existing);
1039 } else {
1040 used_ids->FindAndSetIdUsed(&reference_extension);
1041 all_extensions->push_back(reference_extension);
1042 offered_extensions->push_back(reference_extension);
1043 }
1044 }
1045 }
1031 } 1046 }
1032 1047
1033 static void AddEncryptedVersionsOfHdrExts(RtpHeaderExtensions* extensions, 1048 static void AddEncryptedVersionsOfHdrExts(RtpHeaderExtensions* extensions,
1034 RtpHeaderExtensions* all_extensions, 1049 RtpHeaderExtensions* all_extensions,
1035 UsedRtpHeaderExtensionIds* used_ids) { 1050 UsedRtpHeaderExtensionIds* used_ids) {
1036 RtpHeaderExtensions encrypted_extensions; 1051 RtpHeaderExtensions encrypted_extensions;
1037 for (const webrtc::RtpExtension& extension : *extensions) { 1052 for (const webrtc::RtpExtension& extension : *extensions) {
1038 webrtc::RtpExtension existing; 1053 webrtc::RtpExtension existing;
1039 // Don't add encrypted extensions again that were already included in a 1054 // Don't add encrypted extensions again that were already included in a
1040 // previous offer or regular extensions that are also included as encrypted 1055 // previous offer or regular extensions that are also included as encrypted
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 AudioCodecs::iterator iter = audio_codecs->begin(); 1096 AudioCodecs::iterator iter = audio_codecs->begin();
1082 while (iter != audio_codecs->end()) { 1097 while (iter != audio_codecs->end()) {
1083 if (STR_CASE_CMP(iter->name.c_str(), kComfortNoiseCodecName) == 0) { 1098 if (STR_CASE_CMP(iter->name.c_str(), kComfortNoiseCodecName) == 0) {
1084 iter = audio_codecs->erase(iter); 1099 iter = audio_codecs->erase(iter);
1085 } else { 1100 } else {
1086 ++iter; 1101 ++iter;
1087 } 1102 }
1088 } 1103 }
1089 } 1104 }
1090 1105
1091 // Create a media content to be answered for the given |sender_options| 1106 // Create a media content to be answered in a session-accept,
1092 // according to the given session_options.rtcp_mux, session_options.streams, 1107 // according to the given options.rtcp_mux, options.streams, codecs,
1093 // codecs, crypto, and current_streams. If we don't currently have crypto (in 1108 // crypto, and streams. If we don't currently have crypto (in
1094 // current_cryptos) and it is enabled (in secure_policy), crypto is created 1109 // current_cryptos) and it is enabled (in secure_policy), crypto is
1095 // (according to crypto_suites). The codecs, rtcp_mux, and crypto are all 1110 // created (according to crypto_suites). If add_legacy_stream is
1096 // negotiated with the offer. If the negotiation fails, this method returns 1111 // true, and current_streams is empty, a legacy stream is created.
1097 // false. The created content is added to the offer. 1112 // The codecs, rtcp_mux, and crypto are all negotiated with the offer
1113 // from the incoming session-initiate. If the negotiation fails, this
1114 // method returns false. The created content is added to the offer.
1098 template <class C> 1115 template <class C>
1099 static bool CreateMediaContentAnswer( 1116 static bool CreateMediaContentAnswer(
1100 const MediaContentDescriptionImpl<C>* offer, 1117 const MediaContentDescriptionImpl<C>* offer,
1101 const MediaDescriptionOptions& media_description_options, 1118 const MediaSessionOptions& options,
1102 const MediaSessionOptions& session_options,
1103 const std::vector<C>& local_codecs, 1119 const std::vector<C>& local_codecs,
1104 const SecurePolicy& sdes_policy, 1120 const SecurePolicy& sdes_policy,
1105 const CryptoParamsVec* current_cryptos, 1121 const CryptoParamsVec* current_cryptos,
1106 const RtpHeaderExtensions& local_rtp_extenstions, 1122 const RtpHeaderExtensions& local_rtp_extenstions,
1107 bool enable_encrypted_rtp_header_extensions, 1123 bool enable_encrypted_rtp_header_extensions,
1108 StreamParamsVec* current_streams, 1124 StreamParamsVec* current_streams,
1125 bool add_legacy_stream,
1109 bool bundle_enabled, 1126 bool bundle_enabled,
1110 MediaContentDescriptionImpl<C>* answer) { 1127 MediaContentDescriptionImpl<C>* answer) {
1111 std::vector<C> negotiated_codecs; 1128 std::vector<C> negotiated_codecs;
1112 NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs); 1129 NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs);
1113 answer->AddCodecs(negotiated_codecs); 1130 answer->AddCodecs(negotiated_codecs);
1114 answer->set_protocol(offer->protocol()); 1131 answer->set_protocol(offer->protocol());
1115 RtpHeaderExtensions negotiated_rtp_extensions; 1132 RtpHeaderExtensions negotiated_rtp_extensions;
1116 NegotiateRtpHeaderExtensions(local_rtp_extenstions, 1133 NegotiateRtpHeaderExtensions(local_rtp_extenstions,
1117 offer->rtp_header_extensions(), 1134 offer->rtp_header_extensions(),
1118 enable_encrypted_rtp_header_extensions, 1135 enable_encrypted_rtp_header_extensions,
1119 &negotiated_rtp_extensions); 1136 &negotiated_rtp_extensions);
1120 answer->set_rtp_header_extensions(negotiated_rtp_extensions); 1137 answer->set_rtp_header_extensions(negotiated_rtp_extensions);
1121 1138
1122 answer->set_rtcp_mux(session_options.rtcp_mux_enabled && offer->rtcp_mux()); 1139 answer->set_rtcp_mux(options.rtcp_mux_enabled && offer->rtcp_mux());
1123 if (answer->type() == cricket::MEDIA_TYPE_VIDEO) { 1140 if (answer->type() == cricket::MEDIA_TYPE_VIDEO) {
1124 answer->set_rtcp_reduced_size(offer->rtcp_reduced_size()); 1141 answer->set_rtcp_reduced_size(offer->rtcp_reduced_size());
1125 } 1142 }
1126 1143
1127 if (sdes_policy != SEC_DISABLED) { 1144 if (sdes_policy != SEC_DISABLED) {
1128 CryptoParams crypto; 1145 CryptoParams crypto;
1129 if (SelectCrypto(offer, bundle_enabled, session_options.crypto_options, 1146 if (SelectCrypto(offer, bundle_enabled, options.crypto_options, &crypto)) {
1130 &crypto)) {
1131 if (current_cryptos) { 1147 if (current_cryptos) {
1132 FindMatchingCrypto(*current_cryptos, crypto, &crypto); 1148 FindMatchingCrypto(*current_cryptos, crypto, &crypto);
1133 } 1149 }
1134 answer->AddCrypto(crypto); 1150 answer->AddCrypto(crypto);
1135 } 1151 }
1136 } 1152 }
1137 1153
1138 if (answer->cryptos().empty() && sdes_policy == SEC_REQUIRED) { 1154 if (answer->cryptos().empty() && sdes_policy == SEC_REQUIRED) {
1139 return false; 1155 return false;
1140 } 1156 }
1141 1157
1142 if (!AddStreamParams(media_description_options.sender_options, 1158 if (!AddStreamParams(answer->type(), options, current_streams, answer,
1143 session_options.rtcp_cname, current_streams, answer)) { 1159 add_legacy_stream)) {
1144 return false; // Something went seriously wrong. 1160 return false; // Something went seriously wrong.
1145 } 1161 }
1146 1162
1163 // Make sure the answer media content direction is per default set as
1164 // described in RFC3264 section 6.1.
1165 const bool is_data = !IsRtpProtocol(answer->protocol());
1166 const bool has_send_streams = !answer->streams().empty();
1167 const bool wants_send = has_send_streams || is_data;
1168 const bool recv_audio =
1169 answer->type() == cricket::MEDIA_TYPE_AUDIO && options.recv_audio;
1170 const bool recv_video =
1171 answer->type() == cricket::MEDIA_TYPE_VIDEO && options.recv_video;
1172 const bool recv_data =
1173 answer->type() == cricket::MEDIA_TYPE_DATA;
1174 const bool wants_receive = recv_audio || recv_video || recv_data;
1175
1147 auto offer_rtd = 1176 auto offer_rtd =
1148 RtpTransceiverDirection::FromMediaContentDirection(offer->direction()); 1177 RtpTransceiverDirection::FromMediaContentDirection(offer->direction());
1149 1178 auto wants_rtd = RtpTransceiverDirection(wants_send, wants_receive);
1150 answer->set_direction(NegotiateRtpTransceiverDirection( 1179 answer->set_direction(NegotiateRtpTransceiverDirection(offer_rtd, wants_rtd)
1151 offer_rtd, media_description_options.direction) 1180 .ToMediaContentDirection());
1152 .ToMediaContentDirection());
1153 return true; 1181 return true;
1154 } 1182 }
1155 1183
1156 static bool IsMediaProtocolSupported(MediaType type, 1184 static bool IsMediaProtocolSupported(MediaType type,
1157 const std::string& protocol, 1185 const std::string& protocol,
1158 bool secure_transport) { 1186 bool secure_transport) {
1159 // Since not all applications serialize and deserialize the media protocol, 1187 // Since not all applications serialize and deserialize the media protocol,
1160 // we will have to accept |protocol| to be empty. 1188 // we will have to accept |protocol| to be empty.
1161 if (protocol.empty()) { 1189 if (protocol.empty()) {
1162 return true; 1190 return true;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1204 const TransportInfo* info = 1232 const TransportInfo* info =
1205 current_description->GetTransportInfoByName(content_name); 1233 current_description->GetTransportInfoByName(content_name);
1206 if (info) { 1234 if (info) {
1207 desc = &info->description; 1235 desc = &info->description;
1208 } 1236 }
1209 } 1237 }
1210 return desc; 1238 return desc;
1211 } 1239 }
1212 1240
1213 // Gets the current DTLS state from the transport description. 1241 // Gets the current DTLS state from the transport description.
1214 static bool IsDtlsActive(const ContentInfo* content, 1242 static bool IsDtlsActive(
1215 const SessionDescription* current_description) { 1243 const std::string& content_name,
1216 if (!content) { 1244 const SessionDescription* current_description) {
1245 if (!current_description)
1217 return false; 1246 return false;
1218 }
1219 1247
1220 size_t msection_index = content - &current_description->contents()[0]; 1248 const ContentInfo* content =
1249 current_description->GetContentByName(content_name);
1250 if (!content)
1251 return false;
1221 1252
1222 if (current_description->transport_infos().size() <= msection_index) { 1253 const TransportDescription* current_tdesc =
1254 GetTransportDescription(content_name, current_description);
1255 if (!current_tdesc)
1223 return false; 1256 return false;
1224 }
1225 1257
1226 return current_description->transport_infos()[msection_index] 1258 return current_tdesc->secure();
1227 .description.secure();
1228 } 1259 }
1229 1260
1230 std::string MediaContentDirectionToString(MediaContentDirection direction) { 1261 std::string MediaContentDirectionToString(MediaContentDirection direction) {
1231 std::string dir_str; 1262 std::string dir_str;
1232 switch (direction) { 1263 switch (direction) {
1233 case MD_INACTIVE: 1264 case MD_INACTIVE:
1234 dir_str = "inactive"; 1265 dir_str = "inactive";
1235 break; 1266 break;
1236 case MD_SENDONLY: 1267 case MD_SENDONLY:
1237 dir_str = "sendonly"; 1268 dir_str = "sendonly";
1238 break; 1269 break;
1239 case MD_RECVONLY: 1270 case MD_RECVONLY:
1240 dir_str = "recvonly"; 1271 dir_str = "recvonly";
1241 break; 1272 break;
1242 case MD_SENDRECV: 1273 case MD_SENDRECV:
1243 dir_str = "sendrecv"; 1274 dir_str = "sendrecv";
1244 break; 1275 break;
1245 default: 1276 default:
1246 RTC_NOTREACHED(); 1277 RTC_NOTREACHED();
1247 break; 1278 break;
1248 } 1279 }
1249 1280
1250 return dir_str; 1281 return dir_str;
1251 } 1282 }
1252 1283
1253 void MediaDescriptionOptions::AddAudioSender(const std::string& track_id, 1284 void MediaSessionOptions::AddSendStream(MediaType type,
1254 const std::string& stream_id) { 1285 const std::string& id,
1255 RTC_DCHECK(type == MEDIA_TYPE_AUDIO); 1286 const std::string& sync_label) {
1256 AddSenderInternal(track_id, stream_id, 1); 1287 AddSendStreamInternal(type, id, sync_label, 1);
1257 } 1288 }
1258 1289
1259 void MediaDescriptionOptions::AddVideoSender(const std::string& track_id, 1290 void MediaSessionOptions::AddSendVideoStream(
1260 const std::string& stream_id, 1291 const std::string& id,
1261 int num_sim_layers) { 1292 const std::string& sync_label,
1262 RTC_DCHECK(type == MEDIA_TYPE_VIDEO); 1293 int num_sim_layers) {
1263 AddSenderInternal(track_id, stream_id, num_sim_layers); 1294 AddSendStreamInternal(MEDIA_TYPE_VIDEO, id, sync_label, num_sim_layers);
1264 } 1295 }
1265 1296
1266 void MediaDescriptionOptions::AddRtpDataChannel(const std::string& track_id, 1297 void MediaSessionOptions::AddSendStreamInternal(
1267 const std::string& stream_id) { 1298 MediaType type,
1268 RTC_DCHECK(type == MEDIA_TYPE_DATA); 1299 const std::string& id,
1269 AddSenderInternal(track_id, stream_id, 1); 1300 const std::string& sync_label,
1301 int num_sim_layers) {
1302 streams.push_back(Stream(type, id, sync_label, num_sim_layers));
1303
1304 // If we haven't already set the data_channel_type, and we add a
1305 // stream, we assume it's an RTP data stream.
1306 if (type == MEDIA_TYPE_DATA && data_channel_type == DCT_NONE)
1307 data_channel_type = DCT_RTP;
1270 } 1308 }
1271 1309
1272 void MediaDescriptionOptions::AddSenderInternal(const std::string& track_id, 1310 void MediaSessionOptions::RemoveSendStream(MediaType type,
1273 const std::string& stream_id, 1311 const std::string& id) {
1274 int num_sim_layers) { 1312 Streams::iterator stream_it = streams.begin();
1275 sender_options.push_back(SenderOptions{track_id, stream_id, num_sim_layers}); 1313 for (; stream_it != streams.end(); ++stream_it) {
1314 if (stream_it->type == type && stream_it->id == id) {
1315 streams.erase(stream_it);
1316 return;
1317 }
1318 }
1319 RTC_NOTREACHED();
1276 } 1320 }
1277 1321
1278 bool MediaSessionOptions::HasMediaDescription(MediaType type) const { 1322 bool MediaSessionOptions::HasSendMediaStream(MediaType type) const {
1279 return std::find_if(media_description_options.begin(), 1323 Streams::const_iterator stream_it = streams.begin();
1280 media_description_options.end(), 1324 for (; stream_it != streams.end(); ++stream_it) {
1281 [type](const MediaDescriptionOptions& t) { 1325 if (stream_it->type == type) {
1282 return t.type == type; 1326 return true;
1283 }) != media_description_options.end(); 1327 }
1328 }
1329 return false;
1284 } 1330 }
1285 1331
1286 MediaSessionDescriptionFactory::MediaSessionDescriptionFactory( 1332 MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
1287 const TransportDescriptionFactory* transport_desc_factory) 1333 const TransportDescriptionFactory* transport_desc_factory)
1288 : transport_desc_factory_(transport_desc_factory) {} 1334 : secure_(SEC_DISABLED),
1335 add_legacy_(true),
1336 transport_desc_factory_(transport_desc_factory) {
1337 }
1289 1338
1290 MediaSessionDescriptionFactory::MediaSessionDescriptionFactory( 1339 MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
1291 ChannelManager* channel_manager, 1340 ChannelManager* channel_manager,
1292 const TransportDescriptionFactory* transport_desc_factory) 1341 const TransportDescriptionFactory* transport_desc_factory)
1293 : transport_desc_factory_(transport_desc_factory) { 1342 : secure_(SEC_DISABLED),
1343 add_legacy_(true),
1344 transport_desc_factory_(transport_desc_factory) {
1294 channel_manager->GetSupportedAudioSendCodecs(&audio_send_codecs_); 1345 channel_manager->GetSupportedAudioSendCodecs(&audio_send_codecs_);
1295 channel_manager->GetSupportedAudioReceiveCodecs(&audio_recv_codecs_); 1346 channel_manager->GetSupportedAudioReceiveCodecs(&audio_recv_codecs_);
1296 channel_manager->GetSupportedAudioRtpHeaderExtensions(&audio_rtp_extensions_); 1347 channel_manager->GetSupportedAudioRtpHeaderExtensions(&audio_rtp_extensions_);
1297 channel_manager->GetSupportedVideoCodecs(&video_codecs_); 1348 channel_manager->GetSupportedVideoCodecs(&video_codecs_);
1298 channel_manager->GetSupportedVideoRtpHeaderExtensions(&video_rtp_extensions_); 1349 channel_manager->GetSupportedVideoRtpHeaderExtensions(&video_rtp_extensions_);
1299 channel_manager->GetSupportedDataCodecs(&data_codecs_); 1350 channel_manager->GetSupportedDataCodecs(&data_codecs_);
1300 ComputeAudioCodecsIntersectionAndUnion(); 1351 NegotiateCodecs(audio_recv_codecs_, audio_send_codecs_,
1352 &audio_sendrecv_codecs_);
1301 } 1353 }
1302 1354
1303 const AudioCodecs& MediaSessionDescriptionFactory::audio_sendrecv_codecs() 1355 const AudioCodecs& MediaSessionDescriptionFactory::audio_sendrecv_codecs()
1304 const { 1356 const {
1305 return audio_sendrecv_codecs_; 1357 return audio_sendrecv_codecs_;
1306 } 1358 }
1307 1359
1308 const AudioCodecs& MediaSessionDescriptionFactory::audio_send_codecs() const { 1360 const AudioCodecs& MediaSessionDescriptionFactory::audio_send_codecs() const {
1309 return audio_send_codecs_; 1361 return audio_send_codecs_;
1310 } 1362 }
1311 1363
1312 const AudioCodecs& MediaSessionDescriptionFactory::audio_recv_codecs() const { 1364 const AudioCodecs& MediaSessionDescriptionFactory::audio_recv_codecs() const {
1313 return audio_recv_codecs_; 1365 return audio_recv_codecs_;
1314 } 1366 }
1315 1367
1316 void MediaSessionDescriptionFactory::set_audio_codecs( 1368 void MediaSessionDescriptionFactory::set_audio_codecs(
1317 const AudioCodecs& send_codecs, const AudioCodecs& recv_codecs) { 1369 const AudioCodecs& send_codecs, const AudioCodecs& recv_codecs) {
1318 audio_send_codecs_ = send_codecs; 1370 audio_send_codecs_ = send_codecs;
1319 audio_recv_codecs_ = recv_codecs; 1371 audio_recv_codecs_ = recv_codecs;
1320 ComputeAudioCodecsIntersectionAndUnion(); 1372 audio_sendrecv_codecs_.clear();
1373 // Use NegotiateCodecs to merge our codec lists, since the operation is
1374 // essentially the same. Put send_codecs as the offered_codecs, which is the
1375 // order we'd like to follow. The reasoning is that encoding is usually more
1376 // expensive than decoding, and prioritizing a codec in the send list probably
1377 // means it's a codec we can handle efficiently.
1378 NegotiateCodecs(recv_codecs, send_codecs, &audio_sendrecv_codecs_);
1321 } 1379 }
1322 1380
1323 SessionDescription* MediaSessionDescriptionFactory::CreateOffer( 1381 SessionDescription* MediaSessionDescriptionFactory::CreateOffer(
1324 const MediaSessionOptions& session_options, 1382 const MediaSessionOptions& options,
1325 const SessionDescription* current_description) const { 1383 const SessionDescription* current_description) const {
1326 std::unique_ptr<SessionDescription> offer(new SessionDescription()); 1384 std::unique_ptr<SessionDescription> offer(new SessionDescription());
1327 1385
1328 StreamParamsVec current_streams; 1386 StreamParamsVec current_streams;
1329 GetCurrentStreamParams(current_description, &current_streams); 1387 GetCurrentStreamParams(current_description, &current_streams);
1330 1388
1331 AudioCodecs offer_audio_codecs; 1389 const bool wants_send =
1332 VideoCodecs offer_video_codecs; 1390 options.HasSendMediaStream(MEDIA_TYPE_AUDIO) || add_legacy_;
1333 DataCodecs offer_data_codecs; 1391 const AudioCodecs& supported_audio_codecs =
1334 GetCodecsForOffer(current_description, &offer_audio_codecs, 1392 GetAudioCodecsForOffer({wants_send, options.recv_audio});
1335 &offer_video_codecs, &offer_data_codecs);
1336 1393
1337 if (!session_options.vad_enabled) { 1394 AudioCodecs audio_codecs;
1395 VideoCodecs video_codecs;
1396 DataCodecs data_codecs;
1397 GetCodecsToOffer(current_description, supported_audio_codecs,
1398 video_codecs_, data_codecs_,
1399 &audio_codecs, &video_codecs, &data_codecs);
1400
1401 if (!options.vad_enabled) {
1338 // If application doesn't want CN codecs in offer. 1402 // If application doesn't want CN codecs in offer.
1339 StripCNCodecs(&offer_audio_codecs); 1403 StripCNCodecs(&audio_codecs);
1340 } 1404 }
1341 FilterDataCodecs(&offer_data_codecs,
1342 session_options.data_channel_type == DCT_SCTP);
1343 1405
1344 RtpHeaderExtensions audio_rtp_extensions; 1406 RtpHeaderExtensions audio_rtp_extensions;
1345 RtpHeaderExtensions video_rtp_extensions; 1407 RtpHeaderExtensions video_rtp_extensions;
1346 GetRtpHdrExtsToOffer(current_description, &audio_rtp_extensions, 1408 GetRtpHdrExtsToOffer(current_description, &audio_rtp_extensions,
1347 &video_rtp_extensions); 1409 &video_rtp_extensions);
1348 1410
1349 // Must have options for each existing section. 1411 bool audio_added = false;
1412 bool video_added = false;
1413 bool data_added = false;
1414
1415 // Iterate through the contents of |current_description| to maintain the order
1416 // of the m-lines in the new offer.
1350 if (current_description) { 1417 if (current_description) {
1351 RTC_DCHECK(current_description->contents().size() <= 1418 ContentInfos::const_iterator it = current_description->contents().begin();
1352 session_options.media_description_options.size()); 1419 for (; it != current_description->contents().end(); ++it) {
1420 if (IsMediaContentOfType(&*it, MEDIA_TYPE_AUDIO)) {
1421 if (!AddAudioContentForOffer(options, current_description,
1422 audio_rtp_extensions, audio_codecs,
1423 &current_streams, offer.get())) {
1424 return NULL;
1425 }
1426 audio_added = true;
1427 } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_VIDEO)) {
1428 if (!AddVideoContentForOffer(options, current_description,
1429 video_rtp_extensions, video_codecs,
1430 &current_streams, offer.get())) {
1431 return NULL;
1432 }
1433 video_added = true;
1434 } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_DATA)) {
1435 MediaSessionOptions options_copy(options);
1436 if (IsSctp(static_cast<const MediaContentDescription*>(it->description)
1437 ->protocol())) {
1438 options_copy.data_channel_type = DCT_SCTP;
1439 }
1440 if (!AddDataContentForOffer(options_copy, current_description,
1441 &data_codecs, &current_streams,
1442 offer.get())) {
1443 return NULL;
1444 }
1445 data_added = true;
1446 } else {
1447 RTC_NOTREACHED();
1448 }
1449 }
1353 } 1450 }
1354 1451
1355 // Iterate through the media description options, matching with existing media 1452 // Append contents that are not in |current_description|.
1356 // descriptions in |current_description|. 1453 if (!audio_added && options.has_audio() &&
1357 int msection_index = 0; 1454 !AddAudioContentForOffer(options, current_description,
1358 for (const MediaDescriptionOptions& media_description_options : 1455 audio_rtp_extensions, audio_codecs,
1359 session_options.media_description_options) { 1456 &current_streams, offer.get())) {
1360 const ContentInfo* current_content = nullptr; 1457 return NULL;
1361 if (current_description && 1458 }
1362 msection_index < 1459 if (!video_added && options.has_video() &&
1363 static_cast<int>(current_description->contents().size())) { 1460 !AddVideoContentForOffer(options, current_description,
1364 current_content = &current_description->contents()[msection_index]; 1461 video_rtp_extensions, video_codecs,
1365 // Media type must match. 1462 &current_streams, offer.get())) {
1366 RTC_DCHECK(IsMediaContentOfType(current_content, 1463 return NULL;
1367 media_description_options.type)); 1464 }
1368 } 1465 if (!data_added && options.has_data() &&
1369 switch (media_description_options.type) { 1466 !AddDataContentForOffer(options, current_description, &data_codecs,
1370 case MEDIA_TYPE_AUDIO: 1467 &current_streams, offer.get())) {
1371 if (!AddAudioContentForOffer(media_description_options, session_options, 1468 return NULL;
1372 current_content, current_description,
1373 audio_rtp_extensions, offer_audio_codecs,
1374 &current_streams, offer.get())) {
1375 return nullptr;
1376 }
1377 break;
1378 case MEDIA_TYPE_VIDEO:
1379 if (!AddVideoContentForOffer(media_description_options, session_options,
1380 current_content, current_description,
1381 video_rtp_extensions, offer_video_codecs,
1382 &current_streams, offer.get())) {
1383 return nullptr;
1384 }
1385 break;
1386 case MEDIA_TYPE_DATA:
1387 if (!AddDataContentForOffer(media_description_options, session_options,
1388 current_content, current_description,
1389 offer_data_codecs, &current_streams,
1390 offer.get())) {
1391 return nullptr;
1392 }
1393 break;
1394 default:
1395 RTC_NOTREACHED();
1396 }
1397 ++msection_index;
1398 } 1469 }
1399 1470
1400 // Bundle the contents together, if we've been asked to do so, and update any 1471 // Bundle the contents together, if we've been asked to do so, and update any
1401 // parameters that need to be tweaked for BUNDLE. 1472 // parameters that need to be tweaked for BUNDLE.
1402 if (session_options.bundle_enabled && offer->contents().size() > 0u) { 1473 if (options.bundle_enabled) {
1403 ContentGroup offer_bundle(GROUP_TYPE_BUNDLE); 1474 ContentGroup offer_bundle(GROUP_TYPE_BUNDLE);
1404 for (const ContentInfo& content : offer->contents()) { 1475 for (ContentInfos::const_iterator content = offer->contents().begin();
1405 // TODO(deadbeef): There are conditions that make bundling two media 1476 content != offer->contents().end(); ++content) {
1406 // descriptions together illegal. For example, they use the same payload 1477 offer_bundle.AddContentName(content->name);
1407 // type to represent different codecs, or same IDs for different header
1408 // extensions. We need to detect this and not try to bundle those media
1409 // descriptions together.
1410 offer_bundle.AddContentName(content.name);
1411 } 1478 }
1412 offer->AddGroup(offer_bundle); 1479 offer->AddGroup(offer_bundle);
1413 if (!UpdateTransportInfoForBundle(offer_bundle, offer.get())) { 1480 if (!UpdateTransportInfoForBundle(offer_bundle, offer.get())) {
1414 LOG(LS_ERROR) << "CreateOffer failed to UpdateTransportInfoForBundle."; 1481 LOG(LS_ERROR) << "CreateOffer failed to UpdateTransportInfoForBundle.";
1415 return nullptr; 1482 return NULL;
1416 } 1483 }
1417 if (!UpdateCryptoParamsForBundle(offer_bundle, offer.get())) { 1484 if (!UpdateCryptoParamsForBundle(offer_bundle, offer.get())) {
1418 LOG(LS_ERROR) << "CreateOffer failed to UpdateCryptoParamsForBundle."; 1485 LOG(LS_ERROR) << "CreateOffer failed to UpdateCryptoParamsForBundle.";
1419 return nullptr; 1486 return NULL;
1420 } 1487 }
1421 } 1488 }
1489
1422 return offer.release(); 1490 return offer.release();
1423 } 1491 }
1424 1492
1425 SessionDescription* MediaSessionDescriptionFactory::CreateAnswer( 1493 SessionDescription* MediaSessionDescriptionFactory::CreateAnswer(
1426 const SessionDescription* offer, 1494 const SessionDescription* offer, const MediaSessionOptions& options,
1427 const MediaSessionOptions& session_options,
1428 const SessionDescription* current_description) const { 1495 const SessionDescription* current_description) const {
1429 if (!offer) { 1496 if (!offer) {
1430 return nullptr; 1497 return nullptr;
1431 } 1498 }
1432 // The answer contains the intersection of the codecs in the offer with the 1499 // The answer contains the intersection of the codecs in the offer with the
1433 // codecs we support. As indicated by XEP-0167, we retain the same payload ids 1500 // codecs we support. As indicated by XEP-0167, we retain the same payload ids
1434 // from the offer in the answer. 1501 // from the offer in the answer.
1435 std::unique_ptr<SessionDescription> answer(new SessionDescription()); 1502 std::unique_ptr<SessionDescription> answer(new SessionDescription());
1436 1503
1437 StreamParamsVec current_streams; 1504 StreamParamsVec current_streams;
1438 GetCurrentStreamParams(current_description, &current_streams); 1505 GetCurrentStreamParams(current_description, &current_streams);
1439 1506
1440 // If the offer supports BUNDLE, and we want to use it too, create a BUNDLE 1507 // If the offer supports BUNDLE, and we want to use it too, create a BUNDLE
1441 // group in the answer with the appropriate content names. 1508 // group in the answer with the appropriate content names.
1442 const ContentGroup* offer_bundle = offer->GetGroupByName(GROUP_TYPE_BUNDLE); 1509 const ContentGroup* offer_bundle = offer->GetGroupByName(GROUP_TYPE_BUNDLE);
1443 ContentGroup answer_bundle(GROUP_TYPE_BUNDLE); 1510 ContentGroup answer_bundle(GROUP_TYPE_BUNDLE);
1444 // Transport info shared by the bundle group. 1511 // Transport info shared by the bundle group.
1445 std::unique_ptr<TransportInfo> bundle_transport; 1512 std::unique_ptr<TransportInfo> bundle_transport;
1446 1513
1447 // Get list of all possible codecs that respects existing payload type 1514 ContentInfos::const_iterator it = offer->contents().begin();
1448 // mappings and uses a single payload type space. 1515 for (; it != offer->contents().end(); ++it) {
1449 // 1516 if (IsMediaContentOfType(&*it, MEDIA_TYPE_AUDIO)) {
1450 // Note that these lists may be further filtered for each m= section; this 1517 if (!AddAudioContentForAnswer(offer, options, current_description,
1451 // step is done just to establish the payload type mappings shared by all 1518 bundle_transport.get(), &current_streams,
1452 // sections. 1519 answer.get())) {
1453 AudioCodecs answer_audio_codecs; 1520 return NULL;
1454 VideoCodecs answer_video_codecs; 1521 }
1455 DataCodecs answer_data_codecs; 1522 } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_VIDEO)) {
1456 GetCodecsForAnswer(current_description, offer, &answer_audio_codecs, 1523 if (!AddVideoContentForAnswer(offer, options, current_description,
1457 &answer_video_codecs, &answer_data_codecs); 1524 bundle_transport.get(), &current_streams,
1458 1525 answer.get())) {
1459 if (!session_options.vad_enabled) { 1526 return NULL;
1460 // If application doesn't want CN codecs in answer. 1527 }
1461 StripCNCodecs(&answer_audio_codecs); 1528 } else {
1462 } 1529 RTC_DCHECK(IsMediaContentOfType(&*it, MEDIA_TYPE_DATA));
1463 FilterDataCodecs(&answer_data_codecs, 1530 if (!AddDataContentForAnswer(offer, options, current_description,
1464 session_options.data_channel_type == DCT_SCTP); 1531 bundle_transport.get(), &current_streams,
1465 1532 answer.get())) {
1466 // Must have options for exactly as many sections as in the offer. 1533 return NULL;
1467 RTC_DCHECK(offer->contents().size() == 1534 }
1468 session_options.media_description_options.size());
1469 // Iterate through the media description options, matching with existing
1470 // media descriptions in |current_description|.
1471 int msection_index = 0;
1472 for (const MediaDescriptionOptions& media_description_options :
1473 session_options.media_description_options) {
1474 const ContentInfo* offer_content = &offer->contents()[msection_index];
1475 // Media types and MIDs must match between the remote offer and the
1476 // MediaDescriptionOptions.
1477 RTC_DCHECK(
1478 IsMediaContentOfType(offer_content, media_description_options.type));
1479 RTC_DCHECK(media_description_options.mid == offer_content->name);
1480 const ContentInfo* current_content = nullptr;
1481 if (current_description &&
1482 msection_index <
1483 static_cast<int>(current_description->contents().size())) {
1484 current_content = &current_description->contents()[msection_index];
1485 } 1535 }
1486 switch (media_description_options.type) {
1487 case MEDIA_TYPE_AUDIO:
1488 if (!AddAudioContentForAnswer(
1489 media_description_options, session_options, offer_content,
1490 offer, current_content, current_description,
1491 bundle_transport.get(), answer_audio_codecs, &current_streams,
1492 answer.get())) {
1493 return nullptr;
1494 }
1495 break;
1496 case MEDIA_TYPE_VIDEO:
1497 if (!AddVideoContentForAnswer(
1498 media_description_options, session_options, offer_content,
1499 offer, current_content, current_description,
1500 bundle_transport.get(), answer_video_codecs, &current_streams,
1501 answer.get())) {
1502 return nullptr;
1503 }
1504 break;
1505 case MEDIA_TYPE_DATA:
1506 if (!AddDataContentForAnswer(media_description_options, session_options,
1507 offer_content, offer, current_content,
1508 current_description,
1509 bundle_transport.get(), answer_data_codecs,
1510 &current_streams, answer.get())) {
1511 return nullptr;
1512 }
1513 break;
1514 default:
1515 RTC_NOTREACHED();
1516 }
1517 ++msection_index;
1518 // See if we can add the newly generated m= section to the BUNDLE group in 1536 // See if we can add the newly generated m= section to the BUNDLE group in
1519 // the answer. 1537 // the answer.
1520 ContentInfo& added = answer->contents().back(); 1538 ContentInfo& added = answer->contents().back();
1521 if (!added.rejected && session_options.bundle_enabled && offer_bundle && 1539 if (!added.rejected && options.bundle_enabled && offer_bundle &&
1522 offer_bundle->HasContentName(added.name)) { 1540 offer_bundle->HasContentName(added.name)) {
1523 answer_bundle.AddContentName(added.name); 1541 answer_bundle.AddContentName(added.name);
1524 bundle_transport.reset( 1542 bundle_transport.reset(
1525 new TransportInfo(*answer->GetTransportInfoByName(added.name))); 1543 new TransportInfo(*answer->GetTransportInfoByName(added.name)));
1526 } 1544 }
1527 } 1545 }
1528 1546
1529 // Only put BUNDLE group in answer if nonempty. 1547 // Only put BUNDLE group in answer if nonempty.
1530 if (answer_bundle.FirstContentName()) { 1548 if (answer_bundle.FirstContentName()) {
1531 answer->AddGroup(answer_bundle); 1549 answer->AddGroup(answer_bundle);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1571 } else { 1589 } else {
1572 return audio_send_codecs_; 1590 return audio_send_codecs_;
1573 } 1591 }
1574 } else if (answer.send) { 1592 } else if (answer.send) {
1575 return audio_send_codecs_; 1593 return audio_send_codecs_;
1576 } else { 1594 } else {
1577 return audio_recv_codecs_; 1595 return audio_recv_codecs_;
1578 } 1596 }
1579 } 1597 }
1580 1598
1581 void MergeCodecsFromDescription(const SessionDescription* description, 1599 void MediaSessionDescriptionFactory::GetCodecsToOffer(
1582 AudioCodecs* audio_codecs,
1583 VideoCodecs* video_codecs,
1584 DataCodecs* data_codecs,
1585 UsedPayloadTypes* used_pltypes) {
1586 RTC_DCHECK(description);
1587 for (const ContentInfo& content : description->contents()) {
1588 if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) {
1589 const AudioContentDescription* audio =
1590 static_cast<AudioContentDescription*>(content.description);
1591 MergeCodecs<AudioCodec>(audio->codecs(), audio_codecs, used_pltypes);
1592 } else if (IsMediaContentOfType(&content, MEDIA_TYPE_VIDEO)) {
1593 const VideoContentDescription* video =
1594 static_cast<VideoContentDescription*>(content.description);
1595 MergeCodecs<VideoCodec>(video->codecs(), video_codecs, used_pltypes);
1596 } else if (IsMediaContentOfType(&content, MEDIA_TYPE_DATA)) {
1597 const DataContentDescription* data =
1598 static_cast<DataContentDescription*>(content.description);
1599 MergeCodecs<DataCodec>(data->codecs(), data_codecs, used_pltypes);
1600 }
1601 }
1602 }
1603
1604 // Getting codecs for an offer involves these steps:
1605 //
1606 // 1. Construct payload type -> codec mappings for current description.
1607 // 2. Add any reference codecs that weren't already present
1608 // 3. For each individual media description (m= section), filter codecs based
1609 // on the directional attribute (happens in another method).
1610 void MediaSessionDescriptionFactory::GetCodecsForOffer(
1611 const SessionDescription* current_description, 1600 const SessionDescription* current_description,
1601 const AudioCodecs& supported_audio_codecs,
1602 const VideoCodecs& supported_video_codecs,
1603 const DataCodecs& supported_data_codecs,
1612 AudioCodecs* audio_codecs, 1604 AudioCodecs* audio_codecs,
1613 VideoCodecs* video_codecs, 1605 VideoCodecs* video_codecs,
1614 DataCodecs* data_codecs) const { 1606 DataCodecs* data_codecs) const {
1615 UsedPayloadTypes used_pltypes; 1607 UsedPayloadTypes used_pltypes;
1616 audio_codecs->clear(); 1608 audio_codecs->clear();
1617 video_codecs->clear(); 1609 video_codecs->clear();
1618 data_codecs->clear(); 1610 data_codecs->clear();
1619 1611
1612
1620 // First - get all codecs from the current description if the media type 1613 // First - get all codecs from the current description if the media type
1621 // is used. Add them to |used_pltypes| so the payload type is not reused if a 1614 // is used.
1622 // new media type is added. 1615 // Add them to |used_pltypes| so the payloadtype is not reused if a new media
1616 // type is added.
1623 if (current_description) { 1617 if (current_description) {
1624 MergeCodecsFromDescription(current_description, audio_codecs, video_codecs, 1618 const AudioContentDescription* audio =
1625 data_codecs, &used_pltypes); 1619 GetFirstAudioContentDescription(current_description);
1620 if (audio) {
1621 *audio_codecs = audio->codecs();
1622 used_pltypes.FindAndSetIdUsed<AudioCodec>(audio_codecs);
1623 }
1624 const VideoContentDescription* video =
1625 GetFirstVideoContentDescription(current_description);
1626 if (video) {
1627 *video_codecs = video->codecs();
1628 used_pltypes.FindAndSetIdUsed<VideoCodec>(video_codecs);
1629 }
1630 const DataContentDescription* data =
1631 GetFirstDataContentDescription(current_description);
1632 if (data) {
1633 *data_codecs = data->codecs();
1634 used_pltypes.FindAndSetIdUsed<DataCodec>(data_codecs);
1635 }
1626 } 1636 }
1627 1637
1628 // Add our codecs that are not in |current_description|. 1638 // Add our codecs that are not in |current_description|.
1629 MergeCodecs<AudioCodec>(all_audio_codecs_, audio_codecs, &used_pltypes); 1639 FindCodecsToOffer<AudioCodec>(supported_audio_codecs, audio_codecs,
1630 MergeCodecs<VideoCodec>(video_codecs_, video_codecs, &used_pltypes); 1640 &used_pltypes);
1631 MergeCodecs<DataCodec>(data_codecs_, data_codecs, &used_pltypes); 1641 FindCodecsToOffer<VideoCodec>(supported_video_codecs, video_codecs,
1632 } 1642 &used_pltypes);
1633 1643 FindCodecsToOffer<DataCodec>(supported_data_codecs, data_codecs,
1634 // Getting codecs for an answer involves these steps: 1644 &used_pltypes);
1635 //
1636 // 1. Construct payload type -> codec mappings for current description.
1637 // 2. Add any codecs from the offer that weren't already present.
1638 // 3. Add any remaining codecs that weren't already present.
1639 // 4. For each individual media description (m= section), filter codecs based
1640 // on the directional attribute (happens in another method).
1641 void MediaSessionDescriptionFactory::GetCodecsForAnswer(
1642 const SessionDescription* current_description,
1643 const SessionDescription* remote_offer,
1644 AudioCodecs* audio_codecs,
1645 VideoCodecs* video_codecs,
1646 DataCodecs* data_codecs) const {
1647 UsedPayloadTypes used_pltypes;
1648 audio_codecs->clear();
1649 video_codecs->clear();
1650 data_codecs->clear();
1651
1652 // First - get all codecs from the current description if the media type
1653 // is used. Add them to |used_pltypes| so the payload type is not reused if a
1654 // new media type is added.
1655 if (current_description) {
1656 MergeCodecsFromDescription(current_description, audio_codecs, video_codecs,
1657 data_codecs, &used_pltypes);
1658 }
1659
1660 // Second - filter out codecs that we don't support at all and should ignore.
1661 AudioCodecs filtered_offered_audio_codecs;
1662 VideoCodecs filtered_offered_video_codecs;
1663 DataCodecs filtered_offered_data_codecs;
1664 for (const ContentInfo& content : remote_offer->contents()) {
1665 if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) {
1666 const AudioContentDescription* audio =
1667 static_cast<AudioContentDescription*>(content.description);
1668 for (const AudioCodec& offered_audio_codec : audio->codecs()) {
1669 if (!FindMatchingCodec<AudioCodec>(audio->codecs(),
1670 filtered_offered_audio_codecs,
1671 offered_audio_codec, nullptr) &&
1672 FindMatchingCodec<AudioCodec>(audio->codecs(), all_audio_codecs_,
1673 offered_audio_codec, nullptr)) {
1674 filtered_offered_audio_codecs.push_back(offered_audio_codec);
1675 }
1676 }
1677 } else if (IsMediaContentOfType(&content, MEDIA_TYPE_VIDEO)) {
1678 const VideoContentDescription* video =
1679 static_cast<VideoContentDescription*>(content.description);
1680 for (const VideoCodec& offered_video_codec : video->codecs()) {
1681 if (!FindMatchingCodec<VideoCodec>(video->codecs(),
1682 filtered_offered_video_codecs,
1683 offered_video_codec, nullptr) &&
1684 FindMatchingCodec<VideoCodec>(video->codecs(), video_codecs_,
1685 offered_video_codec, nullptr)) {
1686 filtered_offered_video_codecs.push_back(offered_video_codec);
1687 }
1688 }
1689 } else if (IsMediaContentOfType(&content, MEDIA_TYPE_DATA)) {
1690 const DataContentDescription* data =
1691 static_cast<DataContentDescription*>(content.description);
1692 for (const DataCodec& offered_data_codec : data->codecs()) {
1693 if (!FindMatchingCodec<DataCodec>(data->codecs(),
1694 filtered_offered_data_codecs,
1695 offered_data_codec, nullptr) &&
1696 FindMatchingCodec<DataCodec>(data->codecs(), data_codecs_,
1697 offered_data_codec, nullptr)) {
1698 filtered_offered_data_codecs.push_back(offered_data_codec);
1699 }
1700 }
1701 }
1702 }
1703
1704 // Add codecs that are not in |current_description| but were in
1705 // |remote_offer|.
1706 MergeCodecs<AudioCodec>(filtered_offered_audio_codecs, audio_codecs,
1707 &used_pltypes);
1708 MergeCodecs<VideoCodec>(filtered_offered_video_codecs, video_codecs,
1709 &used_pltypes);
1710 MergeCodecs<DataCodec>(filtered_offered_data_codecs, data_codecs,
1711 &used_pltypes);
1712 } 1645 }
1713 1646
1714 void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer( 1647 void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer(
1715 const SessionDescription* current_description, 1648 const SessionDescription* current_description,
1716 RtpHeaderExtensions* offer_audio_extensions, 1649 RtpHeaderExtensions* audio_extensions,
1717 RtpHeaderExtensions* offer_video_extensions) const { 1650 RtpHeaderExtensions* video_extensions) const {
1718 // All header extensions allocated from the same range to avoid potential 1651 // All header extensions allocated from the same range to avoid potential
1719 // issues when using BUNDLE. 1652 // issues when using BUNDLE.
1720 UsedRtpHeaderExtensionIds used_ids; 1653 UsedRtpHeaderExtensionIds used_ids;
1721 RtpHeaderExtensions all_regular_extensions; 1654 RtpHeaderExtensions all_regular_extensions;
1722 RtpHeaderExtensions all_encrypted_extensions; 1655 RtpHeaderExtensions all_encrypted_extensions;
1723 offer_audio_extensions->clear(); 1656 audio_extensions->clear();
1724 offer_video_extensions->clear(); 1657 video_extensions->clear();
1725 1658
1726 // First - get all extensions from the current description if the media type 1659 // First - get all extensions from the current description if the media type
1727 // is used. 1660 // is used.
1728 // Add them to |used_ids| so the local ids are not reused if a new media 1661 // Add them to |used_ids| so the local ids are not reused if a new media
1729 // type is added. 1662 // type is added.
1730 if (current_description) { 1663 if (current_description) {
1731 for (const ContentInfo& content : current_description->contents()) { 1664 const AudioContentDescription* audio =
1732 if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) { 1665 GetFirstAudioContentDescription(current_description);
1733 const AudioContentDescription* audio = 1666 if (audio) {
1734 static_cast<const AudioContentDescription*>(content.description); 1667 *audio_extensions = audio->rtp_header_extensions();
1735 MergeRtpHdrExts(audio->rtp_header_extensions(), offer_audio_extensions, 1668 FindAndSetRtpHdrExtUsed(audio_extensions, &all_regular_extensions,
1736 &all_regular_extensions, &all_encrypted_extensions, 1669 &all_encrypted_extensions, &used_ids);
1737 &used_ids); 1670 }
1738 } else if (IsMediaContentOfType(&content, MEDIA_TYPE_VIDEO)) { 1671 const VideoContentDescription* video =
1739 const VideoContentDescription* video = 1672 GetFirstVideoContentDescription(current_description);
1740 static_cast<const VideoContentDescription*>(content.description); 1673 if (video) {
1741 MergeRtpHdrExts(video->rtp_header_extensions(), offer_video_extensions, 1674 *video_extensions = video->rtp_header_extensions();
1742 &all_regular_extensions, &all_encrypted_extensions, 1675 FindAndSetRtpHdrExtUsed(video_extensions, &all_regular_extensions,
1743 &used_ids); 1676 &all_encrypted_extensions, &used_ids);
1744 }
1745 } 1677 }
1746 } 1678 }
1747 1679
1748 // Add our default RTP header extensions that are not in 1680 // Add our default RTP header extensions that are not in
1749 // |current_description|. 1681 // |current_description|.
1750 MergeRtpHdrExts(audio_rtp_header_extensions(), offer_audio_extensions, 1682 FindRtpHdrExtsToOffer(audio_rtp_header_extensions(), audio_extensions,
1751 &all_regular_extensions, &all_encrypted_extensions, 1683 &all_regular_extensions, &used_ids);
1752 &used_ids); 1684 FindRtpHdrExtsToOffer(video_rtp_header_extensions(), video_extensions,
1753 MergeRtpHdrExts(video_rtp_header_extensions(), offer_video_extensions, 1685 &all_regular_extensions, &used_ids);
1754 &all_regular_extensions, &all_encrypted_extensions,
1755 &used_ids);
1756
1757 // TODO(jbauch): Support adding encrypted header extensions to existing 1686 // TODO(jbauch): Support adding encrypted header extensions to existing
1758 // sessions. 1687 // sessions.
1759 if (enable_encrypted_rtp_header_extensions_ && !current_description) { 1688 if (enable_encrypted_rtp_header_extensions_ && !current_description) {
1760 AddEncryptedVersionsOfHdrExts(offer_audio_extensions, 1689 AddEncryptedVersionsOfHdrExts(audio_extensions, &all_encrypted_extensions,
1761 &all_encrypted_extensions, &used_ids); 1690 &used_ids);
1762 AddEncryptedVersionsOfHdrExts(offer_video_extensions, 1691 AddEncryptedVersionsOfHdrExts(video_extensions, &all_encrypted_extensions,
1763 &all_encrypted_extensions, &used_ids); 1692 &used_ids);
1764 } 1693 }
1765 } 1694 }
1766 1695
1767 bool MediaSessionDescriptionFactory::AddTransportOffer( 1696 bool MediaSessionDescriptionFactory::AddTransportOffer(
1768 const std::string& content_name, 1697 const std::string& content_name,
1769 const TransportOptions& transport_options, 1698 const TransportOptions& transport_options,
1770 const SessionDescription* current_desc, 1699 const SessionDescription* current_desc,
1771 SessionDescription* offer_desc) const { 1700 SessionDescription* offer_desc) const {
1772 if (!transport_desc_factory_) 1701 if (!transport_desc_factory_)
1773 return false; 1702 return false;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1807 SessionDescription* answer_desc) const { 1736 SessionDescription* answer_desc) const {
1808 if (!answer_desc->AddTransportInfo(TransportInfo(content_name, 1737 if (!answer_desc->AddTransportInfo(TransportInfo(content_name,
1809 transport_desc))) { 1738 transport_desc))) {
1810 LOG(LS_ERROR) 1739 LOG(LS_ERROR)
1811 << "Failed to AddTransportAnswer, content name=" << content_name; 1740 << "Failed to AddTransportAnswer, content name=" << content_name;
1812 return false; 1741 return false;
1813 } 1742 }
1814 return true; 1743 return true;
1815 } 1744 }
1816 1745
1817 // |audio_codecs| = set of all possible codecs that can be used, with correct
1818 // payload type mappings
1819 //
1820 // |supported_audio_codecs| = set of codecs that are supported for the direction
1821 // of this m= section
1822 //
1823 // acd->codecs() = set of previously negotiated codecs for this m= section
1824 //
1825 // The payload types should come from audio_codecs, but the order should come
1826 // from acd->codecs() and then supported_codecs, to ensure that re-offers don't
1827 // change existing codec priority, and that new codecs are added with the right
1828 // priority.
1829 bool MediaSessionDescriptionFactory::AddAudioContentForOffer( 1746 bool MediaSessionDescriptionFactory::AddAudioContentForOffer(
1830 const MediaDescriptionOptions& media_description_options, 1747 const MediaSessionOptions& options,
1831 const MediaSessionOptions& session_options,
1832 const ContentInfo* current_content,
1833 const SessionDescription* current_description, 1748 const SessionDescription* current_description,
1834 const RtpHeaderExtensions& audio_rtp_extensions, 1749 const RtpHeaderExtensions& audio_rtp_extensions,
1835 const AudioCodecs& audio_codecs, 1750 const AudioCodecs& audio_codecs,
1836 StreamParamsVec* current_streams, 1751 StreamParamsVec* current_streams,
1837 SessionDescription* desc) const { 1752 SessionDescription* desc) const {
1838 // Filter audio_codecs (which includes all codecs, with correctly remapped 1753 const ContentInfo* current_audio_content =
1839 // payload types) based on transceiver direction. 1754 GetFirstAudioContent(current_description);
1840 const AudioCodecs& supported_audio_codecs = 1755 std::string content_name =
1841 GetAudioCodecsForOffer(media_description_options.direction); 1756 current_audio_content ? current_audio_content->name : CN_AUDIO;
1842
1843 AudioCodecs filtered_codecs;
1844 // Add the codecs from current content if exists.
1845 if (current_content) {
1846 RTC_DCHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_AUDIO));
1847 const AudioContentDescription* acd =
1848 static_cast<const AudioContentDescription*>(
1849 current_content->description);
1850 for (const AudioCodec& codec : acd->codecs()) {
1851 if (FindMatchingCodec<AudioCodec>(supported_audio_codecs, audio_codecs,
1852 codec, nullptr)) {
1853 filtered_codecs.push_back(codec);
1854 }
1855 }
1856 }
1857 // Add other supported audio codecs.
1858 AudioCodec found_codec;
1859 for (const AudioCodec& codec : supported_audio_codecs) {
1860 if (FindMatchingCodec<AudioCodec>(supported_audio_codecs, audio_codecs,
1861 codec, &found_codec) &&
1862 !FindMatchingCodec<AudioCodec>(supported_audio_codecs, filtered_codecs,
1863 codec, nullptr)) {
1864 // Use the |found_codec| from |audio_codecs| because it has the correctly
1865 // mapped payload type.
1866 filtered_codecs.push_back(found_codec);
1867 }
1868 }
1869 1757
1870 cricket::SecurePolicy sdes_policy = 1758 cricket::SecurePolicy sdes_policy =
1871 IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED 1759 IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED
1872 : secure(); 1760 : secure();
1873 1761
1874 std::unique_ptr<AudioContentDescription> audio(new AudioContentDescription()); 1762 std::unique_ptr<AudioContentDescription> audio(new AudioContentDescription());
1875 std::vector<std::string> crypto_suites; 1763 std::vector<std::string> crypto_suites;
1876 GetSupportedAudioSdesCryptoSuiteNames(session_options.crypto_options, 1764 GetSupportedAudioSdesCryptoSuiteNames(options.crypto_options, &crypto_suites);
1877 &crypto_suites);
1878 if (!CreateMediaContentOffer( 1765 if (!CreateMediaContentOffer(
1879 media_description_options.sender_options, session_options, 1766 options,
1880 filtered_codecs, sdes_policy, GetCryptos(current_content), 1767 audio_codecs,
1881 crypto_suites, audio_rtp_extensions, current_streams, audio.get())) { 1768 sdes_policy,
1769 GetCryptos(GetFirstAudioContentDescription(current_description)),
1770 crypto_suites,
1771 audio_rtp_extensions,
1772 add_legacy_,
1773 current_streams,
1774 audio.get())) {
1882 return false; 1775 return false;
1883 } 1776 }
1884 audio->set_lang(lang_); 1777 audio->set_lang(lang_);
1885 1778
1886 bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED); 1779 bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
1887 SetMediaProtocol(secure_transport, audio.get()); 1780 SetMediaProtocol(secure_transport, audio.get());
1888 1781
1889 audio->set_direction( 1782 auto offer_rtd =
1890 media_description_options.direction.ToMediaContentDirection()); 1783 RtpTransceiverDirection(!audio->streams().empty(), options.recv_audio);
1784 audio->set_direction(offer_rtd.ToMediaContentDirection());
1891 1785
1892 desc->AddContent(media_description_options.mid, NS_JINGLE_RTP, 1786 desc->AddContent(content_name, NS_JINGLE_RTP, audio.release());
1893 media_description_options.stopped, audio.release()); 1787 if (!AddTransportOffer(content_name,
1894 if (!AddTransportOffer(media_description_options.mid, 1788 GetTransportOptions(options, content_name),
1895 media_description_options.transport_options,
1896 current_description, desc)) { 1789 current_description, desc)) {
1897 return false; 1790 return false;
1898 } 1791 }
1899 1792
1900 return true; 1793 return true;
1901 } 1794 }
1902 1795
1903 bool MediaSessionDescriptionFactory::AddVideoContentForOffer( 1796 bool MediaSessionDescriptionFactory::AddVideoContentForOffer(
1904 const MediaDescriptionOptions& media_description_options, 1797 const MediaSessionOptions& options,
1905 const MediaSessionOptions& session_options,
1906 const ContentInfo* current_content,
1907 const SessionDescription* current_description, 1798 const SessionDescription* current_description,
1908 const RtpHeaderExtensions& video_rtp_extensions, 1799 const RtpHeaderExtensions& video_rtp_extensions,
1909 const VideoCodecs& video_codecs, 1800 const VideoCodecs& video_codecs,
1910 StreamParamsVec* current_streams, 1801 StreamParamsVec* current_streams,
1911 SessionDescription* desc) const { 1802 SessionDescription* desc) const {
1803 const ContentInfo* current_video_content =
1804 GetFirstVideoContent(current_description);
1805 std::string content_name =
1806 current_video_content ? current_video_content->name : CN_VIDEO;
1807
1912 cricket::SecurePolicy sdes_policy = 1808 cricket::SecurePolicy sdes_policy =
1913 IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED 1809 IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED
1914 : secure(); 1810 : secure();
1915 1811
1916 std::unique_ptr<VideoContentDescription> video(new VideoContentDescription()); 1812 std::unique_ptr<VideoContentDescription> video(new VideoContentDescription());
1917 std::vector<std::string> crypto_suites; 1813 std::vector<std::string> crypto_suites;
1918 GetSupportedVideoSdesCryptoSuiteNames(session_options.crypto_options, 1814 GetSupportedVideoSdesCryptoSuiteNames(options.crypto_options, &crypto_suites);
1919 &crypto_suites);
1920
1921 VideoCodecs filtered_codecs;
1922 // Add the codecs from current content if exists.
1923 if (current_content) {
1924 RTC_DCHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_VIDEO));
1925 const VideoContentDescription* vcd =
1926 static_cast<const VideoContentDescription*>(
1927 current_content->description);
1928 for (const VideoCodec& codec : vcd->codecs()) {
1929 if (FindMatchingCodec<VideoCodec>(video_codecs_, video_codecs, codec,
1930 nullptr)) {
1931 filtered_codecs.push_back(codec);
1932 }
1933 }
1934 }
1935 // Add other supported video codecs.
1936 VideoCodec found_codec;
1937 for (const VideoCodec& codec : video_codecs_) {
1938 if (FindMatchingCodec<VideoCodec>(video_codecs_, video_codecs, codec,
1939 &found_codec) &&
1940 !FindMatchingCodec<VideoCodec>(video_codecs_, filtered_codecs, codec,
1941 nullptr)) {
1942 // Use the |found_codec| from |video_codecs| because it has the correctly
1943 // mapped payload type.
1944 filtered_codecs.push_back(found_codec);
1945 }
1946 }
1947
1948 if (!CreateMediaContentOffer( 1815 if (!CreateMediaContentOffer(
1949 media_description_options.sender_options, session_options, 1816 options,
1950 filtered_codecs, sdes_policy, GetCryptos(current_content), 1817 video_codecs,
1951 crypto_suites, video_rtp_extensions, current_streams, video.get())) { 1818 sdes_policy,
1819 GetCryptos(GetFirstVideoContentDescription(current_description)),
1820 crypto_suites,
1821 video_rtp_extensions,
1822 add_legacy_,
1823 current_streams,
1824 video.get())) {
1952 return false; 1825 return false;
1953 } 1826 }
1954 1827
1955 video->set_bandwidth(kAutoBandwidth); 1828 video->set_bandwidth(options.video_bandwidth);
1956 1829
1957 bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED); 1830 bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
1958 SetMediaProtocol(secure_transport, video.get()); 1831 SetMediaProtocol(secure_transport, video.get());
1959 1832
1960 video->set_direction( 1833 if (!video->streams().empty()) {
1961 media_description_options.direction.ToMediaContentDirection()); 1834 if (options.recv_video) {
1835 video->set_direction(MD_SENDRECV);
1836 } else {
1837 video->set_direction(MD_SENDONLY);
1838 }
1839 } else {
1840 if (options.recv_video) {
1841 video->set_direction(MD_RECVONLY);
1842 } else {
1843 video->set_direction(MD_INACTIVE);
1844 }
1845 }
1962 1846
1963 desc->AddContent(media_description_options.mid, NS_JINGLE_RTP, 1847 desc->AddContent(content_name, NS_JINGLE_RTP, video.release());
1964 media_description_options.stopped, video.release()); 1848 if (!AddTransportOffer(content_name,
1965 if (!AddTransportOffer(media_description_options.mid, 1849 GetTransportOptions(options, content_name),
1966 media_description_options.transport_options,
1967 current_description, desc)) { 1850 current_description, desc)) {
1968 return false; 1851 return false;
1969 } 1852 }
1853
1970 return true; 1854 return true;
1971 } 1855 }
1972 1856
1973 bool MediaSessionDescriptionFactory::AddDataContentForOffer( 1857 bool MediaSessionDescriptionFactory::AddDataContentForOffer(
1974 const MediaDescriptionOptions& media_description_options, 1858 const MediaSessionOptions& options,
1975 const MediaSessionOptions& session_options,
1976 const ContentInfo* current_content,
1977 const SessionDescription* current_description, 1859 const SessionDescription* current_description,
1978 const DataCodecs& data_codecs, 1860 DataCodecs* data_codecs,
1979 StreamParamsVec* current_streams, 1861 StreamParamsVec* current_streams,
1980 SessionDescription* desc) const { 1862 SessionDescription* desc) const {
1981 bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED); 1863 bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
1982 1864
1983 std::unique_ptr<DataContentDescription> data(new DataContentDescription()); 1865 std::unique_ptr<DataContentDescription> data(new DataContentDescription());
1984 bool is_sctp = (session_options.data_channel_type == DCT_SCTP); 1866 bool is_sctp = (options.data_channel_type == DCT_SCTP);
1985 // If the DataChannel type is not specified, use the DataChannel type in 1867
1986 // the current description. 1868 FilterDataCodecs(data_codecs, is_sctp);
1987 if (session_options.data_channel_type == DCT_NONE && current_content) { 1869
1988 is_sctp = (static_cast<const DataContentDescription*>( 1870 const ContentInfo* current_data_content =
1989 current_content->description) 1871 GetFirstDataContent(current_description);
1990 ->protocol() == kMediaProtocolSctp); 1872 std::string content_name =
1991 } 1873 current_data_content ? current_data_content->name : CN_DATA;
1992 1874
1993 cricket::SecurePolicy sdes_policy = 1875 cricket::SecurePolicy sdes_policy =
1994 IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED 1876 IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED
1995 : secure(); 1877 : secure();
1996 std::vector<std::string> crypto_suites; 1878 std::vector<std::string> crypto_suites;
1997 if (is_sctp) { 1879 if (is_sctp) {
1998 // SDES doesn't make sense for SCTP, so we disable it, and we only 1880 // SDES doesn't make sense for SCTP, so we disable it, and we only
1999 // get SDES crypto suites for RTP-based data channels. 1881 // get SDES crypto suites for RTP-based data channels.
2000 sdes_policy = cricket::SEC_DISABLED; 1882 sdes_policy = cricket::SEC_DISABLED;
2001 // Unlike SetMediaProtocol below, we need to set the protocol 1883 // Unlike SetMediaProtocol below, we need to set the protocol
2002 // before we call CreateMediaContentOffer. Otherwise, 1884 // before we call CreateMediaContentOffer. Otherwise,
2003 // CreateMediaContentOffer won't know this is SCTP and will 1885 // CreateMediaContentOffer won't know this is SCTP and will
2004 // generate SSRCs rather than SIDs. 1886 // generate SSRCs rather than SIDs.
2005 // TODO(deadbeef): Offer kMediaProtocolUdpDtlsSctp (or TcpDtlsSctp), once 1887 // TODO(deadbeef): Offer kMediaProtocolUdpDtlsSctp (or TcpDtlsSctp), once
2006 // it's safe to do so. Older versions of webrtc would reject these 1888 // it's safe to do so. Older versions of webrtc would reject these
2007 // protocols; see https://bugs.chromium.org/p/webrtc/issues/detail?id=7706. 1889 // protocols; see https://bugs.chromium.org/p/webrtc/issues/detail?id=7706.
2008 data->set_protocol( 1890 data->set_protocol(
2009 secure_transport ? kMediaProtocolDtlsSctp : kMediaProtocolSctp); 1891 secure_transport ? kMediaProtocolDtlsSctp : kMediaProtocolSctp);
2010 } else { 1892 } else {
2011 GetSupportedDataSdesCryptoSuiteNames(session_options.crypto_options, 1893 GetSupportedDataSdesCryptoSuiteNames(options.crypto_options,
2012 &crypto_suites); 1894 &crypto_suites);
2013 } 1895 }
2014 1896
2015 // Even SCTP uses a "codec".
2016 if (!CreateMediaContentOffer( 1897 if (!CreateMediaContentOffer(
2017 media_description_options.sender_options, session_options, 1898 options,
2018 data_codecs, sdes_policy, GetCryptos(current_content), crypto_suites, 1899 *data_codecs,
2019 RtpHeaderExtensions(), current_streams, data.get())) { 1900 sdes_policy,
1901 GetCryptos(GetFirstDataContentDescription(current_description)),
1902 crypto_suites,
1903 RtpHeaderExtensions(),
1904 add_legacy_,
1905 current_streams,
1906 data.get())) {
2020 return false; 1907 return false;
2021 } 1908 }
2022 1909
2023 if (is_sctp) { 1910 if (is_sctp) {
2024 desc->AddContent(media_description_options.mid, NS_JINGLE_DRAFT_SCTP, 1911 desc->AddContent(content_name, NS_JINGLE_DRAFT_SCTP, data.release());
2025 data.release()); 1912 } else {
2026 } else { 1913 data->set_bandwidth(options.data_bandwidth);
2027 data->set_bandwidth(kDataMaxBandwidth);
2028 SetMediaProtocol(secure_transport, data.get()); 1914 SetMediaProtocol(secure_transport, data.get());
2029 desc->AddContent(media_description_options.mid, NS_JINGLE_RTP, 1915 desc->AddContent(content_name, NS_JINGLE_RTP, data.release());
2030 media_description_options.stopped, data.release()); 1916 }
2031 } 1917 if (!AddTransportOffer(content_name,
2032 if (!AddTransportOffer(media_description_options.mid, 1918 GetTransportOptions(options, content_name),
2033 media_description_options.transport_options,
2034 current_description, desc)) { 1919 current_description, desc)) {
2035 return false; 1920 return false;
2036 } 1921 }
2037 return true; 1922 return true;
2038 } 1923 }
2039 1924
2040 // |audio_codecs| = set of all possible codecs that can be used, with correct
2041 // payload type mappings
2042 //
2043 // |supported_audio_codecs| = set of codecs that are supported for the direction
2044 // of this m= section
2045 //
2046 // acd->codecs() = set of previously negotiated codecs for this m= section
2047 //
2048 // The payload types should come from audio_codecs, but the order should come
2049 // from acd->codecs() and then supported_codecs, to ensure that re-offers don't
2050 // change existing codec priority, and that new codecs are added with the right
2051 // priority.
2052 bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( 1925 bool MediaSessionDescriptionFactory::AddAudioContentForAnswer(
2053 const MediaDescriptionOptions& media_description_options, 1926 const SessionDescription* offer,
2054 const MediaSessionOptions& session_options, 1927 const MediaSessionOptions& options,
2055 const ContentInfo* offer_content,
2056 const SessionDescription* offer_description,
2057 const ContentInfo* current_content,
2058 const SessionDescription* current_description, 1928 const SessionDescription* current_description,
2059 const TransportInfo* bundle_transport, 1929 const TransportInfo* bundle_transport,
2060 const AudioCodecs& audio_codecs,
2061 StreamParamsVec* current_streams, 1930 StreamParamsVec* current_streams,
2062 SessionDescription* answer) const { 1931 SessionDescription* answer) const {
2063 const AudioContentDescription* offer_audio_description = 1932 const ContentInfo* audio_content = GetFirstAudioContent(offer);
2064 static_cast<const AudioContentDescription*>(offer_content->description); 1933 const AudioContentDescription* offer_audio =
1934 static_cast<const AudioContentDescription*>(audio_content->description);
2065 1935
2066 std::unique_ptr<TransportDescription> audio_transport( 1936 std::unique_ptr<TransportDescription> audio_transport(
2067 CreateTransportAnswer(media_description_options.mid, offer_description, 1937 CreateTransportAnswer(audio_content->name, offer,
2068 media_description_options.transport_options, 1938 GetTransportOptions(options, audio_content->name),
2069 current_description, bundle_transport != nullptr)); 1939 current_description, bundle_transport != nullptr));
2070 if (!audio_transport) { 1940 if (!audio_transport) {
2071 return false; 1941 return false;
2072 } 1942 }
2073 1943
2074 // Pick codecs based on the requested communications direction in the offer 1944 // Pick codecs based on the requested communications direction in the offer.
2075 // and the selected direction in the answer. 1945 const bool wants_send =
2076 // Note these will be filtered one final time in CreateMediaContentAnswer. 1946 options.HasSendMediaStream(MEDIA_TYPE_AUDIO) || add_legacy_;
2077 auto wants_rtd = media_description_options.direction; 1947 auto wants_rtd = RtpTransceiverDirection(wants_send, options.recv_audio);
2078 auto offer_rtd = RtpTransceiverDirection::FromMediaContentDirection( 1948 auto offer_rtd =
2079 offer_audio_description->direction()); 1949 RtpTransceiverDirection::FromMediaContentDirection(
1950 offer_audio->direction());
2080 auto answer_rtd = NegotiateRtpTransceiverDirection(offer_rtd, wants_rtd); 1951 auto answer_rtd = NegotiateRtpTransceiverDirection(offer_rtd, wants_rtd);
2081 AudioCodecs supported_audio_codecs = 1952 AudioCodecs audio_codecs = GetAudioCodecsForAnswer(offer_rtd, answer_rtd);
2082 GetAudioCodecsForAnswer(offer_rtd, answer_rtd); 1953 if (!options.vad_enabled) {
2083 1954 StripCNCodecs(&audio_codecs);
2084 AudioCodecs filtered_codecs; 1955 }
2085 // Add the codecs from current content if exists. 1956
2086 if (current_content) { 1957 bool bundle_enabled =
2087 RTC_DCHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_AUDIO)); 1958 offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled;
2088 const AudioContentDescription* acd =
2089 static_cast<const AudioContentDescription*>(
2090 current_content->description);
2091 for (const AudioCodec& codec : acd->codecs()) {
2092 if (FindMatchingCodec<AudioCodec>(supported_audio_codecs, audio_codecs,
2093 codec, nullptr)) {
2094 filtered_codecs.push_back(codec);
2095 }
2096 }
2097 }
2098 // Add other supported audio codecs.
2099 AudioCodec found_codec;
2100 for (const AudioCodec& codec : supported_audio_codecs) {
2101 if (FindMatchingCodec<AudioCodec>(supported_audio_codecs, audio_codecs,
2102 codec, &found_codec) &&
2103 !FindMatchingCodec<AudioCodec>(supported_audio_codecs, filtered_codecs,
2104 codec, nullptr)) {
2105 // Use the |found_codec| from |audio_codecs| because it has the correctly
2106 // mapped payload type.
2107 filtered_codecs.push_back(found_codec);
2108 }
2109 }
2110
2111 bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
2112 session_options.bundle_enabled;
2113 std::unique_ptr<AudioContentDescription> audio_answer( 1959 std::unique_ptr<AudioContentDescription> audio_answer(
2114 new AudioContentDescription()); 1960 new AudioContentDescription());
2115 // Do not require or create SDES cryptos if DTLS is used. 1961 // Do not require or create SDES cryptos if DTLS is used.
2116 cricket::SecurePolicy sdes_policy = 1962 cricket::SecurePolicy sdes_policy =
2117 audio_transport->secure() ? cricket::SEC_DISABLED : secure(); 1963 audio_transport->secure() ? cricket::SEC_DISABLED : secure();
2118 if (!CreateMediaContentAnswer( 1964 if (!CreateMediaContentAnswer(
2119 offer_audio_description, media_description_options, session_options, 1965 offer_audio,
2120 filtered_codecs, sdes_policy, GetCryptos(current_content), 1966 options,
2121 audio_rtp_extensions_, enable_encrypted_rtp_header_extensions_, 1967 audio_codecs,
2122 current_streams, bundle_enabled, audio_answer.get())) { 1968 sdes_policy,
1969 GetCryptos(GetFirstAudioContentDescription(current_description)),
1970 audio_rtp_extensions_,
1971 enable_encrypted_rtp_header_extensions_,
1972 current_streams,
1973 add_legacy_,
1974 bundle_enabled,
1975 audio_answer.get())) {
2123 return false; // Fails the session setup. 1976 return false; // Fails the session setup.
2124 } 1977 }
2125 1978
2126 bool secure = bundle_transport ? bundle_transport->description.secure() 1979 bool secure = bundle_transport ? bundle_transport->description.secure()
2127 : audio_transport->secure(); 1980 : audio_transport->secure();
2128 bool rejected = media_description_options.stopped || 1981 bool rejected = !options.has_audio() || audio_content->rejected ||
2129 offer_content->rejected ||
2130 !IsMediaProtocolSupported(MEDIA_TYPE_AUDIO, 1982 !IsMediaProtocolSupported(MEDIA_TYPE_AUDIO,
2131 audio_answer->protocol(), secure); 1983 audio_answer->protocol(), secure);
2132 if (!rejected) { 1984 if (!rejected) {
2133 AddTransportAnswer(media_description_options.mid, *(audio_transport.get()), 1985 AddTransportAnswer(audio_content->name, *(audio_transport.get()), answer);
2134 answer); 1986 } else {
2135 } else { 1987 // RFC 3264
2136 LOG(LS_INFO) << "Audio m= section '" << media_description_options.mid 1988 // The answer MUST contain the same number of m-lines as the offer.
2137 << "' being rejected in answer."; 1989 LOG(LS_INFO) << "Audio is not supported in the answer.";
2138 } 1990 }
2139 1991
2140 answer->AddContent(media_description_options.mid, offer_content->type, 1992 answer->AddContent(audio_content->name, audio_content->type, rejected,
2141 rejected, audio_answer.release()); 1993 audio_answer.release());
2142 return true; 1994 return true;
2143 } 1995 }
2144 1996
2145 bool MediaSessionDescriptionFactory::AddVideoContentForAnswer( 1997 bool MediaSessionDescriptionFactory::AddVideoContentForAnswer(
2146 const MediaDescriptionOptions& media_description_options, 1998 const SessionDescription* offer,
2147 const MediaSessionOptions& session_options, 1999 const MediaSessionOptions& options,
2148 const ContentInfo* offer_content,
2149 const SessionDescription* offer_description,
2150 const ContentInfo* current_content,
2151 const SessionDescription* current_description, 2000 const SessionDescription* current_description,
2152 const TransportInfo* bundle_transport, 2001 const TransportInfo* bundle_transport,
2153 const VideoCodecs& video_codecs,
2154 StreamParamsVec* current_streams, 2002 StreamParamsVec* current_streams,
2155 SessionDescription* answer) const { 2003 SessionDescription* answer) const {
2156 const VideoContentDescription* offer_video_description = 2004 const ContentInfo* video_content = GetFirstVideoContent(offer);
2157 static_cast<const VideoContentDescription*>(offer_content->description);
2158
2159 std::unique_ptr<TransportDescription> video_transport( 2005 std::unique_ptr<TransportDescription> video_transport(
2160 CreateTransportAnswer(media_description_options.mid, offer_description, 2006 CreateTransportAnswer(video_content->name, offer,
2161 media_description_options.transport_options, 2007 GetTransportOptions(options, video_content->name),
2162 current_description, bundle_transport != nullptr)); 2008 current_description, bundle_transport != nullptr));
2163 if (!video_transport) { 2009 if (!video_transport) {
2164 return false; 2010 return false;
2165 } 2011 }
2166 2012
2167 VideoCodecs filtered_codecs;
2168 // Add the codecs from current content if exists.
2169 if (current_content) {
2170 RTC_DCHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_VIDEO));
2171 const VideoContentDescription* vcd =
2172 static_cast<const VideoContentDescription*>(
2173 current_content->description);
2174 for (const VideoCodec& codec : vcd->codecs()) {
2175 if (FindMatchingCodec<VideoCodec>(video_codecs_, video_codecs, codec,
2176 nullptr)) {
2177 filtered_codecs.push_back(codec);
2178 }
2179 }
2180 }
2181 // Add other supported video codecs.
2182 VideoCodec found_codec;
2183 for (const VideoCodec& codec : video_codecs_) {
2184 if (FindMatchingCodec<VideoCodec>(video_codecs_, video_codecs, codec,
2185 &found_codec) &&
2186 !FindMatchingCodec<VideoCodec>(video_codecs_, filtered_codecs, codec,
2187 nullptr)) {
2188 // Use the |found_codec| from |video_codecs| because it has the correctly
2189 // mapped payload type.
2190 filtered_codecs.push_back(found_codec);
2191 }
2192 }
2193
2194 bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
2195 session_options.bundle_enabled;
2196
2197 std::unique_ptr<VideoContentDescription> video_answer( 2013 std::unique_ptr<VideoContentDescription> video_answer(
2198 new VideoContentDescription()); 2014 new VideoContentDescription());
2199 // Do not require or create SDES cryptos if DTLS is used. 2015 // Do not require or create SDES cryptos if DTLS is used.
2200 cricket::SecurePolicy sdes_policy = 2016 cricket::SecurePolicy sdes_policy =
2201 video_transport->secure() ? cricket::SEC_DISABLED : secure(); 2017 video_transport->secure() ? cricket::SEC_DISABLED : secure();
2018 bool bundle_enabled =
2019 offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled;
2202 if (!CreateMediaContentAnswer( 2020 if (!CreateMediaContentAnswer(
2203 offer_video_description, media_description_options, session_options, 2021 static_cast<const VideoContentDescription*>(
2204 filtered_codecs, sdes_policy, GetCryptos(current_content), 2022 video_content->description),
2205 video_rtp_extensions_, enable_encrypted_rtp_header_extensions_, 2023 options,
2206 current_streams, bundle_enabled, video_answer.get())) { 2024 video_codecs_,
2207 return false; // Failed the sessin setup. 2025 sdes_policy,
2026 GetCryptos(GetFirstVideoContentDescription(current_description)),
2027 video_rtp_extensions_,
2028 enable_encrypted_rtp_header_extensions_,
2029 current_streams,
2030 add_legacy_,
2031 bundle_enabled,
2032 video_answer.get())) {
2033 return false;
2208 } 2034 }
2209 bool secure = bundle_transport ? bundle_transport->description.secure() 2035 bool secure = bundle_transport ? bundle_transport->description.secure()
2210 : video_transport->secure(); 2036 : video_transport->secure();
2211 bool rejected = media_description_options.stopped || 2037 bool rejected = !options.has_video() || video_content->rejected ||
2212 offer_content->rejected ||
2213 !IsMediaProtocolSupported(MEDIA_TYPE_VIDEO, 2038 !IsMediaProtocolSupported(MEDIA_TYPE_VIDEO,
2214 video_answer->protocol(), secure); 2039 video_answer->protocol(), secure);
2215 if (!rejected) { 2040 if (!rejected) {
2216 if (!AddTransportAnswer(media_description_options.mid, 2041 if (!AddTransportAnswer(video_content->name, *(video_transport.get()),
2217 *(video_transport.get()), answer)) { 2042 answer)) {
2218 return false; 2043 return false;
2219 } 2044 }
2220 video_answer->set_bandwidth(kAutoBandwidth); 2045 video_answer->set_bandwidth(options.video_bandwidth);
2221 } else { 2046 } else {
2222 LOG(LS_INFO) << "Video m= section '" << media_description_options.mid 2047 // RFC 3264
2223 << "' being rejected in answer."; 2048 // The answer MUST contain the same number of m-lines as the offer.
2224 } 2049 LOG(LS_INFO) << "Video is not supported in the answer.";
2225 answer->AddContent(media_description_options.mid, offer_content->type, 2050 }
2226 rejected, video_answer.release()); 2051 answer->AddContent(video_content->name, video_content->type, rejected,
2052 video_answer.release());
2227 return true; 2053 return true;
2228 } 2054 }
2229 2055
2230 bool MediaSessionDescriptionFactory::AddDataContentForAnswer( 2056 bool MediaSessionDescriptionFactory::AddDataContentForAnswer(
2231 const MediaDescriptionOptions& media_description_options, 2057 const SessionDescription* offer,
2232 const MediaSessionOptions& session_options, 2058 const MediaSessionOptions& options,
2233 const ContentInfo* offer_content,
2234 const SessionDescription* offer_description,
2235 const ContentInfo* current_content,
2236 const SessionDescription* current_description, 2059 const SessionDescription* current_description,
2237 const TransportInfo* bundle_transport, 2060 const TransportInfo* bundle_transport,
2238 const DataCodecs& data_codecs,
2239 StreamParamsVec* current_streams, 2061 StreamParamsVec* current_streams,
2240 SessionDescription* answer) const { 2062 SessionDescription* answer) const {
2063 const ContentInfo* data_content = GetFirstDataContent(offer);
2241 std::unique_ptr<TransportDescription> data_transport( 2064 std::unique_ptr<TransportDescription> data_transport(
2242 CreateTransportAnswer(media_description_options.mid, offer_description, 2065 CreateTransportAnswer(data_content->name, offer,
2243 media_description_options.transport_options, 2066 GetTransportOptions(options, data_content->name),
2244 current_description, bundle_transport != nullptr)); 2067 current_description, bundle_transport != nullptr));
2245 if (!data_transport) { 2068 if (!data_transport) {
2246 return false; 2069 return false;
2247 } 2070 }
2071 bool is_sctp = (options.data_channel_type == DCT_SCTP);
2072 std::vector<DataCodec> data_codecs(data_codecs_);
2073 FilterDataCodecs(&data_codecs, is_sctp);
2248 2074
2249 std::unique_ptr<DataContentDescription> data_answer( 2075 std::unique_ptr<DataContentDescription> data_answer(
2250 new DataContentDescription()); 2076 new DataContentDescription());
2251 // Do not require or create SDES cryptos if DTLS is used. 2077 // Do not require or create SDES cryptos if DTLS is used.
2252 cricket::SecurePolicy sdes_policy = 2078 cricket::SecurePolicy sdes_policy =
2253 data_transport->secure() ? cricket::SEC_DISABLED : secure(); 2079 data_transport->secure() ? cricket::SEC_DISABLED : secure();
2254 bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) && 2080 bool bundle_enabled =
2255 session_options.bundle_enabled; 2081 offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled;
2256 if (!CreateMediaContentAnswer( 2082 if (!CreateMediaContentAnswer(
2257 static_cast<const DataContentDescription*>( 2083 static_cast<const DataContentDescription*>(
2258 offer_content->description), 2084 data_content->description),
2259 media_description_options, session_options, data_codecs, sdes_policy, 2085 options,
2260 GetCryptos(current_content), RtpHeaderExtensions(), 2086 data_codecs_,
2261 enable_encrypted_rtp_header_extensions_, current_streams, 2087 sdes_policy,
2262 bundle_enabled, data_answer.get())) { 2088 GetCryptos(GetFirstDataContentDescription(current_description)),
2089 RtpHeaderExtensions(),
2090 enable_encrypted_rtp_header_extensions_,
2091 current_streams,
2092 add_legacy_,
2093 bundle_enabled,
2094 data_answer.get())) {
2263 return false; // Fails the session setup. 2095 return false; // Fails the session setup.
2264 } 2096 }
2265 2097
2266 // Respond with sctpmap if the offer uses sctpmap. 2098 // Respond with sctpmap if the offer uses sctpmap.
2267 const DataContentDescription* offer_data_description = 2099 const DataContentDescription* offer_data_description =
2268 static_cast<const DataContentDescription*>(offer_content->description); 2100 static_cast<const DataContentDescription*>(data_content->description);
2269 bool offer_uses_sctpmap = offer_data_description->use_sctpmap(); 2101 bool offer_uses_sctpmap = offer_data_description->use_sctpmap();
2270 data_answer->set_use_sctpmap(offer_uses_sctpmap); 2102 data_answer->set_use_sctpmap(offer_uses_sctpmap);
2271 2103
2272 bool secure = bundle_transport ? bundle_transport->description.secure() 2104 bool secure = bundle_transport ? bundle_transport->description.secure()
2273 : data_transport->secure(); 2105 : data_transport->secure();
2274 2106
2275 bool rejected = session_options.data_channel_type == DCT_NONE || 2107 bool rejected = !options.has_data() || data_content->rejected ||
2276 media_description_options.stopped ||
2277 offer_content->rejected ||
2278 !IsMediaProtocolSupported(MEDIA_TYPE_DATA, 2108 !IsMediaProtocolSupported(MEDIA_TYPE_DATA,
2279 data_answer->protocol(), secure); 2109 data_answer->protocol(), secure);
2280 if (!rejected) { 2110 if (!rejected) {
2281 data_answer->set_bandwidth(kDataMaxBandwidth); 2111 data_answer->set_bandwidth(options.data_bandwidth);
2282 if (!AddTransportAnswer(media_description_options.mid, 2112 if (!AddTransportAnswer(data_content->name, *(data_transport.get()),
2283 *(data_transport.get()), answer)) { 2113 answer)) {
2284 return false; 2114 return false;
2285 } 2115 }
2286 } else { 2116 } else {
2287 // RFC 3264 2117 // RFC 3264
2288 // The answer MUST contain the same number of m-lines as the offer. 2118 // The answer MUST contain the same number of m-lines as the offer.
2289 LOG(LS_INFO) << "Data is not supported in the answer."; 2119 LOG(LS_INFO) << "Data is not supported in the answer.";
2290 } 2120 }
2291 answer->AddContent(media_description_options.mid, offer_content->type, 2121 answer->AddContent(data_content->name, data_content->type, rejected,
2292 rejected, data_answer.release()); 2122 data_answer.release());
2293 return true; 2123 return true;
2294 } 2124 }
2295 2125
2296 void MediaSessionDescriptionFactory::ComputeAudioCodecsIntersectionAndUnion() {
2297 audio_sendrecv_codecs_.clear();
2298 all_audio_codecs_.clear();
2299 // Compute the audio codecs union.
2300 for (const AudioCodec& send : audio_send_codecs_) {
2301 all_audio_codecs_.push_back(send);
2302 if (!FindMatchingCodec<AudioCodec>(audio_send_codecs_, audio_recv_codecs_,
2303 send, nullptr)) {
2304 // It doesn't make sense to have an RTX codec we support sending but not
2305 // receiving.
2306 RTC_DCHECK(!IsRtxCodec(send));
2307 }
2308 }
2309 for (const AudioCodec& recv : audio_recv_codecs_) {
2310 if (!FindMatchingCodec<AudioCodec>(audio_recv_codecs_, audio_send_codecs_,
2311 recv, nullptr)) {
2312 all_audio_codecs_.push_back(recv);
2313 }
2314 }
2315 // Use NegotiateCodecs to merge our codec lists, since the operation is
2316 // essentially the same. Put send_codecs as the offered_codecs, which is the
2317 // order we'd like to follow. The reasoning is that encoding is usually more
2318 // expensive than decoding, and prioritizing a codec in the send list probably
2319 // means it's a codec we can handle efficiently.
2320 NegotiateCodecs(audio_recv_codecs_, audio_send_codecs_,
2321 &audio_sendrecv_codecs_);
2322 }
2323
2324 bool IsMediaContent(const ContentInfo* content) { 2126 bool IsMediaContent(const ContentInfo* content) {
2325 return (content && 2127 return (content &&
2326 (content->type == NS_JINGLE_RTP || 2128 (content->type == NS_JINGLE_RTP ||
2327 content->type == NS_JINGLE_DRAFT_SCTP)); 2129 content->type == NS_JINGLE_DRAFT_SCTP));
2328 } 2130 }
2329 2131
2330 bool IsAudioContent(const ContentInfo* content) { 2132 bool IsAudioContent(const ContentInfo* content) {
2331 return IsMediaContentOfType(content, MEDIA_TYPE_AUDIO); 2133 return IsMediaContentOfType(content, MEDIA_TYPE_AUDIO);
2332 } 2134 }
2333 2135
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
2474 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO)); 2276 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO));
2475 } 2277 }
2476 2278
2477 DataContentDescription* GetFirstDataContentDescription( 2279 DataContentDescription* GetFirstDataContentDescription(
2478 SessionDescription* sdesc) { 2280 SessionDescription* sdesc) {
2479 return static_cast<DataContentDescription*>( 2281 return static_cast<DataContentDescription*>(
2480 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA)); 2282 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA));
2481 } 2283 }
2482 2284
2483 } // namespace cricket 2285 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/pc/mediasession.h ('k') | webrtc/pc/mediasession_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698