Bug 1437166: Part 2: Implemented RsdparsaSdpAttributeList::GetSsrcGroup. r=dminor,bwc draft
authorJohannes Willbold <j.willbold@mozilla.com>
Thu, 21 Jun 2018 12:44:27 -0700
changeset 809324 4d89745a75c4e1f0d42cdd1e262aeae2391fd41f
parent 809323 bfa8e97836a0a8ac8ab24f3ffba57be8fce51b66
push id113640
push userbmo:johannes.willbold@rub.de
push dateThu, 21 Jun 2018 20:56:30 +0000
reviewersdminor, bwc
bugs1437166
milestone62.0a1
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
media/webrtc/signaling/gtest/sdp_unittests.cpp
media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.cpp
media/webrtc/signaling/src/sdp/RsdparsaSdpAttributeList.h
media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.cpp
media/webrtc/signaling/src/sdp/RsdparsaSdpGlue.h
media/webrtc/signaling/src/sdp/RsdparsaSdpInc.h
media/webrtc/signaling/src/sdp/rsdparsa_capi/src/attribute.rs
--- 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 {