Bug 1225877 - Part 1: Update simulcast ABNF. r?drno draft
authorByron Campen [:bwc] <docfaraday@gmail.com>
Thu, 12 May 2016 14:55:31 -0500
changeset 367020 1b4722becdafe92708bcfe9e33d6d7198c3162d1
parent 366346 c3f5e6079284a7b7053c41f05d0fe06ff031db03
child 367021 9af870ace02befdd1f20494191b1da39eff26c8d
push id18116
push userbcampen@mozilla.com
push dateFri, 13 May 2016 22:52:29 +0000
reviewersdrno
bugs1225877
milestone49.0a1
Bug 1225877 - Part 1: Update simulcast ABNF. r?drno MozReview-Commit-ID: 5zmuAPzqEtB
dom/media/tests/mochitest/sdpUtils.js
media/webrtc/signaling/src/jsep/JsepTrack.cpp
media/webrtc/signaling/src/sdp/SdpAttribute.cpp
media/webrtc/signaling/src/sdp/SdpAttribute.h
media/webrtc/signaling/src/sdp/SipccSdpMediaSection.cpp
media/webrtc/signaling/test/sdp_unittests.cpp
--- a/dom/media/tests/mochitest/sdpUtils.js
+++ b/dom/media/tests/mochitest/sdpUtils.js
@@ -56,19 +56,19 @@ removeAllRtpMaps: function(sdp) {
 reduceAudioMLineToDynamicPtAndOpus: function(sdp) {
   return sdp.replace(/m=audio .*\r\n/g, "m=audio 9 UDP/TLS/RTP/SAVPF 101 109\r\n");
 },
 
 transferSimulcastProperties: function(offer_sdp, answer_sdp) {
   if (!offer_sdp.includes("a=simulcast:")) {
     return answer_sdp;
   }
-  var o_simul = offer_sdp.match(/simulcast: send rid=(.*)([\n$])*/i);
+  var o_simul = offer_sdp.match(/simulcast: send (.*)([\n$])*/i);
   var o_rids = offer_sdp.match(/a=rid:(.*)/ig);
-  var new_answer_sdp = answer_sdp + "a=simulcast: recv rid=" + o_simul[1] + "\r\n";
+  var new_answer_sdp = answer_sdp + "a=simulcast: recv " + o_simul[1] + "\r\n";
   o_rids.forEach((o_rid) => {
     new_answer_sdp = new_answer_sdp + o_rid.replace(/send/, "recv") + "\r\n";
   });
   return new_answer_sdp;
 },
 
 verifySdp: function(desc, expectedType, offerConstraintsList, offerOptions,
                     testOptions) {
--- a/media/webrtc/signaling/src/jsep/JsepTrack.cpp
+++ b/media/webrtc/signaling/src/jsep/JsepTrack.cpp
@@ -225,21 +225,16 @@ JsepTrack::GetRids(const SdpMediaSection
       versions = &simulcast.recvVersions;
       break;
   }
 
   if (!versions->IsSet()) {
     return;
   }
 
-  if (versions->type != SdpSimulcastAttribute::Versions::kRid) {
-    // No support for PT-based simulcast, yet.
-    return;
-  }
-
   for (const SdpSimulcastAttribute::Version& version : *versions) {
     if (!version.choices.empty()) {
       // We validate that rids are present (and sane) elsewhere.
       rids->push_back(*msection.FindRid(version.choices[0]));
     }
   }
 }
 
--- a/media/webrtc/signaling/src/sdp/SdpAttribute.cpp
+++ b/media/webrtc/signaling/src/sdp/SdpAttribute.cpp
@@ -1154,85 +1154,38 @@ SdpSimulcastAttribute::Version::Parse(st
       return false;
     }
     choices.push_back(value);
   } while (SkipChar(is, ',', error));
 
   return true;
 }
 
