Bug 1437166: Part 2: Implemented RsdparsaSdpAttributeList::GetSsrcGroup. r=dminor,bwc
Implemented RsdparsaSdpAttributeList::GetSsrcGroup
Added LoadSsrcGroup
Added C++/Rust glue code for the ssrc-group attribute
Added U32Vec in glue code.
Added C++ unit test CheckSsrcGroup (only for the rust parser
MozReview-Commit-ID: 3RxoQ1U0WZy
--- a/media/webrtc/signaling/gtest/sdp_unittests.cpp
+++ b/media/webrtc/signaling/gtest/sdp_unittests.cpp
@@ -3725,16 +3725,64 @@ TEST_P(NewSdpTest, CheckSsrcGroupInSessi
if (mSdp) {
ASSERT_FALSE(mSdp->GetMediaSection(0).GetAttributeList().HasAttribute(
SdpAttribute::kSsrcGroupAttribute));
ASSERT_FALSE(mSdp->GetAttributeList().HasAttribute(
SdpAttribute::kSsrcGroupAttribute));
}
}
+const std::string kSsrcGroupSDP =
+"v=0" CRLF
+"o=- 4294967296 2 IN IP4 127.0.0.1" CRLF
+"s=SIP Call" CRLF
+"c=IN IP4 198.51.100.7" CRLF
+"t=0 0" CRLF
+"m=audio 9 RTP/SAVPF 109" CRLF
+"c=IN IP4 0.0.0.0" CRLF
+"a=mid:first" CRLF
+"a=rtpmap:109 opus/48000/2" CRLF
+"a=fmtp:109 maxplaybackrate=32000;stereo=1" CRLF
+"a=ptime:20" CRLF
+"a=maxptime:20" CRLF
+"a=ssrc-group:FID 11111 22222" CRLF
+"a=ssrc:11111 cname:user3@example.com" CRLF
+"a=ssrc:22222 cname:user3@example.com" CRLF
+"a=ssrc-group:FEC 33333 44444" CRLF
+"a=ssrc:33333 cname:user3@example.com" CRLF
+"a=ssrc:44444 cname:user3@example.com" CRLF;
+
+TEST_P(NewSdpTest, CheckSsrcGroup) {
+ // The sipcc does not support ssrc-group parsing
+ if(!IsParsingWithSipccParser()) {
+ ParseSdp(kSsrcGroupSDP);
+
+ ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
+ ASSERT_EQ(1U, mSdp->GetMediaSectionCount());
+
+ ASSERT_TRUE(mSdp->GetMediaSection(0).GetAttributeList().
+ HasAttribute(SdpAttribute::kSsrcGroupAttribute));
+ const auto& ssrc_groups = mSdp->GetMediaSection(0).GetAttributeList().
+ GetSsrcGroup();
+ ASSERT_EQ(2U, ssrc_groups.mSsrcGroups.size());
+
+ const auto& ssrc_group_0 = ssrc_groups.mSsrcGroups[0];
+ ASSERT_EQ(SdpSsrcGroupAttributeList::kFid, ssrc_group_0.semantics);
+ ASSERT_EQ(2U, ssrc_group_0.ssrcs.size());
+ ASSERT_EQ(11111U, ssrc_group_0.ssrcs[0]);
+ ASSERT_EQ(22222U, ssrc_group_0.ssrcs[1]);
+
+ const auto& ssrc_group_1 = ssrc_groups.mSsrcGroups[1];
+ ASSERT_EQ(SdpSsrcGroupAttributeList::kFec, ssrc_group_1.semantics);
+ ASSERT_EQ(2U, ssrc_group_1.ssrcs.size());
+ ASSERT_EQ(33333U, ssrc_group_1.ssrcs[0]);
+ ASSERT_EQ(44444U, ssrc_group_1.ssrcs[1]);
+ }
+}
+
const std::string kMalformedImageattr =
"v=0" CRLF
"o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
"s=SIP Call" CRLF
"c=IN IP4 224.0.0.1/100/12" CRLF
"t=0 0" CRLF
"m=video 9 RTP/SAVPF 120" CRLF
"c=IN IP4 0.0.0.0" CRLF
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.cpp
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.cpp
@@ -391,18 +391,21 @@ RsdparsaSdpAttributeList::GetSsrc() cons
}
const SdpAttribute* attr = GetAttribute(SdpAttribute::kSsrcAttribute);
return *static_cast<const SdpSsrcAttributeList*>(attr);
}
const SdpSsrcGroupAttributeList&
RsdparsaSdpAttributeList::GetSsrcGroup() const
{
- // TODO: See Bug 1437166.
- MOZ_CRASH("Not yet implemented");
+ if (!HasAttribute(SdpAttribute::kSsrcGroupAttribute)) {
+ MOZ_CRASH();
+ }
+ const SdpAttribute* attr = GetAttribute(SdpAttribute::kSsrcGroupAttribute);
+ return *static_cast<const SdpSsrcGroupAttributeList*>(attr);
}
void
RsdparsaSdpAttributeList::LoadAttribute(RustAttributeList *attributeList,
AttributeType type)
{
if(!mAttributes[type]) {
switch(type) {
@@ -422,16 +425,19 @@ RsdparsaSdpAttributeList::LoadAttribute(
LoadIdentity(attributeList);
return;
case SdpAttribute::kSetupAttribute:
LoadSetup(attributeList);
return;
case SdpAttribute::kSsrcAttribute:
LoadSsrc(attributeList);
return;
+ case SdpAttribute::kSsrcGroupAttribute:
+ LoadSsrcGroup(attributeList);
+ return;
case SdpAttribute::kRtpmapAttribute:
LoadRtpmap(attributeList);
return;
case SdpAttribute::kFmtpAttribute:
LoadFmtp(attributeList);
return;
case SdpAttribute::kPtimeAttribute:
LoadPtime(attributeList);
@@ -477,17 +483,16 @@ RsdparsaSdpAttributeList::LoadAttribute(
return;
case SdpAttribute::kExtmapAttribute:
LoadExtmap(attributeList);
return;
case SdpAttribute::kDtlsMessageAttribute:
case SdpAttribute::kLabelAttribute:
case SdpAttribute::kMaxptimeAttribute:
- case SdpAttribute::kSsrcGroupAttribute:
case SdpAttribute::kMaxMessageSizeAttribute:
case SdpAttribute::kRtcpRsizeAttribute:
case SdpAttribute::kSctpPortAttribute:
case SdpAttribute::kCandidateAttribute:
case SdpAttribute::kSimulcastAttribute:
case SdpAttribute::kConnectionAttribute:
case SdpAttribute::kIceMismatchAttribute:
// TODO: Not implemented, or not applicable.
@@ -629,16 +634,36 @@ RsdparsaSdpAttributeList::LoadSsrc(RustA
ssrcs->PushEntry(ssrc.id, attribute);
} else {
ssrcs->PushEntry(ssrc.id, attribute + ":" + value);
}
}
SetAttribute(ssrcs.release());
}
+void
+RsdparsaSdpAttributeList::LoadSsrcGroup(RustAttributeList* attributeList)
+{
+ size_t ssrcGroupCount = sdp_get_ssrc_group_count(attributeList);
+ if (ssrcGroupCount == 0) {
+ return;
+ }
+ auto rustSsrcGroups = MakeUnique<RustSdpAttributeSsrcGroup[]>(ssrcGroupCount);
+ sdp_get_ssrc_groups(attributeList, ssrcGroupCount, rustSsrcGroups.get());
+ auto ssrc_groups = MakeUnique<SdpSsrcGroupAttributeList>();
+ for(size_t i = 0; i < ssrcGroupCount; i++) {
+ const RustSdpAttributeSsrcGroup& ssrc_group = rustSsrcGroups[i];
+ auto semantics = static_cast<SdpSsrcGroupAttributeList::Semantics>
+ (ssrc_group.semantics);
+ std::vector<uint32_t> ssrcs = convertU32Vec(ssrc_group.ssrcs);
+ ssrc_groups->PushEntry(semantics, ssrcs);
+ }
+ SetAttribute(ssrc_groups.release());
+}
+
SdpRtpmapAttributeList::CodecType
strToCodecType(const std::string &name)
{
auto codec = SdpRtpmapAttributeList::kOtherCodec;
if (!nsCRT::strcasecmp(name.c_str(), "opus")) {
codec = SdpRtpmapAttributeList::kOpus;
} else if (!nsCRT::strcasecmp(name.c_str(), "G722")) {
codec = SdpRtpmapAttributeList::kG722;
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.h
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.h
@@ -121,16 +121,17 @@ private:
void LoadAttribute(RustAttributeList* attributeList, AttributeType type);
void LoadIceUfrag(RustAttributeList* attributeList);
void LoadIcePwd(RustAttributeList* attributeList);
void LoadIdentity(RustAttributeList* attributeList);
void LoadIceOptions(RustAttributeList* attributeList);
void LoadFingerprint(RustAttributeList* attributeList);
void LoadSetup(RustAttributeList* attributeList);
void LoadSsrc(RustAttributeList* attributeList);
+ void LoadSsrcGroup(RustAttributeList* attributeList);
void LoadRtpmap(RustAttributeList* attributeList);
void LoadFmtp(RustAttributeList* attributeList);
void LoadPtime(RustAttributeList* attributeList);
void LoadFlags(RustAttributeList* attributeList);
void LoadMid(RustAttributeList* attributeList);
void LoadMsid(RustAttributeList* attributeList);
void LoadMsidSemantics(RustAttributeList* attributeList);
void LoadGroup(RustAttributeList* attributeList);
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.cpp
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.cpp
@@ -54,9 +54,23 @@ std::vector<uint8_t> convertU8Vec(U8Vec*
uint8_t byte;
u8_vec_get(vec, i, &byte);
ret.push_back(byte);
}
return ret;
}
+std::vector<uint32_t> convertU32Vec(U32Vec* vec)
+{
+ std::vector<std::uint32_t> ret;
+
+ size_t len = u32_vec_len(vec);
+ for (size_t i = 0; i < len; i++) {
+ uint32_t dword;
+ u32_vec_get(vec, i, &dword);
+ ret.push_back(dword);
+ }
+
+ return ret;
}
+
+}
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.h
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.h
@@ -20,13 +20,14 @@ struct FreeRustSdpSession {
};
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);
+std::vector<uint32_t> convertU32Vec(U32Vec* vec);
}
#endif
--- a/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h
+++ b/media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h
@@ -83,16 +83,21 @@ enum class RustSdpSetup {
};
struct RustSdpAttributeSsrc {
uint32_t id;
StringView attribute;
StringView value;
};
+struct RustSdpAttributeSsrcGroup {
+ uint32_t semantics;
+ U32Vec* ssrcs;
+};
+
struct RustSdpAttributeRtpmap {
uint8_t payloadType;
StringView codecName;
uint32_t frequency;
uint32_t channels;
};
struct RustSdpAttributeRtcpFb {
@@ -274,16 +279,20 @@ void sdp_get_fingerprints(const RustAttr
RustSdpAttributeFingerprint* ret);
nsresult sdp_get_setup(const RustAttributeList* aList, RustSdpSetup* ret);
size_t sdp_get_ssrc_count(const RustAttributeList* aList);
void sdp_get_ssrcs(const RustAttributeList* aList,
size_t listSize, RustSdpAttributeSsrc* ret);
+size_t sdp_get_ssrc_group_count(const RustAttributeList* aList);
+void sdp_get_ssrc_groups(const RustAttributeList* aList,
+ size_t listSize, RustSdpAttributeSsrcGroup* ret);
+
size_t sdp_get_rtpmap_count(const RustAttributeList* aList);
void sdp_get_rtpmaps(const RustAttributeList* aList, size_t listSize,
RustSdpAttributeRtpmap* ret);
size_t sdp_get_fmtp_count(const RustAttributeList* aList);
size_t sdp_get_fmtp(const RustAttributeList* aList, size_t listSize,
RustSdpAttributeFmtp* ret);
--- a/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs
+++ b/media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs
@@ -4,17 +4,17 @@ use libc::{size_t, uint8_t, uint16_t, ui
use rsdparsa::SdpSession;
use rsdparsa::attribute_type::{SdpAttribute, SdpAttributeType, SdpAttributePayloadType,
SdpAttributeFingerprint, SdpAttributeSetup, SdpAttributeSsrc,
SdpAttributeRtpmap, SdpAttributeFmtpParameters,
SdpAttributeMsid, SdpAttributeMsidSemantic,
SdpAttributeGroupSemantic, SdpAttributeGroup, SdpAttributeRtcp,
SdpAttributeRtcpFb, SdpAttributeSctpmap,
SdpAttributeRemoteCandidate, SdpAttributeExtmap,
- SdpAttributeDirection};
+ SdpAttributeDirection, SdpAttributeSsrcGroup};
use nserror::{nsresult, NS_OK, NS_ERROR_INVALID_ARG};
use types::StringView;
use network::RustIpAddr;
#[repr(C)]
#[derive(Clone, Copy, PartialEq, Eq)]
@@ -285,16 +285,52 @@ pub unsafe extern "C" fn sdp_get_ssrcs(a
None
}).collect();
let ssrcs = slice::from_raw_parts_mut(ret_ssrcs, ret_size);
ssrcs.copy_from_slice(attrs.as_slice());
}
#[repr(C)]
#[derive(Clone, Copy)]
+pub struct RustSdpAttributeSsrcGroup {
+ pub semantics: uint32_t,
+ pub ssrcs: *const Vec<uint32_t>
+}
+
+impl<'a> From<&'a SdpAttributeSsrcGroup> for RustSdpAttributeSsrcGroup {
+ fn from(other: &SdpAttributeSsrcGroup) -> Self {
+ RustSdpAttributeSsrcGroup {
+ semantics: other.semantics.clone() as u32,
+ ssrcs: &other.ssrcs
+ }
+ }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn sdp_get_ssrc_group_count(attributes: *const Vec<SdpAttribute>) -> size_t {
+ count_attribute((*attributes).as_slice(), RustSdpAttributeType::SsrcGroup)
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn sdp_get_ssrc_groups(attributes: *const Vec<SdpAttribute>,
+ ret_size: size_t,
+ ret_ssrc_groups: *mut RustSdpAttributeSsrcGroup) {
+ let attrs: Vec<_> = (*attributes).iter()
+ .filter_map(|x| if let SdpAttribute::SsrcGroup(ref data) = *x {
+ Some(RustSdpAttributeSsrcGroup::from(data))
+ } else {
+ None
+ }).collect();
+ let ssrc_groups = slice::from_raw_parts_mut(ret_ssrc_groups, ret_size);
+ ssrc_groups.copy_from_slice(attrs.as_slice());
+}
+
+
+#[repr(C)]
+#[derive(Clone, Copy)]
pub struct RustSdpAttributeRtpmap {
pub payload_type: uint8_t,
pub codec_name: StringView,
pub frequency: uint32_t,
pub channels: uint32_t,
}
impl<'a> From<&'a SdpAttributeRtpmap> for RustSdpAttributeRtpmap {