From ec9e4923dbc422c7d8a448e64d72518d0d457c10 Mon Sep 17 00:00:00 2001 From: Jonas Olsson Date: Wed, 5 Sep 2018 09:53:49 +0200 Subject: [PATCH] Remove stringstreams from sdp parsing. Bug: webrtc:8982 Change-Id: Id5e8aa22794206864c8ce4b1ba155e49606a1b2d Reviewed-on: https://webrtc-review.googlesource.com/97360 Commit-Queue: Jonas Olsson Reviewed-by: Steve Anton Cr-Commit-Position: refs/heads/master@{#24564} --- pc/webrtcsdp.cc | 167 ++++++++++++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 78 deletions(-) diff --git a/pc/webrtcsdp.cc b/pc/webrtcsdp.cc index 73df354dd5..a7afdb0bbb 100644 --- a/pc/webrtcsdp.cc +++ b/pc/webrtcsdp.cc @@ -40,6 +40,7 @@ #include "rtc_base/checks.h" #include "rtc_base/logging.h" #include "rtc_base/messagedigest.h" +#include "rtc_base/strings/string_builder.h" #include "rtc_base/stringutils.h" using cricket::AudioContentDescription; @@ -170,13 +171,21 @@ static const char kCandidatePrflx[] = "prflx"; static const char kCandidateRelay[] = "relay"; static const char kTcpCandidateType[] = "tcptype"; -static const char kSdpDelimiterEqual = '='; -static const char kSdpDelimiterSpace = ' '; -static const char kSdpDelimiterColon = ':'; -static const char kSdpDelimiterSemicolon = ';'; -static const char kSdpDelimiterSlash = '/'; -static const char kNewLine = '\n'; -static const char kReturn = '\r'; +// rtc::StringBuilder doesn't have a << overload for chars, while rtc::split and +// rtc::tokenize_first both take a char delimiter. To handle both cases these +// constants come in pairs of a chars and length-one strings. +static const char kSdpDelimiterEqual[] = "="; +static const char kSdpDelimiterEqualChar = '='; +static const char kSdpDelimiterSpace[] = " "; +static const char kSdpDelimiterSpaceChar = ' '; +static const char kSdpDelimiterColon[] = ":"; +static const char kSdpDelimiterColonChar = ':'; +static const char kSdpDelimiterSemicolon[] = ";"; +static const char kSdpDelimiterSemicolonChar = ';'; +static const char kSdpDelimiterSlashChar = '/'; +static const char kNewLine[] = "\n"; +static const char kNewLineChar = '\n'; +static const char kReturnChar = '\r'; static const char kLineBreak[] = "\r\n"; // TODO(deadbeef): Generate the Session and Time description @@ -355,7 +364,7 @@ static bool ParseFailed(const std::string& message, std::string first_line; size_t line_end = message.find(kNewLine, line_start); if (line_end != std::string::npos) { - if (line_end > 0 && (message.at(line_end - 1) == kReturn)) { + if (line_end > 0 && (message.at(line_end - 1) == kReturnChar)) { --line_end; } first_line = message.substr(line_start, (line_end - line_start)); @@ -391,7 +400,7 @@ static bool ParseFailed(const std::string& description, SdpParseError* error) { static bool ParseFailedExpectFieldNum(const std::string& line, int expected_fields, SdpParseError* error) { - std::ostringstream description; + rtc::StringBuilder description; description << "Expects " << expected_fields << " fields."; return ParseFailed(line, description.str(), error); } @@ -401,7 +410,7 @@ static bool ParseFailedExpectFieldNum(const std::string& line, static bool ParseFailedExpectMinFieldNum(const std::string& line, int expected_min_fields, SdpParseError* error) { - std::ostringstream description; + rtc::StringBuilder description; description << "Expects at least " << expected_min_fields << " fields."; return ParseFailed(line, description.str(), error); } @@ -411,7 +420,7 @@ static bool ParseFailedExpectMinFieldNum(const std::string& line, static bool ParseFailedGetValue(const std::string& line, const std::string& attribute, SdpParseError* error) { - std::ostringstream description; + rtc::StringBuilder description; description << "Failed to get the value of attribute: " << attribute; return ParseFailed(line, description.str(), error); } @@ -425,8 +434,9 @@ static bool ParseFailedExpectLine(const std::string& message, const char line_type, const std::string& line_value, SdpParseError* error) { - std::ostringstream description; - description << "Expect line: " << line_type << "=" << line_value; + rtc::StringBuilder description; + description << "Expect line: " << std::string(1, line_type) << "=" + << line_value; return ParseFailed(message, line_start, description.str(), error); } @@ -449,7 +459,7 @@ static bool GetLine(const std::string& message, } // Update the new start position *pos = line_end + 1; - if (line_end > 0 && (message.at(line_end - 1) == kReturn)) { + if (line_end > 0 && (message.at(line_end - 1) == kReturnChar)) { --line_end; } *line = message.substr(line_begin, (line_end - line_begin)); @@ -468,8 +478,9 @@ static bool GetLine(const std::string& message, // If a session has no meaningful name, the value "s= " SHOULD be used // (i.e., a single space as the session name). if (line->length() < 3 || !islower(cline[0]) || - cline[1] != kSdpDelimiterEqual || - (cline[0] != kLineTypeSessionName && cline[2] == kSdpDelimiterSpace)) { + cline[1] != kSdpDelimiterEqualChar || + (cline[0] != kLineTypeSessionName && + cline[2] == kSdpDelimiterSpaceChar)) { *pos = line_begin; return false; } @@ -479,13 +490,13 @@ static bool GetLine(const std::string& message, // Init |os| to "|type|=|value|". static void InitLine(const char type, const std::string& value, - std::ostringstream* os) { - os->str(""); - *os << type << kSdpDelimiterEqual << value; + rtc::StringBuilder* os) { + os->Clear(); + *os << std::string(1, type) << kSdpDelimiterEqual << value; } // Init |os| to "a=|attribute|". -static void InitAttrLine(const std::string& attribute, std::ostringstream* os) { +static void InitAttrLine(const std::string& attribute, rtc::StringBuilder* os) { InitLine(kLineTypeAttributes, attribute, os); } @@ -493,7 +504,7 @@ static void InitAttrLine(const std::string& attribute, std::ostringstream* os) { static void AddAttributeLine(const std::string& attribute, int value, std::string* message) { - std::ostringstream os; + rtc::StringBuilder os; InitAttrLine(attribute, &os); os << kSdpDelimiterColon << value; AddLine(os.str(), message); @@ -507,7 +518,7 @@ static bool IsLineType(const std::string& message, } const char* cmessage = message.c_str(); return (cmessage[line_start] == type && - cmessage[line_start + 1] == kSdpDelimiterEqual); + cmessage[line_start + 1] == kSdpDelimiterEqualChar); } static bool IsLineType(const std::string& line, const char type) { @@ -539,7 +550,7 @@ static bool AddSsrcLine(uint32_t ssrc_id, std::string* message) { // RFC 5576 // a=ssrc: : - std::ostringstream os; + rtc::StringBuilder os; InitAttrLine(kAttributeSsrc, &os); os << kSdpDelimiterColon << ssrc_id << kSdpDelimiterSpace << attribute << kSdpDelimiterColon << value; @@ -552,7 +563,7 @@ static bool GetValue(const std::string& message, std::string* value, SdpParseError* error) { std::string leftpart; - if (!rtc::tokenize_first(message, kSdpDelimiterColon, &leftpart, value)) { + if (!rtc::tokenize_first(message, kSdpDelimiterColonChar, &leftpart, value)) { return ParseFailedGetValue(message, attribute, error); } // The left part should end with the expected attribute. @@ -576,7 +587,7 @@ static bool GetValueFromString(const std::string& line, T* t, SdpParseError* error) { if (!rtc::FromString(s, t)) { - std::ostringstream description; + rtc::StringBuilder description; description << "Invalid value: " << s << "."; return ParseFailed(line, description.str(), error); } @@ -764,7 +775,7 @@ static std::string GetRtcpLine(const std::vector& candidates) { // RFC 3605 // rtcp-attribute = "a=rtcp:" port [nettype space addrtype space // connection-address] CRLF - std::ostringstream os; + rtc::StringBuilder os; InitAttrLine(kAttributeRtcp, &os); os << kSdpDelimiterColon << rtcp_port << " " << kConnectionNettype << " " << addr_type << " " << rtcp_ip; @@ -804,7 +815,7 @@ std::string SdpSerialize(const JsepSessionDescription& jdesc) { // RFC 4566 // o= // - std::ostringstream os; + rtc::StringBuilder os; InitLine(kLineTypeOrigin, kSessionOriginUsername, &os); const std::string& session_id = jdesc.session_id().empty() ? kSessionOriginSessionId : jdesc.session_id(); @@ -981,7 +992,7 @@ bool ParseCandidate(const std::string& message, // Makes sure |message| contains only one line. if (message.size() > first_line.size()) { std::string left, right; - if (rtc::tokenize_first(message, kNewLine, &left, &right) && + if (rtc::tokenize_first(message, kNewLineChar, &left, &right) && !right.empty()) { return ParseFailed(message, 0, "Expect one line only", error); } @@ -999,11 +1010,11 @@ bool ParseCandidate(const std::string& message, std::string candidate_value; // |first_line| must be in the form of "candidate:". - if (!rtc::tokenize_first(first_line, kSdpDelimiterColon, &attribute_candidate, - &candidate_value) || + if (!rtc::tokenize_first(first_line, kSdpDelimiterColonChar, + &attribute_candidate, &candidate_value) || attribute_candidate != kAttributeCandidate) { if (is_raw) { - std::ostringstream description; + rtc::StringBuilder description; description << "Expect line: " << kAttributeCandidate << ":" << ""; return ParseFailed(first_line, 0, description.str(), error); @@ -1014,7 +1025,7 @@ bool ParseCandidate(const std::string& message, } std::vector fields; - rtc::split(candidate_value, kSdpDelimiterSpace, &fields); + rtc::split(candidate_value, kSdpDelimiterSpaceChar, &fields); // RFC 5245 // a=candidate: @@ -1168,7 +1179,7 @@ bool ParseIceOptions(const std::string& line, return false; } std::vector fields; - rtc::split(ice_options, kSdpDelimiterSpace, &fields); + rtc::split(ice_options, kSdpDelimiterSpaceChar, &fields); for (size_t i = 0; i < fields.size(); ++i) { transport_options->push_back(fields[i]); } @@ -1182,10 +1193,10 @@ bool ParseSctpPort(const std::string& line, // a=sctp-port std::vector fields; const size_t expected_min_fields = 2; - rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterColon, &fields); + rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterColonChar, &fields); if (fields.size() < expected_min_fields) { fields.resize(0); - rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpace, &fields); + rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpaceChar, &fields); } if (fields.size() < expected_min_fields) { return ParseFailedExpectMinFieldNum(line, expected_min_fields, error); @@ -1202,7 +1213,7 @@ bool ParseExtmap(const std::string& line, // RFC 5285 // a=extmap:["/"] std::vector fields; - rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpace, &fields); + rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpaceChar, &fields); const size_t expected_min_fields = 2; if (fields.size() < expected_min_fields) { return ParseFailedExpectMinFieldNum(line, expected_min_fields, error); @@ -1214,7 +1225,7 @@ bool ParseExtmap(const std::string& line, return false; } std::vector sub_fields; - rtc::split(value_direction, kSdpDelimiterSlash, &sub_fields); + rtc::split(value_direction, kSdpDelimiterSlashChar, &sub_fields); int value = 0; if (!GetValueFromString(line, sub_fields[0], &value, error)) { return false; @@ -1252,11 +1263,7 @@ void BuildMediaDescription(const ContentInfo* content_info, if (content_info == NULL || message == NULL) { return; } - // TODO(deadbeef): Rethink if we should use sprintfn instead of stringstream. - // According to the style guide, streams should only be used for logging. - // http://google-styleguide.googlecode.com/svn/ - // trunk/cppguide.xml?showone=Streams#Streams - std::ostringstream os; + rtc::StringBuilder os; const MediaContentDescription* media_desc = content_info->media_description(); RTC_DCHECK(media_desc); @@ -1459,7 +1466,7 @@ void BuildMediaDescription(const ContentInfo* content_info, void BuildSctpContentAttributes(std::string* message, int sctp_port, bool use_sctpmap) { - std::ostringstream os; + rtc::StringBuilder os; if (use_sctpmap) { // draft-ietf-mmusic-sctp-sdp-04 // a=sctpmap:sctpmap-number protocol [streams] @@ -1481,7 +1488,7 @@ void BuildRtpContentAttributes(const MediaContentDescription* media_desc, const cricket::MediaType media_type, int msid_signaling, std::string* message) { - std::ostringstream os; + rtc::StringBuilder os; // RFC 5285 // a=extmap:["/"] // The definitions MUST be either all session level or all media level. This @@ -1635,7 +1642,7 @@ void BuildRtpContentAttributes(const MediaContentDescription* media_desc, } } -void WriteFmtpHeader(int payload_type, std::ostringstream* os) { +void WriteFmtpHeader(int payload_type, rtc::StringBuilder* os) { // fmtp header: a=fmtp:|payload_type| // Add a=fmtp InitAttrLine(kAttributeFmtp, os); @@ -1643,7 +1650,7 @@ void WriteFmtpHeader(int payload_type, std::ostringstream* os) { *os << kSdpDelimiterColon << payload_type; } -void WriteRtcpFbHeader(int payload_type, std::ostringstream* os) { +void WriteRtcpFbHeader(int payload_type, rtc::StringBuilder* os) { // rtcp-fb header: a=rtcp-fb:|payload_type| // /> // Add a=rtcp-fb @@ -1659,13 +1666,13 @@ void WriteRtcpFbHeader(int payload_type, std::ostringstream* os) { void WriteFmtpParameter(const std::string& parameter_name, const std::string& parameter_value, - std::ostringstream* os) { + rtc::StringBuilder* os) { // fmtp parameters: |parameter_name|=|parameter_value| *os << parameter_name << kSdpDelimiterEqual << parameter_value; } void WriteFmtpParameters(const cricket::CodecParameterMap& parameters, - std::ostringstream* os) { + rtc::StringBuilder* os) { for (cricket::CodecParameterMap::const_iterator fmtp = parameters.begin(); fmtp != parameters.end(); ++fmtp) { // Parameters are a semicolon-separated list, no spaces. @@ -1707,7 +1714,7 @@ void AddFmtpLine(const T& codec, std::string* message) { // No need to add an fmtp if it will have no (optional) parameters. return; } - std::ostringstream os; + rtc::StringBuilder os; WriteFmtpHeader(codec.id, &os); WriteFmtpParameters(fmtp_parameters, &os); AddLine(os.str(), message); @@ -1719,7 +1726,7 @@ void AddRtcpFbLines(const T& codec, std::string* message) { for (std::vector::const_iterator iter = codec.feedback_params.params().begin(); iter != codec.feedback_params.params().end(); ++iter) { - std::ostringstream os; + rtc::StringBuilder os; WriteRtcpFbHeader(codec.id, &os); os << " " << iter->id(); if (!iter->param().empty()) { @@ -1772,7 +1779,7 @@ void BuildRtpMap(const MediaContentDescription* media_desc, std::string* message) { RTC_DCHECK(message != NULL); RTC_DCHECK(media_desc != NULL); - std::ostringstream os; + rtc::StringBuilder os; if (media_type == cricket::MEDIA_TYPE_VIDEO) { const VideoContentDescription* video_desc = media_desc->as_video(); for (std::vector::const_iterator it = @@ -1858,7 +1865,7 @@ void BuildRtpMap(const MediaContentDescription* media_desc, void BuildCandidate(const std::vector& candidates, bool include_ufrag, std::string* message) { - std::ostringstream os; + rtc::StringBuilder os; for (std::vector::const_iterator it = candidates.begin(); it != candidates.end(); ++it) { @@ -1923,7 +1930,7 @@ void BuildCandidate(const std::vector& candidates, void BuildIceOptions(const std::vector& transport_options, std::string* message) { if (!transport_options.empty()) { - std::ostringstream os; + rtc::StringBuilder os; InitAttrLine(kAttributeIceOption, &os); os << kSdpDelimiterColon << transport_options[0]; for (size_t i = 1; i < transport_options.size(); ++i) { @@ -1952,12 +1959,13 @@ bool ParseConnectionData(const std::string& line, // RFC 4566 // c= // Skip the "c=" - if (!rtc::tokenize_first(line, kSdpDelimiterEqual, &token, &rightpart)) { + if (!rtc::tokenize_first(line, kSdpDelimiterEqualChar, &token, &rightpart)) { return ParseFailed(line, "Failed to parse the network type.", error); } // Extract and verify the - if (!rtc::tokenize_first(rightpart, kSdpDelimiterSpace, &token, &rightpart) || + if (!rtc::tokenize_first(rightpart, kSdpDelimiterSpaceChar, &token, + &rightpart) || token != kConnectionNettype) { return ParseFailed(line, "Failed to parse the connection data. The network type " @@ -1966,7 +1974,8 @@ bool ParseConnectionData(const std::string& line, } // Extract the "" and "". - if (!rtc::tokenize_first(rightpart, kSdpDelimiterSpace, &token, &rightpart)) { + if (!rtc::tokenize_first(rightpart, kSdpDelimiterSpaceChar, &token, + &rightpart)) { return ParseFailed(line, "Failed to parse the address type.", error); } @@ -2019,7 +2028,7 @@ bool ParseSessionDescription(const std::string& message, error); } std::vector fields; - rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpace, &fields); + rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpaceChar, &fields); const size_t expected_fields = 6; if (fields.size() != expected_fields) { return ParseFailedExpectFieldNum(line, expected_fields, error); @@ -2161,7 +2170,7 @@ bool ParseGroupAttribute(const std::string& line, // RFC 5888 and draft-holmberg-mmusic-sdp-bundle-negotiation-00 // a=group:BUNDLE video voice std::vector fields; - rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpace, &fields); + rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpaceChar, &fields); std::string semantics; if (!GetValue(fields[0], kAttributeGroup, &semantics, error)) { return false; @@ -2184,7 +2193,7 @@ static bool ParseFingerprintAttribute(const std::string& line, } std::vector fields; - rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpace, &fields); + rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpaceChar, &fields); const size_t expected_fields = 2; if (fields.size() != expected_fields) { return ParseFailedExpectFieldNum(line, expected_fields, error); @@ -2217,7 +2226,7 @@ static bool ParseDtlsSetup(const std::string& line, // setup-attr = "a=setup:" role // role = "active" / "passive" / "actpass" / "holdconn" std::vector fields; - rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterColon, &fields); + rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterColonChar, &fields); const size_t expected_fields = 2; if (fields.size() != expected_fields) { return ParseFailedExpectFieldNum(line, expected_fields, error); @@ -2241,8 +2250,8 @@ static bool ParseMsidAttribute(const std::string& line, std::string field1; std::string new_stream_id; std::string new_track_id; - if (!rtc::tokenize_first(line.substr(kLinePrefixLength), kSdpDelimiterSpace, - &field1, &new_track_id)) { + if (!rtc::tokenize_first(line.substr(kLinePrefixLength), + kSdpDelimiterSpaceChar, &field1, &new_track_id)) { const size_t expected_fields = 2; return ParseFailedExpectFieldNum(line, expected_fields, error); } @@ -2402,7 +2411,7 @@ bool ParseMediaDescription(const std::string& message, ++mline_index; std::vector fields; - rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpace, &fields); + rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpaceChar, &fields); const size_t expected_min_fields = 4; if (fields.size() < expected_min_fields) { @@ -2541,7 +2550,7 @@ bool ParseMediaDescription(const std::string& message, TransportInfo transport_info(content_name, transport); if (!desc->AddTransportInfo(transport_info)) { - std::ostringstream description; + rtc::StringBuilder description; description << "Failed to AddTransportInfo with content name: " << content_name; return ParseFailed("", description.str(), error); @@ -2787,7 +2796,7 @@ bool ParseContent(const std::string& message, // See: https://code.google.com/p/chromium/issues/detail?id=280726 if (media_type == cricket::MEDIA_TYPE_DATA && IsRtp(protocol) && b > cricket::kDataMaxBandwidth / 1000) { - std::ostringstream description; + rtc::StringBuilder description; description << "RTP-based data channels may not send more than " << cricket::kDataMaxBandwidth / 1000 << "kbps."; return ParseFailed(line, description.str(), error); @@ -3036,8 +3045,8 @@ bool ParseSsrcAttribute(const std::string& line, // a=ssrc: // a=ssrc: : std::string field1, field2; - if (!rtc::tokenize_first(line.substr(kLinePrefixLength), kSdpDelimiterSpace, - &field1, &field2)) { + if (!rtc::tokenize_first(line.substr(kLinePrefixLength), + kSdpDelimiterSpaceChar, &field1, &field2)) { const size_t expected_fields = 2; return ParseFailedExpectFieldNum(line, expected_fields, error); } @@ -3054,8 +3063,9 @@ bool ParseSsrcAttribute(const std::string& line, std::string attribute; std::string value; - if (!rtc::tokenize_first(field2, kSdpDelimiterColon, &attribute, &value)) { - std::ostringstream description; + if (!rtc::tokenize_first(field2, kSdpDelimiterColonChar, &attribute, + &value)) { + rtc::StringBuilder description; description << "Failed to get the ssrc attribute value from " << field2 << ". Expected format :."; return ParseFailed(line, description.str(), error); @@ -3085,7 +3095,7 @@ bool ParseSsrcAttribute(const std::string& line, // draft-alvestrand-mmusic-msid-00 // msid:identifier [appdata] std::vector fields; - rtc::split(value, kSdpDelimiterSpace, &fields); + rtc::split(value, kSdpDelimiterSpaceChar, &fields); if (fields.size() < 1 || fields.size() > 2) { return ParseFailed( line, "Expected format \"msid:[ ]\".", error); @@ -3114,7 +3124,7 @@ bool ParseSsrcGroupAttribute(const std::string& line, // RFC 5576 // a=ssrc-group: ... std::vector fields; - rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpace, &fields); + rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpaceChar, &fields); const size_t expected_min_fields = 2; if (fields.size() < expected_min_fields) { return ParseFailedExpectMinFieldNum(line, expected_min_fields, error); @@ -3139,7 +3149,7 @@ bool ParseCryptoAttribute(const std::string& line, MediaContentDescription* media_desc, SdpParseError* error) { std::vector fields; - rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpace, &fields); + rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpaceChar, &fields); // RFC 4568 // a=crypto: [] const size_t expected_min_fields = 3; @@ -3205,7 +3215,7 @@ bool ParseRtpmapAttribute(const std::string& line, MediaContentDescription* media_desc, SdpParseError* error) { std::vector fields; - rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpace, &fields); + rtc::split(line.substr(kLinePrefixLength), kSdpDelimiterSpaceChar, &fields); // RFC 4566 // a=rtpmap: /[/] const size_t expected_min_fields = 2; @@ -3274,7 +3284,7 @@ bool ParseFmtpParam(const std::string& line, std::string* parameter, std::string* value, SdpParseError* error) { - if (!rtc::tokenize_first(line, kSdpDelimiterEqual, parameter, value)) { + if (!rtc::tokenize_first(line, kSdpDelimiterEqualChar, parameter, value)) { ParseFailed(line, "Unable to parse fmtp parameter. \'=\' missing.", error); return false; } @@ -3298,8 +3308,9 @@ bool ParseFmtpAttributes(const std::string& line, // a=fmtp: // At least two fields, whereas the second one is any of the optional // parameters. - if (!rtc::tokenize_first(line.substr(kLinePrefixLength), kSdpDelimiterSpace, - &line_payload, &line_params)) { + if (!rtc::tokenize_first(line.substr(kLinePrefixLength), + kSdpDelimiterSpaceChar, &line_payload, + &line_params)) { ParseFailedExpectMinFieldNum(line, 2, error); return false; } @@ -3318,7 +3329,7 @@ bool ParseFmtpAttributes(const std::string& line, // Parse out format specific parameters. std::vector fields; - rtc::split(line_params, kSdpDelimiterSemicolon, &fields); + rtc::split(line_params, kSdpDelimiterSemicolonChar, &fields); cricket::CodecParameterMap codec_params; for (auto& iter : fields) { @@ -3355,7 +3366,7 @@ bool ParseRtcpFbAttribute(const std::string& line, return true; } std::vector rtcp_fb_fields; - rtc::split(line.c_str(), kSdpDelimiterSpace, &rtcp_fb_fields); + rtc::split(line.c_str(), kSdpDelimiterSpaceChar, &rtcp_fb_fields); if (rtcp_fb_fields.size() < 2) { return ParseFailedGetValue(line, kAttributeRtcpFb, error); }