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 |