Chromium Code Reviews| 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 |