OLD | NEW |
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 |
11 #include "webrtc/pc/mediasession.h" | 11 #include "webrtc/pc/mediasession.h" |
12 | 12 |
13 #include <algorithm> // For std::find_if. | 13 #include <algorithm> // For std::find_if, std::sort. |
14 #include <functional> | 14 #include <functional> |
15 #include <map> | 15 #include <map> |
16 #include <memory> | 16 #include <memory> |
17 #include <set> | 17 #include <set> |
| 18 #include <unordered_map> |
18 #include <utility> | 19 #include <utility> |
19 | 20 |
20 #include "webrtc/base/helpers.h" | 21 #include "webrtc/base/helpers.h" |
21 #include "webrtc/base/logging.h" | 22 #include "webrtc/base/logging.h" |
22 #include "webrtc/base/stringutils.h" | 23 #include "webrtc/base/stringutils.h" |
23 #include "webrtc/media/base/cryptoparams.h" | 24 #include "webrtc/media/base/cryptoparams.h" |
24 #include "webrtc/media/base/mediaconstants.h" | 25 #include "webrtc/media/base/mediaconstants.h" |
25 #include "webrtc/p2p/base/p2pconstants.h" | 26 #include "webrtc/p2p/base/p2pconstants.h" |
26 #include "webrtc/pc/channelmanager.h" | 27 #include "webrtc/pc/channelmanager.h" |
27 #include "webrtc/pc/srtpfilter.h" | 28 #include "webrtc/pc/srtpfilter.h" |
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 const MediaSessionOptions& options, | 743 const MediaSessionOptions& options, |
743 const std::vector<C>& codecs, | 744 const std::vector<C>& codecs, |
744 const SecurePolicy& secure_policy, | 745 const SecurePolicy& secure_policy, |
745 const CryptoParamsVec* current_cryptos, | 746 const CryptoParamsVec* current_cryptos, |
746 const std::vector<std::string>& crypto_suites, | 747 const std::vector<std::string>& crypto_suites, |
747 const RtpHeaderExtensions& rtp_extensions, | 748 const RtpHeaderExtensions& rtp_extensions, |
748 bool add_legacy_stream, | 749 bool add_legacy_stream, |
749 StreamParamsVec* current_streams, | 750 StreamParamsVec* current_streams, |
750 MediaContentDescriptionImpl<C>* offer) { | 751 MediaContentDescriptionImpl<C>* offer) { |
751 offer->AddCodecs(codecs); | 752 offer->AddCodecs(codecs); |
752 offer->SortCodecs(); | |
753 | 753 |
754 if (secure_policy == SEC_REQUIRED) { | 754 if (secure_policy == SEC_REQUIRED) { |
755 offer->set_crypto_required(CT_SDES); | 755 offer->set_crypto_required(CT_SDES); |
756 } | 756 } |
757 offer->set_rtcp_mux(options.rtcp_mux_enabled); | 757 offer->set_rtcp_mux(options.rtcp_mux_enabled); |
758 if (offer->type() == cricket::MEDIA_TYPE_VIDEO) { | 758 if (offer->type() == cricket::MEDIA_TYPE_VIDEO) { |
759 offer->set_rtcp_reduced_size(true); | 759 offer->set_rtcp_reduced_size(true); |
760 } | 760 } |
761 offer->set_multistream(options.is_muc); | 761 offer->set_multistream(options.is_muc); |
762 offer->set_rtp_header_extensions(rtp_extensions); | 762 offer->set_rtp_header_extensions(rtp_extensions); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 } | 803 } |
804 return codec1.Matches(codec2); | 804 return codec1.Matches(codec2); |
805 } | 805 } |
806 | 806 |
807 template <class C> | 807 template <class C> |
808 static void NegotiateCodecs(const std::vector<C>& local_codecs, | 808 static void NegotiateCodecs(const std::vector<C>& local_codecs, |
809 const std::vector<C>& offered_codecs, | 809 const std::vector<C>& offered_codecs, |
810 std::vector<C>* negotiated_codecs) { | 810 std::vector<C>* negotiated_codecs) { |
811 for (const C& ours : local_codecs) { | 811 for (const C& ours : local_codecs) { |
812 C theirs; | 812 C theirs; |
| 813 // Note that we intentionally only find one matching codec for each of our |
| 814 // local codecs, in case the remote offer contains duplicate codecs. |
813 if (FindMatchingCodec(local_codecs, offered_codecs, ours, &theirs)) { | 815 if (FindMatchingCodec(local_codecs, offered_codecs, ours, &theirs)) { |
814 C negotiated = ours; | 816 C negotiated = ours; |
815 negotiated.IntersectFeedbackParams(theirs); | 817 negotiated.IntersectFeedbackParams(theirs); |
816 if (IsRtxCodec(negotiated)) { | 818 if (IsRtxCodec(negotiated)) { |
817 std::string offered_apt_value; | 819 std::string offered_apt_value; |
818 theirs.GetParam(kCodecParamAssociatedPayloadType, &offered_apt_value); | 820 theirs.GetParam(kCodecParamAssociatedPayloadType, &offered_apt_value); |
819 // FindMatchingCodec shouldn't return something with no apt value. | 821 // FindMatchingCodec shouldn't return something with no apt value. |
820 RTC_DCHECK(!offered_apt_value.empty()); | 822 RTC_DCHECK(!offered_apt_value.empty()); |
821 negotiated.SetParam(kCodecParamAssociatedPayloadType, | 823 negotiated.SetParam(kCodecParamAssociatedPayloadType, |
822 offered_apt_value); | 824 offered_apt_value); |
823 } | 825 } |
824 negotiated.id = theirs.id; | 826 negotiated.id = theirs.id; |
825 // RFC3264: Although the answerer MAY list the formats in their desired | |
826 // order of preference, it is RECOMMENDED that unless there is a | |
827 // specific reason, the answerer list formats in the same relative order | |
828 // they were present in the offer. | |
829 negotiated.preference = theirs.preference; | |
830 negotiated_codecs->push_back(negotiated); | 827 negotiated_codecs->push_back(negotiated); |
831 } | 828 } |
832 } | 829 } |
| 830 // RFC3264: Although the answerer MAY list the formats in their desired |
| 831 // order of preference, it is RECOMMENDED that unless there is a |
| 832 // specific reason, the answerer list formats in the same relative order |
| 833 // they were present in the offer. |
| 834 std::unordered_map<int, int> payload_type_preferences; |
| 835 int preference = static_cast<int>(offered_codecs.size() + 1); |
| 836 for (const C& codec : offered_codecs) { |
| 837 payload_type_preferences[codec.id] = preference--; |
| 838 } |
| 839 std::sort(negotiated_codecs->begin(), negotiated_codecs->end(), |
| 840 [&payload_type_preferences](const C& a, const C& b) { |
| 841 return payload_type_preferences[a.id] > |
| 842 payload_type_preferences[b.id]; |
| 843 }); |
833 } | 844 } |
834 | 845 |
835 // Finds a codec in |codecs2| that matches |codec_to_match|, which is | 846 // Finds a codec in |codecs2| that matches |codec_to_match|, which is |
836 // a member of |codecs1|. If |codec_to_match| is an RTX codec, both | 847 // a member of |codecs1|. If |codec_to_match| is an RTX codec, both |
837 // the codecs themselves and their associated codecs must match. | 848 // the codecs themselves and their associated codecs must match. |
838 template <class C> | 849 template <class C> |
839 static bool FindMatchingCodec(const std::vector<C>& codecs1, | 850 static bool FindMatchingCodec(const std::vector<C>& codecs1, |
840 const std::vector<C>& codecs2, | 851 const std::vector<C>& codecs2, |
841 const C& codec_to_match, | 852 const C& codec_to_match, |
842 C* found_codec) { | 853 C* found_codec) { |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 const SecurePolicy& sdes_policy, | 1046 const SecurePolicy& sdes_policy, |
1036 const CryptoParamsVec* current_cryptos, | 1047 const CryptoParamsVec* current_cryptos, |
1037 const RtpHeaderExtensions& local_rtp_extenstions, | 1048 const RtpHeaderExtensions& local_rtp_extenstions, |
1038 StreamParamsVec* current_streams, | 1049 StreamParamsVec* current_streams, |
1039 bool add_legacy_stream, | 1050 bool add_legacy_stream, |
1040 bool bundle_enabled, | 1051 bool bundle_enabled, |
1041 MediaContentDescriptionImpl<C>* answer) { | 1052 MediaContentDescriptionImpl<C>* answer) { |
1042 std::vector<C> negotiated_codecs; | 1053 std::vector<C> negotiated_codecs; |
1043 NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs); | 1054 NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs); |
1044 answer->AddCodecs(negotiated_codecs); | 1055 answer->AddCodecs(negotiated_codecs); |
1045 answer->SortCodecs(); | |
1046 answer->set_protocol(offer->protocol()); | 1056 answer->set_protocol(offer->protocol()); |
1047 RtpHeaderExtensions negotiated_rtp_extensions; | 1057 RtpHeaderExtensions negotiated_rtp_extensions; |
1048 NegotiateRtpHeaderExtensions(local_rtp_extenstions, | 1058 NegotiateRtpHeaderExtensions(local_rtp_extenstions, |
1049 offer->rtp_header_extensions(), | 1059 offer->rtp_header_extensions(), |
1050 &negotiated_rtp_extensions); | 1060 &negotiated_rtp_extensions); |
1051 answer->set_rtp_header_extensions(negotiated_rtp_extensions); | 1061 answer->set_rtp_header_extensions(negotiated_rtp_extensions); |
1052 | 1062 |
1053 answer->set_rtcp_mux(options.rtcp_mux_enabled && offer->rtcp_mux()); | 1063 answer->set_rtcp_mux(options.rtcp_mux_enabled && offer->rtcp_mux()); |
1054 if (answer->type() == cricket::MEDIA_TYPE_VIDEO) { | 1064 if (answer->type() == cricket::MEDIA_TYPE_VIDEO) { |
1055 answer->set_rtcp_reduced_size(offer->rtcp_reduced_size()); | 1065 answer->set_rtcp_reduced_size(offer->rtcp_reduced_size()); |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1358 } | 1368 } |
1359 } | 1369 } |
1360 | 1370 |
1361 return offer.release(); | 1371 return offer.release(); |
1362 } | 1372 } |
1363 | 1373 |
1364 SessionDescription* MediaSessionDescriptionFactory::CreateAnswer( | 1374 SessionDescription* MediaSessionDescriptionFactory::CreateAnswer( |
1365 const SessionDescription* offer, const MediaSessionOptions& options, | 1375 const SessionDescription* offer, const MediaSessionOptions& options, |
1366 const SessionDescription* current_description) const { | 1376 const SessionDescription* current_description) const { |
1367 // The answer contains the intersection of the codecs in the offer with the | 1377 // The answer contains the intersection of the codecs in the offer with the |
1368 // codecs we support, ordered by our local preference. As indicated by | 1378 // codecs we support. As indicated by XEP-0167, we retain the same payload ids |
1369 // XEP-0167, we retain the same payload ids from the offer in the answer. | 1379 // from the offer in the answer. |
1370 std::unique_ptr<SessionDescription> answer(new SessionDescription()); | 1380 std::unique_ptr<SessionDescription> answer(new SessionDescription()); |
1371 | 1381 |
1372 StreamParamsVec current_streams; | 1382 StreamParamsVec current_streams; |
1373 GetCurrentStreamParams(current_description, ¤t_streams); | 1383 GetCurrentStreamParams(current_description, ¤t_streams); |
1374 | 1384 |
1375 if (offer) { | 1385 if (offer) { |
1376 ContentInfos::const_iterator it = offer->contents().begin(); | 1386 ContentInfos::const_iterator it = offer->contents().begin(); |
1377 for (; it != offer->contents().end(); ++it) { | 1387 for (; it != offer->contents().end(); ++it) { |
1378 if (IsMediaContentOfType(&*it, MEDIA_TYPE_AUDIO)) { | 1388 if (IsMediaContentOfType(&*it, MEDIA_TYPE_AUDIO)) { |
1379 if (!AddAudioContentForAnswer(offer, options, current_description, | 1389 if (!AddAudioContentForAnswer(offer, options, current_description, |
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1994 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO)); | 2004 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO)); |
1995 } | 2005 } |
1996 | 2006 |
1997 const DataContentDescription* GetFirstDataContentDescription( | 2007 const DataContentDescription* GetFirstDataContentDescription( |
1998 const SessionDescription* sdesc) { | 2008 const SessionDescription* sdesc) { |
1999 return static_cast<const DataContentDescription*>( | 2009 return static_cast<const DataContentDescription*>( |
2000 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA)); | 2010 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA)); |
2001 } | 2011 } |
2002 | 2012 |
2003 } // namespace cricket | 2013 } // namespace cricket |
OLD | NEW |