-bool
-SdpSimulcastAttribute::Version::GetChoicesAsFormats(
-    std::vector<uint16_t>* formats) const
-{
-  for (const std::string& choice : choices) {
-    uint16_t format;
-    if (!SdpHelper::GetPtAsInt(choice, &format) || (format > 127)) {
-      return false;
-    }
-    formats->push_back(format);
-  }
-
-  return true;
-}
-
 void
 SdpSimulcastAttribute::Versions::Serialize(std::ostream& os) const
 {
-  switch (type) {
-    case kRid:
-      os << "rid=";
-      break;
-    case kPt:
-      os << "pt=";
-      break;
-  }
-
   SkipFirstDelimiter semic(";");
   for (const Version& version : *this) {
     if (!version.IsSet()) {
       continue;
     }
     os << semic;
     version.Serialize(os);
   }
 }
 
 bool
 SdpSimulcastAttribute::Versions::Parse(std::istream& is, std::string* error)
 {
-  std::string rawType = ParseKey(is, error);
-  if (rawType.empty()) {
-    return false;
-  }
-
-  if (rawType == "pt") {
-    type = kPt;
-  } else if (rawType == "rid") {
-    type = kRid;
-  } else {
-    *error = "Unknown simulcast identification type ";
-    error->append(rawType);
-    return false;
-  }
-
   do {
     Version version;
     if (!version.Parse(is, error)) {
       return false;
     }
 
-    if (type == kPt) {
-      std::vector<uint16_t> formats;
-      if (!version.GetChoicesAsFormats(&formats)) {
-        *error = "Invalid payload type";
-        return false;
-      }
-    }
-
     push_back(version);
   } while(SkipChar(is, ';', error));
 
   return true;
 }
 
 void
 SdpSimulcastAttribute::Serialize(std::ostream& os) const
--- a/media/webrtc/signaling/src/sdp/SdpAttribute.h
+++ b/media/webrtc/signaling/src/sdp/SdpAttribute.h
@@ -1411,26 +1411,26 @@ inline std::ostream& operator<<(std::ost
       break;
     default:
       MOZ_ASSERT(false);
       os << "?";
   }
   return os;
 }
 
-// sc-attr     = "a=simulcast:" 1*2( WSP sc-str-list ) [WSP sc-pause-list]
-// sc-str-list = sc-dir WSP sc-id-type "=" sc-alt-list *( ";" sc-alt-list )
-// sc-pause-list = "paused=" sc-alt-list
-// sc-dir      = "send" / "recv"
-// sc-id-type  = "pt" / "rid" / token
-// sc-alt-list = sc-id *( "," sc-id )
-// sc-id       = fmt / rid-identifier / token
-// ; WSP defined in [RFC5234]
-// ; fmt, token defined in [RFC4566]
-// ; rid-identifier defined in [I-D.pthatcher-mmusic-rid]
+// sc-attr      = "a=simulcast:" sc-value
+// sc-value     = sc-str-list [SP sc-str-list]
+// sc-str-list  = sc-dir SP sc-alt-list *( ";" sc-alt-list )
+// sc-dir       = "send" / "recv"
+// sc-alt-list  = sc-id *( "," sc-id )
+// sc-id-paused = "~"
+// sc-id        = [sc-id-paused] rid-identifier / token
+// ; SP defined in [RFC5234]
+// ; token defined in [RFC4566]
+// ; rid-identifier defined in [I-D.ietf-mmusic-rid]
 class SdpSimulcastAttribute : public SdpAttribute
 {
 public:
   SdpSimulcastAttribute() : SdpAttribute(kSimulcastAttribute) {}
 
   void Serialize(std::ostream& os) const override;
   bool Parse(std::istream& is, std::string* error);
 
@@ -1438,30 +1438,24 @@ public:
   {
     public:
       void Serialize(std::ostream& os) const;
       bool IsSet() const
       {
         return !choices.empty();
       }
       bool Parse(std::istream& is, std::string* error);
-      bool GetChoicesAsFormats(std::vector<uint16_t>* formats) const;
 
       std::vector<std::string> choices;
   };
 
   class Versions : public std::vector<Version>
   {
     public:
-      enum Type {
-        kPt,
-        kRid
-      };
-
-      Versions() : type(kRid) {}
+      Versions() {}
       void Serialize(std::ostream& os) const;
       bool IsSet() const
       {
         if (empty()) {
           return false;
         }
 
         for (const Version& version : *this) {
@@ -1469,17 +1463,16 @@ public:
             return true;
           }
         }
 
         return false;
       }
 
       bool Parse(std::istream& is, std::string* error);
-      Type type;
   };
 
   Versions sendVersions;
   Versions recvVersions;
 };
 
 ///////////////////////////////////////////////////////////////////////////
 // a=ssrc, RFC5576
