Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * libjingle | 2 * libjingle |
| 3 * Copyright 2004 Google Inc. | 3 * Copyright 2004 Google Inc. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
| 9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
| 11 * this list of conditions and the following disclaimer in the documentation | 11 * this list of conditions and the following disclaimer in the documentation |
| 12 * and/or other materials provided with the distribution. | 12 * and/or other materials provided with the distribution. |
| 13 * 3. The name of the author may not be used to endorse or promote products | 13 * 3. The name of the author may not be used to endorse or promote products |
| 14 * derived from this software without specific prior written permission. | 14 * derived from this software without specific prior written permission. |
| 15 * | 15 * |
| 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED | 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 */ | 26 */ |
| 27 | 27 |
| 28 #include "talk/session/media/mediasession.h" | 28 #include "talk/session/media/mediasession.h" |
| 29 | 29 |
| 30 #include <algorithm> // For std::find_if. | |
| 30 #include <functional> | 31 #include <functional> |
| 31 #include <map> | 32 #include <map> |
| 32 #include <set> | 33 #include <set> |
| 33 #include <utility> | 34 #include <utility> |
| 34 | 35 |
| 35 #include "talk/media/base/constants.h" | 36 #include "talk/media/base/constants.h" |
| 36 #include "talk/media/base/cryptoparams.h" | 37 #include "talk/media/base/cryptoparams.h" |
| 37 #include "talk/session/media/channelmanager.h" | 38 #include "talk/session/media/channelmanager.h" |
| 38 #include "talk/session/media/srtpfilter.h" | 39 #include "talk/session/media/srtpfilter.h" |
| 39 #include "webrtc/base/helpers.h" | 40 #include "webrtc/base/helpers.h" |
| (...skipping 771 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 811 !FindCodecById(codecs2, codec2_id, &codec2)) { | 812 !FindCodecById(codecs2, codec2_id, &codec2)) { |
| 812 return false; | 813 return false; |
| 813 } | 814 } |
| 814 return codec1.Matches(codec2); | 815 return codec1.Matches(codec2); |
| 815 } | 816 } |
| 816 | 817 |
| 817 template <class C> | 818 template <class C> |
| 818 static void NegotiateCodecs(const std::vector<C>& local_codecs, | 819 static void NegotiateCodecs(const std::vector<C>& local_codecs, |
| 819 const std::vector<C>& offered_codecs, | 820 const std::vector<C>& offered_codecs, |
| 820 std::vector<C>* negotiated_codecs) { | 821 std::vector<C>* negotiated_codecs) { |
| 821 typename std::vector<C>::const_iterator ours; | 822 for (const C& ours : local_codecs) { |
| 822 for (ours = local_codecs.begin(); | 823 C theirs; |
| 823 ours != local_codecs.end(); ++ours) { | 824 if (FindMatchingCodec(local_codecs, offered_codecs, ours, &theirs)) { |
| 824 typename std::vector<C>::const_iterator theirs; | 825 C negotiated = ours; |
| 825 for (theirs = offered_codecs.begin(); | 826 negotiated.IntersectFeedbackParams(theirs); |
| 826 theirs != offered_codecs.end(); ++theirs) { | 827 if (IsRtxCodec(negotiated)) { |
| 827 if (ours->Matches(*theirs)) { | 828 std::string offered_apt_value; |
| 828 C negotiated = *ours; | 829 theirs.GetParam(kCodecParamAssociatedPayloadType, &offered_apt_value); |
| 829 negotiated.IntersectFeedbackParams(*theirs); | 830 // FindMatchingCodec shouldn't return something with no apt value. |
| 830 if (IsRtxCodec(negotiated)) { | 831 RTC_DCHECK(!offered_apt_value.empty()); |
| 831 std::string offered_apt_value; | 832 negotiated.SetParam(kCodecParamAssociatedPayloadType, |
| 832 std::string local_apt_value; | 833 offered_apt_value); |
| 833 if (!ours->GetParam(kCodecParamAssociatedPayloadType, | |
| 834 &local_apt_value) || | |
| 835 !theirs->GetParam(kCodecParamAssociatedPayloadType, | |
| 836 &offered_apt_value)) { | |
| 837 LOG(LS_WARNING) << "RTX missing associated payload type."; | |
| 838 continue; | |
| 839 } | |
| 840 // Only negotiate RTX if kCodecParamAssociatedPayloadType has been | |
| 841 // set in local and remote codecs, and they match. | |
| 842 if (!ReferencedCodecsMatch(local_codecs, local_apt_value, | |
| 843 offered_codecs, offered_apt_value)) { | |
| 844 LOG(LS_WARNING) << "RTX associated codecs don't match."; | |
| 845 continue; | |
| 846 } | |
| 847 negotiated.SetParam(kCodecParamAssociatedPayloadType, | |
| 848 offered_apt_value); | |
| 849 } | |
| 850 | |
| 851 negotiated.id = theirs->id; | |
| 852 // RFC3264: Although the answerer MAY list the formats in their desired | |
| 853 // order of preference, it is RECOMMENDED that unless there is a | |
| 854 // specific reason, the answerer list formats in the same relative order | |
| 855 // they were present in the offer. | |
| 856 negotiated.preference = theirs->preference; | |
| 857 negotiated_codecs->push_back(negotiated); | |
| 858 } | 834 } |
| 835 negotiated.id = theirs.id; | |
| 836 // RFC3264: Although the answerer MAY list the formats in their desired | |
| 837 // order of preference, it is RECOMMENDED that unless there is a | |
| 838 // specific reason, the answerer list formats in the same relative order | |
| 839 // they were present in the offer. | |
| 840 negotiated.preference = theirs.preference; | |
| 841 negotiated_codecs->push_back(negotiated); | |
| 859 } | 842 } |
| 860 } | 843 } |
| 861 } | 844 } |
| 862 | 845 |
| 846 // Finds a codec in |codecs2| that matches |codec_to_match|, which is | |
| 847 // a member of |codecs1|. If |codec_to_match| is an RTX codec, both | |
| 848 // the codecs themselves and their associated codecs must match. | |
| 863 template <class C> | 849 template <class C> |
| 864 static bool FindMatchingCodec(const std::vector<C>& codecs, | 850 static bool FindMatchingCodec(const std::vector<C>& codecs1, |
| 851 const std::vector<C>& codecs2, | |
| 865 const C& codec_to_match, | 852 const C& codec_to_match, |
| 866 C* found_codec) { | 853 C* found_codec) { |
| 867 for (typename std::vector<C>::const_iterator it = codecs.begin(); | 854 for (const C& potential_match : codecs2) { |
| 868 it != codecs.end(); ++it) { | 855 if (potential_match.Matches(codec_to_match)) { |
| 869 if (it->Matches(codec_to_match)) { | 856 if (IsRtxCodec(codec_to_match)) { |
| 870 if (found_codec != NULL) { | 857 std::string apt_value_1; |
| 871 *found_codec= *it; | 858 std::string apt_value_2; |
| 859 if (!codec_to_match.GetParam(kCodecParamAssociatedPayloadType, | |
| 860 &apt_value_1) || | |
| 861 !potential_match.GetParam(kCodecParamAssociatedPayloadType, | |
| 862 &apt_value_2)) { | |
| 863 LOG(LS_WARNING) << "RTX missing associated payload type."; | |
| 864 continue; | |
| 865 } | |
| 866 if (!ReferencedCodecsMatch(codecs1, apt_value_1, codecs2, | |
| 867 apt_value_2)) { | |
| 868 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
| |
| 869 continue; | |
| 870 } | |
| 871 } | |
| 872 if (found_codec) { | |
| 873 *found_codec = potential_match; | |
| 872 } | 874 } |
| 873 return true; | 875 return true; |
| 874 } | 876 } |
| 875 } | 877 } |
| 876 return false; | 878 return false; |
| 877 } | 879 } |
| 878 | 880 |
| 879 // Adds all codecs from |reference_codecs| to |offered_codecs| that dont' | 881 // Adds all codecs from |reference_codecs| to |offered_codecs| that dont' |
| 880 // already exist in |offered_codecs| and ensure the payload types don't | 882 // already exist in |offered_codecs| and ensure the payload types don't |
| 881 // collide. | 883 // collide. |
| 882 template <class C> | 884 template <class C> |
| 883 static void FindCodecsToOffer( | 885 static void FindCodecsToOffer( |
| 884 const std::vector<C>& reference_codecs, | 886 const std::vector<C>& reference_codecs, |
| 885 std::vector<C>* offered_codecs, | 887 std::vector<C>* offered_codecs, |
| 886 UsedPayloadTypes* used_pltypes) { | 888 UsedPayloadTypes* used_pltypes) { |
| 887 | 889 |
| 888 typedef std::map<int, C> RtxCodecReferences; | |
| 889 RtxCodecReferences new_rtx_codecs; | |
| 890 | |
| 891 // Find all new RTX codecs. | |
| 892 for (typename std::vector<C>::const_iterator it = reference_codecs.begin(); | |
| 893 it != reference_codecs.end(); ++it) { | |
| 894 if (!FindMatchingCodec<C>(*offered_codecs, *it, NULL) && IsRtxCodec(*it)) { | |
| 895 C rtx_codec = *it; | |
| 896 int referenced_pl_type = | |
| 897 rtc::FromString<int>(0, | |
| 898 rtx_codec.params[kCodecParamAssociatedPayloadType]); | |
| 899 new_rtx_codecs.insert(std::pair<int, C>(referenced_pl_type, | |
| 900 rtx_codec)); | |
| 901 } | |
| 902 } | |
| 903 | |
| 904 // Add all new codecs that are not RTX codecs. | 890 // Add all new codecs that are not RTX codecs. |
| 905 for (typename std::vector<C>::const_iterator it = reference_codecs.begin(); | 891 for (const C& reference_codec : reference_codecs) { |
| 906 it != reference_codecs.end(); ++it) { | 892 if (!IsRtxCodec(reference_codec) && |
| 907 if (!FindMatchingCodec<C>(*offered_codecs, *it, NULL) && !IsRtxCodec(*it)) { | 893 !FindMatchingCodec<C>(reference_codecs, *offered_codecs, |
| 908 C codec = *it; | 894 reference_codec, nullptr)) { |
| 909 int original_payload_id = codec.id; | 895 C codec = reference_codec; |
| 910 used_pltypes->FindAndSetIdUsed(&codec); | 896 used_pltypes->FindAndSetIdUsed(&codec); |
| 911 offered_codecs->push_back(codec); | 897 offered_codecs->push_back(codec); |
| 912 | |
| 913 // If this codec is referenced by a new RTX codec, update the reference | |
| 914 // in the RTX codec with the new payload type. | |
| 915 typename RtxCodecReferences::iterator rtx_it = | |
| 916 new_rtx_codecs.find(original_payload_id); | |
| 917 if (rtx_it != new_rtx_codecs.end()) { | |
| 918 C& rtx_codec = rtx_it->second; | |
| 919 rtx_codec.params[kCodecParamAssociatedPayloadType] = | |
| 920 rtc::ToString(codec.id); | |
| 921 } | |
| 922 } | 898 } |
| 923 } | 899 } |
| 924 | 900 |
| 925 // Add all new RTX codecs. | 901 // Add all new RTX codecs. |
| 926 for (typename RtxCodecReferences::iterator it = new_rtx_codecs.begin(); | 902 for (const C& reference_codec : reference_codecs) { |
| 927 it != new_rtx_codecs.end(); ++it) { | 903 if (IsRtxCodec(reference_codec) && |
| 928 C& rtx_codec = it->second; | 904 !FindMatchingCodec<C>(reference_codecs, *offered_codecs, |
| 929 used_pltypes->FindAndSetIdUsed(&rtx_codec); | 905 reference_codec, nullptr)) { |
| 930 offered_codecs->push_back(rtx_codec); | 906 C rtx_codec = reference_codec; |
| 907 | |
| 908 std::string associated_pt_str; | |
| 909 if (!rtx_codec.GetParam(kCodecParamAssociatedPayloadType, | |
| 910 &associated_pt_str)) { | |
| 911 LOG(LS_WARNING) << "RTX codec " << rtx_codec.name | |
| 912 << " is missing an associated payload type."; | |
| 913 continue; | |
| 914 } | |
| 915 | |
| 916 int associated_pt; | |
| 917 if (!rtc::FromString(associated_pt_str, &associated_pt)) { | |
| 918 LOG(LS_WARNING) << "Couldn't convert payload type " << associated_pt_str | |
| 919 << " of RTX codec " << rtx_codec.name | |
| 920 << " to an integer."; | |
| 921 continue; | |
| 922 } | |
| 923 | |
| 924 // Find the associated reference codec for the reference RTX codec. | |
| 925 C associated_codec; | |
| 926 if (!FindCodecById(reference_codecs, associated_pt, &associated_codec)) { | |
| 927 LOG(LS_WARNING) << "Couldn't find associated codec with payload type " | |
| 928 << associated_pt << " for RTX codec " << rtx_codec.name | |
| 929 << "."; | |
| 930 continue; | |
| 931 } | |
| 932 | |
| 933 // Find a codec in the offered list that matches the reference codec. | |
| 934 // Its payload type may be different than the reference codec. | |
| 935 C matching_codec; | |
| 936 if (!FindMatchingCodec<C>(reference_codecs, *offered_codecs, | |
| 937 associated_codec, &matching_codec)) { | |
| 938 LOG(LS_WARNING) << "Couldn't find matching " << associated_codec.name | |
| 939 << " codec."; | |
| 940 continue; | |
| 941 } | |
| 942 | |
| 943 rtx_codec.params[kCodecParamAssociatedPayloadType] = | |
| 944 rtc::ToString(matching_codec.id); | |
| 945 used_pltypes->FindAndSetIdUsed(&rtx_codec); | |
| 946 offered_codecs->push_back(rtx_codec); | |
| 947 } | |
| 931 } | 948 } |
| 932 } | 949 } |
| 933 | 950 |
| 934 | 951 |
| 935 static bool FindByUri(const RtpHeaderExtensions& extensions, | 952 static bool FindByUri(const RtpHeaderExtensions& extensions, |
| 936 const RtpHeaderExtension& ext_to_match, | 953 const RtpHeaderExtension& ext_to_match, |
| 937 RtpHeaderExtension* found_extension) { | 954 RtpHeaderExtension* found_extension) { |
| 938 for (RtpHeaderExtensions::const_iterator it = extensions.begin(); | 955 for (RtpHeaderExtensions::const_iterator it = extensions.begin(); |
| 939 it != extensions.end(); ++it) { | 956 it != extensions.end(); ++it) { |
| 940 // We assume that all URIs are given in a canonical format. | 957 // We assume that all URIs are given in a canonical format. |
| (...skipping 1046 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1987 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO)); | 2004 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO)); |
| 1988 } | 2005 } |
| 1989 | 2006 |
| 1990 const DataContentDescription* GetFirstDataContentDescription( | 2007 const DataContentDescription* GetFirstDataContentDescription( |
| 1991 const SessionDescription* sdesc) { | 2008 const SessionDescription* sdesc) { |
| 1992 return static_cast<const DataContentDescription*>( | 2009 return static_cast<const DataContentDescription*>( |
| 1993 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA)); | 2010 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA)); |
| 1994 } | 2011 } |
| 1995 | 2012 |
| 1996 } // namespace cricket | 2013 } // namespace cricket |
| OLD | NEW |