--- a/media/webrtc/signaling/gtest/sdp_unittests.cpp
+++ b/media/webrtc/signaling/gtest/sdp_unittests.cpp
@@ -1561,16 +1561,24 @@ class NewSdpTest : public ::testing::Tes
std::string GetParseErrors() const {
std::stringstream output;
for (auto e: mSdpErrorHolder->GetParseErrors()) {
output << e.first << ": " << e.second << std::endl;
}
return output.str();
}
+ std::string GetParseWarnings() const {
+ std::stringstream output;
+ for (auto e: mSdpErrorHolder->GetParseWarnings()) {
+ output << e.first << ": " << e.second << std::endl;
+ }
+ return output.str();
+ }
+
void CheckRtpmap(const std::string& expected_pt,
SdpRtpmapAttributeList::CodecType codec,
const std::string& name,
uint32_t clock,
uint16_t channels,
const std::string& search_pt,
const SdpRtpmapAttributeList& rtpmaps) const {
ASSERT_TRUE(rtpmaps.HasEntry(search_pt));
@@ -1624,16 +1632,20 @@ class NewSdpTest : public ::testing::Tes
void CheckSerialize(const std::string& expected,
const SdpAttribute& attr) const {
std::stringstream str;
attr.Serialize(str);
ASSERT_EQ(expected, str.str());
}
+ bool IsParsingWithSipccParser() const {
+ return ::testing::get<1>(GetParam());
+ }
+
SdpErrorHolder* mSdpErrorHolder;
SipccSdpParser mSipccParser;
RsdparsaSdpParser mRustParser;
mozilla::UniquePtr<Sdp> mSdp;
}; // class NewSdpTest
TEST_P(NewSdpTest, CreateDestroy) {
}
@@ -1899,17 +1911,16 @@ const std::string kBasicAudioVideoOffer
"a=msid:noappdata" CRLF
"a=bundle-only" CRLF;
TEST_P(NewSdpTest, BasicAudioVideoSdpParse) {
ParseSdp(kBasicAudioVideoOffer);
}
TEST_P(NewSdpTest, CheckRemoveFmtp) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kBasicAudioVideoOffer);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(3U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
SdpAttributeList& audioAttrList = mSdp->GetMediaSection(0).GetAttributeList();
ASSERT_TRUE(audioAttrList.HasAttribute(SdpAttribute::kFmtpAttribute));
@@ -2253,17 +2264,16 @@ static const std::string kAudioWithTelep
"a=ptime:20" CRLF
"a=maxptime:20" CRLF
"a=rtpmap:9 G722/8000" CRLF
"a=rtpmap:0 PCMU/8000" CRLF
"a=rtpmap:8 PCMA/8000" CRLF
"a=rtpmap:101 telephone-event/8000" CRLF;
TEST_P(NewSdpTest, CheckTelephoneEventNoFmtp) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
ASSERT_TRUE(mSdp->GetMediaSection(0).GetAttributeList().HasAttribute(
SdpAttribute::kFmtpAttribute));
auto audio_format_params =
@@ -2272,118 +2282,108 @@ TEST_P(NewSdpTest, CheckTelephoneEventNo
// make sure we don't get a fmtp for codec 101
for (size_t i = 0; i < audio_format_params.size(); ++i) {
ASSERT_NE("101", audio_format_params[i].format);
}
}
TEST_P(NewSdpTest, CheckTelephoneEventWithDefaultEvents) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 0-15" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
CheckDtmfFmtp("0-15");
}
TEST_P(NewSdpTest, CheckTelephoneEventWithBadCharacter) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 0-5." CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
CheckDtmfFmtp("0-15");
}
TEST_P(NewSdpTest, CheckTelephoneEventIncludingCommas) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 0-15,66,67" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
CheckDtmfFmtp("0-15,66,67");
}
TEST_P(NewSdpTest, CheckTelephoneEventComplexEvents) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 0,1,2-4,5-15,66,67" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
CheckDtmfFmtp("0,1,2-4,5-15,66,67");
}
TEST_P(NewSdpTest, CheckTelephoneEventNoHyphen) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 5,6,7" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
CheckDtmfFmtp("5,6,7");
}
TEST_P(NewSdpTest, CheckTelephoneEventOnlyZero) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 0" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
CheckDtmfFmtp("0");
}
TEST_P(NewSdpTest, CheckTelephoneEventOnlyOne) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 1" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
CheckDtmfFmtp("1");
}
TEST_P(NewSdpTest, CheckTelephoneEventBadThreeDigit) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 123" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
// check for the default dtmf tones
CheckDtmfFmtp("0-15");
}
TEST_P(NewSdpTest, CheckTelephoneEventBadThreeDigitWithHyphen) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 0-123" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
// check for the default dtmf tones
CheckDtmfFmtp("0-15");
}
TEST_P(NewSdpTest, CheckTelephoneEventBadLeadingHyphen) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 -12" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
// check for the default dtmf tones
CheckDtmfFmtp("0-15");
@@ -2395,89 +2395,82 @@ TEST_P(NewSdpTest, CheckTelephoneEventBa
}
TEST_P(NewSdpTest, CheckTelephoneEventBadTrailingHyphenInMiddle) {
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 1,12-,4" CRLF, false);
}
TEST_P(NewSdpTest, CheckTelephoneEventBadLeadingComma) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 ,2,3" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
// check for the default dtmf tones
CheckDtmfFmtp("0-15");
}
TEST_P(NewSdpTest, CheckTelephoneEventBadMultipleLeadingComma) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 ,,,2,3" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
// check for the default dtmf tones
CheckDtmfFmtp("0-15");
}
TEST_P(NewSdpTest, CheckTelephoneEventBadConsecutiveCommas) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 1,,,,,,,,3" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
// check for the default dtmf tones
CheckDtmfFmtp("0-15");
}
TEST_P(NewSdpTest, CheckTelephoneEventBadTrailingComma) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 1,2,3," CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
// check for the default dtmf tones
CheckDtmfFmtp("0-15");
}
TEST_P(NewSdpTest, CheckTelephoneEventBadTwoHyphens) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 1-2-3" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
// check for the default dtmf tones
CheckDtmfFmtp("0-15");
}
TEST_P(NewSdpTest, CheckTelephoneEventBadSixDigit) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 112233" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
// check for the default dtmf tones
CheckDtmfFmtp("0-15");
}
TEST_P(NewSdpTest, CheckTelephoneEventBadRangeReversed) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kAudioWithTelephoneEvent
+ "a=fmtp:101 33-2" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
// check for the default dtmf tones
CheckDtmfFmtp("0-15");
@@ -2497,17 +2490,16 @@ static const std::string kVideoWithRedAn
"a=rtpmap:120 VP8/90000" CRLF
"a=fmtp:120 max-fs=3600;max-fr=30" CRLF
"a=rtpmap:121 VP9/90000" CRLF
"a=fmtp:121 max-fs=3600;max-fr=30" CRLF
"a=rtpmap:122 red/90000" CRLF
"a=rtpmap:123 ulpfec/90000" CRLF;
TEST_P(NewSdpTest, CheckRedNoFmtp) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kVideoWithRedAndUlpfecSdp);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
ASSERT_TRUE(mSdp->GetMediaSection(0).GetAttributeList().HasAttribute(
SdpAttribute::kFmtpAttribute));
auto video_format_params =
@@ -2516,23 +2508,29 @@ TEST_P(NewSdpTest, CheckRedNoFmtp) {
// make sure we don't get a fmtp for codec 122
for (size_t i = 0; i < video_format_params.size(); ++i) {
ASSERT_NE("122", video_format_params[i].format);
}
}
TEST_P(NewSdpTest, CheckRedEmptyFmtp) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
// if serializing and re-parsing, we expect errors
if (::testing::get<0>(GetParam())) {
ParseSdp(kVideoWithRedAndUlpfecSdp + "a=fmtp:122" CRLF);
} else {
ParseSdp(kVideoWithRedAndUlpfecSdp + "a=fmtp:122" CRLF, false);
- ASSERT_NE(0U, GetParseErrors().size());
+
+ if (IsParsingWithSipccParser()) {
+ ASSERT_NE(0U, GetParseErrors().size());
+ } else {
+ // This is the branch for the rust parser to check for warnings, as the
+ // rust parser will give a warning at that point instead of an error.
+ ASSERT_NE(0U, GetParseWarnings().size());
+ }
}
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
ASSERT_TRUE(mSdp->GetMediaSection(0).GetAttributeList().HasAttribute(
SdpAttribute::kFmtpAttribute));
@@ -2542,17 +2540,16 @@ TEST_P(NewSdpTest, CheckRedEmptyFmtp) {
// make sure we don't get a fmtp for codec 122
for (size_t i = 0; i < video_format_params.size(); ++i) {
ASSERT_NE("122", video_format_params[i].format);
}
}
TEST_P(NewSdpTest, CheckRedFmtpWith2Codecs) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kVideoWithRedAndUlpfecSdp + "a=fmtp:122 120/121" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
ASSERT_TRUE(mSdp->GetMediaSection(0).GetAttributeList().HasAttribute(
SdpAttribute::kFmtpAttribute));
auto video_format_params =
@@ -2567,17 +2564,16 @@ TEST_P(NewSdpTest, CheckRedFmtpWith2Code
static_cast<SdpFmtpAttributeList::RedParameters*>(
video_format_params[3].parameters.get()));
ASSERT_EQ(2U, red_parameters->encodings.size());
ASSERT_EQ(120U, red_parameters->encodings[0]);
ASSERT_EQ(121U, red_parameters->encodings[1]);
}
TEST_P(NewSdpTest, CheckRedFmtpWith3Codecs) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kVideoWithRedAndUlpfecSdp + "a=fmtp:122 120/121/123" CRLF);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(1U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
ASSERT_TRUE(mSdp->GetMediaSection(0).GetAttributeList().HasAttribute(
SdpAttribute::kFmtpAttribute));
auto video_format_params =
@@ -2639,17 +2635,17 @@ const std::string kH264AudioVideoOffer =
"a=candidate:6 2 UDP 16515070 162.222.183.171 50340 typ relay raddr 162.222.183.171 rport 50340" CRLF
"a=candidate:0 2 UDP 2130379006 10.0.0.36 55428 typ host" CRLF
"m=video 9 RTP/SAVPF 97 98 120" CRLF
"c=IN IP6 ::1" CRLF
"a=mid:second" CRLF
"a=rtpmap:97 H264/90000" CRLF
"a=fmtp:97 profile-level-id=42a01e" CRLF
"a=rtpmap:98 H264/90000" CRLF
-"a=fmtp:98 PROFILE=0;LEVEL=0;profile-level-id=42a00d;packetization-mode=1;level-asymmetry-allowed=1;max-mbps=42000;max-fs=1400;max-cpb=1000;max-dpb=1000;max-br=180000;parameter-add=1;usedtx=0;stereo=0;useinbandfec=0;cbr=0" CRLF
+"a=fmtp:98 PROFILE=0;LEVEL=0;parameter-add=1;profile-level-id=42a00d;packetization-mode=1;level-asymmetry-allowed=1;max-mbps=42000;max-fs=1400;max-cpb=1000;max-dpb=1000;max-br=180000;usedtx=0;stereo=0;useinbandfec=0;cbr=0" CRLF
"a=rtpmap:120 VP8/90000" CRLF
"a=fmtp:120 max-fs=3601;max-fr=31" CRLF
"a=recvonly" CRLF
"a=setup:active" CRLF
"a=rtcp-mux" CRLF
"a=msid:streama tracka" CRLF
"a=msid:streamb trackb" CRLF
"a=candidate:0 1 UDP 2130379007 10.0.0.36 59530 typ host" CRLF
@@ -2661,17 +2657,16 @@ const std::string kH264AudioVideoOffer =
"a=candidate:3 1 UDP 100401151 162.222.183.171 62935 typ relay raddr 162.222.183.171 rport 62935" CRLF
"a=candidate:3 2 UDP 100401150 162.222.183.171 61026 typ relay raddr 162.222.183.171 rport 61026" CRLF
"m=audio 9 RTP/SAVPF 0" CRLF
"a=mid:third" CRLF
"a=rtpmap:0 PCMU/8000" CRLF
"a=msid:noappdata" CRLF;
TEST_P(NewSdpTest, CheckFormatParameters) {
- SKIP_TEST_WITH_RUST_PARSER; // See Bug 1432918
ParseSdp(kH264AudioVideoOffer);
ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
ASSERT_EQ(3U, mSdp->GetMediaSectionCount())
<< "Wrong number of media sections";
ASSERT_TRUE(mSdp->GetMediaSection(0).GetAttributeList().HasAttribute(
SdpAttribute::kFmtpAttribute));
auto audio_format_params =
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.cpp
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.cpp
@@ -693,29 +693,95 @@ RsdparsaSdpAttributeList::LoadRtpmap(Rus
rtpmap.frequency, channels);
}
SetAttribute(rtpmapList.release());
}
void
RsdparsaSdpAttributeList::LoadFmtp(RustAttributeList* attributeList)
{
- // TODO: Not implemented, see Bug 1432918
-#if 0
size_t numFmtp = sdp_get_fmtp_count(attributeList);
if (numFmtp == 0) {
return;
}
auto rustFmtps = MakeUnique<RustSdpAttributeFmtp[]>(numFmtp);
- size_t numValidFmtp = sdp_get_fmtp(attributeList, numFmtp,
- rustFmtps.get());
+ size_t numValidFmtp = sdp_get_fmtp(attributeList, numFmtp,rustFmtps.get());
+ auto fmtpList = MakeUnique<SdpFmtpAttributeList>();
for(size_t i = 0; i < numValidFmtp; i++) {
- RustSdpAttributeFmtp& fmtp = rustFmtps[i];
+ const RustSdpAttributeFmtp& fmtp = rustFmtps[i];
+ uint8_t payloadType = fmtp.payloadType;
+ std::string codecName = convertStringView(fmtp.codecName);
+ const RustSdpAttributeFmtpParameters& rustFmtpParameters = fmtp.parameters;
+
+ UniquePtr<SdpFmtpAttributeList::Parameters> fmtpParameters;
+
+ // use the upper case version of the codec name
+ std::transform(codecName.begin(), codecName.end(),
+ codecName.begin(), ::toupper);
+
+ if(codecName == "H264"){
+ SdpFmtpAttributeList::H264Parameters h264Parameters;
+
+ h264Parameters.packetization_mode = rustFmtpParameters.packetization_mode;
+ h264Parameters.level_asymmetry_allowed =
+ rustFmtpParameters.level_asymmetry_allowed;
+ h264Parameters.profile_level_id = rustFmtpParameters.profile_level_id;
+ h264Parameters.max_mbps = rustFmtpParameters.max_mbps;
+ h264Parameters.max_fs = rustFmtpParameters.max_fs;
+ h264Parameters.max_cpb = rustFmtpParameters.max_cpb;
+ h264Parameters.max_dpb = rustFmtpParameters.max_dpb;
+ h264Parameters.max_br = rustFmtpParameters.max_br;
+
+ // TODO(bug 1466859): Support sprop-parameter-sets
+
+ fmtpParameters.reset(new SdpFmtpAttributeList::H264Parameters(
+ std::move(h264Parameters)));
+ } else if(codecName == "OPUS"){
+ SdpFmtpAttributeList::OpusParameters opusParameters;
+
+ opusParameters.maxplaybackrate = rustFmtpParameters.maxplaybackrate;
+ opusParameters.stereo = rustFmtpParameters.stereo;
+ opusParameters.useInBandFec = rustFmtpParameters.useinbandfec;
+
+ fmtpParameters.reset(new SdpFmtpAttributeList::OpusParameters(
+ std::move(opusParameters)));
+ } else if((codecName == "VP8") || (codecName == "VP9")){
+ SdpFmtpAttributeList::VP8Parameters
+ vp8Parameters(codecName == "VP8" ?
+ SdpRtpmapAttributeList::kVP8 :
+ SdpRtpmapAttributeList::kVP9);
+
+ vp8Parameters.max_fs = rustFmtpParameters.max_fs;
+ vp8Parameters.max_fr = rustFmtpParameters.max_fr;
+
+ fmtpParameters.reset(new SdpFmtpAttributeList::VP8Parameters(
+ std::move(vp8Parameters)));
+ } else if(codecName == "TELEPHONE-EVENT"){
+ SdpFmtpAttributeList::TelephoneEventParameters telephoneEventParameters;
+
+ telephoneEventParameters.dtmfTones =
+ convertStringView(rustFmtpParameters.dtmf_tones);
+
+ fmtpParameters.reset(new SdpFmtpAttributeList::TelephoneEventParameters(
+ std::move(telephoneEventParameters)));
+ } else if(codecName == "RED") {
+ SdpFmtpAttributeList::RedParameters redParameters;
+
+ redParameters.encodings = convertU8Vec(rustFmtpParameters.encodings);
+
+ fmtpParameters.reset(new SdpFmtpAttributeList::RedParameters(
+ std::move(redParameters)));
+ } else{
+ // The parameter set is unknown so skip it
+ continue;
+ }
+
+ fmtpList->PushEntry(std::to_string(payloadType), std::move(fmtpParameters));
}
-#endif
+ SetAttribute(fmtpList.release());
}
void
RsdparsaSdpAttributeList::LoadPtime(RustAttributeList* attributeList)
{
int64_t ptime = sdp_get_ptime(attributeList);
if (ptime >= 0) {
SetAttribute(new SdpNumberAttribute(SdpAttribute::kPtimeAttribute,
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.cpp
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.cpp
@@ -40,9 +40,23 @@ sdp::AddrType convertAddressType(RustSdp
return sdp::kIPv4;
case RustSdpAddrType::kRustAddrIp6:
return sdp::kIPv6;
}
MOZ_CRASH("unknown address type");
}
+std::vector<uint8_t> convertU8Vec(U8Vec* vec)
+{
+ std::vector<std::uint8_t> ret;
+
+ size_t len = u8_vec_len(vec);
+ for (size_t i = 0; i < len; i++) {
+ uint8_t byte;
+ u8_vec_get(vec, i, &byte);
+ ret.push_back(byte);
+ }
+
+ return ret;
}
+
+}
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.h
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.h
@@ -19,13 +19,14 @@ struct FreeRustSdpSession {
void operator()(RustSdpSession* aSess) { sdp_free_session(aSess); }
};
typedef UniquePtr<RustSdpSession, FreeRustSdpSession> RsdparsaSessionHandle;
std::string convertStringView(StringView str);
std::vector<std::string> convertStringVec(StringVec* vec);
sdp::AddrType convertAddressType(RustSdpAddrType addr);
+std::vector<uint8_t> convertU8Vec(U8Vec* vec);
}
#endif
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h
@@ -12,16 +12,17 @@
#include <stdbool.h>
struct BandwidthVec;
struct RustSdpSession;
struct RustSdpError;
struct RustMediaSection;
struct RustAttributeList;
struct StringVec;
+struct U8Vec;
struct U32Vec;
struct RustHeapString;
enum class RustSdpAddrType {
kRustAddrNone,
kRustAddrIp4,
kRustAddrIp6
};
@@ -96,20 +97,52 @@ struct RustSdpAttributeRtpmap {
struct RustSdpAttributeRtcpFb {
uint32_t payloadType;
uint32_t feedbackType;
StringView parameter;
StringView extra;
};
+struct RustSdpAttributeFmtpParameters {
+ // H264
+ uint32_t packetization_mode;
+ bool level_asymmetry_allowed;
+ uint32_t profile_level_id;
+ uint32_t max_fs;
+ uint32_t max_cpb;
+ uint32_t max_dpb;
+ uint32_t max_br;
+ uint32_t max_mbps;
+
+ // VP8 and VP9
+ // max_fs, already defined in H264
+ uint32_t max_fr;
+
+ // Opus
+ uint32_t maxplaybackrate;
+ bool usedtx;
+ bool stereo;
+ bool useinbandfec;
+ bool cbr;
+
+ // telephone-event
+ StringView dtmf_tones;
+
+ // Red codecs
+ U8Vec* encodings;
+
+ // Unknown
+ StringVec* unknown_tokens;
+};
+
struct RustSdpAttributeFmtp {
uint8_t payloadType;
StringView codecName;
- StringVec* tokens;
+ RustSdpAttributeFmtpParameters parameters;
};
struct RustSdpAttributeFlags {
bool iceLite;
bool rtcpMux;
bool bundleOnly;
bool endOfCandidates;
};
@@ -175,16 +208,19 @@ extern "C" {
size_t string_vec_len(const StringVec* vec);
nsresult string_vec_get_view(const StringVec* vec, size_t index,
StringView* str);
size_t u32_vec_len(const U32Vec* vec);
nsresult u32_vec_get(const U32Vec* vec, size_t index, uint32_t* ret);
+size_t u8_vec_len(const U8Vec* vec);
+nsresult u8_vec_get(const U8Vec* vec, size_t index, uint8_t* ret);
+
void sdp_free_string(char* string);
nsresult parse_sdp(const char* sdp, uint32_t length, bool fail_on_warning,
RustSdpSession** ret, RustSdpError** err);
RustSdpSession* sdp_new_reference(RustSdpSession* aSess);
void sdp_free_session(RustSdpSession* ret);
size_t sdp_get_error_line_num(const RustSdpError* err);
StringView sdp_get_error_message(const RustSdpError* err);
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpParser.cpp
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpParser.cpp
@@ -35,19 +35,28 @@ RsdparsaSdpParser::Parse(const std::stri
std::string errMsg = convertStringView(sdp_get_error_message(err));
sdp_free_error(err);
AddParseError(line, errMsg);
} else {
AddParseError(0, "Unhandled Rsdparsa parsing error");
}
return nullptr;
}
+
+ if(err) {
+ size_t line = sdp_get_error_line_num(err);
+ std::string warningMsg = convertStringView(sdp_get_error_message(err));
+ sdp_free_error(err);
+ AddParseWarnings(line, warningMsg);
+ }
+
RsdparsaSessionHandle uniqueResult;
uniqueResult.reset(result);
RustSdpOrigin rustOrigin = sdp_get_origin(uniqueResult.get());
sdp::AddrType addrType = convertAddressType(rustOrigin.addr.addrType);
SdpOrigin origin(convertStringView(rustOrigin.username),
rustOrigin.sessionId, rustOrigin.sessionVersion,
addrType, std::string(rustOrigin.addr.unicastAddr));
- return MakeUnique<RsdparsaSdp>(std::move(uniqueResult), origin);
+
+ return MakeUnique<RsdparsaSdp>(std::move(uniqueResult), origin);
}
} // namespace mozilla
--- a/media/webrtc/signaling/src/sdp/SdpErrorHolder.h
+++ b/media/webrtc/signaling/src/sdp/SdpErrorHolder.h
@@ -21,30 +21,49 @@ public:
void
AddParseError(size_t line, const std::string& message)
{
mErrors.push_back(std::make_pair(line, message));
}
void
+ AddParseWarnings(size_t line, const std::string& message)
+ {
+ mWarnings.push_back(std::make_pair(line, message));
+ }
+
+ void
ClearParseErrors()
{
mErrors.clear();
}
+ void
+ ClearParseWarnings()
+ {
+ mWarnings.clear();
+ }
+
/**
* Returns a reference to the list of parse errors.
* This gets cleared out when you call Parse.
*/
const std::vector<std::pair<size_t, std::string> >&
GetParseErrors() const
{
return mErrors;
}
+ const std::vector<std::pair<size_t, std::string> >&
+ GetParseWarnings() const
+ {
+ return mWarnings;
+ }
+
private:
std::vector<std::pair<size_t, std::string> > mErrors;
+ std::vector<std::pair<size_t, std::string> > mWarnings;
};
} // namespace mozilla
#endif
--- a/media/webrtc/signaling/src/sdp/rsdparsa/src/attribute_type.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa/src/attribute_type.rs
@@ -235,19 +235,57 @@ pub struct SdpAttributeExtmap {
pub id: u16,
pub direction: Option<SdpAttributeDirection>,
pub url: String,
pub extension_attributes: Option<String>,
}
#[derive(Clone)]
#[cfg_attr(feature="serialize", derive(Serialize))]
+pub struct SdpAttributeFmtpParameters {
+ // H264
+ // TODO(bug 1466859): Support sprop-parameter-sets
+ // pub static const max_sprop_len: u32 = 128,
+ // pub sprop_parameter_sets: [u8, max_sprop_len],
+ pub packetization_mode: u32,
+ pub level_asymmetry_allowed: bool,
+ pub profile_level_id: u32,
+ pub max_fs: u32,
+ pub max_cpb: u32,
+ pub max_dpb: u32,
+ pub max_br: u32,
+ pub max_mbps: u32,
+
+ // VP8 and VP9
+ // max_fs, already defined in H264
+ pub max_fr: u32,
+
+ // Opus
+ pub maxplaybackrate: u32,
+ pub usedtx: bool,
+ pub stereo: bool,
+ pub useinbandfec: bool,
+ pub cbr: bool,
+
+ // Red
+ pub encodings: Vec<u8>,
+
+ // telephone-event
+ pub dtmf_tones: String,
+
+ // Unknown
+ pub unknown_tokens: Vec<String>,
+}
+
+
+#[derive(Clone)]
+#[cfg_attr(feature="serialize", derive(Serialize))]
pub struct SdpAttributeFmtp {
pub payload_type: u8,
- pub tokens: Vec<String>,
+ pub parameters: SdpAttributeFmtpParameters,
}
#[derive(Clone)]
#[cfg_attr(feature="serialize", derive(Serialize))]
pub struct SdpAttributeFingerprint {
// TODO turn the supported hash algorithms into an enum?
pub hash_algorithm: String,
pub fingerprint: String,
@@ -865,29 +903,185 @@ fn parse_fingerprint(to_parse: &str) ->
}
Ok(SdpAttribute::Fingerprint(SdpAttributeFingerprint {
hash_algorithm: tokens[0].to_string(),
fingerprint: tokens[1].to_string(),
}))
}
fn parse_fmtp(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
- let tokens: Vec<&str> = to_parse.split_whitespace().collect();
+ let tokens: Vec<&str> = to_parse.splitn(2," ").collect();
+
if tokens.len() != 2 {
- return Err(SdpParserInternalError::Generic("Fmtp needs to have two tokens".to_string()));
+ return Err(SdpParserInternalError::Unsupported(
+ "Fmtp attributes require a payload type and a parameter block.".to_string()
+ ));
}
+
+ let payload_token = tokens[0];
+ let parameter_token = tokens[1];
+
+
+ // Default initiliaze SdpAttributeFmtpParameters
+ let mut parameters = SdpAttributeFmtpParameters{
+ packetization_mode: 0,
+ level_asymmetry_allowed: false,
+ profile_level_id: 0x420010,
+ max_fs: 0,
+ max_cpb: 0,
+ max_dpb: 0,
+ max_br: 0,
+ max_mbps: 0,
+ usedtx: false,
+ stereo: false,
+ useinbandfec: false,
+ cbr: false,
+ max_fr: 0,
+ maxplaybackrate: 48000,
+ encodings: Vec::new(),
+ dtmf_tones: "".to_string(),
+ unknown_tokens: Vec::new(),
+ };
+
+ if parameter_token.contains("=") {
+ let parameter_tokens: Vec<&str> = parameter_token.split(";").collect();
+
+ for parameter_token in parameter_tokens.iter() {
+ let name_value_pair: Vec<&str> = parameter_token.splitn(2,"=").collect();
+
+ if name_value_pair.len() != 2 {
+ return Err(SdpParserInternalError::Generic(
+ "A fmtp parameter must be either a telephone event, a parameter list or
+ a red codec list".to_string()
+ ))
+ }
+
+ let parse_bool = |val: &str, param_name: &str| -> Result<bool,SdpParserInternalError> {
+ match val.parse::<u8>()? {
+ 0 => Ok(false),
+ 1 => Ok(true),
+ _ => return Err(SdpParserInternalError::Generic(
+ format!("The fmtp parameter '{:}' must be 0 or 1", param_name)
+ .to_string()
+ ))
+ }
+ };
+
+ let parameter_name = name_value_pair[0];
+ let parameter_val = name_value_pair[1];
+
+ match parameter_name.to_uppercase().as_str() {
+ // H264
+ "PROFILE-LEVEL-ID" => parameters.profile_level_id =
+ match u32::from_str_radix(parameter_val,16)? {
+ x @ 0 ... 0xffffff => x,
+ _ => return Err(SdpParserInternalError::Generic(
+ "The fmtp parameter 'profile-level-id' must be in range [0,0xffffff]"
+ .to_string()
+ ))
+ },
+ "PACKETIZATION-MODE" => parameters.packetization_mode =
+ match parameter_val.parse::<u32>()? {
+ x @ 0...2 => x,
+ _ => return Err(SdpParserInternalError::Generic(
+ "The fmtp parameter 'packetization-mode' must be 0,1 or 2"
+ .to_string()
+ ))
+ },
+ "LEVEL-ASYMMETRY-ALLOWED" => parameters.level_asymmetry_allowed =
+ parse_bool(parameter_val,"level-asymmetry-allowed")?,
+ "MAX-MBPS" => parameters.max_mbps = parameter_val.parse::<u32>()?,
+ "MAX-FS" => parameters.max_fs = parameter_val.parse::<u32>()?,
+ "MAX-CPB" => parameters.max_cpb = parameter_val.parse::<u32>()?,
+ "MAX-DPB" => parameters.max_dpb = parameter_val.parse::<u32>()?,
+ "MAX-BR" => parameters.max_br = parameter_val.parse::<u32>()?,
+
+ // VP8 and VP9
+ "MAX-FR" => parameters.max_fr = parameter_val.parse::<u32>()?,
+
+ //Opus
+ "MAXPLAYBACKRATE" => parameters.maxplaybackrate = parameter_val.parse::<u32>()?,
+ "USEDTX" => parameters.usedtx = parse_bool(parameter_val,"usedtx")?,
+ "STEREO" => parameters.stereo = parse_bool(parameter_val,"stereo")?,
+ "USEINBANDFEC" => parameters.useinbandfec =
+ parse_bool(parameter_val,"useinbandfec")?,
+ "CBR" => parameters.cbr = parse_bool(parameter_val,"cbr")?,
+ _ => {
+ parameters.unknown_tokens.push(parameter_token.to_string())
+ }
+ }
+ }
+ } else {
+ if parameter_token.contains("/") {
+ let encodings: Vec<&str> = parameter_token.split("/").collect();
+
+ for encoding in encodings {
+ match encoding.parse::<u8>()? {
+ x @ 0...128 => parameters.encodings.push(x),
+ _ => return Err(SdpParserInternalError::Generic(
+ "Red codec must be in range [0,128]".to_string()
+ ))
+ }
+ }
+ } else { // This is the case for the 'telephone-event' codec
+ let dtmf_tones: Vec<&str> = parameter_token.split(",").collect();
+ let mut dtmf_tone_is_ok = true;
+
+ // This closure verifies the output of some_number_as_string.parse::<u8>().ok() like calls
+ let validate_digits = |digit_option: Option<u8> | -> Option<u8> {
+ match digit_option{
+ Some(x) => match x {
+ 0...100 => Some(x),
+ _ => None,
+ },
+ None => None,
+ }
+ };
+
+ // This loop does some sanity checking on the passed dtmf tones
+ for dtmf_tone in dtmf_tones {
+ let dtmf_tone_range: Vec<&str> = dtmf_tone.splitn(2,"-").collect();
+
+ dtmf_tone_is_ok = match dtmf_tone_range.len() {
+ // In this case the dtmf tone is a range
+ 2 => {
+ match validate_digits(dtmf_tone_range[0].parse::<u8>().ok()) {
+ Some(l) => match validate_digits(dtmf_tone_range[1].parse::<u8>().ok()) {
+ Some(u) => {
+ // Check that the first part of the range is smaller than the second part
+ l < u
+ },
+ None => false
+ },
+ None => false,
+ }
+ },
+ // In this case the dtmf tone is a single tone
+ 1 => validate_digits(dtmf_tone.parse::<u8>().ok()).is_some(),
+ _ => false
+ };
+
+ if !dtmf_tone_is_ok {
+ break ;
+ }
+ }
+
+ // Set the parsed dtmf tones or in case the parsing was insuccessfull, set it to the default "0-15"
+ parameters.dtmf_tones = match dtmf_tone_is_ok{
+ true => parameter_token.to_string(),
+ false => "0-15".to_string()
+ }
+ }
+ }
+
Ok(SdpAttribute::Fmtp(SdpAttributeFmtp {
- // TODO check for dynamic PT range
- payload_type: tokens[0].parse::<u8>()?,
- // TODO this should probably be slit into known tokens
- // plus a list of unknown tokens
- tokens: to_parse.split(';').map(|x| x.to_string()).collect(),
+ payload_type: payload_token.parse::<u8>()?,
+ parameters: parameters,
}))
}
-
fn parse_group(to_parse: &str) -> Result<SdpAttribute, SdpParserInternalError> {
let mut tokens = to_parse.split_whitespace();
let semantics = match tokens.next() {
None => {
return Err(SdpParserInternalError::Generic("Group attribute is missing semantics token"
.to_string()))
}
Some(x) => {
@@ -1400,17 +1594,28 @@ fn test_parse_attribute_extmap() {
#[test]
fn test_parse_attribute_fingerprint() {
assert!(parse_attribute("fingerprint:sha-256 CD:34:D1:62:16:95:7B:B7:EB:74:E2:39:27:97:EB:0B:23:73:AC:BC:BF:2F:E3:91:CB:57:A9:9D:4A:A2:0B:40").is_ok())
}
#[test]
fn test_parse_attribute_fmtp() {
- assert!(parse_attribute("fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1").is_ok())
+ assert!(parse_attribute("fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1").is_ok());
+ assert!(parse_attribute("fmtp:66 0-15").is_ok());
+ assert!(parse_attribute("fmtp:109 0-15,66").is_ok());
+ assert!(parse_attribute("fmtp:66 111/115").is_ok());
+ assert!(parse_attribute("fmtp:109 maxplaybackrate=48000;stereo=1;useinbandfec=1").is_ok());
+ assert!(parse_attribute("fmtp:109 maxplaybackrate=48000; stereo=1; useinbandfec=1").is_ok());
+ assert!(parse_attribute("fmtp:109 maxplaybackrate=48000; stereo=1;useinbandfec=1").is_ok());
+ assert!(parse_attribute("fmtp:8 maxplaybackrate=48000").is_ok());
+
+ assert!(parse_attribute("fmtp:77 ").is_err());
+ assert!(parse_attribute("fmtp:109 maxplaybackrate=48000stereo=1;").is_err());
+ assert!(parse_attribute("fmtp:8 ;maxplaybackrate=48000").is_err());
}
#[test]
fn test_parse_attribute_group() {
assert!(parse_attribute("group:LS").is_ok());
assert!(parse_attribute("group:LS 1 2").is_ok());
assert!(parse_attribute("group:BUNDLE sdparta_0 sdparta_1 sdparta_2").is_ok());
--- a/media/webrtc/signaling/src/sdp/rsdparsa/src/error.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa/src/error.rs
@@ -2,17 +2,17 @@ use std::num::ParseIntError;
use std::net::AddrParseError;
use std::fmt;
use std::error;
use std::error::Error;
#[cfg(feature = "serialize")]
use serde::ser::{Serializer, Serialize, SerializeStruct};
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub enum SdpParserInternalError {
Generic(String),
Unsupported(String),
Integer(ParseIntError),
Address(AddrParseError),
}
impl fmt::Display for SdpParserInternalError {
@@ -94,17 +94,17 @@ fn test_sdp_parser_internal_error_addres
assert!(addr.is_err());
let addr_err = SdpParserInternalError::Address(addr.err().unwrap());
assert_eq!(format!("{}", addr_err),
"IP address parsing error: invalid IP address syntax");
assert_eq!(addr_err.description(), "invalid IP address syntax");
assert!(!addr_err.cause().is_none());
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub enum SdpParserError {
Line {
error: SdpParserInternalError,
line: String,
line_number: usize,
},
Unsupported {
error: SdpParserInternalError,
--- a/media/webrtc/signaling/src/sdp/rsdparsa/src/lib.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa/src/lib.rs
@@ -96,16 +96,17 @@ pub struct SdpSession {
pub version: u64,
pub origin: SdpOrigin,
pub session: String,
pub connection: Option<SdpConnection>,
pub bandwidth: Vec<SdpBandwidth>,
pub timing: Option<SdpTiming>,
pub attribute: Vec<SdpAttribute>,
pub media: Vec<SdpMedia>,
+ pub warnings: Vec<SdpParserError>
// unsupported values:
// information: Option<String>,
// uri: Option<String>,
// email: Option<String>,
// phone: Option<String>,
// repeat: Option<String>,
// zone: Option<String>,
// key: Option<String>,
@@ -117,16 +118,17 @@ impl SdpSession {
version,
origin,
session,
connection: None,
bandwidth: Vec::new(),
timing: None,
attribute: Vec::new(),
media: Vec::new(),
+ warnings: Vec::new(),
}
}
pub fn get_version(&self) -> u64 {
self.version
}
pub fn get_origin(&self) -> &SdpOrigin {
@@ -880,28 +882,33 @@ pub fn parse_sdp(sdp: &str, fail_on_warn
message,
line_number,
})
}
}
}
};
}
- for warning in warnings {
- if fail_on_warning {
- return Err(warning);
- } else {
- println!("Warning: {}", warning);
- };
+
+ if fail_on_warning && (warnings.len() > 0) {
+ return Err(warnings[0].clone());
}
+
// We just return the last of the errors here
if let Some(e) = errors.pop() {
return Err(e);
};
- let session = parse_sdp_vector(&sdp_lines)?;
+
+ let mut session = parse_sdp_vector(&sdp_lines)?;
+ session.warnings = warnings;
+
+ for warning in &session.warnings {
+ println!("Warning: {}", &warning);
+ }
+
Ok(session)
}
#[test]
fn test_parse_sdp_zero_length_string_fails() {
assert!(parse_sdp("", true).is_err());
}
--- a/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs
@@ -1,13 +1,20 @@
use std::slice;
use libc::{size_t, uint8_t, uint16_t, uint32_t, int64_t};
use rsdparsa::SdpSession;
-use rsdparsa::attribute_type::{SdpAttribute, SdpAttributeType, SdpAttributePayloadType, SdpAttributeFingerprint, SdpAttributeSetup, SdpAttributeSsrc, SdpAttributeRtpmap, SdpAttributeMsid, SdpAttributeMsidSemantic, SdpAttributeGroupSemantic, SdpAttributeGroup, SdpAttributeRtcp, SdpAttributeRtcpFb, SdpAttributeSctpmap, SdpAttributeRemoteCandidate, SdpAttributeExtmap, SdpAttributeDirection};
+use rsdparsa::attribute_type::{SdpAttribute, SdpAttributeType, SdpAttributePayloadType,
+ SdpAttributeFingerprint, SdpAttributeSetup, SdpAttributeSsrc,
+ SdpAttributeRtpmap, SdpAttributeFmtpParameters,
+ SdpAttributeMsid, SdpAttributeMsidSemantic,
+ SdpAttributeGroupSemantic, SdpAttributeGroup, SdpAttributeRtcp,
+ SdpAttributeRtcpFb, SdpAttributeSctpmap,
+ SdpAttributeRemoteCandidate, SdpAttributeExtmap,
+ SdpAttributeDirection};
use nserror::{nsresult, NS_OK, NS_ERROR_INVALID_ARG};
use types::StringView;
use network::RustIpAddr;
#[repr(C)]
#[derive(Clone, Copy, PartialEq, Eq)]
@@ -314,20 +321,79 @@ pub unsafe extern "C" fn sdp_get_rtpmaps
None
}).collect();
let rtpmaps = slice::from_raw_parts_mut(ret_rtpmaps, ret_size);
rtpmaps.copy_from_slice(attrs.as_slice());
}
#[repr(C)]
#[derive(Clone, Copy)]
+pub struct RustSdpAttributeFmtpParameters {
+
+ // H264
+ pub packetization_mode: uint32_t,
+ pub level_asymmetry_allowed: bool,
+ pub profile_level_id: uint32_t,
+ pub max_fs: uint32_t,
+ pub max_cpb: uint32_t,
+ pub max_dpb: uint32_t,
+ pub max_br: uint32_t,
+ pub max_mbps: uint32_t,
+
+ // VP8 and VP9
+ // max_fs, already defined in H264
+ pub max_fr: uint32_t,
+
+ // Opus
+ pub maxplaybackrate: uint32_t,
+ pub usedtx: bool,
+ pub stereo: bool,
+ pub useinbandfec: bool,
+ pub cbr: bool,
+
+ // telephone-event
+ pub dtmf_tones: StringView,
+
+ // Red
+ pub encodings: *const Vec<uint8_t>,
+
+ // Unknown
+ pub unknown_tokens: *const Vec<String>,
+}
+
+impl<'a> From<&'a SdpAttributeFmtpParameters> for RustSdpAttributeFmtpParameters {
+ fn from(other: &SdpAttributeFmtpParameters) -> Self {
+ RustSdpAttributeFmtpParameters{
+ packetization_mode: other.packetization_mode,
+ level_asymmetry_allowed: other.level_asymmetry_allowed,
+ profile_level_id: other.profile_level_id,
+ max_fs: other.max_fs,
+ max_cpb: other.max_cpb,
+ max_dpb: other.max_dpb,
+ max_br: other.max_br,
+ max_mbps: other.max_mbps,
+ usedtx: other.usedtx,
+ stereo: other.stereo,
+ useinbandfec: other.useinbandfec,
+ cbr: other.cbr,
+ max_fr: other.max_fr,
+ maxplaybackrate: other.maxplaybackrate,
+ dtmf_tones: StringView::from(other.dtmf_tones.as_str()),
+ encodings: &other.encodings,
+ unknown_tokens: &other.unknown_tokens,
+ }
+ }
+}
+
+#[repr(C)]
+#[derive(Clone, Copy)]
pub struct RustSdpAttributeFmtp {
pub payload_type: uint8_t,
pub codec_name: StringView,
- pub tokens: *const Vec<String>,
+ pub parameters: RustSdpAttributeFmtpParameters,
}
#[no_mangle]
pub unsafe extern "C" fn sdp_get_fmtp_count(attributes: *const Vec<SdpAttribute>) -> size_t {
count_attribute((*attributes).as_slice(), RustSdpAttributeType::Fmtp)
}
fn find_payload_type(attributes: &[SdpAttribute], payload_type: u8) -> Option<&SdpAttributeRtpmap> {
@@ -338,30 +404,31 @@ fn find_payload_type(attributes: &[SdpAt
None
}
} else {
None
}).next()
}
#[no_mangle]
-pub unsafe extern "C" fn sdp_get_fmtp(attributes: *const Vec<SdpAttribute>, ret_size: size_t, ret_fmtp: *mut RustSdpAttributeFmtp) -> size_t {
+pub unsafe extern "C" fn sdp_get_fmtp(attributes: *const Vec<SdpAttribute>, ret_size: size_t,
+ ret_fmtp: *mut RustSdpAttributeFmtp) -> size_t {
let fmtps = (*attributes).iter().filter_map(|x| if let SdpAttribute::Fmtp(ref data) = *x {
Some(data)
} else {
None
});
let mut rust_fmtps = Vec::new();
for fmtp in fmtps {
if let Some(rtpmap) = find_payload_type((*attributes).as_slice(), fmtp.payload_type) {
rust_fmtps.push( RustSdpAttributeFmtp{
payload_type: fmtp.payload_type as u8,
codec_name: StringView::from(rtpmap.codec_name.as_str()),
- tokens: &fmtp.tokens
- }
+ parameters: RustSdpAttributeFmtpParameters::from(&fmtp.parameters),
+ }
);
}
}
let fmtps = if ret_size <= rust_fmtps.len() {
slice::from_raw_parts_mut(ret_fmtp, ret_size)
} else {
slice::from_raw_parts_mut(ret_fmtp, rust_fmtps.len())
};
--- a/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/lib.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/lib.rs
@@ -52,18 +52,21 @@ pub unsafe extern "C" fn parse_sdp(sdp:
*error = ptr::null(); // TODO: Give more useful return value here
debug!("Error converting string to utf8");
return NS_ERROR_INVALID_ARG;
}
};
let parser_result = rsdparsa::parse_sdp(sdp_str_slice, fail_on_warning);
match parser_result {
Ok(parsed) => {
+ *error = match parsed.warnings.len(){
+ 0 => ptr::null(),
+ _ => Box::into_raw(Box::new(parsed.warnings[0].clone())),
+ };
*session = Rc::into_raw(Rc::new(parsed));
- *error = ptr::null();
NS_OK
},
Err(e) => {
*session = ptr::null();
debug!("{:?}", e);
debug!("Error parsing SDP in rust: {}", e.description());
*error = Box::into_raw(Box::new(e));
NS_ERROR_INVALID_ARG
--- a/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/types.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/types.rs
@@ -1,9 +1,9 @@
-use libc::{size_t, uint32_t};
+use libc::{size_t, uint8_t, uint32_t};
use std::ffi::CStr;
use std::{str, slice};
use std::error::Error;
use std::boxed::Box;
use nserror::{nsresult, NS_OK, NS_ERROR_INVALID_ARG};
#[repr(C)]
@@ -88,8 +88,27 @@ pub unsafe extern "C" fn u32_vec_get(vec
match (*vec).get(index) {
Some(val) => {
*ret = *val;
NS_OK
},
None => NS_ERROR_INVALID_ARG
}
}
+
+
+#[no_mangle]
+pub unsafe extern "C" fn u8_vec_len(vec: *const Vec<u8>) -> size_t {
+ (*vec).len()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn u8_vec_get(vec: *const Vec<u8>,
+ index: size_t,
+ ret: *mut uint8_t) -> nsresult {
+ match (*vec).get(index) {
+ Some(val) => {
+ *ret = *val;
+ NS_OK
+ },
+ None => NS_ERROR_INVALID_ARG
+ }
+}