--- a/media/webrtc/signaling/src/sdp/SipccSdpMediaSection.cpp
+++ b/media/webrtc/signaling/src/sdp/SipccSdpMediaSection.cpp
@@ -260,34 +260,23 @@ SipccSdpMediaSection::ValidateSimulcastV
                               "simulcast attribute has a direction that is "
                               "inconsistent with the direction of this media "
                               "section.");
     return false;
   }
 
   for (const SdpSimulcastAttribute::Version& version : versions) {
     for (const std::string& id : version.choices) {
-      if (versions.type == SdpSimulcastAttribute::Versions::kRid) {
-        const SdpRidAttributeList::Rid* ridAttr = FindRid(id);
-        if (!ridAttr || (ridAttr->direction != direction)) {
-          std::ostringstream os;
-          os << "No rid attribute for \'" << id << "\'";
-          errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
-                                    os.str());
-          return false;
-        }
-      } else if (versions.type == SdpSimulcastAttribute::Versions::kPt) {
-        if (std::find(mFormats.begin(), mFormats.end(), id)
-            == mFormats.end()) {
-          std::ostringstream os;
-          os << "No pt for \'" << id << "\'";
-          errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
-                                    os.str());
-          return false;
-        }
+      const SdpRidAttributeList::Rid* ridAttr = FindRid(id);
+      if (!ridAttr || (ridAttr->direction != direction)) {
+        std::ostringstream os;
+        os << "No rid attribute for \'" << id << "\'";
+        errorHolder.AddParseError(sdp_get_media_line_number(sdp, level),
+                                  os.str());
+        return false;
       }
     }
   }
   return true;
 }
 
 bool
 SipccSdpMediaSection::LoadConnection(sdp_t* sdp, uint16_t level,
--- a/media/webrtc/signaling/test/sdp_unittests.cpp
+++ b/media/webrtc/signaling/test/sdp_unittests.cpp
@@ -1212,17 +1212,18 @@ const std::string kBasicAudioVideoOffer 
 "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
 "a=rtcp:61026" CRLF
 "a=end-of-candidates" CRLF
 "a=ssrc:1111 foo" CRLF
 "a=ssrc:1111 foo:bar" CRLF
 "a=imageattr:120 send * recv *" CRLF
 "a=imageattr:121 send [x=640,y=480] recv [x=640,y=480]" CRLF
-"a=simulcast:recv pt=120;121" CRLF
+"a=simulcast:recv foo;bar" CRLF
+"a=rid:foo recv pt=96;max-width=80;max-height=60" CRLF
 "a=rid:bar recv pt=96;max-width=800;max-height=600" CRLF
 "m=audio 9 RTP/SAVPF 0" CRLF
 "a=mid:third" CRLF
 "a=rtpmap:0 PCMU/8000" CRLF
 "a=ice-lite" CRLF
 "a=ice-options:foo bar" CRLF
 "a=msid:noappdata" CRLF
 "a=bundle-only" CRLF;
@@ -1799,23 +1800,29 @@ TEST_P(NewSdpTest, CheckRid)
   ASSERT_TRUE(mSdp->GetMediaSection(1).GetAttributeList().HasAttribute(
         SdpAttribute::kRidAttribute));
   ASSERT_FALSE(mSdp->GetMediaSection(2).GetAttributeList().HasAttribute(
         SdpAttribute::kRidAttribute));
 
   const SdpRidAttributeList& rids =
     mSdp->GetMediaSection(1).GetAttributeList().GetRid();
 
-  ASSERT_EQ(1U, rids.mRids.size());
-  ASSERT_EQ("bar", rids.mRids[0].id);
+  ASSERT_EQ(2U, rids.mRids.size());
+  ASSERT_EQ("foo", rids.mRids[0].id);
   ASSERT_EQ(sdp::kRecv, rids.mRids[0].direction);
   ASSERT_EQ(1U, rids.mRids[0].formats.size());
   ASSERT_EQ(96U, rids.mRids[0].formats[0]);
-  ASSERT_EQ(800U, rids.mRids[0].constraints.maxWidth);
-  ASSERT_EQ(600U, rids.mRids[0].constraints.maxHeight);
+  ASSERT_EQ(80U, rids.mRids[0].constraints.maxWidth);
+  ASSERT_EQ(60U, rids.mRids[0].constraints.maxHeight);
+  ASSERT_EQ("bar", rids.mRids[1].id);
+  ASSERT_EQ(sdp::kRecv, rids.mRids[1].direction);
+  ASSERT_EQ(1U, rids.mRids[1].formats.size());
+  ASSERT_EQ(96U, rids.mRids[1].formats[0]);
+  ASSERT_EQ(800U, rids.mRids[1].constraints.maxWidth);
+  ASSERT_EQ(600U, rids.mRids[1].constraints.maxHeight);
 }
 
 TEST_P(NewSdpTest, CheckMediaLevelIceUfrag) {
   ParseSdp(kBasicAudioVideoOffer);
   ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
   ASSERT_EQ(3U, mSdp->GetMediaSectionCount()) << "Wrong number of media sections";
 
   ASSERT_TRUE(mSdp->GetMediaSection(0).GetAttributeList().HasAttribute(
@@ -2120,21 +2127,19 @@ TEST_P(NewSdpTest, CheckSimulcast)
         SdpAttribute::kSimulcastAttribute));
 
   const SdpSimulcastAttribute& simulcast =
     mSdp->GetMediaSection(1).GetAttributeList().GetSimulcast();
 
   ASSERT_EQ(2U, simulcast.recvVersions.size());
   ASSERT_EQ(0U, simulcast.sendVersions.size());
   ASSERT_EQ(1U, simulcast.recvVersions[0].choices.size());
-  ASSERT_EQ("120", simulcast.recvVersions[0].choices[0]);
+  ASSERT_EQ("foo", simulcast.recvVersions[0].choices[0]);
   ASSERT_EQ(1U, simulcast.recvVersions[1].choices.size());
-  ASSERT_EQ("121", simulcast.recvVersions[1].choices[0]);
-  ASSERT_EQ(SdpSimulcastAttribute::Versions::kPt,
-            simulcast.recvVersions.type);
+  ASSERT_EQ("bar", simulcast.recvVersions[1].choices[0]);
 }
 
 TEST_P(NewSdpTest, CheckSctpmap) {
   ParseSdp(kBasicAudioVideoDataOffer);
   ASSERT_TRUE(!!mSdp) << "Parse failed: " << GetParseErrors();
   ASSERT_EQ(3U, mSdp->GetMediaSectionCount())
     << "Wrong number of media sections";
 
@@ -2641,76 +2646,63 @@ TEST_P(NewSdpTest, ParseInvalidSimulcast
            "o=- 4294967296 2 IN IP4 127.0.0.1" CRLF
            "s=SIP Call" CRLF
            "c=IN IP4 198.51.100.7" CRLF
            "b=CT:5000" CRLF
            "t=0 0" CRLF
            "m=video 56436 RTP/SAVPF 120" CRLF
            "a=rtpmap:120 VP8/90000" CRLF
            "a=sendrecv" CRLF
-           "a=simulcast: send rid=9" CRLF,
+           "a=simulcast: send 9" CRLF,
            false);
   ASSERT_NE("", GetParseErrors());
 }
 
 TEST_P(NewSdpTest, ParseInvalidSimulcastNoSuchRecvRid) {
   ParseSdp("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
            "b=CT:5000" CRLF
            "t=0 0" CRLF
            "m=video 56436 RTP/SAVPF 120" CRLF
            "a=rtpmap:120 VP8/90000" CRLF
            "a=sendrecv" CRLF
-           "a=simulcast: recv rid=9" CRLF,
-           false);
-  ASSERT_NE("", GetParseErrors());
-}
-
-TEST_P(NewSdpTest, ParseInvalidSimulcastNoSuchPt) {
-  ParseSdp("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
-           "b=CT:5000" CRLF
-           "t=0 0" CRLF
-           "m=video 56436 RTP/SAVPF 120" CRLF
-           "a=rtpmap:120 VP8/90000" CRLF
-           "a=sendrecv" CRLF
-           "a=simulcast: send pt=9" CRLF,
+           "a=simulcast: recv 9" CRLF,
            false);
   ASSERT_NE("", GetParseErrors());
 }
 
 TEST_P(NewSdpTest, ParseInvalidSimulcastNotSending) {
   ParseSdp("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
            "b=CT:5000" CRLF
            "t=0 0" CRLF
            "m=video 56436 RTP/SAVPF 120" CRLF
            "a=rtpmap:120 VP8/90000" CRLF
            "a=recvonly" CRLF
-           "a=simulcast: send pt=120" CRLF,
+           "a=rid:foo recv pt=120" CRLF
+           "a=simulcast: send foo" CRLF,
            false);
   ASSERT_NE("", GetParseErrors());
 }
 
 TEST_P(NewSdpTest, ParseInvalidSimulcastNotReceiving) {
   ParseSdp("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
            "b=CT:5000" CRLF
            "t=0 0" CRLF
            "m=video 56436 RTP/SAVPF 120" CRLF
            "a=rtpmap:120 VP8/90000" CRLF
            "a=sendonly" CRLF
+           "a=rid:foo send pt=120" CRLF
            "a=simulcast: recv pt=120" CRLF,
            false);
   ASSERT_NE("", GetParseErrors());
 }
 
 const std::string kNoAttributes =
 "v=0" CRLF
 "o=Mozilla-SIPUA-35.0a1 5184 0 IN IP4 0.0.0.0" CRLF
