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 |