| 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;
|
|
|