Add a parser for the x-mt line.
This change adds a parser for the x-mt line to the WebRTC SDP, and adds a collection in the SessionDescription for media transport. x-mt line contains information about media transport settings. This is an experimental line. This change will be followed up by two other changes: * Setting the offer with x-mt * Using the x-mt line to pass it to the media transport Bug: webrtc:9719 Change-Id: I46568610d4092a69ada7b7c1d3987d698ddba0be Reviewed-on: https://webrtc-review.googlesource.com/c/124601 Reviewed-by: Steve Anton <steveanton@webrtc.org> Reviewed-by: Bjorn Mellem <mellem@webrtc.org> Commit-Queue: Peter Slatala <psla@webrtc.org> Cr-Commit-Position: refs/heads/master@{#26881}
This commit is contained in:

committed by
Commit Bot

parent
4f6ef1894e
commit
13e570fcb0
@ -423,6 +423,8 @@ class SessionDescription {
|
||||
|
||||
SessionDescription* Copy() const;
|
||||
|
||||
struct MediaTransportSetting;
|
||||
|
||||
// Content accessors.
|
||||
const ContentInfos& contents() const { return contents_; }
|
||||
ContentInfos& contents() { return contents_; }
|
||||
@ -510,6 +512,32 @@ class SessionDescription {
|
||||
}
|
||||
bool extmap_allow_mixed() const { return extmap_allow_mixed_; }
|
||||
|
||||
// Adds the media transport setting.
|
||||
// Media transport name uniquely identifies the type of media transport.
|
||||
// The name cannot be empty, or repeated in the previously added transport
|
||||
// settings.
|
||||
void AddMediaTransportSetting(const std::string& media_transport_name,
|
||||
const std::string& media_transport_setting) {
|
||||
RTC_DCHECK(!media_transport_name.empty());
|
||||
for (const auto& setting : media_transport_settings_) {
|
||||
RTC_DCHECK(media_transport_name != setting.transport_name)
|
||||
<< "MediaTransportSetting was already registered, transport_name="
|
||||
<< setting.transport_name;
|
||||
}
|
||||
media_transport_settings_.push_back(
|
||||
{media_transport_name, media_transport_setting});
|
||||
}
|
||||
|
||||
// Gets the media transport settings, in order of preference.
|
||||
const std::vector<MediaTransportSetting>& MediaTransportSettings() const {
|
||||
return media_transport_settings_;
|
||||
}
|
||||
|
||||
struct MediaTransportSetting {
|
||||
std::string transport_name;
|
||||
std::string transport_setting;
|
||||
};
|
||||
|
||||
private:
|
||||
SessionDescription(const SessionDescription&);
|
||||
|
||||
@ -526,6 +554,8 @@ class SessionDescription {
|
||||
// correctly. If it's included in offer to us we will respond that we support
|
||||
// it.
|
||||
bool extmap_allow_mixed_ = false;
|
||||
|
||||
std::vector<MediaTransportSetting> media_transport_settings_;
|
||||
};
|
||||
|
||||
// Indicates whether a session description was sent by the local client or
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/message_digest.h"
|
||||
#include "rtc_base/strings/string_builder.h"
|
||||
#include "rtc_base/third_party/base64/base64.h"
|
||||
|
||||
using cricket::AudioContentDescription;
|
||||
using cricket::Candidate;
|
||||
@ -235,6 +236,13 @@ static const char kApplicationSpecificMaximum[] = "AS";
|
||||
|
||||
static const char kDefaultSctpmapProtocol[] = "webrtc-datachannel";
|
||||
|
||||
// This is a non-standardized media transport settings.
|
||||
// This setting is going to be set in the offer. There may be one or more
|
||||
// a=x-mt: settings, and they are in the priority order (the most preferred on
|
||||
// top). x-mt setting format depends on the media transport, and is generated by
|
||||
// |MediaTransportInterface::GetTransportParametersOffer|.
|
||||
static const char kMediaTransportSettingLine[] = "x-mt";
|
||||
|
||||
// RTP payload type is in the 0-127 range. Use -1 to indicate "all" payload
|
||||
// types.
|
||||
const int kWildcardPayloadType = -1;
|
||||
@ -2049,6 +2057,28 @@ bool ParseConnectionData(const std::string& line,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseMediaTransportLine(const std::string& line,
|
||||
std::string* transport_name,
|
||||
std::string* transport_setting,
|
||||
SdpParseError* error) {
|
||||
std::string value;
|
||||
if (!GetValue(line, kMediaTransportSettingLine, &value, error)) {
|
||||
return false;
|
||||
}
|
||||
std::string media_transport_settings_base64;
|
||||
if (!rtc::tokenize_first(value, kSdpDelimiterColonChar, transport_name,
|
||||
&media_transport_settings_base64)) {
|
||||
return ParseFailedGetValue(line, kMediaTransportSettingLine, error);
|
||||
}
|
||||
if (!rtc::Base64::Decode(media_transport_settings_base64,
|
||||
rtc::Base64::DO_STRICT, transport_setting,
|
||||
nullptr)) {
|
||||
return ParseFailedGetValue(line, kMediaTransportSettingLine, error);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseSessionDescription(const std::string& message,
|
||||
size_t* pos,
|
||||
std::string* session_id,
|
||||
@ -2206,6 +2236,24 @@ bool ParseSessionDescription(const std::string& message,
|
||||
return false;
|
||||
}
|
||||
session_extmaps->push_back(extmap);
|
||||
} else if (HasAttribute(line, kMediaTransportSettingLine)) {
|
||||
std::string transport_name;
|
||||
std::string transport_setting;
|
||||
if (!ParseMediaTransportLine(line, &transport_name, &transport_setting,
|
||||
error)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& setting : desc->MediaTransportSettings()) {
|
||||
if (setting.transport_name == transport_name) {
|
||||
// Ignore repeated transport names rather than failing to parse so
|
||||
// that in the future the same transport could have multiple configs.
|
||||
RTC_LOG(INFO) << "x-mt line with repeated transport, transport_name="
|
||||
<< transport_name;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
desc->AddMediaTransportSetting(transport_name, transport_setting);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4324,3 +4324,97 @@ TEST_F(WebRtcSdpTest, ParseNoMid) {
|
||||
ElementsAre(Field("name", &cricket::ContentInfo::name, ""),
|
||||
Field("name", &cricket::ContentInfo::name, "")));
|
||||
}
|
||||
|
||||
// Test that the media transport name and base64-decoded setting is parsed from
|
||||
// an a=x-mt line.
|
||||
TEST_F(WebRtcSdpTest, ParseMediaTransport) {
|
||||
JsepSessionDescription output(kDummyType);
|
||||
std::string sdp = kSdpSessionString;
|
||||
sdp += "a=x-mt:rtp:dGVzdDY0\r\n";
|
||||
SdpParseError error;
|
||||
|
||||
ASSERT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error))
|
||||
<< error.description;
|
||||
const auto& settings = output.description()->MediaTransportSettings();
|
||||
ASSERT_EQ(1u, settings.size());
|
||||
EXPECT_EQ("rtp", settings[0].transport_name);
|
||||
EXPECT_EQ("test64", settings[0].transport_setting);
|
||||
}
|
||||
|
||||
// Test that an a=x-mt line fails to parse if its setting is invalid base 64.
|
||||
TEST_F(WebRtcSdpTest, ParseMediaTransportInvalidBase64) {
|
||||
JsepSessionDescription output(kDummyType);
|
||||
std::string sdp = kSdpSessionString;
|
||||
sdp += "a=x-mt:rtp:ThisIsInvalidBase64\r\n";
|
||||
SdpParseError error;
|
||||
|
||||
ASSERT_FALSE(webrtc::SdpDeserialize(sdp, &output, &error));
|
||||
}
|
||||
|
||||
// Test that multiple a=x-mt lines are parsed in the order of preference (the
|
||||
// order of the lines in the SDP).
|
||||
TEST_F(WebRtcSdpTest, ParseMediaTransportMultipleLines) {
|
||||
JsepSessionDescription output(kDummyType);
|
||||
std::string sdp = kSdpSessionString;
|
||||
sdp +=
|
||||
"a=x-mt:rtp:dGVzdDY0\r\n"
|
||||
"a=x-mt:generic:Z2VuZXJpY3NldHRpbmc=\r\n";
|
||||
SdpParseError error;
|
||||
|
||||
ASSERT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error))
|
||||
<< error.description;
|
||||
const auto& settings = output.description()->MediaTransportSettings();
|
||||
ASSERT_EQ(2u, settings.size());
|
||||
EXPECT_EQ("rtp", settings[0].transport_name);
|
||||
EXPECT_EQ("test64", settings[0].transport_setting);
|
||||
EXPECT_EQ("generic", settings[1].transport_name);
|
||||
EXPECT_EQ("genericsetting", settings[1].transport_setting);
|
||||
}
|
||||
|
||||
// Test that only the first a=x-mt line associated with a transport name is
|
||||
// parsed and the rest ignored.
|
||||
TEST_F(WebRtcSdpTest, ParseMediaTransportSkipRepeatedTransport) {
|
||||
JsepSessionDescription output(kDummyType);
|
||||
std::string sdp = kSdpSessionString;
|
||||
sdp +=
|
||||
"a=x-mt:rtp:dGVzdDY0\r\n"
|
||||
"a=x-mt:rtp:Z2VuZXJpY3NldHRpbmc=\r\n";
|
||||
SdpParseError error;
|
||||
|
||||
// Repeated 'rtp' transport setting. We still parse the SDP successfully,
|
||||
// but ignore the repeated transport.
|
||||
ASSERT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error));
|
||||
const auto& settings = output.description()->MediaTransportSettings();
|
||||
EXPECT_EQ("test64", settings[0].transport_setting);
|
||||
}
|
||||
|
||||
// Test that an a=x-mt line fails to parse if it is missing a setting.
|
||||
TEST_F(WebRtcSdpTest, ParseMediaTransportMalformedLine) {
|
||||
JsepSessionDescription output(kDummyType);
|
||||
std::string sdp = kSdpSessionString;
|
||||
sdp += "a=x-mt:rtp\r\n";
|
||||
SdpParseError error;
|
||||
|
||||
ASSERT_FALSE(webrtc::SdpDeserialize(sdp, &output, &error));
|
||||
}
|
||||
|
||||
// Test that an a=x-mt line fails to parse if its missing a name and setting.
|
||||
TEST_F(WebRtcSdpTest, ParseMediaTransportMalformedLine2) {
|
||||
JsepSessionDescription output(kDummyType);
|
||||
std::string sdp = kSdpSessionString;
|
||||
sdp += "a=x-mt\r\n";
|
||||
SdpParseError error;
|
||||
|
||||
ASSERT_FALSE(webrtc::SdpDeserialize(sdp, &output, &error));
|
||||
}
|
||||
|
||||
TEST_F(WebRtcSdpTest, ParseMediaTransportIgnoreNonsenseAttributeLines) {
|
||||
JsepSessionDescription output(kDummyType);
|
||||
std::string sdp = kSdpSessionString;
|
||||
sdp += "a=x-nonsense:rtp:dGVzdDY0\r\n";
|
||||
SdpParseError error;
|
||||
|
||||
ASSERT_TRUE(webrtc::SdpDeserialize(sdp, &output, &error))
|
||||
<< error.description;
|
||||
EXPECT_TRUE(output.description()->MediaTransportSettings().empty());
|
||||
}
|
||||
|
Reference in New Issue
Block a user