OLD | NEW |
---|---|
1 /* | 1 /* |
2 * libjingle | 2 * libjingle |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 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, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
94 } | 94 } |
95 | 95 |
96 namespace webrtc { | 96 namespace webrtc { |
97 | 97 |
98 // Line type | 98 // Line type |
99 // RFC 4566 | 99 // RFC 4566 |
100 // An SDP session description consists of a number of lines of text of | 100 // An SDP session description consists of a number of lines of text of |
101 // the form: | 101 // the form: |
102 // <type>=<value> | 102 // <type>=<value> |
103 // where <type> MUST be exactly one case-significant character. | 103 // where <type> MUST be exactly one case-significant character. |
104 static const int kLinePrefixLength = 2; // Lenght of <type>= | 104 static const int kLinePrefixLength = 2; // Length of <type>= |
105 static const char kLineTypeVersion = 'v'; | 105 static const char kLineTypeVersion = 'v'; |
106 static const char kLineTypeOrigin = 'o'; | 106 static const char kLineTypeOrigin = 'o'; |
107 static const char kLineTypeSessionName = 's'; | 107 static const char kLineTypeSessionName = 's'; |
108 static const char kLineTypeSessionInfo = 'i'; | 108 static const char kLineTypeSessionInfo = 'i'; |
109 static const char kLineTypeSessionUri = 'u'; | 109 static const char kLineTypeSessionUri = 'u'; |
110 static const char kLineTypeSessionEmail = 'e'; | 110 static const char kLineTypeSessionEmail = 'e'; |
111 static const char kLineTypeSessionPhone = 'p'; | 111 static const char kLineTypeSessionPhone = 'p'; |
112 static const char kLineTypeSessionBandwidth = 'b'; | 112 static const char kLineTypeSessionBandwidth = 'b'; |
113 static const char kLineTypeTiming = 't'; | 113 static const char kLineTypeTiming = 't'; |
114 static const char kLineTypeRepeatTimes = 'r'; | 114 static const char kLineTypeRepeatTimes = 'r'; |
115 static const char kLineTypeTimeZone = 'z'; | 115 static const char kLineTypeTimeZone = 'z'; |
116 static const char kLineTypeEncryptionKey = 'k'; | 116 static const char kLineTypeEncryptionKey = 'k'; |
117 static const char kLineTypeMedia = 'm'; | 117 static const char kLineTypeMedia = 'm'; |
118 static const char kLineTypeConnection = 'c'; | 118 static const char kLineTypeConnection = 'c'; |
119 static const char kLineTypeAttributes = 'a'; | 119 static const char kLineTypeAttributes = 'a'; |
120 | 120 |
121 // Attributes | 121 // Attributes |
122 static const char kAttributeGroup[] = "group"; | 122 static const char kAttributeGroup[] = "group"; |
123 static const char kAttributeMid[] = "mid"; | 123 static const char kAttributeMid[] = "mid"; |
124 static const char kAttributeMsid[] = "msid"; | |
124 static const char kAttributeRtcpMux[] = "rtcp-mux"; | 125 static const char kAttributeRtcpMux[] = "rtcp-mux"; |
125 static const char kAttributeRtcpReducedSize[] = "rtcp-rsize"; | 126 static const char kAttributeRtcpReducedSize[] = "rtcp-rsize"; |
126 static const char kAttributeSsrc[] = "ssrc"; | 127 static const char kAttributeSsrc[] = "ssrc"; |
127 static const char kSsrcAttributeCname[] = "cname"; | 128 static const char kSsrcAttributeCname[] = "cname"; |
128 static const char kAttributeExtmap[] = "extmap"; | 129 static const char kAttributeExtmap[] = "extmap"; |
129 // draft-alvestrand-mmusic-msid-01 | 130 // draft-alvestrand-mmusic-msid-01 |
130 // a=msid-semantic: WMS | 131 // a=msid-semantic: WMS |
131 static const char kAttributeMsidSemantics[] = "msid-semantic"; | 132 static const char kAttributeMsidSemantics[] = "msid-semantic"; |
132 static const char kMediaStreamSemantic[] = "WMS"; | 133 static const char kMediaStreamSemantic[] = "WMS"; |
133 static const char kSsrcAttributeMsid[] = "msid"; | 134 static const char kSsrcAttributeMsid[] = "msid"; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 }; | 246 }; |
246 typedef std::vector<SsrcInfo> SsrcInfoVec; | 247 typedef std::vector<SsrcInfo> SsrcInfoVec; |
247 typedef std::vector<SsrcGroup> SsrcGroupVec; | 248 typedef std::vector<SsrcGroup> SsrcGroupVec; |
248 | 249 |
249 template <class T> | 250 template <class T> |
250 static void AddFmtpLine(const T& codec, std::string* message); | 251 static void AddFmtpLine(const T& codec, std::string* message); |
251 static void BuildMediaDescription(const ContentInfo* content_info, | 252 static void BuildMediaDescription(const ContentInfo* content_info, |
252 const TransportInfo* transport_info, | 253 const TransportInfo* transport_info, |
253 const MediaType media_type, | 254 const MediaType media_type, |
254 const std::vector<Candidate>& candidates, | 255 const std::vector<Candidate>& candidates, |
256 bool unified_plan_sdp, | |
255 std::string* message); | 257 std::string* message); |
256 static void BuildSctpContentAttributes(std::string* message, int sctp_port); | 258 static void BuildSctpContentAttributes(std::string* message, int sctp_port); |
257 static void BuildRtpContentAttributes( | 259 static void BuildRtpContentAttributes(const MediaContentDescription* media_desc, |
258 const MediaContentDescription* media_desc, | 260 const MediaType media_type, |
259 const MediaType media_type, | 261 bool unified_plan_sdp, |
260 std::string* message); | 262 std::string* message); |
261 static void BuildRtpMap(const MediaContentDescription* media_desc, | 263 static void BuildRtpMap(const MediaContentDescription* media_desc, |
262 const MediaType media_type, | 264 const MediaType media_type, |
263 std::string* message); | 265 std::string* message); |
264 static void BuildCandidate(const std::vector<Candidate>& candidates, | 266 static void BuildCandidate(const std::vector<Candidate>& candidates, |
265 bool include_ufrag, | 267 bool include_ufrag, |
266 std::string* message); | 268 std::string* message); |
267 static void BuildIceOptions(const std::vector<std::string>& transport_options, | 269 static void BuildIceOptions(const std::vector<std::string>& transport_options, |
268 std::string* message); | 270 std::string* message); |
269 static bool IsRtp(const std::string& protocol); | 271 static bool IsRtp(const std::string& protocol); |
270 static bool IsDtlsSctp(const std::string& protocol); | 272 static bool IsDtlsSctp(const std::string& protocol); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
327 SdpParseError* error); | 329 SdpParseError* error); |
328 static bool ParseExtmap(const std::string& line, | 330 static bool ParseExtmap(const std::string& line, |
329 RtpHeaderExtension* extmap, | 331 RtpHeaderExtension* extmap, |
330 SdpParseError* error); | 332 SdpParseError* error); |
331 static bool ParseFingerprintAttribute(const std::string& line, | 333 static bool ParseFingerprintAttribute(const std::string& line, |
332 rtc::SSLFingerprint** fingerprint, | 334 rtc::SSLFingerprint** fingerprint, |
333 SdpParseError* error); | 335 SdpParseError* error); |
334 static bool ParseDtlsSetup(const std::string& line, | 336 static bool ParseDtlsSetup(const std::string& line, |
335 cricket::ConnectionRole* role, | 337 cricket::ConnectionRole* role, |
336 SdpParseError* error); | 338 SdpParseError* error); |
339 static bool ParseMsidAttribute(const std::string& line, | |
340 std::string* stream_id, | |
341 std::string* track_id, | |
342 SdpParseError* error); | |
337 | 343 |
338 // Helper functions | 344 // Helper functions |
339 | 345 |
340 // Below ParseFailed*** functions output the line that caused the parsing | 346 // Below ParseFailed*** functions output the line that caused the parsing |
341 // failure and the detailed reason (|description|) of the failure to |error|. | 347 // failure and the detailed reason (|description|) of the failure to |error|. |
342 // The functions always return false so that they can be used directly in the | 348 // The functions always return false so that they can be used directly in the |
343 // following way when error happens: | 349 // following way when error happens: |
344 // "return ParseFailed***(...);" | 350 // "return ParseFailed***(...);" |
345 | 351 |
346 // The line starting at |line_start| of |message| is the failing line. | 352 // The line starting at |line_start| of |message| is the failing line. |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
785 if (!candidates) { | 791 if (!candidates) { |
786 return; | 792 return; |
787 } | 793 } |
788 const IceCandidateCollection* cc = desci.candidates(mline_index); | 794 const IceCandidateCollection* cc = desci.candidates(mline_index); |
789 for (size_t i = 0; i < cc->count(); ++i) { | 795 for (size_t i = 0; i < cc->count(); ++i) { |
790 const IceCandidateInterface* candidate = cc->at(i); | 796 const IceCandidateInterface* candidate = cc->at(i); |
791 candidates->push_back(candidate->candidate()); | 797 candidates->push_back(candidate->candidate()); |
792 } | 798 } |
793 } | 799 } |
794 | 800 |
795 std::string SdpSerialize(const JsepSessionDescription& jdesc) { | 801 std::string SdpSerialize(const JsepSessionDescription& jdesc, |
802 bool unified_plan_sdp) { | |
796 const cricket::SessionDescription* desc = jdesc.description(); | 803 const cricket::SessionDescription* desc = jdesc.description(); |
797 if (!desc) { | 804 if (!desc) { |
798 return ""; | 805 return ""; |
799 } | 806 } |
800 | 807 |
801 std::string message; | 808 std::string message; |
802 | 809 |
803 // Session Description. | 810 // Session Description. |
804 AddLine(kSessionVersion, &message); | 811 AddLine(kSessionVersion, &message); |
805 // Session Origin | 812 // Session Origin |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
856 AddLine(os.str(), &message); | 863 AddLine(os.str(), &message); |
857 | 864 |
858 // Preserve the order of the media contents. | 865 // Preserve the order of the media contents. |
859 int mline_index = -1; | 866 int mline_index = -1; |
860 for (cricket::ContentInfos::const_iterator it = desc->contents().begin(); | 867 for (cricket::ContentInfos::const_iterator it = desc->contents().begin(); |
861 it != desc->contents().end(); ++it) { | 868 it != desc->contents().end(); ++it) { |
862 const MediaContentDescription* mdesc = | 869 const MediaContentDescription* mdesc = |
863 static_cast<const MediaContentDescription*>(it->description); | 870 static_cast<const MediaContentDescription*>(it->description); |
864 std::vector<Candidate> candidates; | 871 std::vector<Candidate> candidates; |
865 GetCandidatesByMindex(jdesc, ++mline_index, &candidates); | 872 GetCandidatesByMindex(jdesc, ++mline_index, &candidates); |
866 BuildMediaDescription(&*it, | 873 BuildMediaDescription(&*it, desc->GetTransportInfoByName(it->name), |
867 desc->GetTransportInfoByName(it->name), | 874 mdesc->type(), candidates, unified_plan_sdp, |
868 mdesc->type(), | |
869 candidates, | |
870 &message); | 875 &message); |
871 } | 876 } |
872 return message; | 877 return message; |
873 } | 878 } |
874 | 879 |
875 // Serializes the passed in IceCandidateInterface to a SDP string. | 880 // Serializes the passed in IceCandidateInterface to a SDP string. |
876 // candidate - The candidate to be serialized. | 881 // candidate - The candidate to be serialized. |
877 std::string SdpSerializeCandidate( | 882 std::string SdpSerializeCandidate( |
878 const IceCandidateInterface& candidate) { | 883 const IceCandidateInterface& candidate) { |
879 std::string message; | 884 std::string message; |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1165 } | 1170 } |
1166 | 1171 |
1167 *extmap = RtpHeaderExtension(uri, value); | 1172 *extmap = RtpHeaderExtension(uri, value); |
1168 return true; | 1173 return true; |
1169 } | 1174 } |
1170 | 1175 |
1171 void BuildMediaDescription(const ContentInfo* content_info, | 1176 void BuildMediaDescription(const ContentInfo* content_info, |
1172 const TransportInfo* transport_info, | 1177 const TransportInfo* transport_info, |
1173 const MediaType media_type, | 1178 const MediaType media_type, |
1174 const std::vector<Candidate>& candidates, | 1179 const std::vector<Candidate>& candidates, |
1180 bool unified_plan_sdp, | |
1175 std::string* message) { | 1181 std::string* message) { |
1176 ASSERT(message != NULL); | 1182 ASSERT(message != NULL); |
1177 if (content_info == NULL || message == NULL) { | 1183 if (content_info == NULL || message == NULL) { |
1178 return; | 1184 return; |
1179 } | 1185 } |
1180 // TODO: Rethink if we should use sprintfn instead of stringstream. | 1186 // TODO: Rethink if we should use sprintfn instead of stringstream. |
1181 // According to the style guide, streams should only be used for logging. | 1187 // According to the style guide, streams should only be used for logging. |
1182 // http://google-styleguide.googlecode.com/svn/ | 1188 // http://google-styleguide.googlecode.com/svn/ |
1183 // trunk/cppguide.xml?showone=Streams#Streams | 1189 // trunk/cppguide.xml?showone=Streams#Streams |
1184 std::ostringstream os; | 1190 std::ostringstream os; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1340 // mid-attribute = "a=mid:" identification-tag | 1346 // mid-attribute = "a=mid:" identification-tag |
1341 // identification-tag = token | 1347 // identification-tag = token |
1342 // Use the content name as the mid identification-tag. | 1348 // Use the content name as the mid identification-tag. |
1343 InitAttrLine(kAttributeMid, &os); | 1349 InitAttrLine(kAttributeMid, &os); |
1344 os << kSdpDelimiterColon << content_info->name; | 1350 os << kSdpDelimiterColon << content_info->name; |
1345 AddLine(os.str(), message); | 1351 AddLine(os.str(), message); |
1346 | 1352 |
1347 if (IsDtlsSctp(media_desc->protocol())) { | 1353 if (IsDtlsSctp(media_desc->protocol())) { |
1348 BuildSctpContentAttributes(message, sctp_port); | 1354 BuildSctpContentAttributes(message, sctp_port); |
1349 } else if (IsRtp(media_desc->protocol())) { | 1355 } else if (IsRtp(media_desc->protocol())) { |
1350 BuildRtpContentAttributes(media_desc, media_type, message); | 1356 BuildRtpContentAttributes(media_desc, media_type, unified_plan_sdp, |
1357 message); | |
1351 } | 1358 } |
1352 } | 1359 } |
1353 | 1360 |
1354 void BuildSctpContentAttributes(std::string* message, int sctp_port) { | 1361 void BuildSctpContentAttributes(std::string* message, int sctp_port) { |
1355 // draft-ietf-mmusic-sctp-sdp-04 | 1362 // draft-ietf-mmusic-sctp-sdp-04 |
1356 // a=sctpmap:sctpmap-number protocol [streams] | 1363 // a=sctpmap:sctpmap-number protocol [streams] |
1357 // TODO(lally): switch this over to mmusic-sctp-sdp-12 (or later), with | 1364 // TODO(lally): switch this over to mmusic-sctp-sdp-12 (or later), with |
1358 // 'a=sctp-port:' | 1365 // 'a=sctp-port:' |
1359 std::ostringstream os; | 1366 std::ostringstream os; |
1360 InitAttrLine(kAttributeSctpmap, &os); | 1367 InitAttrLine(kAttributeSctpmap, &os); |
1361 os << kSdpDelimiterColon << sctp_port << kSdpDelimiterSpace | 1368 os << kSdpDelimiterColon << sctp_port << kSdpDelimiterSpace |
1362 << kDefaultSctpmapProtocol << kSdpDelimiterSpace | 1369 << kDefaultSctpmapProtocol << kSdpDelimiterSpace |
1363 << (cricket::kMaxSctpSid + 1); | 1370 << (cricket::kMaxSctpSid + 1); |
1364 AddLine(os.str(), message); | 1371 AddLine(os.str(), message); |
1365 } | 1372 } |
1366 | 1373 |
1367 void BuildRtpContentAttributes( | 1374 // If unified_plan_sdp is true, will use "a=msid". |
1368 const MediaContentDescription* media_desc, | 1375 void BuildRtpContentAttributes(const MediaContentDescription* media_desc, |
1369 const MediaType media_type, | 1376 const MediaType media_type, |
1370 std::string* message) { | 1377 bool unified_plan_sdp, |
1378 std::string* message) { | |
1371 std::ostringstream os; | 1379 std::ostringstream os; |
1372 // RFC 5285 | 1380 // RFC 5285 |
1373 // a=extmap:<value>["/"<direction>] <URI> <extensionattributes> | 1381 // a=extmap:<value>["/"<direction>] <URI> <extensionattributes> |
1374 // The definitions MUST be either all session level or all media level. This | 1382 // The definitions MUST be either all session level or all media level. This |
1375 // implementation uses all media level. | 1383 // implementation uses all media level. |
1376 for (size_t i = 0; i < media_desc->rtp_header_extensions().size(); ++i) { | 1384 for (size_t i = 0; i < media_desc->rtp_header_extensions().size(); ++i) { |
1377 InitAttrLine(kAttributeExtmap, &os); | 1385 InitAttrLine(kAttributeExtmap, &os); |
1378 os << kSdpDelimiterColon << media_desc->rtp_header_extensions()[i].id | 1386 os << kSdpDelimiterColon << media_desc->rtp_header_extensions()[i].id |
1379 << kSdpDelimiterSpace << media_desc->rtp_header_extensions()[i].uri; | 1387 << kSdpDelimiterSpace << media_desc->rtp_header_extensions()[i].uri; |
1380 AddLine(os.str(), message); | 1388 AddLine(os.str(), message); |
(...skipping 11 matching lines...) Expand all Loading... | |
1392 case cricket::MD_RECVONLY: | 1400 case cricket::MD_RECVONLY: |
1393 InitAttrLine(kAttributeRecvOnly, &os); | 1401 InitAttrLine(kAttributeRecvOnly, &os); |
1394 break; | 1402 break; |
1395 case cricket::MD_SENDRECV: | 1403 case cricket::MD_SENDRECV: |
1396 default: | 1404 default: |
1397 InitAttrLine(kAttributeSendRecv, &os); | 1405 InitAttrLine(kAttributeSendRecv, &os); |
1398 break; | 1406 break; |
1399 } | 1407 } |
1400 AddLine(os.str(), message); | 1408 AddLine(os.str(), message); |
1401 | 1409 |
1410 // draft-ietf-mmusic-msid-11 | |
1411 // a=msid:<stream id> <track id> | |
1412 if (unified_plan_sdp && !media_desc->streams().empty()) { | |
1413 if (media_desc->streams().size() > 1u) { | |
1414 LOG(LS_WARNING) << "Trying to serialize unified plan SDP with more than " | |
1415 << "one track in a media section. Omitting 'a=msid'."; | |
Taylor Brandstetter
2016/02/12 02:20:10
You may ask "why not throw an exception/return a w
pthatcher1
2016/02/12 03:54:35
Should we at least serialize the first media descr
Taylor Brandstetter
2016/02/12 20:44:57
We do.
| |
1416 } else { | |
1417 auto track = media_desc->streams().begin(); | |
1418 std::string appdata = track->id; | |
pthatcher1
2016/02/12 03:54:34
1. Why is this "appdata" instead of track_id?
2.
Taylor Brandstetter
2016/02/12 20:44:57
1. That's what the code below does for the SSRC li
| |
1419 std::ostringstream os; | |
1420 InitAttrLine(kAttributeMsid, &os); | |
1421 os << kSdpDelimiterColon << track->sync_label << kSdpDelimiterSpace | |
1422 << appdata; | |
1423 AddLine(os.str(), message); | |
1424 } | |
1425 } | |
1426 | |
1402 // RFC 5761 | 1427 // RFC 5761 |
1403 // a=rtcp-mux | 1428 // a=rtcp-mux |
1404 if (media_desc->rtcp_mux()) { | 1429 if (media_desc->rtcp_mux()) { |
1405 InitAttrLine(kAttributeRtcpMux, &os); | 1430 InitAttrLine(kAttributeRtcpMux, &os); |
1406 AddLine(os.str(), message); | 1431 AddLine(os.str(), message); |
1407 } | 1432 } |
1408 | 1433 |
1409 // RFC 5506 | 1434 // RFC 5506 |
1410 // a=rtcp-rsize | 1435 // a=rtcp-rsize |
1411 if (media_desc->rtcp_reduced_size()) { | 1436 if (media_desc->rtcp_reduced_size()) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1460 // Build the ssrc lines for each ssrc. | 1485 // Build the ssrc lines for each ssrc. |
1461 for (size_t i = 0; i < track->ssrcs.size(); ++i) { | 1486 for (size_t i = 0; i < track->ssrcs.size(); ++i) { |
1462 uint32_t ssrc = track->ssrcs[i]; | 1487 uint32_t ssrc = track->ssrcs[i]; |
1463 // RFC 5576 | 1488 // RFC 5576 |
1464 // a=ssrc:<ssrc-id> cname:<value> | 1489 // a=ssrc:<ssrc-id> cname:<value> |
1465 AddSsrcLine(ssrc, kSsrcAttributeCname, | 1490 AddSsrcLine(ssrc, kSsrcAttributeCname, |
1466 track->cname, message); | 1491 track->cname, message); |
1467 | 1492 |
1468 // draft-alvestrand-mmusic-msid-00 | 1493 // draft-alvestrand-mmusic-msid-00 |
1469 // a=ssrc:<ssrc-id> msid:identifier [appdata] | 1494 // a=ssrc:<ssrc-id> msid:identifier [appdata] |
1470 // The appdata consists of the "id" attribute of a MediaStreamTrack, which | 1495 // The appdata consists of the "id" attribute of a MediaStreamTrack, |
1471 // is corresponding to the "name" attribute of StreamParams. | 1496 // which corresponds to the "id" attribute of StreamParams. |
1472 std::string appdata = track->id; | 1497 std::string appdata = track->id; |
1473 std::ostringstream os; | 1498 std::ostringstream os; |
1474 InitAttrLine(kAttributeSsrc, &os); | 1499 InitAttrLine(kAttributeSsrc, &os); |
1475 os << kSdpDelimiterColon << ssrc << kSdpDelimiterSpace | 1500 os << kSdpDelimiterColon << ssrc << kSdpDelimiterSpace |
1476 << kSsrcAttributeMsid << kSdpDelimiterColon << track->sync_label | 1501 << kSsrcAttributeMsid << kSdpDelimiterColon << track->sync_label |
1477 << kSdpDelimiterSpace << appdata; | 1502 << kSdpDelimiterSpace << appdata; |
1478 AddLine(os.str(), message); | 1503 AddLine(os.str(), message); |
1479 | 1504 |
1480 // TODO(ronghuawu): Remove below code which is for backward compatibility. | 1505 // TODO(ronghuawu): Remove below code which is for backward |
1506 // compatibility. | |
1481 // draft-alvestrand-rtcweb-mid-01 | 1507 // draft-alvestrand-rtcweb-mid-01 |
1482 // a=ssrc:<ssrc-id> mslabel:<value> | 1508 // a=ssrc:<ssrc-id> mslabel:<value> |
1483 // The label isn't yet defined. | 1509 // The label isn't yet defined. |
1484 // a=ssrc:<ssrc-id> label:<value> | 1510 // a=ssrc:<ssrc-id> label:<value> |
1485 AddSsrcLine(ssrc, kSsrcAttributeMslabel, track->sync_label, message); | 1511 AddSsrcLine(ssrc, kSsrcAttributeMslabel, track->sync_label, message); |
1486 AddSsrcLine(ssrc, kSSrcAttributeLabel, track->id, message); | 1512 AddSsrcLine(ssrc, kSSrcAttributeLabel, track->id, message); |
1487 } | 1513 } |
1488 } | 1514 } |
1489 } | 1515 } |
1490 | 1516 |
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2032 if (fields.size() != expected_fields) { | 2058 if (fields.size() != expected_fields) { |
2033 return ParseFailedExpectFieldNum(line, expected_fields, error); | 2059 return ParseFailedExpectFieldNum(line, expected_fields, error); |
2034 } | 2060 } |
2035 std::string role_str = fields[1]; | 2061 std::string role_str = fields[1]; |
2036 if (!cricket::StringToConnectionRole(role_str, role)) { | 2062 if (!cricket::StringToConnectionRole(role_str, role)) { |
2037 return ParseFailed(line, "Invalid attribute value.", error); | 2063 return ParseFailed(line, "Invalid attribute value.", error); |
2038 } | 2064 } |
2039 return true; | 2065 return true; |
2040 } | 2066 } |
2041 | 2067 |
2068 static bool ParseMsidAttribute(const std::string& line, | |
2069 std::string* stream_id, | |
2070 std::string* track_id, | |
2071 SdpParseError* error) { | |
2072 // msid-value = msid-id [ SP msid-appdata ] | |
2073 // msid-id = 1*64token-char ; see RFC 4566 | |
2074 // msid-appdata = 1*64token-char ; see RFC 4566 | |
pthatcher1
2016/02/12 03:54:34
The parsing code and the serializing code don't se
Taylor Brandstetter
2016/02/12 20:44:56
Again, was just copying the way it was done elsewh
| |
2075 std::string field1; | |
2076 if (!rtc::tokenize_first(line.substr(kLinePrefixLength), kSdpDelimiterSpace, | |
2077 &field1, track_id)) { | |
2078 const size_t expected_fields = 2; | |
2079 return ParseFailedExpectFieldNum(line, expected_fields, error); | |
2080 } | |
2081 | |
2082 // msid:<msid-id> | |
2083 if (!GetValue(field1, kAttributeMsid, stream_id, error)) { | |
2084 return false; | |
2085 } | |
2086 return true; | |
2087 } | |
2088 | |
2042 // RFC 3551 | 2089 // RFC 3551 |
2043 // PT encoding media type clock rate channels | 2090 // PT encoding media type clock rate channels |
2044 // name (Hz) | 2091 // name (Hz) |
2045 // 0 PCMU A 8,000 1 | 2092 // 0 PCMU A 8,000 1 |
2046 // 1 reserved A | 2093 // 1 reserved A |
2047 // 2 reserved A | 2094 // 2 reserved A |
2048 // 3 GSM A 8,000 1 | 2095 // 3 GSM A 8,000 1 |
2049 // 4 G723 A 8,000 1 | 2096 // 4 G723 A 8,000 1 |
2050 // 5 DVI4 A 8,000 1 | 2097 // 5 DVI4 A 8,000 1 |
2051 // 6 DVI4 A 16,000 1 | 2098 // 6 DVI4 A 16,000 1 |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2456 // The candidates before update the media level "ice-pwd" and "ice-ufrag". | 2503 // The candidates before update the media level "ice-pwd" and "ice-ufrag". |
2457 Candidates candidates_orig; | 2504 Candidates candidates_orig; |
2458 std::string line; | 2505 std::string line; |
2459 std::string mline_id; | 2506 std::string mline_id; |
2460 // Tracks created out of the ssrc attributes. | 2507 // Tracks created out of the ssrc attributes. |
2461 StreamParamsVec tracks; | 2508 StreamParamsVec tracks; |
2462 SsrcInfoVec ssrc_infos; | 2509 SsrcInfoVec ssrc_infos; |
2463 SsrcGroupVec ssrc_groups; | 2510 SsrcGroupVec ssrc_groups; |
2464 std::string maxptime_as_string; | 2511 std::string maxptime_as_string; |
2465 std::string ptime_as_string; | 2512 std::string ptime_as_string; |
2513 std::string stream_id; | |
2514 std::string track_id; | |
2466 | 2515 |
2467 // Loop until the next m line | 2516 // Loop until the next m line |
2468 while (!IsLineType(message, kLineTypeMedia, *pos)) { | 2517 while (!IsLineType(message, kLineTypeMedia, *pos)) { |
2469 if (!GetLine(message, pos, &line)) { | 2518 if (!GetLine(message, pos, &line)) { |
2470 if (*pos >= message.size()) { | 2519 if (*pos >= message.size()) { |
2471 break; // Done parsing | 2520 break; // Done parsing |
2472 } else { | 2521 } else { |
2473 return ParseFailed(message, *pos, "Invalid SDP line.", error); | 2522 return ParseFailed(message, *pos, "Invalid SDP line.", error); |
2474 } | 2523 } |
2475 } | 2524 } |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2615 } else if (HasAttribute(line, kAttributeXGoogleFlag)) { | 2664 } else if (HasAttribute(line, kAttributeXGoogleFlag)) { |
2616 // Experimental attribute. Conference mode activates more aggressive | 2665 // Experimental attribute. Conference mode activates more aggressive |
2617 // AEC and NS settings. | 2666 // AEC and NS settings. |
2618 // TODO: expose API to set these directly. | 2667 // TODO: expose API to set these directly. |
2619 std::string flag_value; | 2668 std::string flag_value; |
2620 if (!GetValue(line, kAttributeXGoogleFlag, &flag_value, error)) { | 2669 if (!GetValue(line, kAttributeXGoogleFlag, &flag_value, error)) { |
2621 return false; | 2670 return false; |
2622 } | 2671 } |
2623 if (flag_value.compare(kValueConference) == 0) | 2672 if (flag_value.compare(kValueConference) == 0) |
2624 media_desc->set_conference_mode(true); | 2673 media_desc->set_conference_mode(true); |
2674 } else if (HasAttribute(line, kAttributeMsid)) { | |
2675 if (!ParseMsidAttribute(line, &stream_id, &track_id, error)) { | |
2676 return false; | |
2677 } | |
2625 } | 2678 } |
2626 } else { | 2679 } else { |
2627 // Only parse lines that we are interested of. | 2680 // Only parse lines that we are interested of. |
2628 LOG(LS_INFO) << "Ignored line: " << line; | 2681 LOG(LS_INFO) << "Ignored line: " << line; |
2629 continue; | 2682 continue; |
2630 } | 2683 } |
2631 } | 2684 } |
2632 | 2685 |
2686 // Found an msid attribute. | |
2687 // Setting the msid_identifier/msid_appdata will cause only one StreamParams | |
2688 // to be created, containing all the SSRCs from the m= section. | |
2689 if (!stream_id.empty() && !track_id.empty()) { | |
2690 for (SsrcInfo& ssrc_info : ssrc_infos) { | |
2691 ssrc_info.msid_identifier = stream_id; | |
2692 ssrc_info.msid_appdata = track_id; | |
pthatcher1
2016/02/12 03:54:34
Can we rename ssrc_info.msid_identifier and .msid_
Taylor Brandstetter
2016/02/12 20:44:56
Done.
| |
2693 } | |
pthatcher1
2016/02/12 03:54:35
Do we need to merge all of the ssrc_infos into one
Taylor Brandstetter
2016/02/12 20:44:56
Yes, CreateTracksFromSsrcInfos does that. I meant
| |
2694 } | |
2695 | |
2633 // Create tracks from the |ssrc_infos|. | 2696 // Create tracks from the |ssrc_infos|. |
2634 CreateTracksFromSsrcInfos(ssrc_infos, &tracks); | 2697 CreateTracksFromSsrcInfos(ssrc_infos, &tracks); |
2635 | 2698 |
2636 // Add the ssrc group to the track. | 2699 // Add the ssrc group to the track. |
2637 for (SsrcGroupVec::iterator ssrc_group = ssrc_groups.begin(); | 2700 for (SsrcGroupVec::iterator ssrc_group = ssrc_groups.begin(); |
2638 ssrc_group != ssrc_groups.end(); ++ssrc_group) { | 2701 ssrc_group != ssrc_groups.end(); ++ssrc_group) { |
2639 if (ssrc_group->ssrcs.empty()) { | 2702 if (ssrc_group->ssrcs.empty()) { |
2640 continue; | 2703 continue; |
2641 } | 2704 } |
2642 uint32_t ssrc = ssrc_group->ssrcs.front(); | 2705 uint32_t ssrc = ssrc_group->ssrcs.front(); |
2643 for (StreamParamsVec::iterator track = tracks.begin(); | 2706 for (StreamParamsVec::iterator track = tracks.begin(); |
2644 track != tracks.end(); ++track) { | 2707 track != tracks.end(); ++track) { |
2645 if (track->has_ssrc(ssrc)) { | 2708 if (track->has_ssrc(ssrc)) { |
2646 track->ssrc_groups.push_back(*ssrc_group); | 2709 track->ssrc_groups.push_back(*ssrc_group); |
2647 } | 2710 } |
2648 } | 2711 } |
2649 } | 2712 } |
2650 | 2713 |
2651 // Add the new tracks to the |media_desc|. | 2714 // Add the new tracks to the |media_desc|. |
2652 for (StreamParamsVec::iterator track = tracks.begin(); | 2715 for (StreamParams& track : tracks) { |
2653 track != tracks.end(); ++track) { | 2716 media_desc->AddStream(track); |
2654 media_desc->AddStream(*track); | |
2655 } | 2717 } |
2656 | 2718 |
2657 if (media_type == cricket::MEDIA_TYPE_AUDIO) { | 2719 if (media_type == cricket::MEDIA_TYPE_AUDIO) { |
2658 AudioContentDescription* audio_desc = | 2720 AudioContentDescription* audio_desc = |
2659 static_cast<AudioContentDescription*>(media_desc); | 2721 static_cast<AudioContentDescription*>(media_desc); |
2660 UpdateFromWildcardCodecs(audio_desc); | 2722 UpdateFromWildcardCodecs(audio_desc); |
2661 | 2723 |
2662 // Verify audio codec ensures that no audio codec has been populated with | 2724 // Verify audio codec ensures that no audio codec has been populated with |
2663 // only fmtp. | 2725 // only fmtp. |
2664 if (!VerifyAudioCodecs(audio_desc)) { | 2726 if (!VerifyAudioCodecs(audio_desc)) { |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3074 UpdateCodec<AudioContentDescription, cricket::AudioCodec>( | 3136 UpdateCodec<AudioContentDescription, cricket::AudioCodec>( |
3075 media_desc, payload_type, feedback_param); | 3137 media_desc, payload_type, feedback_param); |
3076 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { | 3138 } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { |
3077 UpdateCodec<VideoContentDescription, cricket::VideoCodec>( | 3139 UpdateCodec<VideoContentDescription, cricket::VideoCodec>( |
3078 media_desc, payload_type, feedback_param); | 3140 media_desc, payload_type, feedback_param); |
3079 } | 3141 } |
3080 return true; | 3142 return true; |
3081 } | 3143 } |
3082 | 3144 |
3083 } // namespace webrtc | 3145 } // namespace webrtc |
OLD | NEW |