@@ -3575,42 +3567,31 @@ TEST(NewSdpTestNoFixture, CheckSimulcast
   ParseInvalid<SdpSimulcastAttribute::Version>("8,;", 2);
 }
 
 TEST(NewSdpTestNoFixture, CheckSimulcastVersionsSerialize)
 {
   std::ostringstream os;
 
   SdpSimulcastAttribute::Versions versions;
-  versions.type = SdpSimulcastAttribute::Versions::kPt;
   versions.push_back(SdpSimulcastAttribute::Version());
   versions.back().choices.push_back("8");
   versions.Serialize(os);
-  ASSERT_EQ("pt=8", os.str());
-  os.str("");
-
-  versions.type = SdpSimulcastAttribute::Versions::kRid;
-  versions.Serialize(os);
-  ASSERT_EQ("rid=8", os.str());
-  os.str("");
-
-  versions.push_back(SdpSimulcastAttribute::Version());
-  versions.Serialize(os);
-  ASSERT_EQ("rid=8", os.str());
+  ASSERT_EQ("8", os.str());
   os.str("");
 
   versions.back().choices.push_back("9");
   versions.Serialize(os);
-  ASSERT_EQ("rid=8;9", os.str());
+  ASSERT_EQ("8,9", os.str());
   os.str("");
 
   versions.push_back(SdpSimulcastAttribute::Version());
   versions.back().choices.push_back("0");
   versions.Serialize(os);
-  ASSERT_EQ("rid=8;9;0", os.str());
+  ASSERT_EQ("8,9;0", os.str());
   os.str("");
 }
 
 static SdpSimulcastAttribute::Versions
 ParseSimulcastVersions(const std::string& input)
 {
   std::istringstream is(input + " ");
   std::string error;
@@ -3620,85 +3601,66 @@ ParseSimulcastVersions(const std::string
   EXPECT_EQ(EOF, is.get());
   return list;
 }
 
 TEST(NewSdpTestNoFixture, CheckSimulcastVersionsValidParse)
 {
   {
     SdpSimulcastAttribute::Versions versions(
-        ParseSimulcastVersions("pt=8"));
+        ParseSimulcastVersions("8"));
     ASSERT_EQ(1U, versions.size());
-    ASSERT_EQ(SdpSimulcastAttribute::Versions::kPt, versions.type);
     ASSERT_EQ(1U, versions[0].choices.size());
     ASSERT_EQ("8", versions[0].choices[0]);
   }
 
   {
     SdpSimulcastAttribute::Versions versions(
-        ParseSimulcastVersions("rid=8"));
-    ASSERT_EQ(1U, versions.size());
-    ASSERT_EQ(SdpSimulcastAttribute::Versions::kRid, versions.type);
-    ASSERT_EQ(1U, versions[0].choices.size());
-    ASSERT_EQ("8", versions[0].choices[0]);
-  }
-
-  {
-    SdpSimulcastAttribute::Versions versions(
-        ParseSimulcastVersions("pt=8,9"));
+        ParseSimulcastVersions("8,9"));
     ASSERT_EQ(1U, versions.size());
     ASSERT_EQ(2U, versions[0].choices.size());
     ASSERT_EQ("8", versions[0].choices[0]);
     ASSERT_EQ("9", versions[0].choices[1]);
   }
 
   {
     SdpSimulcastAttribute::Versions versions(
-        ParseSimulcastVersions("pt=8,9;10"));
+        ParseSimulcastVersions("8,9;10"));
     ASSERT_EQ(2U, versions.size());
     ASSERT_EQ(2U, versions[0].choices.size());
     ASSERT_EQ("8", versions[0].choices[0]);
     ASSERT_EQ("9", versions[0].choices[1]);
     ASSERT_EQ(1U, versions[1].choices.size());
     ASSERT_EQ("10", versions[1].choices[0]);
   }
 }
 
 TEST(NewSdpTestNoFixture, CheckSimulcastVersionsInvalidParse)
 {
   ParseInvalid<SdpSimulcastAttribute::Versions>("", 0);
-  ParseInvalid<SdpSimulcastAttribute::Versions>("x", 1);
-  ParseInvalid<SdpSimulcastAttribute::Versions>(";", 1);
-  ParseInvalid<SdpSimulcastAttribute::Versions>("8", 1);
-  ParseInvalid<SdpSimulcastAttribute::Versions>("foo=", 4);
-  ParseInvalid<SdpSimulcastAttribute::Versions>("foo=8", 4);
-  ParseInvalid<SdpSimulcastAttribute::Versions>("pt=9999", 7);
-  ParseInvalid<SdpSimulcastAttribute::Versions>("pt=-1", 5);
-  ParseInvalid<SdpSimulcastAttribute::Versions>("pt=x", 4);
-  ParseInvalid<SdpSimulcastAttribute::Versions>("pt=8;", 5);
-  ParseInvalid<SdpSimulcastAttribute::Versions>("pt=8;x", 6);
-  ParseInvalid<SdpSimulcastAttribute::Versions>("pt=8;;", 5);
+  ParseInvalid<SdpSimulcastAttribute::Versions>(";", 0);
+  ParseInvalid<SdpSimulcastAttribute::Versions>("8;", 2);
+  ParseInvalid<SdpSimulcastAttribute::Versions>("8;;", 2);
 }
 
 TEST(NewSdpTestNoFixture, CheckSimulcastSerialize)
 {
   std::ostringstream os;
 
   SdpSimulcastAttribute simulcast;
-  simulcast.recvVersions.type = SdpSimulcastAttribute::Versions::kPt;
   simulcast.recvVersions.push_back(SdpSimulcastAttribute::Version());
   simulcast.recvVersions.back().choices.push_back("8");
   simulcast.Serialize(os);
-  ASSERT_EQ("a=simulcast: recv pt=8" CRLF, os.str());
+  ASSERT_EQ("a=simulcast: recv 8" CRLF, os.str());
   os.str("");
 
   simulcast.sendVersions.push_back(SdpSimulcastAttribute::Version());
   simulcast.sendVersions.back().choices.push_back("9");
   simulcast.Serialize(os);
-  ASSERT_EQ("a=simulcast: send rid=9 recv pt=8" CRLF, os.str());
+  ASSERT_EQ("a=simulcast: send 9 recv 8" CRLF, os.str());
   os.str("");
 }
 
 static SdpSimulcastAttribute
 ParseSimulcast(const std::string& input)
 {
   std::istringstream is(input);
   std::string error;
@@ -3706,81 +3668,71 @@ ParseSimulcast(const std::string& input)
   EXPECT_TRUE(simulcast.Parse(is, &error)) << error;
   EXPECT_TRUE(is.eof());
   return simulcast;
 }
 
 TEST(NewSdpTestNoFixture, CheckSimulcastValidParse)
 {
   {
-    SdpSimulcastAttribute simulcast(ParseSimulcast(" send pt=8"));
+    SdpSimulcastAttribute simulcast(ParseSimulcast(" send 8"));
     ASSERT_EQ(1U, simulcast.sendVersions.size());
-    ASSERT_EQ(SdpSimulcastAttribute::Versions::kPt,
-              simulcast.sendVersions.type);
     ASSERT_EQ(1U, simulcast.sendVersions[0].choices.size());
     ASSERT_EQ("8", simulcast.sendVersions[0].choices[0]);
     ASSERT_EQ(0U, simulcast.recvVersions.size());
   }
 
   {
-    SdpSimulcastAttribute simulcast(ParseSimulcast(" SEND pt=8"));
+    SdpSimulcastAttribute simulcast(ParseSimulcast(" SEND 8"));
     ASSERT_EQ(1U, simulcast.sendVersions.size());
-    ASSERT_EQ(SdpSimulcastAttribute::Versions::kPt,
-              simulcast.sendVersions.type);
     ASSERT_EQ(1U, simulcast.sendVersions[0].choices.size());
     ASSERT_EQ("8", simulcast.sendVersions[0].choices[0]);
     ASSERT_EQ(0U, simulcast.recvVersions.size());
   }
 
   {
-    SdpSimulcastAttribute simulcast(ParseSimulcast(" recv pt=8"));
+    SdpSimulcastAttribute simulcast(ParseSimulcast(" recv 8"));
     ASSERT_EQ(1U, simulcast.recvVersions.size());
-    ASSERT_EQ(SdpSimulcastAttribute::Versions::kPt,
-              simulcast.recvVersions.type);
     ASSERT_EQ(1U, simulcast.recvVersions[0].choices.size());
     ASSERT_EQ("8", simulcast.recvVersions[0].choices[0]);
     ASSERT_EQ(0U, simulcast.sendVersions.size());
   }
 
   {
     SdpSimulcastAttribute simulcast(
         ParseSimulcast(
-          " send pt=8,9;101;97,98 recv pt=101,120;97"));
+          " send 8,9;101;97,98 recv 101,120;97"));
     ASSERT_EQ(3U, simulcast.sendVersions.size());
