Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2011 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2011 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 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 77 } | 77 } |
| 78 | 78 |
| 79 namespace webrtc { | 79 namespace webrtc { |
| 80 | 80 |
| 81 // Line type | 81 // Line type |
| 82 // RFC 4566 | 82 // RFC 4566 |
| 83 // An SDP session description consists of a number of lines of text of | 83 // An SDP session description consists of a number of lines of text of |
| 84 // the form: | 84 // the form: |
| 85 // <type>=<value> | 85 // <type>=<value> |
| 86 // where <type> MUST be exactly one case-significant character. | 86 // where <type> MUST be exactly one case-significant character. |
| 87 static const int kLinePrefixLength = 2; // Lenght of <type>= | 87 static const int kLinePrefixLength = 2; // Length of <type>= |
| 88 static const char kLineTypeVersion = 'v'; | 88 static const char kLineTypeVersion = 'v'; |
| 89 static const char kLineTypeOrigin = 'o'; | 89 static const char kLineTypeOrigin = 'o'; |
| 90 static const char kLineTypeSessionName = 's'; | 90 static const char kLineTypeSessionName = 's'; |
| 91 static const char kLineTypeSessionInfo = 'i'; | 91 static const char kLineTypeSessionInfo = 'i'; |
| 92 static const char kLineTypeSessionUri = 'u'; | 92 static const char kLineTypeSessionUri = 'u'; |
| 93 static const char kLineTypeSessionEmail = 'e'; | 93 static const char kLineTypeSessionEmail = 'e'; |
| 94 static const char kLineTypeSessionPhone = 'p'; | 94 static const char kLineTypeSessionPhone = 'p'; |
| 95 static const char kLineTypeSessionBandwidth = 'b'; | 95 static const char kLineTypeSessionBandwidth = 'b'; |
| 96 static const char kLineTypeTiming = 't'; | 96 static const char kLineTypeTiming = 't'; |
| 97 static const char kLineTypeRepeatTimes = 'r'; | 97 static const char kLineTypeRepeatTimes = 'r'; |
| 98 static const char kLineTypeTimeZone = 'z'; | 98 static const char kLineTypeTimeZone = 'z'; |
| 99 static const char kLineTypeEncryptionKey = 'k'; | 99 static const char kLineTypeEncryptionKey = 'k'; |
| 100 static const char kLineTypeMedia = 'm'; | 100 static const char kLineTypeMedia = 'm'; |
| 101 static const char kLineTypeConnection = 'c'; | 101 static const char kLineTypeConnection = 'c'; |
| 102 static const char kLineTypeAttributes = 'a'; | 102 static const char kLineTypeAttributes = 'a'; |
| 103 | 103 |
| 104 // Attributes | 104 // Attributes |
| 105 static const char kAttributeGroup[] = "group"; | 105 static const char kAttributeGroup[] = "group"; |
| 106 static const char kAttributeMid[] = "mid"; | 106 static const char kAttributeMid[] = "mid"; |
| 107 static const char kAttributeMsid[] = "msid"; | |
| 107 static const char kAttributeRtcpMux[] = "rtcp-mux"; | 108 static const char kAttributeRtcpMux[] = "rtcp-mux"; |
| 108 static const char kAttributeRtcpReducedSize[] = "rtcp-rsize"; | 109 static const char kAttributeRtcpReducedSize[] = "rtcp-rsize"; |
| 109 static const char kAttributeSsrc[] = "ssrc"; | 110 static const char kAttributeSsrc[] = "ssrc"; |
| 110 static const char kSsrcAttributeCname[] = "cname"; | 111 static const char kSsrcAttributeCname[] = "cname"; |
| 111 static const char kAttributeExtmap[] = "extmap"; | 112 static const char kAttributeExtmap[] = "extmap"; |
| 112 // draft-alvestrand-mmusic-msid-01 | 113 // draft-alvestrand-mmusic-msid-01 |
| 113 // a=msid-semantic: WMS | 114 // a=msid-semantic: WMS |
| 114 static const char kAttributeMsidSemantics[] = "msid-semantic"; | 115 static const char kAttributeMsidSemantics[] = "msid-semantic"; |
| 115 static const char kMediaStreamSemantic[] = "WMS"; | 116 static const char kMediaStreamSemantic[] = "WMS"; |
| 116 static const char kSsrcAttributeMsid[] = "msid"; | 117 static const char kSsrcAttributeMsid[] = "msid"; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 204 static const int kIsacSwbDefaultRate = 56000; // From acm_common_defs.h | 205 static const int kIsacSwbDefaultRate = 56000; // From acm_common_defs.h |
| 205 | 206 |
| 206 static const char kDefaultSctpmapProtocol[] = "webrtc-datachannel"; | 207 static const char kDefaultSctpmapProtocol[] = "webrtc-datachannel"; |
| 207 | 208 |
| 208 // RTP payload type is in the 0-127 range. Use -1 to indicate "all" payload | 209 // RTP payload type is in the 0-127 range. Use -1 to indicate "all" payload |
| 209 // types. | 210 // types. |
| 210 const int kWildcardPayloadType = -1; | 211 const int kWildcardPayloadType = -1; |
| 211 | 212 |
| 212 struct SsrcInfo { | 213 struct SsrcInfo { |
| 213 SsrcInfo() | 214 SsrcInfo() |
| 214 : msid_identifier(kDefaultMsid), | 215 : stream_id(kDefaultMsid), |
| 215 // TODO(ronghuawu): What should we do if the appdata doesn't appear? | 216 // TODO(ronghuawu): What should we do if the track id doesn't appear? |
| 216 // Create random string (which will be used as track label later)? | 217 // Create random string (which will be used as track label later)? |
| 217 msid_appdata(rtc::CreateRandomString(8)) { | 218 track_id(rtc::CreateRandomString(8)) {} |
| 218 } | |
| 219 uint32_t ssrc_id; | 219 uint32_t ssrc_id; |
| 220 std::string cname; | 220 std::string cname; |
| 221 std::string msid_identifier; | 221 std::string stream_id; |
| 222 std::string msid_appdata; | 222 std::string track_id; |
| 223 | 223 |
| 224 // For backward compatibility. | 224 // For backward compatibility. |
| 225 // TODO(ronghuawu): Remove below 2 fields once all the clients support msid. | 225 // TODO(ronghuawu): Remove below 2 fields once all the clients support msid. |
| 226 std::string label; | 226 std::string label; |
| 227 std::string mslabel; | 227 std::string mslabel; |
| 228 }; | 228 }; |
| 229 typedef std::vector<SsrcInfo> SsrcInfoVec; | 229 typedef std::vector<SsrcInfo> SsrcInfoVec; |
| 230 typedef std::vector<SsrcGroup> SsrcGroupVec; | 230 typedef std::vector<SsrcGroup> SsrcGroupVec; |
| 231 | 231 |
| 232 template <class T> | 232 template <class T> |
| 233 static void AddFmtpLine(const T& codec, std::string* message); | 233 static void AddFmtpLine(const T& codec, std::string* message); |
| 234 static void BuildMediaDescription(const ContentInfo* content_info, | 234 static void BuildMediaDescription(const ContentInfo* content_info, |
| 235 const TransportInfo* transport_info, | 235 const TransportInfo* transport_info, |
| 236 const MediaType media_type, | 236 const MediaType media_type, |
| 237 const std::vector<Candidate>& candidates, | 237 const std::vector<Candidate>& candidates, |
| 238 bool unified_plan_sdp, | |
| 238 std::string* message); | 239 std::string* message); |
| 239 static void BuildSctpContentAttributes(std::string* message, int sctp_port); | 240 static void BuildSctpContentAttributes(std::string* message, int sctp_port); |
| 240 static void BuildRtpContentAttributes( | 241 static void BuildRtpContentAttributes(const MediaContentDescription* media_desc, |
| 241 const MediaContentDescription* media_desc, | 242 const MediaType media_type, |
| 242 const MediaType media_type, | 243 bool unified_plan_sdp, |
| 243 std::string* message); | 244 std::string* message); |
| 244 static void BuildRtpMap(const MediaContentDescription* media_desc, | 245 static void BuildRtpMap(const MediaContentDescription* media_desc, |
| 245 const MediaType media_type, | 246 const MediaType media_type, |
| 246 std::string* message); | 247 std::string* message); |
| 247 static void BuildCandidate(const std::vector<Candidate>& candidates, | 248 static void BuildCandidate(const std::vector<Candidate>& candidates, |
| 248 bool include_ufrag, | 249 bool include_ufrag, |
| 249 std::string* message); | 250 std::string* message); |
| 250 static void BuildIceOptions(const std::vector<std::string>& transport_options, | 251 static void BuildIceOptions(const std::vector<std::string>& transport_options, |
| 251 std::string* message); | 252 std::string* message); |
| 252 static bool IsRtp(const std::string& protocol); | 253 static bool IsRtp(const std::string& protocol); |
| 253 static bool IsDtlsSctp(const std::string& protocol); | 254 static bool IsDtlsSctp(const std::string& protocol); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 310 SdpParseError* error); | 311 SdpParseError* error); |
| 311 static bool ParseExtmap(const std::string& line, | 312 static bool ParseExtmap(const std::string& line, |
| 312 RtpHeaderExtension* extmap, | 313 RtpHeaderExtension* extmap, |
| 313 SdpParseError* error); | 314 SdpParseError* error); |
| 314 static bool ParseFingerprintAttribute(const std::string& line, | 315 static bool ParseFingerprintAttribute(const std::string& line, |
| 315 rtc::SSLFingerprint** fingerprint, | 316 rtc::SSLFingerprint** fingerprint, |
| 316 SdpParseError* error); | 317 SdpParseError* error); |
| 317 static bool ParseDtlsSetup(const std::string& line, | 318 static bool ParseDtlsSetup(const std::string& line, |
| 318 cricket::ConnectionRole* role, | 319 cricket::ConnectionRole* role, |
| 319 SdpParseError* error); | 320 SdpParseError* error); |
| 321 static bool ParseMsidAttribute(const std::string& line, | |
| 322 std::string* stream_id, | |
| 323 std::string* track_id, | |
| 324 SdpParseError* error); | |
| 320 | 325 |
| 321 // Helper functions | 326 // Helper functions |
| 322 | 327 |
| 323 // Below ParseFailed*** functions output the line that caused the parsing | 328 // Below ParseFailed*** functions output the line that caused the parsing |
| 324 // failure and the detailed reason (|description|) of the failure to |error|. | 329 // failure and the detailed reason (|description|) of the failure to |error|. |
| 325 // The functions always return false so that they can be used directly in the | 330 // The functions always return false so that they can be used directly in the |
| 326 // following way when error happens: | 331 // following way when error happens: |
| 327 // "return ParseFailed***(...);" | 332 // "return ParseFailed***(...);" |
| 328 | 333 |
| 329 // The line starting at |line_start| of |message| is the failing line. | 334 // The line starting at |line_start| of |message| is the failing line. |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 571 StreamParamsVec* tracks) { | 576 StreamParamsVec* tracks) { |
| 572 ASSERT(tracks != NULL); | 577 ASSERT(tracks != NULL); |
| 573 for (SsrcInfoVec::const_iterator ssrc_info = ssrc_infos.begin(); | 578 for (SsrcInfoVec::const_iterator ssrc_info = ssrc_infos.begin(); |
| 574 ssrc_info != ssrc_infos.end(); ++ssrc_info) { | 579 ssrc_info != ssrc_infos.end(); ++ssrc_info) { |
| 575 if (ssrc_info->cname.empty()) { | 580 if (ssrc_info->cname.empty()) { |
| 576 continue; | 581 continue; |
| 577 } | 582 } |
| 578 | 583 |
| 579 std::string sync_label; | 584 std::string sync_label; |
| 580 std::string track_id; | 585 std::string track_id; |
| 581 if (ssrc_info->msid_identifier == kDefaultMsid && | 586 if (ssrc_info->stream_id == kDefaultMsid && !ssrc_info->mslabel.empty()) { |
| 582 !ssrc_info->mslabel.empty()) { | |
| 583 // If there's no msid and there's mslabel, we consider this is a sdp from | 587 // If there's no msid and there's mslabel, we consider this is a sdp from |
| 584 // a older version of client that doesn't support msid. | 588 // a older version of client that doesn't support msid. |
| 585 // In that case, we use the mslabel and label to construct the track. | 589 // In that case, we use the mslabel and label to construct the track. |
| 586 sync_label = ssrc_info->mslabel; | 590 sync_label = ssrc_info->mslabel; |
| 587 track_id = ssrc_info->label; | 591 track_id = ssrc_info->label; |
| 588 } else { | 592 } else { |
| 589 sync_label = ssrc_info->msid_identifier; | 593 sync_label = ssrc_info->stream_id; |
| 590 // The appdata consists of the "id" attribute of a MediaStreamTrack, which | 594 track_id = ssrc_info->track_id; |
| 591 // is corresponding to the "id" attribute of StreamParams. | |
| 592 track_id = ssrc_info->msid_appdata; | |
| 593 } | 595 } |
| 594 if (sync_label.empty() || track_id.empty()) { | 596 if (sync_label.empty() || track_id.empty()) { |
| 595 ASSERT(false); | 597 ASSERT(false); |
| 596 continue; | 598 continue; |
| 597 } | 599 } |
| 598 | 600 |
| 599 StreamParamsVec::iterator track = tracks->begin(); | 601 StreamParamsVec::iterator track = tracks->begin(); |
| 600 for (; track != tracks->end(); ++track) { | 602 for (; track != tracks->end(); ++track) { |
| 601 if (track->id == track_id) { | 603 if (track->id == track_id) { |
| 602 break; | 604 break; |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 768 if (!candidates) { | 770 if (!candidates) { |
| 769 return; | 771 return; |
| 770 } | 772 } |
| 771 const IceCandidateCollection* cc = desci.candidates(mline_index); | 773 const IceCandidateCollection* cc = desci.candidates(mline_index); |
| 772 for (size_t i = 0; i < cc->count(); ++i) { | 774 for (size_t i = 0; i < cc->count(); ++i) { |
| 773 const IceCandidateInterface* candidate = cc->at(i); | 775 const IceCandidateInterface* candidate = cc->at(i); |
| 774 candidates->push_back(candidate->candidate()); | 776 candidates->push_back(candidate->candidate()); |
| 775 } | 777 } |
| 776 } | 778 } |
| 777 | 779 |
| 778 std::string SdpSerialize(const JsepSessionDescription& jdesc) { | 780 std::string SdpSerialize(const JsepSessionDescription& jdesc, |
| 781 bool unified_plan_sdp) { | |
| 779 const cricket::SessionDescription* desc = jdesc.description(); | 782 const cricket::SessionDescription* desc = jdesc.description(); |
| 780 if (!desc) { | 783 if (!desc) { |
| 781 return ""; | 784 return ""; |
| 782 } | 785 } |
| 783 | 786 |
| 784 std::string message; | 787 std::string message; |
| 785 | 788 |
| 786 // Session Description. | 789 // Session Description. |
| 787 AddLine(kSessionVersion, &message); | 790 AddLine(kSessionVersion, &message); |
| 788 // Session Origin | 791 // Session Origin |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 839 AddLine(os.str(), &message); | 842 AddLine(os.str(), &message); |
| 840 | 843 |
| 841 // Preserve the order of the media contents. | 844 // Preserve the order of the media contents. |
| 842 int mline_index = -1; | 845 int mline_index = -1; |
| 843 for (cricket::ContentInfos::const_iterator it = desc->contents().begin(); | 846 for (cricket::ContentInfos::const_iterator it = desc->contents().begin(); |
| 844 it != desc->contents().end(); ++it) { | 847 it != desc->contents().end(); ++it) { |
| 845 const MediaContentDescription* mdesc = | 848 const MediaContentDescription* mdesc = |
| 846 static_cast<const MediaContentDescription*>(it->description); | 849 static_cast<const MediaContentDescription*>(it->description); |
| 847 std::vector<Candidate> candidates; | 850 std::vector<Candidate> candidates; |
| 848 GetCandidatesByMindex(jdesc, ++mline_index, &candidates); | 851 GetCandidatesByMindex(jdesc, ++mline_index, &candidates); |
| 849 BuildMediaDescription(&*it, | 852 BuildMediaDescription(&*it, desc->GetTransportInfoByName(it->name), |
| 850 desc->GetTransportInfoByName(it->name), | 853 mdesc->type(), candidates, unified_plan_sdp, |
| 851 mdesc->type(), | |
| 852 candidates, | |
| 853 &message); | 854 &message); |
| 854 } | 855 } |
| 855 return message; | 856 return message; |
| 856 } | 857 } |
| 857 | 858 |
| 858 // Serializes the passed in IceCandidateInterface to a SDP string. | 859 // Serializes the passed in IceCandidateInterface to a SDP string. |
| 859 // candidate - The candidate to be serialized. | 860 // candidate - The candidate to be serialized. |
| 860 std::string SdpSerializeCandidate( | 861 std::string SdpSerializeCandidate( |
| 861 const IceCandidateInterface& candidate) { | 862 const IceCandidateInterface& candidate) { |
| 862 std::string message; | 863 std::string message; |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1148 } | 1149 } |
| 1149 | 1150 |
| 1150 *extmap = RtpHeaderExtension(uri, value); | 1151 *extmap = RtpHeaderExtension(uri, value); |
| 1151 return true; | 1152 return true; |
| 1152 } | 1153 } |
| 1153 | 1154 |
| 1154 void BuildMediaDescription(const ContentInfo* content_info, | 1155 void BuildMediaDescription(const ContentInfo* content_info, |
| 1155 const TransportInfo* transport_info, | 1156 const TransportInfo* transport_info, |
| 1156 const MediaType media_type, | 1157 const MediaType media_type, |
| 1157 const std::vector<Candidate>& candidates, | 1158 const std::vector<Candidate>& candidates, |
| 1159 bool unified_plan_sdp, | |
| 1158 std::string* message) { | 1160 std::string* message) { |
| 1159 ASSERT(message != NULL); | 1161 ASSERT(message != NULL); |
| 1160 if (content_info == NULL || message == NULL) { | 1162 if (content_info == NULL || message == NULL) { |
| 1161 return; | 1163 return; |
| 1162 } | 1164 } |
| 1163 // TODO: Rethink if we should use sprintfn instead of stringstream. | 1165 // TODO: Rethink if we should use sprintfn instead of stringstream. |
| 1164 // According to the style guide, streams should only be used for logging. | 1166 // According to the style guide, streams should only be used for logging. |
| 1165 // http://google-styleguide.googlecode.com/svn/ | 1167 // http://google-styleguide.googlecode.com/svn/ |
| 1166 // trunk/cppguide.xml?showone=Streams#Streams | 1168 // trunk/cppguide.xml?showone=Streams#Streams |
| 1167 std::ostringstream os; | 1169 std::ostringstream os; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1323 // mid-attribute = "a=mid:" identification-tag | 1325 // mid-attribute = "a=mid:" identification-tag |
| 1324 // identification-tag = token | 1326 // identification-tag = token |
| 1325 // Use the content name as the mid identification-tag. | 1327 // Use the content name as the mid identification-tag. |
| 1326 InitAttrLine(kAttributeMid, &os); | 1328 InitAttrLine(kAttributeMid, &os); |
| 1327 os << kSdpDelimiterColon << content_info->name; | 1329 os << kSdpDelimiterColon << content_info->name; |
| 1328 AddLine(os.str(), message); | 1330 AddLine(os.str(), message); |
| 1329 | 1331 |
| 1330 if (IsDtlsSctp(media_desc->protocol())) { | 1332 if (IsDtlsSctp(media_desc->protocol())) { |
| 1331 BuildSctpContentAttributes(message, sctp_port); | 1333 BuildSctpContentAttributes(message, sctp_port); |
| 1332 } else if (IsRtp(media_desc->protocol())) { | 1334 } else if (IsRtp(media_desc->protocol())) { |
| 1333 BuildRtpContentAttributes(media_desc, media_type, message); | 1335 BuildRtpContentAttributes(media_desc, media_type, unified_plan_sdp, |
| 1336 message); | |
| 1334 } | 1337 } |
| 1335 } | 1338 } |
| 1336 | 1339 |
| 1337 void BuildSctpContentAttributes(std::string* message, int sctp_port) { | 1340 void BuildSctpContentAttributes(std::string* message, int sctp_port) { |
| 1338 // draft-ietf-mmusic-sctp-sdp-04 | 1341 // draft-ietf-mmusic-sctp-sdp-04 |
| 1339 // a=sctpmap:sctpmap-number protocol [streams] | 1342 // a=sctpmap:sctpmap-number protocol [streams] |
| 1340 // TODO(lally): switch this over to mmusic-sctp-sdp-12 (or later), with | 1343 // TODO(lally): switch this over to mmusic-sctp-sdp-12 (or later), with |
| 1341 // 'a=sctp-port:' | 1344 // 'a=sctp-port:' |
| 1342 std::ostringstream os; | 1345 std::ostringstream os; |
| 1343 InitAttrLine(kAttributeSctpmap, &os); | 1346 InitAttrLine(kAttributeSctpmap, &os); |
| 1344 os << kSdpDelimiterColon << sctp_port << kSdpDelimiterSpace | 1347 os << kSdpDelimiterColon << sctp_port << kSdpDelimiterSpace |
| 1345 << kDefaultSctpmapProtocol << kSdpDelimiterSpace | 1348 << kDefaultSctpmapProtocol << kSdpDelimiterSpace |
| 1346 << (cricket::kMaxSctpSid + 1); | 1349 << (cricket::kMaxSctpSid + 1); |
| 1347 AddLine(os.str(), message); | 1350 AddLine(os.str(), message); |
| 1348 } | 1351 } |
| 1349 | 1352 |
| 1350 void BuildRtpContentAttributes( | 1353 // If unified_plan_sdp is true, will use "a=msid". |
| 1351 const MediaContentDescription* media_desc, | 1354 void BuildRtpContentAttributes(const MediaContentDescription* media_desc, |
| 1352 const MediaType media_type, | 1355 const MediaType media_type, |
| 1353 std::string* message) { | 1356 bool unified_plan_sdp, |
| 1357 std::string* message) { | |
| 1354 std::ostringstream os; | 1358 std::ostringstream os; |
| 1355 // RFC 5285 | 1359 // RFC 5285 |
| 1356 // a=extmap:<value>["/"<direction>] <URI> <extensionattributes> | 1360 // a=extmap:<value>["/"<direction>] <URI> <extensionattributes> |
| 1357 // The definitions MUST be either all session level or all media level. This | 1361 // The definitions MUST be either all session level or all media level. This |
| 1358 // implementation uses all media level. | 1362 // implementation uses all media level. |
| 1359 for (size_t i = 0; i < media_desc->rtp_header_extensions().size(); ++i) { | 1363 for (size_t i = 0; i < media_desc->rtp_header_extensions().size(); ++i) { |
| 1360 InitAttrLine(kAttributeExtmap, &os); | 1364 InitAttrLine(kAttributeExtmap, &os); |
| 1361 os << kSdpDelimiterColon << media_desc->rtp_header_extensions()[i].id | 1365 os << kSdpDelimiterColon << media_desc->rtp_header_extensions()[i].id |
| 1362 << kSdpDelimiterSpace << media_desc->rtp_header_extensions()[i].uri; | 1366 << kSdpDelimiterSpace << media_desc->rtp_header_extensions()[i].uri; |
| 1363 AddLine(os.str(), message); | 1367 AddLine(os.str(), message); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1375 case cricket::MD_RECVONLY: | 1379 case cricket::MD_RECVONLY: |
| 1376 InitAttrLine(kAttributeRecvOnly, &os); | 1380 InitAttrLine(kAttributeRecvOnly, &os); |
| 1377 break; | 1381 break; |
| 1378 case cricket::MD_SENDRECV: | 1382 case cricket::MD_SENDRECV: |
| 1379 default: | 1383 default: |
| 1380 InitAttrLine(kAttributeSendRecv, &os); | 1384 InitAttrLine(kAttributeSendRecv, &os); |
| 1381 break; | 1385 break; |
| 1382 } | 1386 } |
| 1383 AddLine(os.str(), message); | 1387 AddLine(os.str(), message); |
| 1384 | 1388 |
| 1389 // draft-ietf-mmusic-msid-11 | |
| 1390 // a=msid:<stream id> <track id> | |
| 1391 if (unified_plan_sdp && !media_desc->streams().empty()) { | |
| 1392 if (media_desc->streams().size() > 1u) { | |
| 1393 LOG(LS_WARNING) << "Trying to serialize unified plan SDP with more than " | |
| 1394 << "one track in a media section. Omitting 'a=msid'."; | |
| 1395 } else { | |
| 1396 auto track = media_desc->streams().begin(); | |
| 1397 const std::string& stream_id = track->sync_label; | |
| 1398 std::ostringstream os; | |
|
brucedawson
2016/02/19 19:23:39
Unnecessarily duplicated variable, also variable s
| |
| 1399 InitAttrLine(kAttributeMsid, &os); | |
| 1400 os << kSdpDelimiterColon << stream_id << kSdpDelimiterSpace << track->id; | |
| 1401 AddLine(os.str(), message); | |
| 1402 } | |
| 1403 } | |
| 1404 | |
| 1385 // RFC 5761 | 1405 // RFC 5761 |
| 1386 // a=rtcp-mux | 1406 // a=rtcp-mux |
| 1387 if (media_desc->rtcp_mux()) { | 1407 if (media_desc->rtcp_mux()) { |
| 1388 InitAttrLine(kAttributeRtcpMux, &os); | 1408 InitAttrLine(kAttributeRtcpMux, &os); |
| 1389 AddLine(os.str(), message); | 1409 AddLine(os.str(), message); |
| 1390 } | 1410 } |
| 1391 | 1411 |
| 1392 // RFC 5506 | 1412 // RFC 5506 |
| 1393 // a=rtcp-rsize | 1413 // a=rtcp-rsize |
| 1394 if (media_desc->rtcp_reduced_size()) { | 1414 if (media_desc->rtcp_reduced_size()) { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 1423 // if no track or media stream have been created. | 1443 // if no track or media stream have been created. |
| 1424 if (track->sync_label.empty()) continue; | 1444 if (track->sync_label.empty()) continue; |
| 1425 | 1445 |
| 1426 // Build the ssrc-group lines. | 1446 // Build the ssrc-group lines. |
| 1427 for (size_t i = 0; i < track->ssrc_groups.size(); ++i) { | 1447 for (size_t i = 0; i < track->ssrc_groups.size(); ++i) { |
| 1428 // RFC 5576 | 1448 // RFC 5576 |
| 1429 // a=ssrc-group:<semantics> <ssrc-id> ... | 1449 // a=ssrc-group:<semantics> <ssrc-id> ... |
| 1430 if (track->ssrc_groups[i].ssrcs.empty()) { | 1450 if (track->ssrc_groups[i].ssrcs.empty()) { |
| 1431 continue; | 1451 continue; |
| 1432 } | 1452 } |
| 1433 std::ostringstream os; | 1453 std::ostringstream os; |
|
brucedawson
2016/02/19 19:23:39
Ditto (but not from this CL).
| |
| 1434 InitAttrLine(kAttributeSsrcGroup, &os); | 1454 InitAttrLine(kAttributeSsrcGroup, &os); |
| 1435 os << kSdpDelimiterColon << track->ssrc_groups[i].semantics; | 1455 os << kSdpDelimiterColon << track->ssrc_groups[i].semantics; |
| 1436 std::vector<uint32_t>::const_iterator ssrc = | 1456 std::vector<uint32_t>::const_iterator ssrc = |
| 1437 track->ssrc_groups[i].ssrcs.begin(); | 1457 track->ssrc_groups[i].ssrcs.begin(); |
| 1438 for (; ssrc != track->ssrc_groups[i].ssrcs.end(); ++ssrc) { | 1458 for (; ssrc != track->ssrc_groups[i].ssrcs.end(); ++ssrc) { |
| 1439 os << kSdpDelimiterSpace << rtc::ToString<uint32_t>(*ssrc); | 1459 os << kSdpDelimiterSpace << rtc::ToString<uint32_t>(*ssrc); |
| 1440 } | 1460 } |
| 1441 AddLine(os.str(), message); | 1461 AddLine(os.str(), message); |
| 1442 } | 1462 } |
| 1443 // Build the ssrc lines for each ssrc. | 1463 // Build the ssrc lines for each ssrc. |
| 1444 for (size_t i = 0; i < track->ssrcs.size(); ++i) { | 1464 for (size_t i = 0; i < track->ssrcs.size(); ++i) { |
| 1445 uint32_t ssrc = track->ssrcs[i]; | 1465 uint32_t ssrc = track->ssrcs[i]; |
| 1446 // RFC 5576 | 1466 // RFC 5576 |
| 1447 // a=ssrc:<ssrc-id> cname:<value> | 1467 // a=ssrc:<ssrc-id> cname:<value> |
| 1448 AddSsrcLine(ssrc, kSsrcAttributeCname, | 1468 AddSsrcLine(ssrc, kSsrcAttributeCname, |
| 1449 track->cname, message); | 1469 track->cname, message); |
| 1450 | 1470 |
| 1451 // draft-alvestrand-mmusic-msid-00 | 1471 // draft-alvestrand-mmusic-msid-00 |
| 1452 // a=ssrc:<ssrc-id> msid:identifier [appdata] | 1472 // a=ssrc:<ssrc-id> msid:identifier [appdata] |
| 1453 // The appdata consists of the "id" attribute of a MediaStreamTrack, which | 1473 // The appdata consists of the "id" attribute of a MediaStreamTrack, |
| 1454 // is corresponding to the "name" attribute of StreamParams. | 1474 // which corresponds to the "id" attribute of StreamParams. |
| 1455 std::string appdata = track->id; | 1475 const std::string& stream_id = track->sync_label; |
| 1456 std::ostringstream os; | 1476 std::ostringstream os; |
|
brucedawson
2016/02/19 19:23:39
Ditto (but not from this CL).
| |
| 1457 InitAttrLine(kAttributeSsrc, &os); | 1477 InitAttrLine(kAttributeSsrc, &os); |
| 1458 os << kSdpDelimiterColon << ssrc << kSdpDelimiterSpace | 1478 os << kSdpDelimiterColon << ssrc << kSdpDelimiterSpace |
| 1459 << kSsrcAttributeMsid << kSdpDelimiterColon << track->sync_label | 1479 << kSsrcAttributeMsid << kSdpDelimiterColon << stream_id |
| 1460 << kSdpDelimiterSpace << appdata; | 1480 << kSdpDelimiterSpace << track->id; |
| 1461 AddLine(os.str(), message); | 1481 AddLine(os.str(), message); |
| 1462 | 1482 |
| 1463 // TODO(ronghuawu): Remove below code which is for backward compatibility. | 1483 // TODO(ronghuawu): Remove below code which is for backward |
| 1484 // compatibility. | |
| 1464 // draft-alvestrand-rtcweb-mid-01 | 1485 // draft-alvestrand-rtcweb-mid-01 |
| 1465 // a=ssrc:<ssrc-id> mslabel:<value> | 1486 // a=ssrc:<ssrc-id> mslabel:<value> |
| 1466 // The label isn't yet defined. | 1487 // The label isn't yet defined. |
| 1467 // a=ssrc:<ssrc-id> label:<value> | 1488 // a=ssrc:<ssrc-id> label:<value> |
| 1468 AddSsrcLine(ssrc, kSsrcAttributeMslabel, track->sync_label, message); | 1489 AddSsrcLine(ssrc, kSsrcAttributeMslabel, track->sync_label, message); |
| 1469 AddSsrcLine(ssrc, kSSrcAttributeLabel, track->id, message); | 1490 AddSsrcLine(ssrc, kSSrcAttributeLabel, track->id, message); |
| 1470 } | 1491 } |
| 1471 } | 1492 } |
| 1472 } | 1493 } |
| 1473 | 1494 |
| (...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2015 if (fields.size() != expected_fields) { | 2036 if (fields.size() != expected_fields) { |
| 2016 return ParseFailedExpectFieldNum(line, expected_fields, error); | 2037 return ParseFailedExpectFieldNum(line, expected_fields, error); |
| 2017 } | 2038 } |
| 2018 std::string role_str = fields[1]; | 2039 std::string role_str = fields[1]; |
| 2019 if (!cricket::StringToConnectionRole(role_str, role)) { | 2040 if (!cricket::StringToConnectionRole(role_str, role)) { |
| 2020 return ParseFailed(line, "Invalid attribute value.", error); | 2041 return ParseFailed(line, "Invalid attribute value.", error); |
| 2021 } | 2042 } |
| 2022 return true; | 2043 return true; |
| 2023 } | 2044 } |
| 2024 | 2045 |
| 2046 static bool ParseMsidAttribute(const std::string& line, | |
| 2047 std::string* stream_id, | |
| 2048 std::string* track_id, | |
| 2049 SdpParseError* error) { | |
| 2050 // draft-ietf-mmusic-msid-11 | |
| 2051 // a=msid:<stream id> <track id> | |
| 2052 // msid-value = msid-id [ SP msid-appdata ] | |
| 2053 // msid-id = 1*64token-char ; see RFC 4566 | |
| 2054 // msid-appdata = 1*64token-char ; see RFC 4566 | |
| 2055 std::string field1; | |
| 2056 if (!rtc::tokenize_first(line.substr(kLinePrefixLength), kSdpDelimiterSpace, | |
| 2057 &field1, track_id)) { | |
| 2058 const size_t expected_fields = 2; | |
| 2059 return ParseFailedExpectFieldNum(line, expected_fields, error); | |
| 2060 } | |
| 2061 | |
| 2062 // msid:<msid-id> | |
| 2063 if (!GetValue(field1, kAttributeMsid, stream_id, error)) { | |
| 2064 return false; | |
| 2065 } | |
| 2066 return true; | |
| 2067 } | |
| 2068 | |
| 2025 // RFC 3551 | 2069 // RFC 3551 |
| 2026 // PT encoding media type clock rate channels | 2070 // PT encoding media type clock rate channels |
| 2027 // name (Hz) | 2071 // name (Hz) |
| 2028 // 0 PCMU A 8,000 1 | 2072 // 0 PCMU A 8,000 1 |
| 2029 // 1 reserved A | 2073 // 1 reserved A |
| 2030 // 2 reserved A | 2074 // 2 reserved A |
| 2031 // 3 GSM A 8,000 1 | 2075 // 3 GSM A 8,000 1 |
| 2032 // 4 G723 A 8,000 1 | 2076 // 4 G723 A 8,000 1 |
| 2033 // 5 DVI4 A 8,000 1 | 2077 // 5 DVI4 A 8,000 1 |
| 2034 // 6 DVI4 A 16,000 1 | 2078 // 6 DVI4 A 16,000 1 |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2439 // The candidates before update the media level "ice-pwd" and "ice-ufrag". | 2483 // The candidates before update the media level "ice-pwd" and "ice-ufrag". |
| 2440 Candidates candidates_orig; | 2484 Candidates candidates_orig; |
| 2441 std::string line; | 2485 std::string line; |
| 2442 std::string mline_id; | 2486 std::string mline_id; |
| 2443 // Tracks created out of the ssrc attributes. | 2487 // Tracks created out of the ssrc attributes. |
| 2444 StreamParamsVec tracks; | 2488 StreamParamsVec tracks; |
| 2445 SsrcInfoVec ssrc_infos; | 2489 SsrcInfoVec ssrc_infos; |
| 2446 SsrcGroupVec ssrc_groups; | 2490 SsrcGroupVec ssrc_groups; |
| 2447 std::string maxptime_as_string; | 2491 std::string maxptime_as_string; |
| 2448 std::string ptime_as_string; | 2492 std::string ptime_as_string; |
| 2493 std::string stream_id; | |
| 2494 std::string track_id; | |
| 2449 | 2495 |
| 2450 // Loop until the next m line | 2496 // Loop until the next m line |
| 2451 while (!IsLineType(message, kLineTypeMedia, *pos)) { | 2497 while (!IsLineType(message, kLineTypeMedia, *pos)) { |
| 2452 if (!GetLine(message, pos, &line)) { | 2498 if (!GetLine(message, pos, &line)) { |
| 2453 if (*pos >= message.size()) { | 2499 if (*pos >= message.size()) { |
| 2454 break; // Done parsing | 2500 break; // Done parsing |
| 2455 } else { | 2501 } else { |
| 2456 return ParseFailed(message, *pos, "Invalid SDP line.", error); | 2502 return ParseFailed(message, *pos, "Invalid SDP line.", error); |
| 2457 } | 2503 } |
| 2458 } | 2504 } |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2598 } else if (HasAttribute(line, kAttributeXGoogleFlag)) { | 2644 } else if (HasAttribute(line, kAttributeXGoogleFlag)) { |
| 2599 // Experimental attribute. Conference mode activates more aggressive | 2645 // Experimental attribute. Conference mode activates more aggressive |
| 2600 // AEC and NS settings. | 2646 // AEC and NS settings. |
| 2601 // TODO: expose API to set these directly. | 2647 // TODO: expose API to set these directly. |
| 2602 std::string flag_value; | 2648 std::string flag_value; |
| 2603 if (!GetValue(line, kAttributeXGoogleFlag, &flag_value, error)) { | 2649 if (!GetValue(line, kAttributeXGoogleFlag, &flag_value, error)) { |
| 2604 return false; | 2650 return false; |
| 2605 } | 2651 } |
| 2606 if (flag_value.compare(kValueConference) == 0) | 2652 if (flag_value.compare(kValueConference) == 0) |
| 2607 media_desc->set_conference_mode(true); | 2653 media_desc->set_conference_mode(true); |
| 2654 } else if (HasAttribute(line, kAttributeMsid)) { | |
| 2655 if (!ParseMsidAttribute(line, &stream_id, &track_id, error)) { | |
| 2656 return false; | |
| 2657 } | |
| 2608 } | 2658 } |
| 2609 } else { | 2659 } else { |
| 2610 // Only parse lines that we are interested of. | 2660 // Only parse lines that we are interested of. |
| 2611 LOG(LS_INFO) << "Ignored line: " << line; | 2661 LOG(LS_INFO) << "Ignored line: " << line; |
| 2612 continue; | 2662 continue; |
| 2613 } | 2663 } |
| 2614 } | 2664 } |
| 2615 | 2665 |
| 2666 // Found an msid attribute. | |
| 2667 // Setting the stream_id/track_id will cause only one StreamParams | |
| 2668 // to be created in CreateTracksFromSsrcInfos, containing all the SSRCs from | |
| 2669 // the m= section. | |
| 2670 if (!stream_id.empty() && !track_id.empty()) { | |
| 2671 for (SsrcInfo& ssrc_info : ssrc_infos) { | |
| 2672 ssrc_info.stream_id = stream_id; | |
| 2673 ssrc_info.track_id = track_id; | |
| 2674 } | |
| 2675 } | |
| 2676 | |
| 2616 // Create tracks from the |ssrc_infos|. | 2677 // Create tracks from the |ssrc_infos|. |
| 2617 CreateTracksFromSsrcInfos(ssrc_infos, &tracks); | 2678 CreateTracksFromSsrcInfos(ssrc_infos, &tracks); |
| 2618 | 2679 |
| 2619 // Add the ssrc group to the track. | 2680 // Add the ssrc group to the track. |
| 2620 for (SsrcGroupVec::iterator ssrc_group = ssrc_groups.begin(); | 2681 for (SsrcGroupVec::iterator ssrc_group = ssrc_groups.begin(); |
| 2621 ssrc_group != ssrc_groups.end(); ++ssrc_group) { | 2682 ssrc_group != ssrc_groups.end(); ++ssrc_group) { |
| 2622 if (ssrc_group->ssrcs.empty()) { | 2683 if (ssrc_group->ssrcs.empty()) { |
| 2623 continue; | 2684 continue; |
| 2624 } | 2685 } |
| 2625 uint32_t ssrc = ssrc_group->ssrcs.front(); | 2686 uint32_t ssrc = ssrc_group->ssrcs.front(); |
| 2626 for (StreamParamsVec::iterator track = tracks.begin(); | 2687 for (StreamParamsVec::iterator track = tracks.begin(); |
| 2627 track != tracks.end(); ++track) { | 2688 track != tracks.end(); ++track) { |
| 2628 if (track->has_ssrc(ssrc)) { | 2689 if (track->has_ssrc(ssrc)) { |
| 2629 track->ssrc_groups.push_back(*ssrc_group); | 2690 track->ssrc_groups.push_back(*ssrc_group); |
| 2630 } | 2691 } |
| 2631 } | 2692 } |
| 2632 } | 2693 } |
| 2633 | 2694 |
| 2634 // Add the new tracks to the |media_desc|. | 2695 // Add the new tracks to the |media_desc|. |
| 2635 for (StreamParamsVec::iterator track = tracks.begin(); | 2696 for (StreamParams& track : tracks) { |
| 2636 track != tracks.end(); ++track) { | 2697 media_desc->AddStream(track); |
| 2637 media_desc->AddStream(*track); | |
| 2638 } | 2698 } |
| 2639 | 2699 |
| 2640 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | 2700 if (media_type == cricket::MEDIA_TYPE_AUDIO) { |
| 2641 AudioContentDescription* audio_desc = | 2701 AudioContentDescription* audio_desc = |
| 2642 static_cast<AudioContentDescription*>(media_desc); | 2702 static_cast<AudioContentDescription*>(media_desc); |
| 2643 UpdateFromWildcardCodecs(audio_desc); | 2703 UpdateFromWildcardCodecs(audio_desc); |
| 2644 | 2704 |
| 2645 // Verify audio codec ensures that no audio codec has been populated with | 2705 // Verify audio codec ensures that no audio codec has been populated with |
| 2646 // only fmtp. | 2706 // only fmtp. |
| 2647 if (!VerifyAudioCodecs(audio_desc)) { | 2707 if (!VerifyAudioCodecs(audio_desc)) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2732 } else if (attribute == kSsrcAttributeMsid) { | 2792 } else if (attribute == kSsrcAttributeMsid) { |
| 2733 // draft-alvestrand-mmusic-msid-00 | 2793 // draft-alvestrand-mmusic-msid-00 |
| 2734 // "msid:" identifier [ " " appdata ] | 2794 // "msid:" identifier [ " " appdata ] |
| 2735 std::vector<std::string> fields; | 2795 std::vector<std::string> fields; |
| 2736 rtc::split(value, kSdpDelimiterSpace, &fields); | 2796 rtc::split(value, kSdpDelimiterSpace, &fields); |
| 2737 if (fields.size() < 1 || fields.size() > 2) { | 2797 if (fields.size() < 1 || fields.size() > 2) { |
| 2738 return ParseFailed(line, | 2798 return ParseFailed(line, |
| 2739 "Expected format \"msid:<identifier>[ <appdata>]\".", | 2799 "Expected format \"msid:<identifier>[ <appdata>]\".", |
| 2740 error); | 2800 error); |
| 2741 } | 2801 } |
| 2742 ssrc_info->msid_identifier = fields[0]; | 2802 ssrc_info->stream_id = fields[0]; |
| 2743 if (fields.size() == 2) { | 2803 if (fields.size() == 2) { |
| 2744 ssrc_info->msid_appdata = fields[1]; | 2804 ssrc_info->track_id = fields[1]; |
| 2745 } | 2805 } |
| 2746 } else if (attribute == kSsrcAttributeMslabel) { | 2806 } else if (attribute == kSsrcAttributeMslabel) { |
| 2747 // draft-alvestrand-rtcweb-mid-01 | 2807 // draft-alvestrand-rtcweb-mid-01 |
| 2748 // mslabel:<value> | 2808 // mslabel:<value> |
| 2749 ssrc_info->mslabel = value; | 2809 ssrc_info->mslabel = value; |
| 2750 } else if (attribute == kSSrcAttributeLabel) { | 2810 } else if (attribute == kSSrcAttributeLabel) { |
| 2751 // The label isn't defined. | 2811 // The label isn't defined. |
| 2752 // label:<value> | 2812 // label:<value> |
| 2753 ssrc_info->label = value; | 2813 ssrc_info->label = value; |
| 2754 } | 2814 } |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3057 UpdateCodec<AudioContentDescription, cricket::AudioCodec>( | 3117 UpdateCodec<AudioContentDescription, cricket::AudioCodec>( |
| 3058 media_desc, payload_type, feedback_param); | 3118 media_desc, payload_type, feedback_param); |
| 3059 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { | 3119 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { |
| 3060 UpdateCodec<VideoContentDescription, cricket::VideoCodec>( | 3120 UpdateCodec<VideoContentDescription, cricket::VideoCodec>( |
| 3061 media_desc, payload_type, feedback_param); | 3121 media_desc, payload_type, feedback_param); |
| 3062 } | 3122 } |
| 3063 return true; | 3123 return true; |
| 3064 } | 3124 } |
| 3065 | 3125 |
| 3066 } // namespace webrtc | 3126 } // namespace webrtc |
| OLD | NEW |