Index: webrtc/pc/mediasession.cc |
diff --git a/webrtc/pc/mediasession.cc b/webrtc/pc/mediasession.cc |
index a9d1b95c22aee6aae9299315a9ecc05586242336..6b05736f0a3f3e74d662bb305e2458b7b7eba8ed 100644 |
--- a/webrtc/pc/mediasession.cc |
+++ b/webrtc/pc/mediasession.cc |
@@ -10,11 +10,12 @@ |
#include "webrtc/pc/mediasession.h" |
-#include <algorithm> // For std::find_if. |
+#include <algorithm> // For std::find_if, std::sort. |
#include <functional> |
#include <map> |
#include <memory> |
#include <set> |
+#include <unordered_map> |
#include <utility> |
#include "webrtc/base/helpers.h" |
@@ -749,7 +750,6 @@ static bool CreateMediaContentOffer( |
StreamParamsVec* current_streams, |
MediaContentDescriptionImpl<C>* offer) { |
offer->AddCodecs(codecs); |
- offer->SortCodecs(); |
if (secure_policy == SEC_REQUIRED) { |
offer->set_crypto_required(CT_SDES); |
@@ -810,6 +810,8 @@ static void NegotiateCodecs(const std::vector<C>& local_codecs, |
std::vector<C>* negotiated_codecs) { |
for (const C& ours : local_codecs) { |
C theirs; |
+ // Note that we intentionally only find one matching codec for each of our |
+ // local codecs, in case the remote offer contains duplicate codecs. |
if (FindMatchingCodec(local_codecs, offered_codecs, ours, &theirs)) { |
C negotiated = ours; |
negotiated.IntersectFeedbackParams(theirs); |
@@ -822,14 +824,23 @@ static void NegotiateCodecs(const std::vector<C>& local_codecs, |
offered_apt_value); |
} |
negotiated.id = theirs.id; |
- // RFC3264: Although the answerer MAY list the formats in their desired |
- // order of preference, it is RECOMMENDED that unless there is a |
- // specific reason, the answerer list formats in the same relative order |
- // they were present in the offer. |
- negotiated.preference = theirs.preference; |
negotiated_codecs->push_back(negotiated); |
} |
} |
+ // RFC3264: Although the answerer MAY list the formats in their desired |
+ // order of preference, it is RECOMMENDED that unless there is a |
+ // specific reason, the answerer list formats in the same relative order |
+ // they were present in the offer. |
+ std::unordered_map<int, int> payload_type_preferences; |
+ int preference = static_cast<int>(offered_codecs.size() + 1); |
+ for (const C& codec : offered_codecs) { |
+ payload_type_preferences[codec.id] = preference--; |
+ } |
+ std::sort(negotiated_codecs->begin(), negotiated_codecs->end(), |
+ [&payload_type_preferences](const C& a, const C& b) { |
+ return payload_type_preferences[a.id] > |
+ payload_type_preferences[b.id]; |
+ }); |
} |
// Finds a codec in |codecs2| that matches |codec_to_match|, which is |
@@ -1042,7 +1053,6 @@ static bool CreateMediaContentAnswer( |
std::vector<C> negotiated_codecs; |
NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs); |
answer->AddCodecs(negotiated_codecs); |
- answer->SortCodecs(); |
answer->set_protocol(offer->protocol()); |
RtpHeaderExtensions negotiated_rtp_extensions; |
NegotiateRtpHeaderExtensions(local_rtp_extenstions, |
@@ -1365,8 +1375,8 @@ SessionDescription* MediaSessionDescriptionFactory::CreateAnswer( |
const SessionDescription* offer, const MediaSessionOptions& options, |
const SessionDescription* current_description) const { |
// The answer contains the intersection of the codecs in the offer with the |
- // codecs we support, ordered by our local preference. As indicated by |
- // XEP-0167, we retain the same payload ids from the offer in the answer. |
+ // codecs we support. As indicated by XEP-0167, we retain the same payload ids |
+ // from the offer in the answer. |
std::unique_ptr<SessionDescription> answer(new SessionDescription()); |
StreamParamsVec current_streams; |