OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2004 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/pc/mediasession.h" | 11 #include "webrtc/pc/mediasession.h" |
12 | 12 |
| 13 #include <algorithm> // For std::find_if. |
13 #include <functional> | 14 #include <functional> |
14 #include <map> | 15 #include <map> |
15 #include <set> | 16 #include <set> |
16 #include <utility> | 17 #include <utility> |
17 | 18 |
18 #include "webrtc/base/helpers.h" | 19 #include "webrtc/base/helpers.h" |
19 #include "webrtc/base/logging.h" | 20 #include "webrtc/base/logging.h" |
20 #include "webrtc/base/scoped_ptr.h" | 21 #include "webrtc/base/scoped_ptr.h" |
21 #include "webrtc/base/stringutils.h" | 22 #include "webrtc/base/stringutils.h" |
22 #include "webrtc/media/base/cryptoparams.h" | 23 #include "webrtc/media/base/cryptoparams.h" |
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 !FindCodecById(codecs2, codec2_id, &codec2)) { | 804 !FindCodecById(codecs2, codec2_id, &codec2)) { |
804 return false; | 805 return false; |
805 } | 806 } |
806 return codec1.Matches(codec2); | 807 return codec1.Matches(codec2); |
807 } | 808 } |
808 | 809 |
809 template <class C> | 810 template <class C> |
810 static void NegotiateCodecs(const std::vector<C>& local_codecs, | 811 static void NegotiateCodecs(const std::vector<C>& local_codecs, |
811 const std::vector<C>& offered_codecs, | 812 const std::vector<C>& offered_codecs, |
812 std::vector<C>* negotiated_codecs) { | 813 std::vector<C>* negotiated_codecs) { |
813 typename std::vector<C>::const_iterator ours; | 814 for (const C& ours : local_codecs) { |
814 for (ours = local_codecs.begin(); | 815 C theirs; |
815 ours != local_codecs.end(); ++ours) { | 816 if (FindMatchingCodec(local_codecs, offered_codecs, ours, &theirs)) { |
816 typename std::vector<C>::const_iterator theirs; | 817 C negotiated = ours; |
817 for (theirs = offered_codecs.begin(); | 818 negotiated.IntersectFeedbackParams(theirs); |
818 theirs != offered_codecs.end(); ++theirs) { | 819 if (IsRtxCodec(negotiated)) { |
819 if (ours->Matches(*theirs)) { | 820 std::string offered_apt_value; |
820 C negotiated = *ours; | 821 theirs.GetParam(kCodecParamAssociatedPayloadType, &offered_apt_value); |
821 negotiated.IntersectFeedbackParams(*theirs); | 822 // FindMatchingCodec shouldn't return something with no apt value. |
822 if (IsRtxCodec(negotiated)) { | 823 RTC_DCHECK(!offered_apt_value.empty()); |
823 std::string offered_apt_value; | 824 negotiated.SetParam(kCodecParamAssociatedPayloadType, |
824 std::string local_apt_value; | 825 offered_apt_value); |
825 if (!ours->GetParam(kCodecParamAssociatedPayloadType, | |
826 &local_apt_value) || | |
827 !theirs->GetParam(kCodecParamAssociatedPayloadType, | |
828 &offered_apt_value)) { | |
829 LOG(LS_WARNING) << "RTX missing associated payload type."; | |
830 continue; | |
831 } | |
832 // Only negotiate RTX if kCodecParamAssociatedPayloadType has been | |
833 // set in local and remote codecs, and they match. | |
834 if (!ReferencedCodecsMatch(local_codecs, local_apt_value, | |
835 offered_codecs, offered_apt_value)) { | |
836 LOG(LS_WARNING) << "RTX associated codecs don't match."; | |
837 continue; | |
838 } | |
839 negotiated.SetParam(kCodecParamAssociatedPayloadType, | |
840 offered_apt_value); | |
841 } | |
842 | |
843 negotiated.id = theirs->id; | |
844 // RFC3264: Although the answerer MAY list the formats in their desired | |
845 // order of preference, it is RECOMMENDED that unless there is a | |
846 // specific reason, the answerer list formats in the same relative order | |
847 // they were present in the offer. | |
848 negotiated.preference = theirs->preference; | |
849 negotiated_codecs->push_back(negotiated); | |
850 } | 826 } |
| 827 negotiated.id = theirs.id; |
| 828 // RFC3264: Although the answerer MAY list the formats in their desired |
| 829 // order of preference, it is RECOMMENDED that unless there is a |
| 830 // specific reason, the answerer list formats in the same relative order |
| 831 // they were present in the offer. |
| 832 negotiated.preference = theirs.preference; |
| 833 negotiated_codecs->push_back(negotiated); |
851 } | 834 } |
852 } | 835 } |
853 } | 836 } |
854 | 837 |
| 838 // Finds a codec in |codecs2| that matches |codec_to_match|, which is |
| 839 // a member of |codecs1|. If |codec_to_match| is an RTX codec, both |
| 840 // the codecs themselves and their associated codecs must match. |
855 template <class C> | 841 template <class C> |
856 static bool FindMatchingCodec(const std::vector<C>& codecs, | 842 static bool FindMatchingCodec(const std::vector<C>& codecs1, |
| 843 const std::vector<C>& codecs2, |
857 const C& codec_to_match, | 844 const C& codec_to_match, |
858 C* found_codec) { | 845 C* found_codec) { |
859 for (typename std::vector<C>::const_iterator it = codecs.begin(); | 846 for (const C& potential_match : codecs2) { |
860 it != codecs.end(); ++it) { | 847 if (potential_match.Matches(codec_to_match)) { |
861 if (it->Matches(codec_to_match)) { | 848 if (IsRtxCodec(codec_to_match)) { |
862 if (found_codec != NULL) { | 849 std::string apt_value_1; |
863 *found_codec= *it; | 850 std::string apt_value_2; |
| 851 if (!codec_to_match.GetParam(kCodecParamAssociatedPayloadType, |
| 852 &apt_value_1) || |
| 853 !potential_match.GetParam(kCodecParamAssociatedPayloadType, |
| 854 &apt_value_2)) { |
| 855 LOG(LS_WARNING) << "RTX missing associated payload type."; |
| 856 continue; |
| 857 } |
| 858 if (!ReferencedCodecsMatch(codecs1, apt_value_1, codecs2, |
| 859 apt_value_2)) { |
| 860 continue; |
| 861 } |
| 862 } |
| 863 if (found_codec) { |
| 864 *found_codec = potential_match; |
864 } | 865 } |
865 return true; | 866 return true; |
866 } | 867 } |
867 } | 868 } |
868 return false; | 869 return false; |
869 } | 870 } |
870 | 871 |
871 // Adds all codecs from |reference_codecs| to |offered_codecs| that dont' | 872 // Adds all codecs from |reference_codecs| to |offered_codecs| that dont' |
872 // already exist in |offered_codecs| and ensure the payload types don't | 873 // already exist in |offered_codecs| and ensure the payload types don't |
873 // collide. | 874 // collide. |
874 template <class C> | 875 template <class C> |
875 static void FindCodecsToOffer( | 876 static void FindCodecsToOffer( |
876 const std::vector<C>& reference_codecs, | 877 const std::vector<C>& reference_codecs, |
877 std::vector<C>* offered_codecs, | 878 std::vector<C>* offered_codecs, |
878 UsedPayloadTypes* used_pltypes) { | 879 UsedPayloadTypes* used_pltypes) { |
879 | 880 |
880 typedef std::map<int, C> RtxCodecReferences; | |
881 RtxCodecReferences new_rtx_codecs; | |
882 | |
883 // Find all new RTX codecs. | |
884 for (typename std::vector<C>::const_iterator it = reference_codecs.begin(); | |
885 it != reference_codecs.end(); ++it) { | |
886 if (!FindMatchingCodec<C>(*offered_codecs, *it, NULL) && IsRtxCodec(*it)) { | |
887 C rtx_codec = *it; | |
888 int referenced_pl_type = | |
889 rtc::FromString<int>(0, | |
890 rtx_codec.params[kCodecParamAssociatedPayloadType]); | |
891 new_rtx_codecs.insert(std::pair<int, C>(referenced_pl_type, | |
892 rtx_codec)); | |
893 } | |
894 } | |
895 | |
896 // Add all new codecs that are not RTX codecs. | 881 // Add all new codecs that are not RTX codecs. |
897 for (typename std::vector<C>::const_iterator it = reference_codecs.begin(); | 882 for (const C& reference_codec : reference_codecs) { |
898 it != reference_codecs.end(); ++it) { | 883 if (!IsRtxCodec(reference_codec) && |
899 if (!FindMatchingCodec<C>(*offered_codecs, *it, NULL) && !IsRtxCodec(*it)) { | 884 !FindMatchingCodec<C>(reference_codecs, *offered_codecs, |
900 C codec = *it; | 885 reference_codec, nullptr)) { |
901 int original_payload_id = codec.id; | 886 C codec = reference_codec; |
902 used_pltypes->FindAndSetIdUsed(&codec); | 887 used_pltypes->FindAndSetIdUsed(&codec); |
903 offered_codecs->push_back(codec); | 888 offered_codecs->push_back(codec); |
904 | |
905 // If this codec is referenced by a new RTX codec, update the reference | |
906 // in the RTX codec with the new payload type. | |
907 typename RtxCodecReferences::iterator rtx_it = | |
908 new_rtx_codecs.find(original_payload_id); | |
909 if (rtx_it != new_rtx_codecs.end()) { | |
910 C& rtx_codec = rtx_it->second; | |
911 rtx_codec.params[kCodecParamAssociatedPayloadType] = | |
912 rtc::ToString(codec.id); | |
913 } | |
914 } | 889 } |
915 } | 890 } |
916 | 891 |
917 // Add all new RTX codecs. | 892 // Add all new RTX codecs. |
918 for (typename RtxCodecReferences::iterator it = new_rtx_codecs.begin(); | 893 for (const C& reference_codec : reference_codecs) { |
919 it != new_rtx_codecs.end(); ++it) { | 894 if (IsRtxCodec(reference_codec) && |
920 C& rtx_codec = it->second; | 895 !FindMatchingCodec<C>(reference_codecs, *offered_codecs, |
921 used_pltypes->FindAndSetIdUsed(&rtx_codec); | 896 reference_codec, nullptr)) { |
922 offered_codecs->push_back(rtx_codec); | 897 C rtx_codec = reference_codec; |
| 898 |
| 899 std::string associated_pt_str; |
| 900 if (!rtx_codec.GetParam(kCodecParamAssociatedPayloadType, |
| 901 &associated_pt_str)) { |
| 902 LOG(LS_WARNING) << "RTX codec " << rtx_codec.name |
| 903 << " is missing an associated payload type."; |
| 904 continue; |
| 905 } |
| 906 |
| 907 int associated_pt; |
| 908 if (!rtc::FromString(associated_pt_str, &associated_pt)) { |
| 909 LOG(LS_WARNING) << "Couldn't convert payload type " << associated_pt_str |
| 910 << " of RTX codec " << rtx_codec.name |
| 911 << " to an integer."; |
| 912 continue; |
| 913 } |
| 914 |
| 915 // Find the associated reference codec for the reference RTX codec. |
| 916 C associated_codec; |
| 917 if (!FindCodecById(reference_codecs, associated_pt, &associated_codec)) { |
| 918 LOG(LS_WARNING) << "Couldn't find associated codec with payload type " |
| 919 << associated_pt << " for RTX codec " << rtx_codec.name |
| 920 << "."; |
| 921 continue; |
| 922 } |
| 923 |
| 924 // Find a codec in the offered list that matches the reference codec. |
| 925 // Its payload type may be different than the reference codec. |
| 926 C matching_codec; |
| 927 if (!FindMatchingCodec<C>(reference_codecs, *offered_codecs, |
| 928 associated_codec, &matching_codec)) { |
| 929 LOG(LS_WARNING) << "Couldn't find matching " << associated_codec.name |
| 930 << " codec."; |
| 931 continue; |
| 932 } |
| 933 |
| 934 rtx_codec.params[kCodecParamAssociatedPayloadType] = |
| 935 rtc::ToString(matching_codec.id); |
| 936 used_pltypes->FindAndSetIdUsed(&rtx_codec); |
| 937 offered_codecs->push_back(rtx_codec); |
| 938 } |
923 } | 939 } |
924 } | 940 } |
925 | 941 |
926 | 942 |
927 static bool FindByUri(const RtpHeaderExtensions& extensions, | 943 static bool FindByUri(const RtpHeaderExtensions& extensions, |
928 const RtpHeaderExtension& ext_to_match, | 944 const RtpHeaderExtension& ext_to_match, |
929 RtpHeaderExtension* found_extension) { | 945 RtpHeaderExtension* found_extension) { |
930 for (RtpHeaderExtensions::const_iterator it = extensions.begin(); | 946 for (RtpHeaderExtensions::const_iterator it = extensions.begin(); |
931 it != extensions.end(); ++it) { | 947 it != extensions.end(); ++it) { |
932 // We assume that all URIs are given in a canonical format. | 948 // We assume that all URIs are given in a canonical format. |
(...skipping 1050 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1983 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO)); | 1999 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO)); |
1984 } | 2000 } |
1985 | 2001 |
1986 const DataContentDescription* GetFirstDataContentDescription( | 2002 const DataContentDescription* GetFirstDataContentDescription( |
1987 const SessionDescription* sdesc) { | 2003 const SessionDescription* sdesc) { |
1988 return static_cast<const DataContentDescription*>( | 2004 return static_cast<const DataContentDescription*>( |
1989 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA)); | 2005 GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA)); |
1990 } | 2006 } |
1991 | 2007 |
1992 } // namespace cricket | 2008 } // namespace cricket |
OLD | NEW |