Chromium Code Reviews| Index: talk/app/webrtc/webrtcsdp.cc |
| diff --git a/talk/app/webrtc/webrtcsdp.cc b/talk/app/webrtc/webrtcsdp.cc |
| index 16c0e6939ed4b65d15de44fda42ccaefb2cd5b85..83d56c1a61f45c41e4e9685130a6e9af38976400 100644 |
| --- a/talk/app/webrtc/webrtcsdp.cc |
| +++ b/talk/app/webrtc/webrtcsdp.cc |
| @@ -101,7 +101,7 @@ namespace webrtc { |
| // the form: |
| // <type>=<value> |
| // where <type> MUST be exactly one case-significant character. |
| -static const int kLinePrefixLength = 2; // Lenght of <type>= |
| +static const int kLinePrefixLength = 2; // Length of <type>= |
| static const char kLineTypeVersion = 'v'; |
| static const char kLineTypeOrigin = 'o'; |
| static const char kLineTypeSessionName = 's'; |
| @@ -121,6 +121,7 @@ static const char kLineTypeAttributes = 'a'; |
| // Attributes |
| static const char kAttributeGroup[] = "group"; |
| static const char kAttributeMid[] = "mid"; |
| +static const char kAttributeMsid[] = "msid"; |
| static const char kAttributeRtcpMux[] = "rtcp-mux"; |
| static const char kAttributeRtcpReducedSize[] = "rtcp-rsize"; |
| static const char kAttributeSsrc[] = "ssrc"; |
| @@ -252,12 +253,13 @@ static void BuildMediaDescription(const ContentInfo* content_info, |
| const TransportInfo* transport_info, |
| const MediaType media_type, |
| const std::vector<Candidate>& candidates, |
| + bool unified_plan_sdp, |
| std::string* message); |
| static void BuildSctpContentAttributes(std::string* message, int sctp_port); |
| -static void BuildRtpContentAttributes( |
| - const MediaContentDescription* media_desc, |
| - const MediaType media_type, |
| - std::string* message); |
| +static void BuildRtpContentAttributes(const MediaContentDescription* media_desc, |
| + const MediaType media_type, |
| + bool unified_plan_sdp, |
| + std::string* message); |
| static void BuildRtpMap(const MediaContentDescription* media_desc, |
| const MediaType media_type, |
| std::string* message); |
| @@ -334,6 +336,10 @@ static bool ParseFingerprintAttribute(const std::string& line, |
| static bool ParseDtlsSetup(const std::string& line, |
| cricket::ConnectionRole* role, |
| SdpParseError* error); |
| +static bool ParseMsidAttribute(const std::string& line, |
| + std::string* stream_id, |
| + std::string* track_id, |
| + SdpParseError* error); |
| // Helper functions |
| @@ -792,7 +798,8 @@ static void GetCandidatesByMindex(const SessionDescriptionInterface& desci, |
| } |
| } |
| -std::string SdpSerialize(const JsepSessionDescription& jdesc) { |
| +std::string SdpSerialize(const JsepSessionDescription& jdesc, |
| + bool unified_plan_sdp) { |
| const cricket::SessionDescription* desc = jdesc.description(); |
| if (!desc) { |
| return ""; |
| @@ -863,10 +870,8 @@ std::string SdpSerialize(const JsepSessionDescription& jdesc) { |
| static_cast<const MediaContentDescription*>(it->description); |
| std::vector<Candidate> candidates; |
| GetCandidatesByMindex(jdesc, ++mline_index, &candidates); |
| - BuildMediaDescription(&*it, |
| - desc->GetTransportInfoByName(it->name), |
| - mdesc->type(), |
| - candidates, |
| + BuildMediaDescription(&*it, desc->GetTransportInfoByName(it->name), |
| + mdesc->type(), candidates, unified_plan_sdp, |
| &message); |
| } |
| return message; |
| @@ -1172,6 +1177,7 @@ void BuildMediaDescription(const ContentInfo* content_info, |
| const TransportInfo* transport_info, |
| const MediaType media_type, |
| const std::vector<Candidate>& candidates, |
| + bool unified_plan_sdp, |
| std::string* message) { |
| ASSERT(message != NULL); |
| if (content_info == NULL || message == NULL) { |
| @@ -1347,7 +1353,8 @@ void BuildMediaDescription(const ContentInfo* content_info, |
| if (IsDtlsSctp(media_desc->protocol())) { |
| BuildSctpContentAttributes(message, sctp_port); |
| } else if (IsRtp(media_desc->protocol())) { |
| - BuildRtpContentAttributes(media_desc, media_type, message); |
| + BuildRtpContentAttributes(media_desc, media_type, unified_plan_sdp, |
| + message); |
| } |
| } |
| @@ -1364,10 +1371,11 @@ void BuildSctpContentAttributes(std::string* message, int sctp_port) { |
| AddLine(os.str(), message); |
| } |
| -void BuildRtpContentAttributes( |
| - const MediaContentDescription* media_desc, |
| - const MediaType media_type, |
| - std::string* message) { |
| +// If unified_plan_sdp is true, will use "a=msid". |
| +void BuildRtpContentAttributes(const MediaContentDescription* media_desc, |
| + const MediaType media_type, |
| + bool unified_plan_sdp, |
| + std::string* message) { |
| std::ostringstream os; |
| // RFC 5285 |
| // a=extmap:<value>["/"<direction>] <URI> <extensionattributes> |
| @@ -1399,6 +1407,23 @@ void BuildRtpContentAttributes( |
| } |
| AddLine(os.str(), message); |
| + // draft-ietf-mmusic-msid-11 |
| + // a=msid:<stream id> <track id> |
| + if (unified_plan_sdp && !media_desc->streams().empty()) { |
| + if (media_desc->streams().size() > 1u) { |
| + LOG(LS_WARNING) << "Trying to serialize unified plan SDP with more than " |
| + << "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.
|
| + } else { |
| + auto track = media_desc->streams().begin(); |
| + 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
|
| + std::ostringstream os; |
| + InitAttrLine(kAttributeMsid, &os); |
| + os << kSdpDelimiterColon << track->sync_label << kSdpDelimiterSpace |
| + << appdata; |
| + AddLine(os.str(), message); |
| + } |
| + } |
| + |
| // RFC 5761 |
| // a=rtcp-mux |
| if (media_desc->rtcp_mux()) { |
| @@ -1467,8 +1492,8 @@ void BuildRtpContentAttributes( |
| // draft-alvestrand-mmusic-msid-00 |
| // a=ssrc:<ssrc-id> msid:identifier [appdata] |
| - // The appdata consists of the "id" attribute of a MediaStreamTrack, which |
| - // is corresponding to the "name" attribute of StreamParams. |
| + // The appdata consists of the "id" attribute of a MediaStreamTrack, |
| + // which corresponds to the "id" attribute of StreamParams. |
| std::string appdata = track->id; |
| std::ostringstream os; |
| InitAttrLine(kAttributeSsrc, &os); |
| @@ -1477,7 +1502,8 @@ void BuildRtpContentAttributes( |
| << kSdpDelimiterSpace << appdata; |
| AddLine(os.str(), message); |
| - // TODO(ronghuawu): Remove below code which is for backward compatibility. |
| + // TODO(ronghuawu): Remove below code which is for backward |
| + // compatibility. |
| // draft-alvestrand-rtcweb-mid-01 |
| // a=ssrc:<ssrc-id> mslabel:<value> |
| // The label isn't yet defined. |
| @@ -2039,6 +2065,27 @@ static bool ParseDtlsSetup(const std::string& line, |
| return true; |
| } |
| +static bool ParseMsidAttribute(const std::string& line, |
| + std::string* stream_id, |
| + std::string* track_id, |
| + SdpParseError* error) { |
| + // msid-value = msid-id [ SP msid-appdata ] |
| + // msid-id = 1*64token-char ; see RFC 4566 |
| + // 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
|
| + std::string field1; |
| + if (!rtc::tokenize_first(line.substr(kLinePrefixLength), kSdpDelimiterSpace, |
| + &field1, track_id)) { |
| + const size_t expected_fields = 2; |
| + return ParseFailedExpectFieldNum(line, expected_fields, error); |
| + } |
| + |
| + // msid:<msid-id> |
| + if (!GetValue(field1, kAttributeMsid, stream_id, error)) { |
| + return false; |
| + } |
| + return true; |
| +} |
| + |
| // RFC 3551 |
| // PT encoding media type clock rate channels |
| // name (Hz) |
| @@ -2463,6 +2510,8 @@ bool ParseContent(const std::string& message, |
| SsrcGroupVec ssrc_groups; |
| std::string maxptime_as_string; |
| std::string ptime_as_string; |
| + std::string stream_id; |
| + std::string track_id; |
| // Loop until the next m line |
| while (!IsLineType(message, kLineTypeMedia, *pos)) { |
| @@ -2622,6 +2671,10 @@ bool ParseContent(const std::string& message, |
| } |
| if (flag_value.compare(kValueConference) == 0) |
| media_desc->set_conference_mode(true); |
| + } else if (HasAttribute(line, kAttributeMsid)) { |
| + if (!ParseMsidAttribute(line, &stream_id, &track_id, error)) { |
| + return false; |
| + } |
| } |
| } else { |
| // Only parse lines that we are interested of. |
| @@ -2630,6 +2683,16 @@ bool ParseContent(const std::string& message, |
| } |
| } |
| + // Found an msid attribute. |
| + // Setting the msid_identifier/msid_appdata will cause only one StreamParams |
| + // to be created, containing all the SSRCs from the m= section. |
| + if (!stream_id.empty() && !track_id.empty()) { |
| + for (SsrcInfo& ssrc_info : ssrc_infos) { |
| + ssrc_info.msid_identifier = stream_id; |
| + 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.
|
| + } |
|
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
|
| + } |
| + |
| // Create tracks from the |ssrc_infos|. |
| CreateTracksFromSsrcInfos(ssrc_infos, &tracks); |
| @@ -2649,9 +2712,8 @@ bool ParseContent(const std::string& message, |
| } |
| // Add the new tracks to the |media_desc|. |
| - for (StreamParamsVec::iterator track = tracks.begin(); |
| - track != tracks.end(); ++track) { |
| - media_desc->AddStream(*track); |
| + for (StreamParams& track : tracks) { |
| + media_desc->AddStream(track); |
| } |
| if (media_type == cricket::MEDIA_TYPE_AUDIO) { |