Chromium Code Reviews| Index: talk/session/media/mediasession.cc |
| diff --git a/talk/session/media/mediasession.cc b/talk/session/media/mediasession.cc |
| index 24f01b4463b5931267475fac98015a343f59cc78..96d94f531beb4926e2ec7a15ceaa04217f49401c 100644 |
| --- a/talk/session/media/mediasession.cc |
| +++ b/talk/session/media/mediasession.cc |
| @@ -27,6 +27,7 @@ |
| #include "talk/session/media/mediasession.h" |
| +#include <algorithm> // For std::find_if. |
| #include <functional> |
| #include <map> |
| #include <set> |
| @@ -818,57 +819,58 @@ template <class C> |
| static void NegotiateCodecs(const std::vector<C>& local_codecs, |
| const std::vector<C>& offered_codecs, |
| std::vector<C>* negotiated_codecs) { |
| - typename std::vector<C>::const_iterator ours; |
| - for (ours = local_codecs.begin(); |
| - ours != local_codecs.end(); ++ours) { |
| - typename std::vector<C>::const_iterator theirs; |
| - for (theirs = offered_codecs.begin(); |
| - theirs != offered_codecs.end(); ++theirs) { |
| - if (ours->Matches(*theirs)) { |
| - C negotiated = *ours; |
| - negotiated.IntersectFeedbackParams(*theirs); |
| - if (IsRtxCodec(negotiated)) { |
| - std::string offered_apt_value; |
| - std::string local_apt_value; |
| - if (!ours->GetParam(kCodecParamAssociatedPayloadType, |
| - &local_apt_value) || |
| - !theirs->GetParam(kCodecParamAssociatedPayloadType, |
| - &offered_apt_value)) { |
| - LOG(LS_WARNING) << "RTX missing associated payload type."; |
| - continue; |
| - } |
| - // Only negotiate RTX if kCodecParamAssociatedPayloadType has been |
| - // set in local and remote codecs, and they match. |
| - if (!ReferencedCodecsMatch(local_codecs, local_apt_value, |
| - offered_codecs, offered_apt_value)) { |
| - LOG(LS_WARNING) << "RTX associated codecs don't match."; |
| - continue; |
| - } |
| - negotiated.SetParam(kCodecParamAssociatedPayloadType, |
| - 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); |
| + for (const C& ours : local_codecs) { |
| + C theirs; |
| + if (FindMatchingCodec(local_codecs, offered_codecs, ours, &theirs)) { |
| + C negotiated = ours; |
| + negotiated.IntersectFeedbackParams(theirs); |
| + if (IsRtxCodec(negotiated)) { |
| + std::string offered_apt_value; |
| + theirs.GetParam(kCodecParamAssociatedPayloadType, &offered_apt_value); |
| + // FindMatchingCodec shouldn't return something with no apt value. |
| + RTC_DCHECK(!offered_apt_value.empty()); |
| + negotiated.SetParam(kCodecParamAssociatedPayloadType, |
| + 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); |
| } |
| } |
| } |
| +// Finds a codec in |codecs2| that matches |codec_to_match|, which is |
| +// a member of |codecs1|. If |codec_to_match| is an RTX codec, both |
| +// the codecs themselves and their associated codecs must match. |
| template <class C> |
| -static bool FindMatchingCodec(const std::vector<C>& codecs, |
| +static bool FindMatchingCodec(const std::vector<C>& codecs1, |
| + const std::vector<C>& codecs2, |
| const C& codec_to_match, |
| C* found_codec) { |
| - for (typename std::vector<C>::const_iterator it = codecs.begin(); |
| - it != codecs.end(); ++it) { |
| - if (it->Matches(codec_to_match)) { |
| - if (found_codec != NULL) { |
| - *found_codec= *it; |
| + for (const C& potential_match : codecs2) { |
| + if (potential_match.Matches(codec_to_match)) { |
| + if (IsRtxCodec(codec_to_match)) { |
| + std::string apt_value_1; |
| + std::string apt_value_2; |
| + if (!codec_to_match.GetParam(kCodecParamAssociatedPayloadType, |
| + &apt_value_1) || |
| + !potential_match.GetParam(kCodecParamAssociatedPayloadType, |
| + &apt_value_2)) { |
| + LOG(LS_WARNING) << "RTX missing associated payload type."; |
| + continue; |
| + } |
| + if (!ReferencedCodecsMatch(codecs1, apt_value_1, codecs2, |
| + apt_value_2)) { |
| + LOG(LS_INFO) << "RTX associated codecs don't match."; |
|
pthatcher1
2016/02/26 21:30:14
Since this is FindMatchingCodec, LS_INFO here seem
Taylor Brandstetter
2016/03/04 16:12:23
It was strong even before (in fact I changed it fr
|
| + continue; |
| + } |
| + } |
| + if (found_codec) { |
| + *found_codec = potential_match; |
| } |
| return true; |
| } |
| @@ -885,49 +887,64 @@ static void FindCodecsToOffer( |
| std::vector<C>* offered_codecs, |
| UsedPayloadTypes* used_pltypes) { |
| - typedef std::map<int, C> RtxCodecReferences; |
| - RtxCodecReferences new_rtx_codecs; |
| - |
| - // Find all new RTX codecs. |
| - for (typename std::vector<C>::const_iterator it = reference_codecs.begin(); |
| - it != reference_codecs.end(); ++it) { |
| - if (!FindMatchingCodec<C>(*offered_codecs, *it, NULL) && IsRtxCodec(*it)) { |
| - C rtx_codec = *it; |
| - int referenced_pl_type = |
| - rtc::FromString<int>(0, |
| - rtx_codec.params[kCodecParamAssociatedPayloadType]); |
| - new_rtx_codecs.insert(std::pair<int, C>(referenced_pl_type, |
| - rtx_codec)); |
| - } |
| - } |
| - |
| // Add all new codecs that are not RTX codecs. |
| - for (typename std::vector<C>::const_iterator it = reference_codecs.begin(); |
| - it != reference_codecs.end(); ++it) { |
| - if (!FindMatchingCodec<C>(*offered_codecs, *it, NULL) && !IsRtxCodec(*it)) { |
| - C codec = *it; |
| - int original_payload_id = codec.id; |
| + for (const C& reference_codec : reference_codecs) { |
| + if (!IsRtxCodec(reference_codec) && |
| + !FindMatchingCodec<C>(reference_codecs, *offered_codecs, |
| + reference_codec, nullptr)) { |
| + C codec = reference_codec; |
| used_pltypes->FindAndSetIdUsed(&codec); |
| offered_codecs->push_back(codec); |
| - |
| - // If this codec is referenced by a new RTX codec, update the reference |
| - // in the RTX codec with the new payload type. |
| - typename RtxCodecReferences::iterator rtx_it = |
| - new_rtx_codecs.find(original_payload_id); |
| - if (rtx_it != new_rtx_codecs.end()) { |
| - C& rtx_codec = rtx_it->second; |
| - rtx_codec.params[kCodecParamAssociatedPayloadType] = |
| - rtc::ToString(codec.id); |
| - } |
| } |
| } |
| // Add all new RTX codecs. |
| - for (typename RtxCodecReferences::iterator it = new_rtx_codecs.begin(); |
| - it != new_rtx_codecs.end(); ++it) { |
| - C& rtx_codec = it->second; |
| - used_pltypes->FindAndSetIdUsed(&rtx_codec); |
| - offered_codecs->push_back(rtx_codec); |
| + for (const C& reference_codec : reference_codecs) { |
| + if (IsRtxCodec(reference_codec) && |
| + !FindMatchingCodec<C>(reference_codecs, *offered_codecs, |
| + reference_codec, nullptr)) { |
| + C rtx_codec = reference_codec; |
| + |
| + std::string associated_pt_str; |
| + if (!rtx_codec.GetParam(kCodecParamAssociatedPayloadType, |
| + &associated_pt_str)) { |
| + LOG(LS_WARNING) << "RTX codec " << rtx_codec.name |
| + << " is missing an associated payload type."; |
| + continue; |
| + } |
| + |
| + int associated_pt; |
| + if (!rtc::FromString(associated_pt_str, &associated_pt)) { |
| + LOG(LS_WARNING) << "Couldn't convert payload type " << associated_pt_str |
| + << " of RTX codec " << rtx_codec.name |
| + << " to an integer."; |
| + continue; |
| + } |
| + |
| + // Find the associated reference codec for the reference RTX codec. |
| + C associated_codec; |
| + if (!FindCodecById(reference_codecs, associated_pt, &associated_codec)) { |
| + LOG(LS_WARNING) << "Couldn't find associated codec with payload type " |
| + << associated_pt << " for RTX codec " << rtx_codec.name |
| + << "."; |
| + continue; |
| + } |
| + |
| + // Find a codec in the offered list that matches the reference codec. |
| + // Its payload type may be different than the reference codec. |
| + C matching_codec; |
| + if (!FindMatchingCodec<C>(reference_codecs, *offered_codecs, |
| + associated_codec, &matching_codec)) { |
| + LOG(LS_WARNING) << "Couldn't find matching " << associated_codec.name |
| + << " codec."; |
| + continue; |
| + } |
| + |
| + rtx_codec.params[kCodecParamAssociatedPayloadType] = |
| + rtc::ToString(matching_codec.id); |
| + used_pltypes->FindAndSetIdUsed(&rtx_codec); |
| + offered_codecs->push_back(rtx_codec); |
| + } |
| } |
| } |