-    ASSERT_EQ(SdpSimulcastAttribute::Versions::kPt,
-              simulcast.sendVersions.type);
     ASSERT_EQ(2U, simulcast.sendVersions[0].choices.size());
     ASSERT_EQ("8", simulcast.sendVersions[0].choices[0]);
     ASSERT_EQ("9", simulcast.sendVersions[0].choices[1]);
     ASSERT_EQ(1U, simulcast.sendVersions[1].choices.size());
     ASSERT_EQ("101", simulcast.sendVersions[1].choices[0]);
     ASSERT_EQ(2U, simulcast.sendVersions[2].choices.size());
     ASSERT_EQ("97", simulcast.sendVersions[2].choices[0]);
     ASSERT_EQ("98", simulcast.sendVersions[2].choices[1]);
 
     ASSERT_EQ(2U, simulcast.recvVersions.size());
-    ASSERT_EQ(SdpSimulcastAttribute::Versions::kPt,
-              simulcast.recvVersions.type);
     ASSERT_EQ(2U, simulcast.recvVersions[0].choices.size());
     ASSERT_EQ("101", simulcast.recvVersions[0].choices[0]);
     ASSERT_EQ("120", simulcast.recvVersions[0].choices[1]);
     ASSERT_EQ(1U, simulcast.recvVersions[1].choices.size());
     ASSERT_EQ("97", simulcast.recvVersions[1].choices[0]);
   }
 }
 
 TEST(NewSdpTestNoFixture, CheckSimulcastInvalidParse)
 {
   ParseInvalid<SdpSimulcastAttribute>("", 0);
   ParseInvalid<SdpSimulcastAttribute>(" ", 1);
   ParseInvalid<SdpSimulcastAttribute>("vcer ", 4);
-  ParseInvalid<SdpSimulcastAttribute>(" send x", 7);
-  ParseInvalid<SdpSimulcastAttribute>(" recv x", 7);
-  ParseInvalid<SdpSimulcastAttribute>(" send pt=8 send ", 15);
-  ParseInvalid<SdpSimulcastAttribute>(" recv pt=8 recv ", 15);
+  ParseInvalid<SdpSimulcastAttribute>(" send ", 6);
+  ParseInvalid<SdpSimulcastAttribute>(" recv ", 6);
+  ParseInvalid<SdpSimulcastAttribute>(" send 8 send ", 12);
+  ParseInvalid<SdpSimulcastAttribute>(" recv 8 recv ", 12);
 }
 
 static SdpRidAttributeList::Rid
 ParseRid(const std::string& input)
 {
   std::istringstream is(input);
   std::string error;
   SdpRidAttributeList::Rid rid;