Revert "Reland "Version 2 "Refactoring DataContentDescription class"""

This reverts commit 37f2b43274a0d718de53a4cfcf02226356edcf6e.

Reason for revert: fuzzer failures

Original change's description:
> Reland "Version 2 "Refactoring DataContentDescription class""
>
> This is a reland of 14b2758726879d21671a21291dfed8fb4fd5c21c
>
> Original change's description:
> > Version 2 "Refactoring DataContentDescription class"
> >
> > (substantial changes since version 1)
> >
> > This CL splits the cricket::DataContentDescription class into
> > two classes: cricket::RtpDataContentDescription (used for RTP data)
> > and cricket::SctpDataContentDescription (used for SCTP only).
> >
> > SctpDataContentDescription no longer inherits from
> > MediaContentDescriptionImpl, and no longer contains "codecs".
> >
> > Due to usage of internal interfaces by consumers, shimming the old
> > DataContentDescription API is needed.
> >
> > A new cricket::DataContentDescription class is defined, which is
> > a shim over RtpDataContentDescription and SctpDataContentDescription.
> > It exposes as little functionality as possible, but supports the
> > concerned consumer's usage
> >
> > Design document:
> > https://docs.google.com/document/d/1H5LfQxJA2ikMWTQ8FZ3_GAmaXM7knfVQWiSz6ph8VQ0/edit#
> >
> > Version 1 reviewed-on: https://webrtc-review.googlesource.com/c/src/+/132700
> >
> > Bug: webrtc:10358
> > Change-Id: Icf95fb7308244d6f2ebfdb403aaffc544e358580
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/133900
> > Commit-Queue: Harald Alvestrand <hta@webrtc.org>
> > Reviewed-by: Steve Anton <steveanton@webrtc.org>
> > Cr-Commit-Position: refs/heads/master@{#27853}
>
> Bug: webrtc:10358
> Change-Id: Iff45c4694167f0b31b34ff2167c1f4ffa650bcc4
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/135281
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Commit-Queue: Harald Alvestrand <hta@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#27896}

TBR=steveanton@webrtc.org,kwiberg@webrtc.org,hbos@webrtc.org,hta@webrtc.org,shampson@webrtc.org

Change-Id: Ied6d9fb96aafe9c957f2658b34b5331b1f359b26
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:10358
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/135986
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27917}
diff --git a/media/base/codec.cc b/media/base/codec.cc
index 4380514..d0ca29b 100644
--- a/media/base/codec.cc
+++ b/media/base/codec.cc
@@ -334,22 +334,22 @@
   return true;
 }
 
-RtpDataCodec::RtpDataCodec(int id, const std::string& name)
+DataCodec::DataCodec(int id, const std::string& name)
     : Codec(id, name, kDataCodecClockrate) {}
 
-RtpDataCodec::RtpDataCodec() : Codec() {
+DataCodec::DataCodec() : Codec() {
   clockrate = kDataCodecClockrate;
 }
 
-RtpDataCodec::RtpDataCodec(const RtpDataCodec& c) = default;
-RtpDataCodec::RtpDataCodec(RtpDataCodec&& c) = default;
-RtpDataCodec& RtpDataCodec::operator=(const RtpDataCodec& c) = default;
-RtpDataCodec& RtpDataCodec::operator=(RtpDataCodec&& c) = default;
+DataCodec::DataCodec(const DataCodec& c) = default;
+DataCodec::DataCodec(DataCodec&& c) = default;
+DataCodec& DataCodec::operator=(const DataCodec& c) = default;
+DataCodec& DataCodec::operator=(DataCodec&& c) = default;
 
-std::string RtpDataCodec::ToString() const {
+std::string DataCodec::ToString() const {
   char buf[256];
   rtc::SimpleStringBuilder sb(buf);
-  sb << "RtpDataCodec[" << id << ":" << name << "]";
+  sb << "DataCodec[" << id << ":" << name << "]";
   return sb.str();
 }
 
diff --git a/media/base/codec.h b/media/base/codec.h
index bbb147d..091adb6 100644
--- a/media/base/codec.h
+++ b/media/base/codec.h
@@ -192,23 +192,19 @@
   void SetDefaultParameters();
 };
 
-struct RtpDataCodec : public Codec {
-  RtpDataCodec(int id, const std::string& name);
-  RtpDataCodec();
-  RtpDataCodec(const RtpDataCodec& c);
-  RtpDataCodec(RtpDataCodec&& c);
-  ~RtpDataCodec() override = default;
+struct DataCodec : public Codec {
+  DataCodec(int id, const std::string& name);
+  DataCodec();
+  DataCodec(const DataCodec& c);
+  DataCodec(DataCodec&& c);
+  ~DataCodec() override = default;
 
-  RtpDataCodec& operator=(const RtpDataCodec& c);
-  RtpDataCodec& operator=(RtpDataCodec&& c);
+  DataCodec& operator=(const DataCodec& c);
+  DataCodec& operator=(DataCodec&& c);
 
   std::string ToString() const;
 };
 
-// For backwards compatibility
-// TODO(bugs.webrtc.org/10597): Remove when no longer needed.
-typedef RtpDataCodec DataCodec;
-
 // Get the codec setting associated with |payload_type|. If there
 // is no codec associated with that payload type it returns nullptr.
 template <class Codec>
diff --git a/media/base/rtp_data_engine.h b/media/base/rtp_data_engine.h
index b8bfca2..a4647ae 100644
--- a/media/base/rtp_data_engine.h
+++ b/media/base/rtp_data_engine.h
@@ -16,7 +16,6 @@
 #include <string>
 #include <vector>
 
-#include "media/base/codec.h"
 #include "media/base/media_channel.h"
 #include "media/base/media_constants.h"
 #include "media/base/media_engine.h"
@@ -27,6 +26,8 @@
 
 namespace cricket {
 
+struct DataCodec;
+
 class RtpDataEngine : public DataEngineInterface {
  public:
   RtpDataEngine();
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 1013f7c..56078c1 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -72,7 +72,6 @@
   ]
 
   deps = [
-    ":media_protocol_names",
     "../api:array_view",
     "../api:audio_options_api",
     "../api:call_api",
@@ -123,13 +122,6 @@
   ]
 }
 
-rtc_source_set("media_protocol_names") {
-  sources = [
-    "media_protocol_names.cc",
-    "media_protocol_names.h",
-  ]
-}
-
 rtc_static_library("peerconnection") {
   visibility = [ "*" ]
   cflags = []
diff --git a/pc/channel.cc b/pc/channel.cc
index 82de7de..647663e 100644
--- a/pc/channel.cc
+++ b/pc/channel.cc
@@ -1143,7 +1143,7 @@
 }
 
 bool RtpDataChannel::CheckDataChannelTypeFromContent(
-    const RtpDataContentDescription* content,
+    const DataContentDescription* content,
     std::string* error_desc) {
   bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
                   (content->protocol() == kMediaProtocolDtlsSctp));
@@ -1169,7 +1169,7 @@
     return false;
   }
 
-  const RtpDataContentDescription* data = content->as_rtp_data();
+  const DataContentDescription* data = content->as_data();
 
   if (!CheckDataChannelTypeFromContent(data, error_desc)) {
     return false;
@@ -1223,12 +1223,7 @@
     return false;
   }
 
-  const RtpDataContentDescription* data = content->as_rtp_data();
-
-  if (!data) {
-    RTC_LOG(LS_INFO) << "Accepting and ignoring non-RTP content description";
-    return true;
-  }
+  const DataContentDescription* data = content->as_data();
 
   // If the remote data doesn't have codecs, it must be empty, so ignore it.
   if (!data->has_codecs()) {
diff --git a/pc/channel.h b/pc/channel.h
index 9747ec2..1a4cc72 100644
--- a/pc/channel.h
+++ b/pc/channel.h
@@ -518,7 +518,7 @@
 
   // overrides from BaseChannel
   // Checks that data channel type is RTP.
-  bool CheckDataChannelTypeFromContent(const RtpDataContentDescription* content,
+  bool CheckDataChannelTypeFromContent(const DataContentDescription* content,
                                        std::string* error_desc);
   bool SetLocalContent_w(const MediaContentDescription* content,
                          webrtc::SdpType type,
diff --git a/pc/channel_unittest.cc b/pc/channel_unittest.cc
index e31ab53..9c5f82b 100644
--- a/pc/channel_unittest.cc
+++ b/pc/channel_unittest.cc
@@ -94,8 +94,8 @@
 
 class DataTraits : public Traits<cricket::RtpDataChannel,
                                  cricket::FakeDataMediaChannel,
-                                 cricket::RtpDataContentDescription,
-                                 cricket::RtpDataCodec,
+                                 cricket::DataContentDescription,
+                                 cricket::DataCodec,
                                  cricket::DataMediaInfo,
                                  cricket::DataOptions> {};
 
@@ -2308,15 +2308,15 @@
     int flags,
     const cricket::AudioCodec& audio_codec,
     const cricket::VideoCodec& video_codec,
-    cricket::RtpDataContentDescription* data) {
+    cricket::DataContentDescription* data) {
   data->AddCodec(kGoogleDataCodec);
   data->set_rtcp_mux((flags & RTCP_MUX) != 0);
 }
 
 template <>
 void ChannelTest<DataTraits>::CopyContent(
-    const cricket::RtpDataContentDescription& source,
-    cricket::RtpDataContentDescription* data) {
+    const cricket::DataContentDescription& source,
+    cricket::DataContentDescription* data) {
   *data = source;
 }
 
@@ -2330,7 +2330,7 @@
 void ChannelTest<DataTraits>::AddLegacyStreamInContent(
     uint32_t ssrc,
     int flags,
-    cricket::RtpDataContentDescription* data) {
+    cricket::DataContentDescription* data) {
   data->AddLegacyStream(ssrc);
 }
 
diff --git a/pc/jsep_transport_controller_unittest.cc b/pc/jsep_transport_controller_unittest.cc
index c0927b9d..e81b667 100644
--- a/pc/jsep_transport_controller_unittest.cc
+++ b/pc/jsep_transport_controller_unittest.cc
@@ -175,9 +175,8 @@
                       cricket::IceMode ice_mode,
                       cricket::ConnectionRole conn_role,
                       rtc::scoped_refptr<rtc::RTCCertificate> cert) {
-    RTC_CHECK(protocol_type == cricket::MediaProtocolType::kSctp);
-    std::unique_ptr<cricket::SctpDataContentDescription> data(
-        new cricket::SctpDataContentDescription());
+    std::unique_ptr<cricket::DataContentDescription> data(
+        new cricket::DataContentDescription());
     data->set_rtcp_mux(true);
     description->AddContent(mid, protocol_type,
                             /*rejected=*/false, data.release());
diff --git a/pc/media_protocol_names.cc b/pc/media_protocol_names.cc
deleted file mode 100644
index 6ce2f02..0000000
--- a/pc/media_protocol_names.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "pc/media_protocol_names.h"
-
-namespace cricket {
-
-const char kMediaProtocolRtpPrefix[] = "RTP/";
-
-const char kMediaProtocolSctp[] = "SCTP";
-const char kMediaProtocolDtlsSctp[] = "DTLS/SCTP";
-const char kMediaProtocolUdpDtlsSctp[] = "UDP/DTLS/SCTP";
-const char kMediaProtocolTcpDtlsSctp[] = "TCP/DTLS/SCTP";
-
-bool IsDtlsSctp(const std::string& protocol) {
-  return protocol == kMediaProtocolDtlsSctp ||
-         protocol == kMediaProtocolUdpDtlsSctp ||
-         protocol == kMediaProtocolTcpDtlsSctp;
-}
-
-bool IsPlainSctp(const std::string& protocol) {
-  return protocol == kMediaProtocolSctp;
-}
-
-bool IsRtpProtocol(const std::string& protocol) {
-  return protocol.empty() ||
-         (protocol.find(cricket::kMediaProtocolRtpPrefix) != std::string::npos);
-}
-
-bool IsSctpProtocol(const std::string& protocol) {
-  return IsPlainSctp(protocol) || IsDtlsSctp(protocol);
-}
-
-}  // namespace cricket
diff --git a/pc/media_protocol_names.h b/pc/media_protocol_names.h
deleted file mode 100644
index 88f1c46..0000000
--- a/pc/media_protocol_names.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef PC_MEDIA_PROTOCOL_NAMES_H_
-#define PC_MEDIA_PROTOCOL_NAMES_H_
-
-#include <string>
-
-namespace cricket {
-
-// Names or name prefixes of protocols as defined by SDP specifications.
-extern const char kMediaProtocolRtpPrefix[];
-extern const char kMediaProtocolSctp[];
-extern const char kMediaProtocolDtlsSctp[];
-extern const char kMediaProtocolUdpDtlsSctp[];
-extern const char kMediaProtocolTcpDtlsSctp[];
-
-bool IsDtlsSctp(const std::string& protocol);
-bool IsPlainSctp(const std::string& protocol);
-
-// Returns true if the given media section protocol indicates use of RTP.
-bool IsRtpProtocol(const std::string& protocol);
-// Returns true if the given media section protocol indicates use of SCTP.
-bool IsSctpProtocol(const std::string& protocol);
-
-}  // namespace cricket
-
-#endif  // PC_MEDIA_PROTOCOL_NAMES_H_
diff --git a/pc/media_session.cc b/pc/media_session.cc
index 9c03a1e..0eace22 100644
--- a/pc/media_session.cc
+++ b/pc/media_session.cc
@@ -27,7 +27,6 @@
 #include "media/base/media_constants.h"
 #include "p2p/base/p2p_constants.h"
 #include "pc/channel_manager.h"
-#include "pc/media_protocol_names.h"
 #include "pc/rtp_media_utils.h"
 #include "pc/srtp_filter.h"
 #include "rtc_base/checks.h"
@@ -69,6 +68,13 @@
 // but we tolerate "RTP/SAVPF" in offers we receive, for compatibility.
 const char kMediaProtocolSavpf[] = "RTP/SAVPF";
 
+const char kMediaProtocolRtpPrefix[] = "RTP/";
+
+const char kMediaProtocolSctp[] = "SCTP";
+const char kMediaProtocolDtlsSctp[] = "DTLS/SCTP";
+const char kMediaProtocolUdpDtlsSctp[] = "UDP/DTLS/SCTP";
+const char kMediaProtocolTcpDtlsSctp[] = "TCP/DTLS/SCTP";
+
 // Note that the below functions support some protocol strings purely for
 // legacy compatibility, as required by JSEP in Section 5.1.2, Profile Names
 // and Interoperability.
@@ -85,6 +91,20 @@
          protocol == "RTP/SAVP" || protocol == "RTP/AVP";
 }
 
+static bool IsDtlsSctp(const std::string& protocol) {
+  return protocol == kMediaProtocolDtlsSctp ||
+         protocol == kMediaProtocolUdpDtlsSctp ||
+         protocol == kMediaProtocolTcpDtlsSctp;
+}
+
+static bool IsPlainSctp(const std::string& protocol) {
+  return protocol == kMediaProtocolSctp;
+}
+
+static bool IsSctp(const std::string& protocol) {
+  return IsPlainSctp(protocol) || IsDtlsSctp(protocol);
+}
+
 static RtpTransceiverDirection NegotiateRtpTransceiverDirection(
     RtpTransceiverDirection offer,
     RtpTransceiverDirection wants) {
@@ -469,7 +489,7 @@
     StreamParamsVec* current_streams,
     MediaContentDescriptionImpl<C>* content_description) {
   // SCTP streams are not negotiated using SDP/ContentDescriptions.
-  if (IsSctpProtocol(content_description->protocol())) {
+  if (IsSctp(content_description->protocol())) {
     return true;
   }
 
@@ -588,6 +608,11 @@
       target_cryptos->end());
 }
 
+bool IsRtpProtocol(const std::string& protocol) {
+  return protocol.empty() ||
+         (protocol.find(cricket::kMediaProtocolRtpPrefix) != std::string::npos);
+}
+
 static bool IsRtpContent(SessionDescription* sdesc,
                          const std::string& content_name) {
   bool is_rtp = false;
@@ -716,22 +741,32 @@
 // crypto (in current_cryptos) and it is enabled (in secure_policy), crypto is
 // created (according to crypto_suites). The created content is added to the
 // offer.
-static bool CreateContentOffer(
+template <class C>
+static bool CreateMediaContentOffer(
     const MediaDescriptionOptions& media_description_options,
     const MediaSessionOptions& session_options,
+    const std::vector<C>& codecs,
     const SecurePolicy& secure_policy,
     const CryptoParamsVec* current_cryptos,
     const std::vector<std::string>& crypto_suites,
     const RtpHeaderExtensions& rtp_extensions,
     UniqueRandomIdGenerator* ssrc_generator,
     StreamParamsVec* current_streams,
-    MediaContentDescription* offer) {
+    MediaContentDescriptionImpl<C>* offer) {
+  offer->AddCodecs(codecs);
+
   offer->set_rtcp_mux(session_options.rtcp_mux_enabled);
   if (offer->type() == cricket::MEDIA_TYPE_VIDEO) {
     offer->set_rtcp_reduced_size(true);
   }
   offer->set_rtp_header_extensions(rtp_extensions);
 
+  if (!AddStreamParams(media_description_options.sender_options,
+                       session_options.rtcp_cname, ssrc_generator,
+                       current_streams, offer)) {
+    return false;
+  }
+
   AddSimulcastToMediaDescription(media_description_options, offer);
 
   if (secure_policy != SEC_DISABLED) {
@@ -750,30 +785,6 @@
   }
   return true;
 }
-template <class C>
-static bool CreateMediaContentOffer(
-    const MediaDescriptionOptions& media_description_options,
-    const MediaSessionOptions& session_options,
-    const std::vector<C>& codecs,
-    const SecurePolicy& secure_policy,
-    const CryptoParamsVec* current_cryptos,
-    const std::vector<std::string>& crypto_suites,
-    const RtpHeaderExtensions& rtp_extensions,
-    UniqueRandomIdGenerator* ssrc_generator,
-    StreamParamsVec* current_streams,
-    MediaContentDescriptionImpl<C>* offer) {
-  offer->AddCodecs(codecs);
-  if (!AddStreamParams(media_description_options.sender_options,
-                       session_options.rtcp_cname, ssrc_generator,
-                       current_streams, offer)) {
-    return false;
-  }
-
-  return CreateContentOffer(media_description_options, session_options,
-                            secure_policy, current_cryptos, crypto_suites,
-                            rtp_extensions, ssrc_generator, current_streams,
-                            offer);
-}
 
 template <class C>
 static bool ReferencedCodecsMatch(const std::vector<C>& codecs1,
@@ -1175,28 +1186,6 @@
                       audio_codecs->end());
 }
 
-template <class C>
-static bool SetCodecsInAnswer(
-    const MediaContentDescriptionImpl<C>* offer,
-    const std::vector<C>& local_codecs,
-    const MediaDescriptionOptions& media_description_options,
-    const MediaSessionOptions& session_options,
-    UniqueRandomIdGenerator* ssrc_generator,
-    StreamParamsVec* current_streams,
-    MediaContentDescriptionImpl<C>* answer) {
-  std::vector<C> negotiated_codecs;
-  NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs,
-                  media_description_options.codec_preferences.empty());
-  answer->AddCodecs(negotiated_codecs);
-  answer->set_protocol(offer->protocol());
-  if (!AddStreamParams(media_description_options.sender_options,
-                       session_options.rtcp_cname, ssrc_generator,
-                       current_streams, answer)) {
-    return false;  // Something went seriously wrong.
-  }
-  return true;
-}
-
 // Create a media content to be answered for the given |sender_options|
 // according to the given session_options.rtcp_mux, session_options.streams,
 // codecs, crypto, and current_streams.  If we don't currently have crypto (in
@@ -1204,10 +1193,12 @@
 // (according to crypto_suites). The codecs, rtcp_mux, and crypto are all
 // negotiated with the offer. If the negotiation fails, this method returns
 // false.  The created content is added to the offer.
+template <class C>
 static bool CreateMediaContentAnswer(
-    const MediaContentDescription* offer,
+    const MediaContentDescriptionImpl<C>* offer,
     const MediaDescriptionOptions& media_description_options,
     const MediaSessionOptions& session_options,
+    const std::vector<C>& local_codecs,
     const SecurePolicy& sdes_policy,
     const CryptoParamsVec* current_cryptos,
     const RtpHeaderExtensions& local_rtp_extenstions,
@@ -1215,7 +1206,13 @@
     bool enable_encrypted_rtp_header_extensions,
     StreamParamsVec* current_streams,
     bool bundle_enabled,
-    MediaContentDescription* answer) {
+    MediaContentDescriptionImpl<C>* answer) {
+  std::vector<C> negotiated_codecs;
+  NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs,
+                  media_description_options.codec_preferences.empty());
+  answer->AddCodecs(negotiated_codecs);
+  answer->set_protocol(offer->protocol());
+
   answer->set_extmap_allow_mixed_enum(offer->extmap_allow_mixed_enum());
   RtpHeaderExtensions negotiated_rtp_extensions;
   NegotiateRtpHeaderExtensions(
@@ -1243,6 +1240,12 @@
     return false;
   }
 
+  if (!AddStreamParams(media_description_options.sender_options,
+                       session_options.rtcp_cname, ssrc_generator,
+                       current_streams, answer)) {
+    return false;  // Something went seriously wrong.
+  }
+
   AddSimulcastToMediaDescription(media_description_options, answer);
 
   answer->set_direction(NegotiateRtpTransceiverDirection(
@@ -1394,7 +1397,7 @@
   channel_manager->GetSupportedAudioRtpHeaderExtensions(&audio_rtp_extensions_);
   channel_manager->GetSupportedVideoCodecs(&video_codecs_);
   channel_manager->GetSupportedVideoRtpHeaderExtensions(&video_rtp_extensions_);
-  channel_manager->GetSupportedDataCodecs(&rtp_data_codecs_);
+  channel_manager->GetSupportedDataCodecs(&data_codecs_);
   ComputeAudioCodecsIntersectionAndUnion();
 }
 
@@ -1481,15 +1484,15 @@
 
   AudioCodecs offer_audio_codecs;
   VideoCodecs offer_video_codecs;
-  RtpDataCodecs offer_rtp_data_codecs;
+  DataCodecs offer_data_codecs;
   GetCodecsForOffer(current_active_contents, &offer_audio_codecs,
-                    &offer_video_codecs, &offer_rtp_data_codecs);
+                    &offer_video_codecs, &offer_data_codecs);
 
   if (!session_options.vad_enabled) {
     // If application doesn't want CN codecs in offer.
     StripCNCodecs(&offer_audio_codecs);
   }
-  FilterDataCodecs(&offer_rtp_data_codecs,
+  FilterDataCodecs(&offer_data_codecs,
                    session_options.data_channel_type == DCT_SCTP);
 
   RtpHeaderExtensions audio_rtp_extensions;
@@ -1533,7 +1536,7 @@
       case MEDIA_TYPE_DATA:
         if (!AddDataContentForOffer(media_description_options, session_options,
                                     current_content, current_description,
-                                    offer_rtp_data_codecs, &current_streams,
+                                    offer_data_codecs, &current_streams,
                                     offer.get(), &ice_credentials)) {
           return nullptr;
         }
@@ -1631,15 +1634,15 @@
   // sections.
   AudioCodecs answer_audio_codecs;
   VideoCodecs answer_video_codecs;
-  RtpDataCodecs answer_rtp_data_codecs;
+  DataCodecs answer_data_codecs;
   GetCodecsForAnswer(current_active_contents, *offer, &answer_audio_codecs,
-                     &answer_video_codecs, &answer_rtp_data_codecs);
+                     &answer_video_codecs, &answer_data_codecs);
 
   if (!session_options.vad_enabled) {
     // If application doesn't want CN codecs in answer.
     StripCNCodecs(&answer_audio_codecs);
   }
-  FilterDataCodecs(&answer_rtp_data_codecs,
+  FilterDataCodecs(&answer_data_codecs,
                    session_options.data_channel_type == DCT_SCTP);
 
   auto answer = absl::make_unique<SessionDescription>();
@@ -1692,8 +1695,8 @@
         if (!AddDataContentForAnswer(
                 media_description_options, session_options, offer_content,
                 offer, current_content, current_description,
-                bundle_transport.get(), answer_rtp_data_codecs,
-                &current_streams, answer.get(), &ice_credentials)) {
+                bundle_transport.get(), answer_data_codecs, &current_streams,
+                answer.get(), &ice_credentials)) {
           return nullptr;
         }
         break;
@@ -1813,7 +1816,7 @@
     const std::vector<const ContentInfo*>& current_active_contents,
     AudioCodecs* audio_codecs,
     VideoCodecs* video_codecs,
-    RtpDataCodecs* rtp_data_codecs,
+    DataCodecs* data_codecs,
     UsedPayloadTypes* used_pltypes) {
   for (const ContentInfo* content : current_active_contents) {
     if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) {
@@ -1825,13 +1828,9 @@
           content->media_description()->as_video();
       MergeCodecs<VideoCodec>(video->codecs(), video_codecs, used_pltypes);
     } else if (IsMediaContentOfType(content, MEDIA_TYPE_DATA)) {
-      const RtpDataContentDescription* data =
-          content->media_description()->as_rtp_data();
-      if (data) {
-        // Only relevant for RTP datachannels
-        MergeCodecs<RtpDataCodec>(data->codecs(), rtp_data_codecs,
-                                  used_pltypes);
-      }
+      const DataContentDescription* data =
+          content->media_description()->as_data();
+      MergeCodecs<DataCodec>(data->codecs(), data_codecs, used_pltypes);
     }
   }
 }
@@ -1846,18 +1845,18 @@
     const std::vector<const ContentInfo*>& current_active_contents,
     AudioCodecs* audio_codecs,
     VideoCodecs* video_codecs,
-    RtpDataCodecs* rtp_data_codecs) const {
+    DataCodecs* data_codecs) const {
   // First - get all codecs from the current description if the media type
   // is used. Add them to |used_pltypes| so the payload type is not reused if a
   // new media type is added.
   UsedPayloadTypes used_pltypes;
   MergeCodecsFromDescription(current_active_contents, audio_codecs,
-                             video_codecs, rtp_data_codecs, &used_pltypes);
+                             video_codecs, data_codecs, &used_pltypes);
 
   // Add our codecs that are not in the current description.
   MergeCodecs<AudioCodec>(all_audio_codecs_, audio_codecs, &used_pltypes);
   MergeCodecs<VideoCodec>(video_codecs_, video_codecs, &used_pltypes);
-  MergeCodecs<DataCodec>(rtp_data_codecs_, rtp_data_codecs, &used_pltypes);
+  MergeCodecs<DataCodec>(data_codecs_, data_codecs, &used_pltypes);
 }
 
 // Getting codecs for an answer involves these steps:
@@ -1872,18 +1871,18 @@
     const SessionDescription& remote_offer,
     AudioCodecs* audio_codecs,
     VideoCodecs* video_codecs,
-    RtpDataCodecs* rtp_data_codecs) const {
+    DataCodecs* data_codecs) const {
   // First - get all codecs from the current description if the media type
   // is used. Add them to |used_pltypes| so the payload type is not reused if a
   // new media type is added.
   UsedPayloadTypes used_pltypes;
   MergeCodecsFromDescription(current_active_contents, audio_codecs,
-                             video_codecs, rtp_data_codecs, &used_pltypes);
+                             video_codecs, data_codecs, &used_pltypes);
 
   // Second - filter out codecs that we don't support at all and should ignore.
   AudioCodecs filtered_offered_audio_codecs;
   VideoCodecs filtered_offered_video_codecs;
-  RtpDataCodecs filtered_offered_rtp_data_codecs;
+  DataCodecs filtered_offered_data_codecs;
   for (const ContentInfo& content : remote_offer.contents()) {
     if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) {
       const AudioContentDescription* audio =
@@ -1910,19 +1909,15 @@
         }
       }
     } else if (IsMediaContentOfType(&content, MEDIA_TYPE_DATA)) {
-      const RtpDataContentDescription* data =
-          content.media_description()->as_rtp_data();
-      if (data) {
-        // RTP data. This part is inactive for SCTP data.
-        for (const RtpDataCodec& offered_rtp_data_codec : data->codecs()) {
-          if (!FindMatchingCodec<RtpDataCodec>(
-                  data->codecs(), filtered_offered_rtp_data_codecs,
-                  offered_rtp_data_codec, nullptr) &&
-              FindMatchingCodec<RtpDataCodec>(data->codecs(), rtp_data_codecs_,
-                                              offered_rtp_data_codec,
-                                              nullptr)) {
-            filtered_offered_rtp_data_codecs.push_back(offered_rtp_data_codec);
-          }
+      const DataContentDescription* data =
+          content.media_description()->as_data();
+      for (const DataCodec& offered_data_codec : data->codecs()) {
+        if (!FindMatchingCodec<DataCodec>(data->codecs(),
+                                          filtered_offered_data_codecs,
+                                          offered_data_codec, nullptr) &&
+            FindMatchingCodec<DataCodec>(data->codecs(), data_codecs_,
+                                         offered_data_codec, nullptr)) {
+          filtered_offered_data_codecs.push_back(offered_data_codec);
         }
       }
     }
@@ -1934,7 +1929,7 @@
                           &used_pltypes);
   MergeCodecs<VideoCodec>(filtered_offered_video_codecs, video_codecs,
                           &used_pltypes);
-  MergeCodecs<DataCodec>(filtered_offered_rtp_data_codecs, rtp_data_codecs,
+  MergeCodecs<DataCodec>(filtered_offered_data_codecs, data_codecs,
                          &used_pltypes);
 }
 
@@ -2211,101 +2206,18 @@
   return true;
 }
 
-bool MediaSessionDescriptionFactory::AddSctpDataContentForOffer(
-    const MediaDescriptionOptions& media_description_options,
-    const MediaSessionOptions& session_options,
-    const ContentInfo* current_content,
-    const SessionDescription* current_description,
-    StreamParamsVec* current_streams,
-    SessionDescription* desc,
-    IceCredentialsIterator* ice_credentials) const {
-  std::unique_ptr<SctpDataContentDescription> data(
-      new SctpDataContentDescription());
-
-  bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
-
-  cricket::SecurePolicy sdes_policy =
-      IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
-                                                         : secure();
-  std::vector<std::string> crypto_suites;
-  // SDES doesn't make sense for SCTP, so we disable it, and we only
-  // get SDES crypto suites for RTP-based data channels.
-  sdes_policy = cricket::SEC_DISABLED;
-  // Unlike SetMediaProtocol below, we need to set the protocol
-  // before we call CreateMediaContentOffer.  Otherwise,
-  // CreateMediaContentOffer won't know this is SCTP and will
-  // generate SSRCs rather than SIDs.
-  // TODO(deadbeef): Offer kMediaProtocolUdpDtlsSctp (or TcpDtlsSctp), once
-  // it's safe to do so. Older versions of webrtc would reject these
-  // protocols; see https://bugs.chromium.org/p/webrtc/issues/detail?id=7706.
-  data->set_protocol(secure_transport ? kMediaProtocolDtlsSctp
-                                      : kMediaProtocolSctp);
-
-  if (!CreateContentOffer(media_description_options, session_options,
-                          sdes_policy, GetCryptos(current_content),
-                          crypto_suites, RtpHeaderExtensions(), ssrc_generator_,
-                          current_streams, data.get())) {
-    return false;
-  }
-
-  desc->AddContent(media_description_options.mid, MediaProtocolType::kSctp,
-                   data.release());
-  if (!AddTransportOffer(media_description_options.mid,
-                         media_description_options.transport_options,
-                         current_description, desc, ice_credentials)) {
-    return false;
-  }
-  return true;
-}
-
-bool MediaSessionDescriptionFactory::AddRtpDataContentForOffer(
-    const MediaDescriptionOptions& media_description_options,
-    const MediaSessionOptions& session_options,
-    const ContentInfo* current_content,
-    const SessionDescription* current_description,
-    const RtpDataCodecs& rtp_data_codecs,
-    StreamParamsVec* current_streams,
-    SessionDescription* desc,
-    IceCredentialsIterator* ice_credentials) const {
-  std::unique_ptr<RtpDataContentDescription> data(
-      new RtpDataContentDescription());
-  bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
-
-  cricket::SecurePolicy sdes_policy =
-      IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
-                                                         : secure();
-  std::vector<std::string> crypto_suites;
-  GetSupportedDataSdesCryptoSuiteNames(session_options.crypto_options,
-                                       &crypto_suites);
-  if (!CreateMediaContentOffer(media_description_options, session_options,
-                               rtp_data_codecs, sdes_policy,
-                               GetCryptos(current_content), crypto_suites,
-                               RtpHeaderExtensions(), ssrc_generator_,
-                               current_streams, data.get())) {
-    return false;
-  }
-
-  data->set_bandwidth(kDataMaxBandwidth);
-  SetMediaProtocol(secure_transport, data.get());
-  desc->AddContent(media_description_options.mid, MediaProtocolType::kRtp,
-                   media_description_options.stopped, data.release());
-  if (!AddTransportOffer(media_description_options.mid,
-                         media_description_options.transport_options,
-                         current_description, desc, ice_credentials)) {
-    return false;
-  }
-  return true;
-}
-
 bool MediaSessionDescriptionFactory::AddDataContentForOffer(
     const MediaDescriptionOptions& media_description_options,
     const MediaSessionOptions& session_options,
     const ContentInfo* current_content,
     const SessionDescription* current_description,
-    const RtpDataCodecs& rtp_data_codecs,
+    const DataCodecs& data_codecs,
     StreamParamsVec* current_streams,
     SessionDescription* desc,
     IceCredentialsIterator* ice_credentials) const {
+  bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
+
+  std::unique_ptr<DataContentDescription> data(new DataContentDescription());
   bool is_sctp = (session_options.data_channel_type == DCT_SCTP);
   // If the DataChannel type is not specified, use the DataChannel type in
   // the current description.
@@ -2314,16 +2226,52 @@
     is_sctp = (current_content->media_description()->protocol() ==
                kMediaProtocolSctp);
   }
+
+  cricket::SecurePolicy sdes_policy =
+      IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
+                                                         : secure();
+  std::vector<std::string> crypto_suites;
   if (is_sctp) {
-    return AddSctpDataContentForOffer(
-        media_description_options, session_options, current_content,
-        current_description, current_streams, desc, ice_credentials);
+    // SDES doesn't make sense for SCTP, so we disable it, and we only
+    // get SDES crypto suites for RTP-based data channels.
+    sdes_policy = cricket::SEC_DISABLED;
+    // Unlike SetMediaProtocol below, we need to set the protocol
+    // before we call CreateMediaContentOffer.  Otherwise,
+    // CreateMediaContentOffer won't know this is SCTP and will
+    // generate SSRCs rather than SIDs.
+    // TODO(deadbeef): Offer kMediaProtocolUdpDtlsSctp (or TcpDtlsSctp), once
+    // it's safe to do so. Older versions of webrtc would reject these
+    // protocols; see https://bugs.chromium.org/p/webrtc/issues/detail?id=7706.
+    data->set_protocol(secure_transport ? kMediaProtocolDtlsSctp
+                                        : kMediaProtocolSctp);
   } else {
-    return AddRtpDataContentForOffer(media_description_options, session_options,
-                                     current_content, current_description,
-                                     rtp_data_codecs, current_streams, desc,
-                                     ice_credentials);
+    GetSupportedDataSdesCryptoSuiteNames(session_options.crypto_options,
+                                         &crypto_suites);
   }
+
+  // Even SCTP uses a "codec".
+  if (!CreateMediaContentOffer(
+          media_description_options, session_options, data_codecs, sdes_policy,
+          GetCryptos(current_content), crypto_suites, RtpHeaderExtensions(),
+          ssrc_generator_, current_streams, data.get())) {
+    return false;
+  }
+
+  if (is_sctp) {
+    desc->AddContent(media_description_options.mid, MediaProtocolType::kSctp,
+                     data.release());
+  } else {
+    data->set_bandwidth(kDataMaxBandwidth);
+    SetMediaProtocol(secure_transport, data.get());
+    desc->AddContent(media_description_options.mid, MediaProtocolType::kRtp,
+                     media_description_options.stopped, data.release());
+  }
+  if (!AddTransportOffer(media_description_options.mid,
+                         media_description_options.transport_options,
+                         current_description, desc, ice_credentials)) {
+    return false;
+  }
+  return true;
 }
 
 // |audio_codecs| = set of all possible codecs that can be used, with correct
@@ -2411,15 +2359,9 @@
   // Do not require or create SDES cryptos if DTLS is used.
   cricket::SecurePolicy sdes_policy =
       audio_transport->secure() ? cricket::SEC_DISABLED : secure();
-  if (!SetCodecsInAnswer(offer_audio_description, filtered_codecs,
-                         media_description_options, session_options,
-                         ssrc_generator_, current_streams,
-                         audio_answer.get())) {
-    return false;
-  }
   if (!CreateMediaContentAnswer(
           offer_audio_description, media_description_options, session_options,
-          sdes_policy, GetCryptos(current_content),
+          filtered_codecs, sdes_policy, GetCryptos(current_content),
           audio_rtp_header_extensions(), ssrc_generator_,
           enable_encrypted_rtp_header_extensions_, current_streams,
           bundle_enabled, audio_answer.get())) {
@@ -2512,15 +2454,9 @@
   // Do not require or create SDES cryptos if DTLS is used.
   cricket::SecurePolicy sdes_policy =
       video_transport->secure() ? cricket::SEC_DISABLED : secure();
-  if (!SetCodecsInAnswer(offer_video_description, filtered_codecs,
-                         media_description_options, session_options,
-                         ssrc_generator_, current_streams,
-                         video_answer.get())) {
-    return false;
-  }
   if (!CreateMediaContentAnswer(
           offer_video_description, media_description_options, session_options,
-          sdes_policy, GetCryptos(current_content),
+          filtered_codecs, sdes_policy, GetCryptos(current_content),
           video_rtp_header_extensions(), ssrc_generator_,
           enable_encrypted_rtp_header_extensions_, current_streams,
           bundle_enabled, video_answer.get())) {
@@ -2556,7 +2492,7 @@
     const ContentInfo* current_content,
     const SessionDescription* current_description,
     const TransportInfo* bundle_transport,
-    const RtpDataCodecs& rtp_data_codecs,
+    const DataCodecs& data_codecs,
     StreamParamsVec* current_streams,
     SessionDescription* answer,
     IceCredentialsIterator* ice_credentials) const {
@@ -2568,52 +2504,29 @@
     return false;
   }
 
+  std::unique_ptr<DataContentDescription> data_answer(
+      new DataContentDescription());
   // Do not require or create SDES cryptos if DTLS is used.
   cricket::SecurePolicy sdes_policy =
       data_transport->secure() ? cricket::SEC_DISABLED : secure();
   bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
                         session_options.bundle_enabled;
   RTC_CHECK(IsMediaContentOfType(offer_content, MEDIA_TYPE_DATA));
-  std::unique_ptr<MediaContentDescription> data_answer;
-  if (offer_content->media_description()->as_sctp()) {
-    // SCTP data content
-    data_answer = absl::make_unique<SctpDataContentDescription>();
-    const SctpDataContentDescription* offer_data_description =
-        offer_content->media_description()->as_sctp();
-    // Respond with the offerer's proto, whatever it is.
-    data_answer->as_sctp()->set_protocol(offer_data_description->protocol());
-    if (!CreateMediaContentAnswer(
-            offer_data_description, media_description_options, session_options,
-            sdes_policy, GetCryptos(current_content), RtpHeaderExtensions(),
-            ssrc_generator_, enable_encrypted_rtp_header_extensions_,
-            current_streams, bundle_enabled, data_answer.get())) {
-      return false;  // Fails the session setup.
-    }
-    // Respond with sctpmap if the offer uses sctpmap.
-    bool offer_uses_sctpmap = offer_data_description->use_sctpmap();
-    data_answer->as_sctp()->set_use_sctpmap(offer_uses_sctpmap);
-  } else {
-    // RTP offer
-    data_answer = absl::make_unique<RtpDataContentDescription>();
-
-    const RtpDataContentDescription* offer_data_description =
-        offer_content->media_description()->as_rtp_data();
-    RTC_CHECK(offer_data_description);
-    if (!SetCodecsInAnswer(offer_data_description, rtp_data_codecs,
-                           media_description_options, session_options,
-                           ssrc_generator_, current_streams,
-                           data_answer->as_rtp_data())) {
-      return false;
-    }
-    if (!CreateMediaContentAnswer(
-            offer_data_description, media_description_options, session_options,
-            sdes_policy, GetCryptos(current_content), RtpHeaderExtensions(),
-            ssrc_generator_, enable_encrypted_rtp_header_extensions_,
-            current_streams, bundle_enabled, data_answer.get())) {
-      return false;  // Fails the session setup.
-    }
+  const DataContentDescription* offer_data_description =
+      offer_content->media_description()->as_data();
+  if (!CreateMediaContentAnswer(
+          offer_data_description, media_description_options, session_options,
+          data_codecs, sdes_policy, GetCryptos(current_content),
+          RtpHeaderExtensions(), ssrc_generator_,
+          enable_encrypted_rtp_header_extensions_, current_streams,
+          bundle_enabled, data_answer.get())) {
+    return false;  // Fails the session setup.
   }
 
+  // Respond with sctpmap if the offer uses sctpmap.
+  bool offer_uses_sctpmap = offer_data_description->use_sctpmap();
+  data_answer->set_use_sctpmap(offer_uses_sctpmap);
+
   bool secure = bundle_transport ? bundle_transport->description.secure()
                                  : data_transport->secure();
 
@@ -2736,35 +2649,20 @@
 
 const AudioContentDescription* GetFirstAudioContentDescription(
     const SessionDescription* sdesc) {
-  auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO);
-  return desc ? desc->as_audio() : nullptr;
+  return static_cast<const AudioContentDescription*>(
+      GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO));
 }
 
 const VideoContentDescription* GetFirstVideoContentDescription(
     const SessionDescription* sdesc) {
-  auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO);
-  return desc ? desc->as_video() : nullptr;
+  return static_cast<const VideoContentDescription*>(
+      GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO));
 }
 
-const RtpDataContentDescription* GetFirstRtpDataContentDescription(
-    const SessionDescription* sdesc) {
-  auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
-  return desc ? desc->as_rtp_data() : nullptr;
-}
-
-const SctpDataContentDescription* GetFirstSctpDataContentDescription(
-    const SessionDescription* sdesc) {
-  auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
-  return desc ? desc->as_sctp() : nullptr;
-}
-
-// Returns a shim representing either an SctpDataContentDescription
-// or an RtpDataContentDescription, as appropriate.
-// TODO(bugs.webrtc.org/10597): Remove together with shim.
 const DataContentDescription* GetFirstDataContentDescription(
     const SessionDescription* sdesc) {
-  auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
-  return desc ? desc->as_data() : nullptr;
+  return static_cast<const DataContentDescription*>(
+      GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA));
 }
 
 //
@@ -2823,33 +2721,20 @@
 
 AudioContentDescription* GetFirstAudioContentDescription(
     SessionDescription* sdesc) {
-  auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO);
-  return desc ? desc->as_audio() : nullptr;
+  return static_cast<AudioContentDescription*>(
+      GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO));
 }
 
 VideoContentDescription* GetFirstVideoContentDescription(
     SessionDescription* sdesc) {
-  auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO);
-  return desc ? desc->as_video() : nullptr;
+  return static_cast<VideoContentDescription*>(
+      GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO));
 }
 
-RtpDataContentDescription* GetFirstRtpDataContentDescription(
-    SessionDescription* sdesc) {
-  auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
-  return desc ? desc->as_rtp_data() : nullptr;
-}
-
-SctpDataContentDescription* GetFirstSctpDataContentDescription(
-    SessionDescription* sdesc) {
-  auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
-  return desc ? desc->as_sctp() : nullptr;
-}
-
-// Returns shim
 DataContentDescription* GetFirstDataContentDescription(
     SessionDescription* sdesc) {
-  auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
-  return desc ? desc->as_data() : nullptr;
+  return static_cast<DataContentDescription*>(
+      GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA));
 }
 
 }  // namespace cricket
diff --git a/pc/media_session.h b/pc/media_session.h
index dc889b2..a369756 100644
--- a/pc/media_session.h
+++ b/pc/media_session.h
@@ -24,7 +24,6 @@
 #include "p2p/base/ice_credentials_iterator.h"
 #include "p2p/base/transport_description_factory.h"
 #include "pc/jsep_transport.h"
-#include "pc/media_protocol_names.h"
 #include "pc/session_description.h"
 #include "rtc_base/unique_id_generator.h"
 
@@ -155,10 +154,8 @@
     video_rtp_extensions_ = extensions;
   }
   RtpHeaderExtensions video_rtp_header_extensions() const;
-  const RtpDataCodecs& rtp_data_codecs() const { return rtp_data_codecs_; }
-  void set_rtp_data_codecs(const RtpDataCodecs& codecs) {
-    rtp_data_codecs_ = codecs;
-  }
+  const DataCodecs& data_codecs() const { return data_codecs_; }
+  void set_data_codecs(const DataCodecs& codecs) { data_codecs_ = codecs; }
   SecurePolicy secure() const { return secure_; }
   void set_secure(SecurePolicy s) { secure_ = s; }
 
@@ -188,13 +185,13 @@
       const std::vector<const ContentInfo*>& current_active_contents,
       AudioCodecs* audio_codecs,
       VideoCodecs* video_codecs,
-      RtpDataCodecs* rtp_data_codecs) const;
+      DataCodecs* data_codecs) const;
   void GetCodecsForAnswer(
       const std::vector<const ContentInfo*>& current_active_contents,
       const SessionDescription& remote_offer,
       AudioCodecs* audio_codecs,
       VideoCodecs* video_codecs,
-      RtpDataCodecs* rtp_data_codecs) const;
+      DataCodecs* data_codecs) const;
   void GetRtpHdrExtsToOffer(
       const std::vector<const ContentInfo*>& current_active_contents,
       RtpHeaderExtensions* audio_extensions,
@@ -243,32 +240,12 @@
       SessionDescription* desc,
       IceCredentialsIterator* ice_credentials) const;
 
-  bool AddSctpDataContentForOffer(
-      const MediaDescriptionOptions& media_description_options,
-      const MediaSessionOptions& session_options,
-      const ContentInfo* current_content,
-      const SessionDescription* current_description,
-      StreamParamsVec* current_streams,
-      SessionDescription* desc,
-      IceCredentialsIterator* ice_credentials) const;
-  bool AddRtpDataContentForOffer(
-      const MediaDescriptionOptions& media_description_options,
-      const MediaSessionOptions& session_options,
-      const ContentInfo* current_content,
-      const SessionDescription* current_description,
-      const RtpDataCodecs& rtp_data_codecs,
-      StreamParamsVec* current_streams,
-      SessionDescription* desc,
-      IceCredentialsIterator* ice_credentials) const;
-  // This function calls either AddRtpDataContentForOffer or
-  // AddSctpDataContentForOffer depending on protocol.
-  // The codecs argument is ignored for SCTP.
   bool AddDataContentForOffer(
       const MediaDescriptionOptions& media_description_options,
       const MediaSessionOptions& session_options,
       const ContentInfo* current_content,
       const SessionDescription* current_description,
-      const RtpDataCodecs& rtp_data_codecs,
+      const DataCodecs& data_codecs,
       StreamParamsVec* current_streams,
       SessionDescription* desc,
       IceCredentialsIterator* ice_credentials) const;
@@ -307,7 +284,7 @@
       const ContentInfo* current_content,
       const SessionDescription* current_description,
       const TransportInfo* bundle_transport,
-      const RtpDataCodecs& rtp_data_codecs,
+      const DataCodecs& data_codecs,
       StreamParamsVec* current_streams,
       SessionDescription* answer,
       IceCredentialsIterator* ice_credentials) const;
@@ -324,7 +301,7 @@
   RtpHeaderExtensions audio_rtp_extensions_;
   VideoCodecs video_codecs_;
   RtpHeaderExtensions video_rtp_extensions_;
-  RtpDataCodecs rtp_data_codecs_;
+  DataCodecs data_codecs_;
   // This object is not owned by the channel so it must outlive it.
   rtc::UniqueRandomIdGenerator* const ssrc_generator_;
   bool enable_encrypted_rtp_header_extensions_ = false;
@@ -353,11 +330,6 @@
     const SessionDescription* sdesc);
 const VideoContentDescription* GetFirstVideoContentDescription(
     const SessionDescription* sdesc);
-const RtpDataContentDescription* GetFirstRtpDataContentDescription(
-    const SessionDescription* sdesc);
-const SctpDataContentDescription* GetFirstSctpDataContentDescription(
-    const SessionDescription* sdesc);
-// Returns shim. Deprecated - ask for the right protocol instead.
 const DataContentDescription* GetFirstDataContentDescription(
     const SessionDescription* sdesc);
 // Non-const versions of the above functions.
@@ -375,10 +347,6 @@
     SessionDescription* sdesc);
 VideoContentDescription* GetFirstVideoContentDescription(
     SessionDescription* sdesc);
-RtpDataContentDescription* GetFirstRtpDataContentDescription(
-    SessionDescription* sdesc);
-SctpDataContentDescription* GetFirstSctpDataContentDescription(
-    SessionDescription* sdesc);
 DataContentDescription* GetFirstDataContentDescription(
     SessionDescription* sdesc);
 
@@ -402,6 +370,9 @@
     const webrtc::CryptoOptions& crypto_options,
     std::vector<std::string>* crypto_suite_names);
 
+// Returns true if the given media section protocol indicates use of RTP.
+bool IsRtpProtocol(const std::string& protocol);
+
 }  // namespace cricket
 
 #endif  // PC_MEDIA_SESSION_H_
diff --git a/pc/media_session_unittest.cc b/pc/media_session_unittest.cc
index b69ded3..1136607 100644
--- a/pc/media_session_unittest.cc
+++ b/pc/media_session_unittest.cc
@@ -42,10 +42,12 @@
 using cricket::AudioContentDescription;
 using cricket::ContentInfo;
 using cricket::CryptoParamsVec;
+using cricket::DataCodec;
+using cricket::DataContentDescription;
 using cricket::GetFirstAudioContent;
 using cricket::GetFirstAudioContentDescription;
 using cricket::GetFirstDataContent;
-using cricket::GetFirstRtpDataContentDescription;
+using cricket::GetFirstDataContentDescription;
 using cricket::GetFirstVideoContent;
 using cricket::GetFirstVideoContentDescription;
 using cricket::kAutoBandwidth;
@@ -60,9 +62,6 @@
 using cricket::MediaType;
 using cricket::RidDescription;
 using cricket::RidDirection;
-using cricket::RtpDataCodec;
-using cricket::RtpDataContentDescription;
-using cricket::SctpDataContentDescription;
 using cricket::SEC_DISABLED;
 using cricket::SEC_ENABLED;
 using cricket::SEC_REQUIRED;
@@ -127,14 +126,14 @@
 
 static const VideoCodec kVideoCodecsAnswer[] = {VideoCodec(97, "H264")};
 
-static const RtpDataCodec kDataCodecs1[] = {RtpDataCodec(98, "binary-data"),
-                                            RtpDataCodec(99, "utf8-text")};
+static const DataCodec kDataCodecs1[] = {DataCodec(98, "binary-data"),
+                                         DataCodec(99, "utf8-text")};
 
-static const RtpDataCodec kDataCodecs2[] = {RtpDataCodec(126, "binary-data"),
-                                            RtpDataCodec(127, "utf8-text")};
+static const DataCodec kDataCodecs2[] = {DataCodec(126, "binary-data"),
+                                         DataCodec(127, "utf8-text")};
 
-static const RtpDataCodec kDataCodecsAnswer[] = {
-    RtpDataCodec(98, "binary-data"), RtpDataCodec(99, "utf8-text")};
+static const DataCodec kDataCodecsAnswer[] = {DataCodec(98, "binary-data"),
+                                              DataCodec(99, "utf8-text")};
 
 static const RtpExtension kAudioRtpExtension1[] = {
     RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
@@ -413,11 +412,11 @@
     f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
                          MAKE_VECTOR(kAudioCodecs1));
     f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
-    f1_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs1));
+    f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
     f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
                          MAKE_VECTOR(kAudioCodecs2));
     f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
-    f2_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs2));
+    f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
     tdf1_.set_certificate(rtc::RTCCertificate::Create(
         std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
     tdf2_.set_certificate(rtc::RTCCertificate::Create(
@@ -802,7 +801,7 @@
 TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
   const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
   const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0];
-  const RtpDataCodec& offered_data_codec = f2_.rtp_data_codecs()[0];
+  const DataCodec& offered_data_codec = f2_.data_codecs()[0];
   ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
   ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
 
@@ -815,8 +814,8 @@
       GetFirstVideoContentDescription(offer.get());
   const AudioContentDescription* acd =
       GetFirstAudioContentDescription(offer.get());
-  const RtpDataContentDescription* dcd =
-      GetFirstRtpDataContentDescription(offer.get());
+  const DataContentDescription* dcd =
+      GetFirstDataContentDescription(offer.get());
   ASSERT_TRUE(NULL != vcd);
   ASSERT_TRUE(NULL != acd);
   ASSERT_TRUE(NULL != dcd);
@@ -859,8 +858,8 @@
       GetFirstAudioContentDescription(updated_offer.get());
   const VideoContentDescription* vcd =
       GetFirstVideoContentDescription(updated_offer.get());
-  const RtpDataContentDescription* dcd =
-      GetFirstRtpDataContentDescription(updated_offer.get());
+  const DataContentDescription* dcd =
+      GetFirstDataContentDescription(updated_offer.get());
   EXPECT_TRUE(NULL != vcd);
   EXPECT_TRUE(NULL != acd);
   EXPECT_TRUE(NULL != dcd);
@@ -888,7 +887,7 @@
   EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
   EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
   const AudioContentDescription* acd = ac->media_description()->as_audio();
-  const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
+  const DataContentDescription* dcd = dc->media_description()->as_data();
   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
   EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
   EXPECT_EQ(0U, acd->first_ssrc());             // no sender is attched.
@@ -897,7 +896,7 @@
   ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
   EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
   EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
-  EXPECT_EQ(f1_.rtp_data_codecs(), dcd->codecs());
+  EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
   EXPECT_EQ(0U, dcd->first_ssrc());  // no sender is attached.
   EXPECT_EQ(cricket::kDataMaxBandwidth,
             dcd->bandwidth());   // default bandwidth (auto)
@@ -1281,7 +1280,7 @@
   EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
   EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
   const AudioContentDescription* acd = ac->media_description()->as_audio();
-  const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
+  const DataContentDescription* dcd = dc->media_description()->as_data();
   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
   EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
@@ -1313,7 +1312,7 @@
   EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
   EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
   const AudioContentDescription* acd = ac->media_description()->as_audio();
-  const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
+  const DataContentDescription* dcd = dc->media_description()->as_data();
   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
   EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
   EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
@@ -1337,16 +1336,15 @@
   ASSERT_TRUE(offer.get() != NULL);
   ContentInfo* dc_offer = offer->GetContentByName("data");
   ASSERT_TRUE(dc_offer != NULL);
-  SctpDataContentDescription* dcd_offer =
-      dc_offer->media_description()->as_sctp();
+  DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
   EXPECT_TRUE(dcd_offer->use_sctpmap());
 
   std::unique_ptr<SessionDescription> answer =
       f2_.CreateAnswer(offer.get(), opts, NULL);
   const ContentInfo* dc_answer = answer->GetContentByName("data");
   ASSERT_TRUE(dc_answer != NULL);
-  const SctpDataContentDescription* dcd_answer =
-      dc_answer->media_description()->as_sctp();
+  const DataContentDescription* dcd_answer =
+      dc_answer->media_description()->as_data();
   EXPECT_TRUE(dcd_answer->use_sctpmap());
 }
 
@@ -1358,16 +1356,15 @@
   ASSERT_TRUE(offer.get() != NULL);
   ContentInfo* dc_offer = offer->GetContentByName("data");
   ASSERT_TRUE(dc_offer != NULL);
-  SctpDataContentDescription* dcd_offer =
-      dc_offer->media_description()->as_sctp();
+  DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
   dcd_offer->set_use_sctpmap(false);
 
   std::unique_ptr<SessionDescription> answer =
       f2_.CreateAnswer(offer.get(), opts, NULL);
   const ContentInfo* dc_answer = answer->GetContentByName("data");
   ASSERT_TRUE(dc_answer != NULL);
-  const SctpDataContentDescription* dcd_answer =
-      dc_answer->media_description()->as_sctp();
+  const DataContentDescription* dcd_answer =
+      dc_answer->media_description()->as_data();
   EXPECT_FALSE(dcd_answer->use_sctpmap());
 }
 
@@ -1388,9 +1385,7 @@
   ASSERT_TRUE(offer.get() != nullptr);
   ContentInfo* dc_offer = offer->GetContentByName("data");
   ASSERT_TRUE(dc_offer != nullptr);
-  SctpDataContentDescription* dcd_offer =
-      dc_offer->media_description()->as_sctp();
-  ASSERT_TRUE(dcd_offer);
+  DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
 
   std::vector<std::string> protos = {"DTLS/SCTP", "UDP/DTLS/SCTP",
                                      "TCP/DTLS/SCTP"};
@@ -1400,8 +1395,8 @@
         f2_.CreateAnswer(offer.get(), opts, nullptr);
     const ContentInfo* dc_answer = answer->GetContentByName("data");
     ASSERT_TRUE(dc_answer != nullptr);
-    const SctpDataContentDescription* dcd_answer =
-        dc_answer->media_description()->as_sctp();
+    const DataContentDescription* dcd_answer =
+        dc_answer->media_description()->as_data();
     EXPECT_FALSE(dc_answer->rejected);
     EXPECT_EQ(proto, dcd_answer->protocol());
   }
@@ -1483,11 +1478,9 @@
   std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
   ContentInfo* dc_offer = offer->GetContentByName("data");
   ASSERT_TRUE(dc_offer != NULL);
-  RtpDataContentDescription* dcd_offer =
-      dc_offer->media_description()->as_rtp_data();
+  DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
   ASSERT_TRUE(dcd_offer != NULL);
-  // Offer must be acceptable as an RTP protocol in order to be set.
-  std::string protocol = "RTP/a weird unknown protocol";
+  std::string protocol = "a weird unknown protocol";
   dcd_offer->set_protocol(protocol);
 
   std::unique_ptr<SessionDescription> answer =
@@ -1496,8 +1489,8 @@
   const ContentInfo* dc_answer = answer->GetContentByName("data");
   ASSERT_TRUE(dc_answer != NULL);
   EXPECT_TRUE(dc_answer->rejected);
-  const RtpDataContentDescription* dcd_answer =
-      dc_answer->media_description()->as_rtp_data();
+  const DataContentDescription* dcd_answer =
+      dc_answer->media_description()->as_data();
   ASSERT_TRUE(dcd_answer != NULL);
   EXPECT_EQ(protocol, dcd_answer->protocol());
 }
@@ -1695,7 +1688,7 @@
   ASSERT_TRUE(vc != NULL);
   const AudioContentDescription* acd = ac->media_description()->as_audio();
   const VideoContentDescription* vcd = vc->media_description()->as_video();
-  const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
+  const DataContentDescription* dcd = dc->media_description()->as_data();
 
   EXPECT_FALSE(acd->has_ssrcs());  // No StreamParams.
   EXPECT_FALSE(vcd->has_ssrcs());  // No StreamParams.
@@ -1723,16 +1716,16 @@
   answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
-  ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get()));
+  ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
-  ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get()));
+  ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
   EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
   EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
-  EXPECT_TRUE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux());
+  EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
   EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
   EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
-  EXPECT_TRUE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux());
+  EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
 
   offer_opts.rtcp_mux_enabled = true;
   answer_opts.rtcp_mux_enabled = false;
@@ -1740,16 +1733,16 @@
   answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
-  ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get()));
+  ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
-  ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get()));
+  ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
   EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
   EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
-  EXPECT_TRUE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux());
+  EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
   EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
   EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
-  EXPECT_FALSE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux());
+  EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
 
   offer_opts.rtcp_mux_enabled = false;
   answer_opts.rtcp_mux_enabled = true;
@@ -1757,16 +1750,16 @@
   answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
-  ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get()));
+  ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
-  ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get()));
+  ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
   EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
   EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
-  EXPECT_FALSE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux());
+  EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
   EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
   EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
-  EXPECT_FALSE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux());
+  EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
 
   offer_opts.rtcp_mux_enabled = false;
   answer_opts.rtcp_mux_enabled = false;
@@ -1774,16 +1767,16 @@
   answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
-  ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get()));
+  ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
   ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
   ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
-  ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get()));
+  ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
   EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
   EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
-  EXPECT_FALSE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux());
+  EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
   EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
   EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
-  EXPECT_FALSE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux());
+  EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
 }
 
 // Create an audio-only answer to a video offer.
@@ -1955,7 +1948,7 @@
   ASSERT_TRUE(dc != NULL);
   const AudioContentDescription* acd = ac->media_description()->as_audio();
   const VideoContentDescription* vcd = vc->media_description()->as_video();
-  const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
+  const DataContentDescription* dcd = dc->media_description()->as_data();
   EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
   EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
 
@@ -1985,7 +1978,7 @@
   EXPECT_TRUE(vcd->rtcp_mux());                 // rtcp-mux defaults on
 
   EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
-  EXPECT_EQ(f1_.rtp_data_codecs(), dcd->codecs());
+  EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
   ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
 
   const StreamParamsVec& data_streams = dcd->streams();
@@ -2027,8 +2020,8 @@
       ac->media_description()->as_audio();
   const VideoContentDescription* updated_vcd =
       vc->media_description()->as_video();
-  const RtpDataContentDescription* updated_dcd =
-      dc->media_description()->as_rtp_data();
+  const DataContentDescription* updated_dcd =
+      dc->media_description()->as_data();
 
   EXPECT_EQ(acd->type(), updated_acd->type());
   EXPECT_EQ(acd->codecs(), updated_acd->codecs());
@@ -2314,7 +2307,7 @@
   ASSERT_TRUE(dc != NULL);
   const AudioContentDescription* acd = ac->media_description()->as_audio();
   const VideoContentDescription* vcd = vc->media_description()->as_video();
-  const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
+  const DataContentDescription* dcd = dc->media_description()->as_data();
   ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
   ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
   ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
@@ -2382,8 +2375,8 @@
       ac->media_description()->as_audio();
   const VideoContentDescription* updated_vcd =
       vc->media_description()->as_video();
-  const RtpDataContentDescription* updated_dcd =
-      dc->media_description()->as_rtp_data();
+  const DataContentDescription* updated_dcd =
+      dc->media_description()->as_data();
 
   ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
   EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
@@ -3543,8 +3536,8 @@
   const VideoContentDescription* video_offer =
       GetFirstVideoContentDescription(offer.get());
   ASSERT_TRUE(video_offer->cryptos().empty());
-  const RtpDataContentDescription* data_offer =
-      GetFirstRtpDataContentDescription(offer.get());
+  const DataContentDescription* data_offer =
+      GetFirstDataContentDescription(offer.get());
   ASSERT_TRUE(data_offer->cryptos().empty());
 
   const cricket::TransportDescription* audio_offer_trans_desc =
@@ -4075,11 +4068,11 @@
     f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
                          MAKE_VECTOR(kAudioCodecs1));
     f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
-    f1_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs1));
+    f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
     f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
                          MAKE_VECTOR(kAudioCodecs2));
     f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
-    f2_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs2));
+    f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
     f1_.set_secure(SEC_ENABLED);
     f2_.set_secure(SEC_ENABLED);
     tdf1_.set_certificate(rtc::RTCCertificate::Create(
diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc
index c454c28..b3247c6 100644
--- a/pc/peer_connection.cc
+++ b/pc/peer_connection.cc
@@ -559,13 +559,24 @@
 // Get the SCTP port out of a SessionDescription.
 // Return -1 if not found.
 int GetSctpPort(const SessionDescription* session_description) {
-  const cricket::SctpDataContentDescription* data_desc =
-      GetFirstSctpDataContentDescription(session_description);
+  const cricket::DataContentDescription* data_desc =
+      GetFirstDataContentDescription(session_description);
   RTC_DCHECK(data_desc);
   if (!data_desc) {
     return -1;
   }
-  return data_desc->port();
+  std::string value;
+  cricket::DataCodec match_pattern(cricket::kGoogleSctpDataCodecPlType,
+                                   cricket::kGoogleSctpDataCodecName);
+  for (const cricket::DataCodec& codec : data_desc->codecs()) {
+    if (!codec.Matches(match_pattern)) {
+      continue;
+    }
+    if (codec.GetParam(cricket::kCodecParamPort, &value)) {
+      return rtc::FromString<int>(value);
+    }
+  }
+  return -1;
 }
 
 // Returns true if |new_desc| requests an ICE restart (i.e., new ufrag/pwd).
@@ -2412,11 +2423,11 @@
   const cricket::ContentInfo* data_content =
       GetFirstDataContent(local_description()->description());
   if (data_content) {
-    const cricket::RtpDataContentDescription* rtp_data_desc =
-        data_content->media_description()->as_rtp_data();
-    // rtp_data_desc will be null if this is an SCTP description.
-    if (rtp_data_desc) {
-      UpdateLocalRtpDataChannels(rtp_data_desc->streams());
+    const cricket::DataContentDescription* data_desc =
+        data_content->media_description()->as_data();
+    if (absl::StartsWith(data_desc->protocol(),
+                         cricket::kMediaProtocolRtpPrefix)) {
+      UpdateLocalRtpDataChannels(data_desc->streams());
     }
   }
 
@@ -2822,8 +2833,8 @@
       GetFirstAudioContentDescription(remote_description()->description());
   const cricket::VideoContentDescription* video_desc =
       GetFirstVideoContentDescription(remote_description()->description());
-  const cricket::RtpDataContentDescription* rtp_data_desc =
-      GetFirstRtpDataContentDescription(remote_description()->description());
+  const cricket::DataContentDescription* data_desc =
+      GetFirstDataContentDescription(remote_description()->description());
 
   // Check if the descriptions include streams, just in case the peer supports
   // MSID, but doesn't indicate so with "a=msid-semantic".
@@ -2876,10 +2887,12 @@
       }
     }
 
-    // If this is an RTP data transport, update the DataChannels with the
-    // information from the remote peer.
-    if (rtp_data_desc) {
-      UpdateRemoteRtpDataChannels(GetActiveStreams(rtp_data_desc));
+    // Update the DataChannels with the information from the remote peer.
+    if (data_desc) {
+      if (absl::StartsWith(data_desc->protocol(),
+                           cricket::kMediaProtocolRtpPrefix)) {
+        UpdateRemoteRtpDataChannels(GetActiveStreams(data_desc));
+      }
     }
 
     // Iterate new_streams and notify the observer about new MediaStreams.
diff --git a/pc/peer_connection_data_channel_unittest.cc b/pc/peer_connection_data_channel_unittest.cc
index 4080dd9..ad3817e 100644
--- a/pc/peer_connection_data_channel_unittest.cc
+++ b/pc/peer_connection_data_channel_unittest.cc
@@ -193,11 +193,14 @@
   // Changes the SCTP data channel port on the given session description.
   void ChangeSctpPortOnDescription(cricket::SessionDescription* desc,
                                    int port) {
+    cricket::DataCodec sctp_codec(cricket::kGoogleSctpDataCodecPlType,
+                                  cricket::kGoogleSctpDataCodecName);
+    sctp_codec.SetParam(cricket::kCodecParamPort, port);
+
     auto* data_content = cricket::GetFirstDataContent(desc);
     RTC_DCHECK(data_content);
-    auto* data_desc = data_content->media_description()->as_sctp();
-    RTC_DCHECK(data_desc);
-    data_desc->set_port(port);
+    auto* data_desc = data_content->media_description()->as_data();
+    data_desc->set_codecs({sctp_codec});
   }
 
   std::unique_ptr<rtc::VirtualSocketServer> vss_;
diff --git a/pc/peer_connection_integrationtest.cc b/pc/peer_connection_integrationtest.cc
index 3a39971..d514152 100644
--- a/pc/peer_connection_integrationtest.cc
+++ b/pc/peer_connection_integrationtest.cc
@@ -3450,8 +3450,8 @@
 }
 
 static void MakeSpecCompliantSctpOffer(cricket::SessionDescription* desc) {
-  cricket::SctpDataContentDescription* dcd_offer =
-      GetFirstSctpDataContentDescription(desc);
+  cricket::DataContentDescription* dcd_offer =
+      GetFirstDataContentDescription(desc);
   ASSERT_TRUE(dcd_offer);
   dcd_offer->set_use_sctpmap(false);
   dcd_offer->set_protocol("UDP/DTLS/SCTP");
diff --git a/pc/session_description.cc b/pc/session_description.cc
index cf3d147..d4ccb50 100644
--- a/pc/session_description.cc
+++ b/pc/session_description.cc
@@ -15,7 +15,6 @@
 
 #include "absl/algorithm/container.h"
 #include "absl/memory/memory.h"
-#include "pc/media_protocol_names.h"
 #include "rtc_base/checks.h"
 
 namespace cricket {
@@ -184,24 +183,6 @@
 }
 
 void SessionDescription::AddContent(ContentInfo* content) {
-  // Unwrap the as_data shim layer before using.
-  auto* description = content->media_description();
-  bool should_delete = false;
-  if (description->as_rtp_data()) {
-    if (description->as_rtp_data() != description) {
-      content->set_media_description(
-          description->as_data()->Unshim(&should_delete));
-    }
-  }
-  if (description->as_sctp()) {
-    if (description->as_sctp() != description) {
-      content->set_media_description(
-          description->as_data()->Unshim(&should_delete));
-    }
-  }
-  if (should_delete) {
-    delete description;
-  }
   if (extmap_allow_mixed()) {
     // Mixed support on session level overrides setting on media level.
     content->description->set_extmap_allow_mixed_enum(
@@ -291,406 +272,4 @@
   return NULL;
 }
 
-// DataContentDescription shim creation
-DataContentDescription* RtpDataContentDescription::as_data() {
-  if (!shim_) {
-    shim_.reset(new DataContentDescription(this));
-  }
-  return shim_.get();
-}
-
-const DataContentDescription* RtpDataContentDescription::as_data() const {
-  return const_cast<RtpDataContentDescription*>(this)->as_data();
-}
-
-DataContentDescription* SctpDataContentDescription::as_data() {
-  if (!shim_) {
-    shim_.reset(new DataContentDescription(this));
-  }
-  return shim_.get();
-}
-
-const DataContentDescription* SctpDataContentDescription::as_data() const {
-  return const_cast<SctpDataContentDescription*>(this)->as_data();
-}
-
-DataContentDescription::DataContentDescription() {
-  // In this case, we will initialize |owned_description_| as soon as
-  // we are told what protocol to use via set_protocol or another function
-  // calling CreateShimTarget.
-}
-
-DataContentDescription::DataContentDescription(
-    SctpDataContentDescription* wrapped)
-    : real_description_(wrapped) {
-  // SctpDataContentDescription doesn't contain codecs, but code
-  // using DataContentDescription expects to see one.
-  Super::AddCodec(
-      cricket::DataCodec(kGoogleSctpDataCodecPlType, kGoogleSctpDataCodecName));
-}
-
-DataContentDescription::DataContentDescription(
-    RtpDataContentDescription* wrapped)
-    : real_description_(wrapped) {}
-
-DataContentDescription::DataContentDescription(
-    const DataContentDescription* o) {
-  if (o->real_description_) {
-    owned_description_ = absl::WrapUnique(o->real_description_->Copy());
-    real_description_ = owned_description_.get();
-  } else {
-    // Copy all information collected so far, including codecs.
-    Super::operator=(*o);
-  }
-}
-
-void DataContentDescription::CreateShimTarget(bool is_sctp) {
-  RTC_LOG(LS_INFO) << "Creating shim target, is_sctp is " << is_sctp;
-  RTC_CHECK(!owned_description_.get());
-  if (is_sctp) {
-    owned_description_ = absl::make_unique<SctpDataContentDescription>();
-    // Copy all information collected so far, except codecs.
-    owned_description_->MediaContentDescription::operator=(*this);
-  } else {
-    owned_description_ = absl::make_unique<RtpDataContentDescription>();
-    // Copy all information collected so far, including codecs.
-    owned_description_->as_rtp_data()
-        ->MediaContentDescriptionImpl<RtpDataCodec>::operator=(*this);
-  }
-  real_description_ = owned_description_.get();
-}
-
-MediaContentDescription* DataContentDescription::Unshim(bool* should_delete) {
-  // If protocol isn't decided at this point, we have a problem.
-  RTC_CHECK(real_description_);
-  if (owned_description_) {
-    // Pass ownership to caller, and remove myself.
-    // Since caller can't know if I was owner or owned, tell them.
-    MediaContentDescription* to_return = owned_description_.release();
-    *should_delete = true;
-    return to_return;
-  }
-  // Real object is owner, and presumably referenced from elsewhere.
-  *should_delete = false;
-  return real_description_;
-}
-
-void DataContentDescription::set_protocol(const std::string& protocol) {
-  if (!real_description_) {
-    CreateShimTarget(IsSctpProtocol(protocol));
-  }
-  real_description_->set_protocol(protocol);
-}
-
-bool DataContentDescription::IsSctp() const {
-  return (real_description_ && real_description_->as_sctp());
-}
-
-void DataContentDescription::EnsureIsRtp() {
-  RTC_CHECK(real_description_);
-  RTC_CHECK(real_description_->as_rtp_data());
-}
-
-RtpDataContentDescription* DataContentDescription::as_rtp_data() {
-  if (real_description_) {
-    return real_description_->as_rtp_data();
-  }
-  return nullptr;
-}
-
-SctpDataContentDescription* DataContentDescription::as_sctp() {
-  if (real_description_) {
-    return real_description_->as_sctp();
-  }
-  return nullptr;
-}
-
-// Override all methods defined in MediaContentDescription.
-bool DataContentDescription::has_codecs() const {
-  if (!real_description_) {
-    return Super::has_codecs();
-  }
-  return real_description_->has_codecs();
-}
-std::string DataContentDescription::protocol() const {
-  if (!real_description_) {
-    return Super::protocol();
-  }
-  return real_description_->protocol();
-}
-
-webrtc::RtpTransceiverDirection DataContentDescription::direction() const {
-  if (!real_description_) {
-    return Super::direction();
-  }
-  return real_description_->direction();
-}
-void DataContentDescription::set_direction(
-    webrtc::RtpTransceiverDirection direction) {
-  if (!real_description_) {
-    return Super::set_direction(direction);
-  }
-  return real_description_->set_direction(direction);
-}
-bool DataContentDescription::rtcp_mux() const {
-  if (!real_description_) {
-    return Super::rtcp_mux();
-  }
-  return real_description_->rtcp_mux();
-}
-void DataContentDescription::set_rtcp_mux(bool mux) {
-  if (!real_description_) {
-    Super::set_rtcp_mux(mux);
-    return;
-  }
-  real_description_->set_rtcp_mux(mux);
-}
-bool DataContentDescription::rtcp_reduced_size() const {
-  if (!real_description_) {
-    return Super::rtcp_reduced_size();
-  }
-  return real_description_->rtcp_reduced_size();
-}
-void DataContentDescription::set_rtcp_reduced_size(bool reduced_size) {
-  if (!real_description_) {
-    return Super::set_rtcp_reduced_size(reduced_size);
-  }
-
-  return real_description_->set_rtcp_reduced_size(reduced_size);
-}
-int DataContentDescription::bandwidth() const {
-  if (!real_description_) {
-    return Super::bandwidth();
-  }
-
-  return real_description_->bandwidth();
-}
-void DataContentDescription::set_bandwidth(int bandwidth) {
-  if (!real_description_) {
-    return Super::set_bandwidth(bandwidth);
-  }
-
-  return real_description_->set_bandwidth(bandwidth);
-}
-const std::vector<CryptoParams>& DataContentDescription::cryptos() const {
-  if (!real_description_) {
-    return Super::cryptos();
-  }
-
-  return real_description_->cryptos();
-}
-void DataContentDescription::AddCrypto(const CryptoParams& params) {
-  if (!real_description_) {
-    return Super::AddCrypto(params);
-  }
-
-  return real_description_->AddCrypto(params);
-}
-void DataContentDescription::set_cryptos(
-    const std::vector<CryptoParams>& cryptos) {
-  if (!real_description_) {
-    return Super::set_cryptos(cryptos);
-  }
-
-  return real_description_->set_cryptos(cryptos);
-}
-const RtpHeaderExtensions& DataContentDescription::rtp_header_extensions()
-    const {
-  if (!real_description_) {
-    return Super::rtp_header_extensions();
-  }
-
-  return real_description_->rtp_header_extensions();
-}
-void DataContentDescription::set_rtp_header_extensions(
-    const RtpHeaderExtensions& extensions) {
-  if (!real_description_) {
-    return Super::set_rtp_header_extensions(extensions);
-  }
-
-  return real_description_->set_rtp_header_extensions(extensions);
-}
-void DataContentDescription::AddRtpHeaderExtension(
-    const webrtc::RtpExtension& ext) {
-  if (!real_description_) {
-    return Super::AddRtpHeaderExtension(ext);
-  }
-  return real_description_->AddRtpHeaderExtension(ext);
-}
-void DataContentDescription::AddRtpHeaderExtension(
-    const cricket::RtpHeaderExtension& ext) {
-  if (!real_description_) {
-    return Super::AddRtpHeaderExtension(ext);
-  }
-  return real_description_->AddRtpHeaderExtension(ext);
-}
-void DataContentDescription::ClearRtpHeaderExtensions() {
-  if (!real_description_) {
-    return Super::ClearRtpHeaderExtensions();
-  }
-  return real_description_->ClearRtpHeaderExtensions();
-}
-bool DataContentDescription::rtp_header_extensions_set() const {
-  if (!real_description_) {
-    return Super::rtp_header_extensions_set();
-  }
-  return real_description_->rtp_header_extensions_set();
-}
-const StreamParamsVec& DataContentDescription::streams() const {
-  if (!real_description_) {
-    return Super::streams();
-  }
-  return real_description_->streams();
-}
-StreamParamsVec& DataContentDescription::mutable_streams() {
-  if (!real_description_) {
-    return Super::mutable_streams();
-  }
-  return real_description_->mutable_streams();
-}
-void DataContentDescription::AddStream(const StreamParams& stream) {
-  if (!real_description_) {
-    return Super::AddStream(stream);
-  }
-  return real_description_->AddStream(stream);
-}
-void DataContentDescription::SetCnameIfEmpty(const std::string& cname) {
-  if (!real_description_) {
-    return Super::SetCnameIfEmpty(cname);
-  }
-  return real_description_->SetCnameIfEmpty(cname);
-}
-uint32_t DataContentDescription::first_ssrc() const {
-  if (!real_description_) {
-    return Super::first_ssrc();
-  }
-  return real_description_->first_ssrc();
-}
-bool DataContentDescription::has_ssrcs() const {
-  if (!real_description_) {
-    return Super::has_ssrcs();
-  }
-  return real_description_->has_ssrcs();
-}
-void DataContentDescription::set_conference_mode(bool enable) {
-  if (!real_description_) {
-    return Super::set_conference_mode(enable);
-  }
-  return real_description_->set_conference_mode(enable);
-}
-bool DataContentDescription::conference_mode() const {
-  if (!real_description_) {
-    return Super::conference_mode();
-  }
-  return real_description_->conference_mode();
-}
-void DataContentDescription::set_connection_address(
-    const rtc::SocketAddress& address) {
-  if (!real_description_) {
-    return Super::set_connection_address(address);
-  }
-  return real_description_->set_connection_address(address);
-}
-const rtc::SocketAddress& DataContentDescription::connection_address() const {
-  if (!real_description_) {
-    return Super::connection_address();
-  }
-  return real_description_->connection_address();
-}
-void DataContentDescription::set_extmap_allow_mixed_enum(
-    ExtmapAllowMixed mixed) {
-  if (!real_description_) {
-    return Super::set_extmap_allow_mixed_enum(mixed);
-  }
-  return real_description_->set_extmap_allow_mixed_enum(mixed);
-}
-MediaContentDescription::ExtmapAllowMixed
-DataContentDescription::extmap_allow_mixed_enum() const {
-  if (!real_description_) {
-    return Super::extmap_allow_mixed_enum();
-  }
-  return real_description_->extmap_allow_mixed_enum();
-}
-bool DataContentDescription::HasSimulcast() const {
-  if (!real_description_) {
-    return Super::HasSimulcast();
-  }
-  return real_description_->HasSimulcast();
-}
-SimulcastDescription& DataContentDescription::simulcast_description() {
-  if (!real_description_) {
-    return Super::simulcast_description();
-  }
-  return real_description_->simulcast_description();
-}
-const SimulcastDescription& DataContentDescription::simulcast_description()
-    const {
-  if (!real_description_) {
-    return Super::simulcast_description();
-  }
-  return real_description_->simulcast_description();
-}
-void DataContentDescription::set_simulcast_description(
-    const SimulcastDescription& simulcast) {
-  if (!real_description_) {
-    return Super::set_simulcast_description(simulcast);
-  }
-  return real_description_->set_simulcast_description(simulcast);
-}
-
-// Methods defined in MediaContentDescriptionImpl.
-// For SCTP, we implement codec handling.
-// For RTP, we pass the codecs.
-// In the cases where type hasn't been decided yet, we return dummies.
-
-const std::vector<DataCodec>& DataContentDescription::codecs() const {
-  if (IsSctp() || !real_description_) {
-    return Super::codecs();
-  }
-  return real_description_->as_rtp_data()->codecs();
-}
-
-void DataContentDescription::set_codecs(const std::vector<DataCodec>& codecs) {
-  if (IsSctp() || !real_description_) {
-    Super::set_codecs(codecs);
-  } else {
-    EnsureIsRtp();
-    real_description_->as_rtp_data()->set_codecs(codecs);
-  }
-}
-
-bool DataContentDescription::HasCodec(int id) {
-  if (IsSctp() || !real_description_) {
-    return Super::HasCodec(id);
-  }
-  return real_description_->as_rtp_data()->HasCodec(id);
-}
-
-void DataContentDescription::AddCodec(const DataCodec& codec) {
-  if (IsSctp() || !real_description_) {
-    Super::AddCodec(codec);
-  } else {
-    EnsureIsRtp();
-    real_description_->as_rtp_data()->AddCodec(codec);
-  }
-}
-
-void DataContentDescription::AddOrReplaceCodec(const DataCodec& codec) {
-  if (IsSctp() || real_description_) {
-    Super::AddOrReplaceCodec(codec);
-  } else {
-    EnsureIsRtp();
-    real_description_->as_rtp_data()->AddOrReplaceCodec(codec);
-  }
-}
-
-void DataContentDescription::AddCodecs(const std::vector<DataCodec>& codecs) {
-  if (IsSctp() || !real_description_) {
-    Super::AddCodecs(codecs);
-  } else {
-    EnsureIsRtp();
-    real_description_->as_rtp_data()->AddCodecs(codecs);
-  }
-}
-
 }  // namespace cricket
diff --git a/pc/session_description.h b/pc/session_description.h
index 27b781f..7e62510 100644
--- a/pc/session_description.h
+++ b/pc/session_description.h
@@ -18,7 +18,6 @@
 #include <string>
 #include <vector>
 
-#include "absl/memory/memory.h"
 #include "api/crypto_params.h"
 #include "api/media_types.h"
 #include "api/rtp_parameters.h"
@@ -27,7 +26,6 @@
 #include "media/base/stream_params.h"
 #include "p2p/base/transport_description.h"
 #include "p2p/base/transport_info.h"
-#include "pc/media_protocol_names.h"
 #include "pc/simulcast_description.h"
 #include "rtc_base/deprecation.h"
 #include "rtc_base/socket_address.h"
@@ -36,7 +34,7 @@
 
 typedef std::vector<AudioCodec> AudioCodecs;
 typedef std::vector<VideoCodec> VideoCodecs;
-typedef std::vector<RtpDataCodec> RtpDataCodecs;
+typedef std::vector<DataCodec> DataCodecs;
 typedef std::vector<CryptoParams> CryptoParamsVec;
 typedef std::vector<webrtc::RtpExtension> RtpHeaderExtensions;
 
@@ -47,15 +45,19 @@
 
 extern const char kMediaProtocolDtlsSavpf[];
 
+extern const char kMediaProtocolRtpPrefix[];
+
+extern const char kMediaProtocolSctp[];
+extern const char kMediaProtocolDtlsSctp[];
+extern const char kMediaProtocolUdpDtlsSctp[];
+extern const char kMediaProtocolTcpDtlsSctp[];
 
 // Options to control how session descriptions are generated.
 const int kAutoBandwidth = -1;
 
 class AudioContentDescription;
-class VideoContentDescription;
 class DataContentDescription;
-class RtpDataContentDescription;
-class SctpDataContentDescription;
+class VideoContentDescription;
 
 // Describes a session description media section. There are subclasses for each
 // media type (audio, video, data) that will have additional information.
@@ -76,77 +78,61 @@
   virtual VideoContentDescription* as_video() { return nullptr; }
   virtual const VideoContentDescription* as_video() const { return nullptr; }
 
-  // Backwards compatible shim: Return a shim object that allows
-  // callers to ignore the distinction between RtpDataContentDescription
-  // and SctpDataContentDescription objects.
+  // Try to cast this media description to a DataContentDescription. Returns
+  // nullptr if the cast fails.
   virtual DataContentDescription* as_data() { return nullptr; }
   virtual const DataContentDescription* as_data() const { return nullptr; }
 
-  virtual RtpDataContentDescription* as_rtp_data() { return nullptr; }
-  virtual const RtpDataContentDescription* as_rtp_data() const {
-    return nullptr;
-  }
-
-  virtual SctpDataContentDescription* as_sctp() { return nullptr; }
-  virtual const SctpDataContentDescription* as_sctp() const { return nullptr; }
-
   virtual bool has_codecs() const = 0;
 
   virtual MediaContentDescription* Copy() const = 0;
 
   // |protocol| is the expected media transport protocol, such as RTP/AVPF,
   // RTP/SAVPF or SCTP/DTLS.
-  virtual std::string protocol() const { return protocol_; }
-  virtual void set_protocol(const std::string& protocol) {
-    protocol_ = protocol;
-  }
+  std::string protocol() const { return protocol_; }
+  void set_protocol(const std::string& protocol) { protocol_ = protocol; }
 
-  virtual webrtc::RtpTransceiverDirection direction() const {
-    return direction_;
-  }
-  virtual void set_direction(webrtc::RtpTransceiverDirection direction) {
+  webrtc::RtpTransceiverDirection direction() const { return direction_; }
+  void set_direction(webrtc::RtpTransceiverDirection direction) {
     direction_ = direction;
   }
 
-  virtual bool rtcp_mux() const { return rtcp_mux_; }
-  virtual void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; }
+  bool rtcp_mux() const { return rtcp_mux_; }
+  void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; }
 
-  virtual bool rtcp_reduced_size() const { return rtcp_reduced_size_; }
-  virtual void set_rtcp_reduced_size(bool reduced_size) {
+  bool rtcp_reduced_size() const { return rtcp_reduced_size_; }
+  void set_rtcp_reduced_size(bool reduced_size) {
     rtcp_reduced_size_ = reduced_size;
   }
 
-  virtual int bandwidth() const { return bandwidth_; }
-  virtual void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; }
+  int bandwidth() const { return bandwidth_; }
+  void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; }
 
-  virtual const std::vector<CryptoParams>& cryptos() const { return cryptos_; }
-  virtual void AddCrypto(const CryptoParams& params) {
-    cryptos_.push_back(params);
-  }
-  virtual void set_cryptos(const std::vector<CryptoParams>& cryptos) {
+  const std::vector<CryptoParams>& cryptos() const { return cryptos_; }
+  void AddCrypto(const CryptoParams& params) { cryptos_.push_back(params); }
+  void set_cryptos(const std::vector<CryptoParams>& cryptos) {
     cryptos_ = cryptos;
   }
 
-  virtual const RtpHeaderExtensions& rtp_header_extensions() const {
+  const RtpHeaderExtensions& rtp_header_extensions() const {
     return rtp_header_extensions_;
   }
-  virtual void set_rtp_header_extensions(
-      const RtpHeaderExtensions& extensions) {
+  void set_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
     rtp_header_extensions_ = extensions;
     rtp_header_extensions_set_ = true;
   }
-  virtual void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) {
+  void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) {
     rtp_header_extensions_.push_back(ext);
     rtp_header_extensions_set_ = true;
   }
-  virtual void AddRtpHeaderExtension(const cricket::RtpHeaderExtension& ext) {
+  void AddRtpHeaderExtension(const cricket::RtpHeaderExtension& ext) {
     webrtc::RtpExtension webrtc_extension;
     webrtc_extension.uri = ext.uri;
     webrtc_extension.id = ext.id;
     rtp_header_extensions_.push_back(webrtc_extension);
     rtp_header_extensions_set_ = true;
   }
-  virtual void ClearRtpHeaderExtensions() {
+  void ClearRtpHeaderExtensions() {
     rtp_header_extensions_.clear();
     rtp_header_extensions_set_ = true;
   }
@@ -155,65 +141,62 @@
   // signal them. For now we assume an empty list means no signaling, but
   // provide the ClearRtpHeaderExtensions method to allow "no support" to be
   // clearly indicated (i.e. when derived from other information).
-  virtual bool rtp_header_extensions_set() const {
-    return rtp_header_extensions_set_;
-  }
-  virtual const StreamParamsVec& streams() const { return send_streams_; }
+  bool rtp_header_extensions_set() const { return rtp_header_extensions_set_; }
+  const StreamParamsVec& streams() const { return send_streams_; }
   // TODO(pthatcher): Remove this by giving mediamessage.cc access
   // to MediaContentDescription
-  virtual StreamParamsVec& mutable_streams() { return send_streams_; }
-  virtual void AddStream(const StreamParams& stream) {
+  StreamParamsVec& mutable_streams() { return send_streams_; }
+  void AddStream(const StreamParams& stream) {
     send_streams_.push_back(stream);
   }
   // Legacy streams have an ssrc, but nothing else.
   void AddLegacyStream(uint32_t ssrc) {
-    AddStream(StreamParams::CreateLegacy(ssrc));
+    send_streams_.push_back(StreamParams::CreateLegacy(ssrc));
   }
   void AddLegacyStream(uint32_t ssrc, uint32_t fid_ssrc) {
     StreamParams sp = StreamParams::CreateLegacy(ssrc);
     sp.AddFidSsrc(ssrc, fid_ssrc);
-    AddStream(sp);
+    send_streams_.push_back(sp);
   }
 
   // Sets the CNAME of all StreamParams if it have not been set.
-  virtual void SetCnameIfEmpty(const std::string& cname) {
+  void SetCnameIfEmpty(const std::string& cname) {
     for (cricket::StreamParamsVec::iterator it = send_streams_.begin();
          it != send_streams_.end(); ++it) {
       if (it->cname.empty())
         it->cname = cname;
     }
   }
-  virtual uint32_t first_ssrc() const {
+  uint32_t first_ssrc() const {
     if (send_streams_.empty()) {
       return 0;
     }
     return send_streams_[0].first_ssrc();
   }
-  virtual bool has_ssrcs() const {
+  bool has_ssrcs() const {
     if (send_streams_.empty()) {
       return false;
     }
     return send_streams_[0].has_ssrcs();
   }
 
-  virtual void set_conference_mode(bool enable) { conference_mode_ = enable; }
-  virtual bool conference_mode() const { return conference_mode_; }
+  void set_conference_mode(bool enable) { conference_mode_ = enable; }
+  bool conference_mode() const { return conference_mode_; }
 
   // https://tools.ietf.org/html/rfc4566#section-5.7
   // May be present at the media or session level of SDP. If present at both
   // levels, the media-level attribute overwrites the session-level one.
-  virtual void set_connection_address(const rtc::SocketAddress& address) {
+  void set_connection_address(const rtc::SocketAddress& address) {
     connection_address_ = address;
   }
-  virtual const rtc::SocketAddress& connection_address() const {
+  const rtc::SocketAddress& connection_address() const {
     return connection_address_;
   }
 
   // Determines if it's allowed to mix one- and two-byte rtp header extensions
   // within the same rtp stream.
   enum ExtmapAllowMixed { kNo, kSession, kMedia };
-  virtual void set_extmap_allow_mixed_enum(
-      ExtmapAllowMixed new_extmap_allow_mixed) {
+  void set_extmap_allow_mixed_enum(ExtmapAllowMixed new_extmap_allow_mixed) {
     if (new_extmap_allow_mixed == kMedia &&
         extmap_allow_mixed_enum_ == kSession) {
       // Do not downgrade from session level to media level.
@@ -221,12 +204,10 @@
     }
     extmap_allow_mixed_enum_ = new_extmap_allow_mixed;
   }
-  virtual ExtmapAllowMixed extmap_allow_mixed_enum() const {
+  ExtmapAllowMixed extmap_allow_mixed_enum() const {
     return extmap_allow_mixed_enum_;
   }
-  virtual bool extmap_allow_mixed() const {
-    return extmap_allow_mixed_enum_ != kNo;
-  }
+  bool extmap_allow_mixed() const { return extmap_allow_mixed_enum_ != kNo; }
 
   // Simulcast functionality.
   virtual bool HasSimulcast() const { return !simulcast_.empty(); }
@@ -267,18 +248,13 @@
 template <class C>
 class MediaContentDescriptionImpl : public MediaContentDescription {
  public:
-  void set_protocol(const std::string& protocol) override {
-    RTC_DCHECK(IsRtpProtocol(protocol));
-    protocol_ = protocol;
-  }
-
   typedef C CodecType;
 
   // Codecs should be in preference order (most preferred codec first).
-  virtual const std::vector<C>& codecs() const { return codecs_; }
-  virtual void set_codecs(const std::vector<C>& codecs) { codecs_ = codecs; }
-  bool has_codecs() const override { return !codecs_.empty(); }
-  virtual bool HasCodec(int id) {
+  const std::vector<C>& codecs() const { return codecs_; }
+  void set_codecs(const std::vector<C>& codecs) { codecs_ = codecs; }
+  virtual bool has_codecs() const { return !codecs_.empty(); }
+  bool HasCodec(int id) {
     bool found = false;
     for (typename std::vector<C>::iterator iter = codecs_.begin();
          iter != codecs_.end(); ++iter) {
@@ -289,8 +265,8 @@
     }
     return found;
   }
-  virtual void AddCodec(const C& codec) { codecs_.push_back(codec); }
-  virtual void AddOrReplaceCodec(const C& codec) {
+  void AddCodec(const C& codec) { codecs_.push_back(codec); }
+  void AddOrReplaceCodec(const C& codec) {
     for (typename std::vector<C>::iterator iter = codecs_.begin();
          iter != codecs_.end(); ++iter) {
       if (iter->id == codec.id) {
@@ -300,7 +276,7 @@
     }
     AddCodec(codec);
   }
-  virtual void AddCodecs(const std::vector<C>& codecs) {
+  void AddCodecs(const std::vector<C>& codecs) {
     typename std::vector<C>::const_iterator codec;
     for (codec = codecs.begin(); codec != codecs.end(); ++codec) {
       AddCodec(*codec);
@@ -333,173 +309,22 @@
   virtual const VideoContentDescription* as_video() const { return this; }
 };
 
-// The DataContentDescription is a shim over the RtpDataContentDescription
-// and SctpDataContentDescription classes that is used for external callers
-// into this internal API.
-// It is a templated derivation of MediaContentDescriptionImpl because
-// that's what the external caller expects it to be.
-// TODO(bugs.webrtc.org/10597): Declare this class obsolete and remove it
-// once external callers have been updated.
 class DataContentDescription : public MediaContentDescriptionImpl<DataCodec> {
  public:
-  DataContentDescription();
-  MediaType type() const override { return MEDIA_TYPE_DATA; }
-  DataContentDescription* as_data() override { return this; }
-  const DataContentDescription* as_data() const override { return this; }
+  DataContentDescription() {}
 
-  // Override all methods defined in MediaContentDescription.
-  bool has_codecs() const override;
-  DataContentDescription* Copy() const override {
-    return new DataContentDescription(this);
+  virtual DataContentDescription* Copy() const {
+    return new DataContentDescription(*this);
   }
-  std::string protocol() const override;
-  void set_protocol(const std::string& protocol) override;
-  webrtc::RtpTransceiverDirection direction() const override;
-  void set_direction(webrtc::RtpTransceiverDirection direction) override;
-  bool rtcp_mux() const override;
-  void set_rtcp_mux(bool mux) override;
-  bool rtcp_reduced_size() const override;
-  void set_rtcp_reduced_size(bool) override;
-  int bandwidth() const override;
-  void set_bandwidth(int bandwidth) override;
-  const std::vector<CryptoParams>& cryptos() const override;
-  void AddCrypto(const CryptoParams& params) override;
-  void set_cryptos(const std::vector<CryptoParams>& cryptos) override;
-  const RtpHeaderExtensions& rtp_header_extensions() const override;
-  void set_rtp_header_extensions(
-      const RtpHeaderExtensions& extensions) override;
-  void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) override;
-  void AddRtpHeaderExtension(const cricket::RtpHeaderExtension& ext) override;
-  void ClearRtpHeaderExtensions() override;
-  bool rtp_header_extensions_set() const override;
-  const StreamParamsVec& streams() const override;
-  StreamParamsVec& mutable_streams() override;
-  void AddStream(const StreamParams& stream) override;
-  void SetCnameIfEmpty(const std::string& cname) override;
-  uint32_t first_ssrc() const override;
-  bool has_ssrcs() const override;
-  void set_conference_mode(bool enable) override;
-  bool conference_mode() const override;
-  void set_connection_address(const rtc::SocketAddress& address) override;
-  const rtc::SocketAddress& connection_address() const override;
-  void set_extmap_allow_mixed_enum(ExtmapAllowMixed) override;
-  ExtmapAllowMixed extmap_allow_mixed_enum() const override;
-  bool HasSimulcast() const override;
-  SimulcastDescription& simulcast_description() override;
-  const SimulcastDescription& simulcast_description() const override;
-  void set_simulcast_description(
-      const SimulcastDescription& simulcast) override;
-
-  // Override all methods defined in MediaContentDescriptionImpl.
-  const std::vector<CodecType>& codecs() const override;
-  void set_codecs(const std::vector<CodecType>& codecs) override;
-  bool HasCodec(int id) override;
-  void AddCodec(const CodecType& codec) override;
-  void AddOrReplaceCodec(const CodecType& codec) override;
-  void AddCodecs(const std::vector<CodecType>& codec) override;
-
- private:
-  typedef MediaContentDescriptionImpl<DataCodec> Super;
-  // Friend classes are allowed to create proxies for themselves.
-  friend class RtpDataContentDescription;  // for constructors
-  friend class SctpDataContentDescription;
-  friend class SessionDescription;  // for Unshim()
-  // Copy constructor. A copy results in an object that owns its
-  // real description, which is a copy of the original description
-  // (whether that was owned or not).
-  explicit DataContentDescription(const DataContentDescription* o);
-
-  explicit DataContentDescription(RtpDataContentDescription*);
-  explicit DataContentDescription(SctpDataContentDescription*);
-
-  // Exposed for internal use - new clients should not use this class.
-  RtpDataContentDescription* as_rtp_data() override;
-  SctpDataContentDescription* as_sctp() override;
-
-  // Create a shimmed object, owned by the shim.
-  void CreateShimTarget(bool is_sctp);
-
-  // Return the shimmed object, passing ownership if owned, and set
-  // |should_delete| to true if it was the owner. If |should_delete|
-  // is true on return, the caller should immediately delete the
-  // DataContentDescription object.
-  MediaContentDescription* Unshim(bool* should_delete);
-
-  // Returns whether SCTP is in use. False when it's not decided.
-  bool IsSctp() const;
-  // Check function for use when caller obviously assumes RTP.
-  void EnsureIsRtp();
-
-  MediaContentDescription* real_description_ = nullptr;
-  std::unique_ptr<MediaContentDescription> owned_description_;
-};
-
-class RtpDataContentDescription
-    : public MediaContentDescriptionImpl<RtpDataCodec> {
- public:
-  RtpDataContentDescription() {}
-  RtpDataContentDescription(const RtpDataContentDescription& o)
-      : MediaContentDescriptionImpl<RtpDataCodec>(o), shim_(nullptr) {}
-  RtpDataContentDescription& operator=(const RtpDataContentDescription& o) {
-    this->MediaContentDescriptionImpl<RtpDataCodec>::operator=(o);
-    // Do not copy the shim.
-    return *this;
-  }
-
-  RtpDataContentDescription* Copy() const override {
-    return new RtpDataContentDescription(*this);
-  }
-  MediaType type() const override { return MEDIA_TYPE_DATA; }
-  RtpDataContentDescription* as_rtp_data() override { return this; }
-  const RtpDataContentDescription* as_rtp_data() const override { return this; }
-  // Shim support
-  DataContentDescription* as_data() override;
-  const DataContentDescription* as_data() const override;
-
- private:
-  std::unique_ptr<DataContentDescription> shim_;
-};
-
-class SctpDataContentDescription : public MediaContentDescription {
- public:
-  SctpDataContentDescription() {}
-  SctpDataContentDescription(const SctpDataContentDescription& o)
-      : MediaContentDescription(o),
-        use_sctpmap_(o.use_sctpmap_),
-        port_(o.port_),
-        max_message_size_(o.max_message_size_),
-        shim_(nullptr) {}
-  SctpDataContentDescription* Copy() const override {
-    return new SctpDataContentDescription(*this);
-  }
-  MediaType type() const override { return MEDIA_TYPE_DATA; }
-  SctpDataContentDescription* as_sctp() override { return this; }
-  const SctpDataContentDescription* as_sctp() const override { return this; }
-  // Shim support
-  DataContentDescription* as_data() override;
-  const DataContentDescription* as_data() const override;
-
-  bool has_codecs() const override { return false; }
-  void set_protocol(const std::string& protocol) override {
-    RTC_DCHECK(IsSctpProtocol(protocol));
-    protocol_ = protocol;
-  }
+  virtual MediaType type() const { return MEDIA_TYPE_DATA; }
+  virtual DataContentDescription* as_data() { return this; }
+  virtual const DataContentDescription* as_data() const { return this; }
 
   bool use_sctpmap() const { return use_sctpmap_; }
   void set_use_sctpmap(bool enable) { use_sctpmap_ = enable; }
-  int port() const { return port_; }
-  void set_port(int port) { port_ = port; }
-  int max_message_size() const { return max_message_size_; }
-  void set_max_message_size(int max_message_size) {
-    max_message_size_ = max_message_size;
-  }
 
  private:
-  bool use_sctpmap_ = true;  // Note: "true" is no longer conformant.
-  // Defaults should be constants imported from SCTP. Quick hack.
-  int port_ = 5000;
-  int max_message_size_ = 256 * 1024;
-  std::unique_ptr<DataContentDescription> shim_;
+  bool use_sctpmap_ = true;
 };
 
 // Protocol used for encoding media. This is the "top level" protocol that may
diff --git a/pc/session_description_unittest.cc b/pc/session_description_unittest.cc
index 9797ed5..3b05dca 100644
--- a/pc/session_description_unittest.cc
+++ b/pc/session_description_unittest.cc
@@ -9,7 +9,6 @@
  */
 #include "pc/session_description.h"
 
-#include "absl/memory/memory.h"
 #include "test/gtest.h"
 
 namespace cricket {
@@ -122,69 +121,11 @@
             video_desc->extmap_allow_mixed_enum());
 
   // Session level setting overrides media level when new content is added.
-  MediaContentDescription* data_desc = new RtpDataContentDescription;
+  MediaContentDescription* data_desc = new DataContentDescription;
   data_desc->set_extmap_allow_mixed_enum(MediaContentDescription::kMedia);
   session_desc.AddContent("data", MediaProtocolType::kRtp, data_desc);
   EXPECT_EQ(MediaContentDescription::kSession,
             data_desc->extmap_allow_mixed_enum());
 }
 
-TEST(SessionDescriptionTest, DataContentDescriptionCanAddStream) {
-  auto description = absl::make_unique<DataContentDescription>();
-  // Adding a stream without setting protocol first should work.
-  description->AddLegacyStream(1234);
-  EXPECT_EQ(1UL, description->streams().size());
-}
-
-TEST(SessionDescriptionTest, DataContentDescriptionCopyWorks) {
-  auto description = absl::make_unique<RtpDataContentDescription>();
-  auto shim_description = description->as_data();
-  auto shim_copy = shim_description->Copy();
-  delete shim_copy;
-}
-
-TEST(SessionDescriptionTest, DataContentDescriptionCodecsCallableOnNull) {
-  auto shim_description = absl::make_unique<DataContentDescription>();
-  auto codec_list = shim_description->codecs();
-  EXPECT_EQ(0UL, codec_list.size());
-}
-
-TEST(SessionDescriptionTest, DataContentDescriptionSctpConferenceMode) {
-  auto description = absl::make_unique<SctpDataContentDescription>();
-  auto shim_description = description->as_data();
-  EXPECT_FALSE(shim_description->conference_mode());
-  shim_description->set_conference_mode(true);
-  EXPECT_TRUE(shim_description->conference_mode());
-}
-
-TEST(SessionDescriptionTest, DataContentDesriptionInSessionIsUnwrapped) {
-  auto description = absl::make_unique<DataContentDescription>();
-  // Create a DTLS object behind the shim.
-  description->set_protocol(kMediaProtocolUdpDtlsSctp);
-  SessionDescription session;
-  session.AddContent("name", MediaProtocolType::kSctp, description.release());
-  ContentInfo* content = &(session.contents()[0]);
-  ASSERT_TRUE(content);
-  ASSERT_TRUE(content->media_description()->type() == MEDIA_TYPE_DATA);
-  ASSERT_TRUE(content->media_description()->as_sctp());
-}
-
-TEST(SessionDescriptionTest,
-     DataContentDescriptionInfoSurvivesInstantiationAsSctp) {
-  auto description = absl::make_unique<DataContentDescription>();
-  description->set_rtcp_mux(true);
-  description->set_protocol(kMediaProtocolUdpDtlsSctp);
-  EXPECT_TRUE(description->rtcp_mux());
-}
-
-TEST(SessionDescriptionTest,
-     DataContentDescriptionStreamInfoSurvivesInstantiationAsRtp) {
-  auto description = absl::make_unique<DataContentDescription>();
-  StreamParams stream;
-  description->AddLegacyStream(1234);
-  EXPECT_EQ(1UL, description->streams().size());
-  description->set_protocol(kMediaProtocolDtlsSavpf);
-  EXPECT_EQ(1UL, description->streams().size());
-}
-
 }  // namespace cricket
diff --git a/pc/webrtc_sdp.cc b/pc/webrtc_sdp.cc
index f8c9e70..97015fe 100644
--- a/pc/webrtc_sdp.cc
+++ b/pc/webrtc_sdp.cc
@@ -76,9 +76,7 @@
 using cricket::MediaProtocolType;
 using cricket::MediaType;
 using cricket::RidDescription;
-using cricket::RtpDataContentDescription;
 using cricket::RtpHeaderExtensions;
-using cricket::SctpDataContentDescription;
 using cricket::SimulcastDescription;
 using cricket::SimulcastLayer;
 using cricket::SimulcastLayerList;
@@ -1339,6 +1337,8 @@
   const MediaContentDescription* media_desc = content_info->media_description();
   RTC_DCHECK(media_desc);
 
+  int sctp_port = cricket::kSctpDefaultPort;
+
   // RFC 4566
   // m=<media> <port> <proto> <fmt>
   // fmt is a list of payload type numbers that MAY be used in the session.
@@ -1366,20 +1366,25 @@
       fmt.append(rtc::ToString(codec.id));
     }
   } else if (media_type == cricket::MEDIA_TYPE_DATA) {
-    const cricket::SctpDataContentDescription* sctp_data_desc =
-        media_desc->as_sctp();
-    if (sctp_data_desc) {
+    const DataContentDescription* data_desc = media_desc->as_data();
+    if (IsDtlsSctp(media_desc->protocol())) {
       fmt.append(" ");
 
-      if (sctp_data_desc->use_sctpmap()) {
-        fmt.append(rtc::ToString(sctp_data_desc->port()));
+      if (data_desc->use_sctpmap()) {
+        for (const cricket::DataCodec& codec : data_desc->codecs()) {
+          if (absl::EqualsIgnoreCase(codec.name,
+                                     cricket::kGoogleSctpDataCodecName) &&
+              codec.GetParam(cricket::kCodecParamPort, &sctp_port)) {
+            break;
+          }
+        }
+
+        fmt.append(rtc::ToString(sctp_port));
       } else {
         fmt.append(kDefaultSctpmapProtocol);
       }
     } else {
-      const RtpDataContentDescription* rtp_data_desc =
-          media_desc->as_rtp_data();
-      for (const cricket::RtpDataCodec& codec : rtp_data_desc->codecs()) {
+      for (const cricket::DataCodec& codec : data_desc->codecs()) {
         fmt.append(" ");
         fmt.append(rtc::ToString(codec.id));
       }
@@ -1518,10 +1523,9 @@
   AddLine(os.str(), message);
 
   if (IsDtlsSctp(media_desc->protocol())) {
-    const cricket::SctpDataContentDescription* data_desc =
-        media_desc->as_sctp();
+    const DataContentDescription* data_desc = media_desc->as_data();
     bool use_sctpmap = data_desc->use_sctpmap();
-    BuildSctpContentAttributes(message, data_desc->port(), use_sctpmap);
+    BuildSctpContentAttributes(message, sctp_port, use_sctpmap);
   } else if (IsRtp(media_desc->protocol())) {
     BuildRtpContentAttributes(media_desc, media_type, msid_signaling, message);
   }
@@ -1830,6 +1834,43 @@
   }
 }
 
+cricket::DataCodec FindOrMakeSctpDataCodec(DataContentDescription* media_desc) {
+  for (const auto& codec : media_desc->codecs()) {
+    if (absl::EqualsIgnoreCase(codec.name, cricket::kGoogleSctpDataCodecName)) {
+      return codec;
+    }
+  }
+  cricket::DataCodec codec_port(cricket::kGoogleSctpDataCodecPlType,
+                                cricket::kGoogleSctpDataCodecName);
+  return codec_port;
+}
+
+bool AddOrModifySctpDataCodecPort(DataContentDescription* media_desc,
+                                  int sctp_port) {
+  // Add the SCTP Port number as a pseudo-codec "port" parameter
+  auto codec = FindOrMakeSctpDataCodec(media_desc);
+  int dummy;
+  if (codec.GetParam(cricket::kCodecParamPort, &dummy)) {
+    return false;
+  }
+  codec.SetParam(cricket::kCodecParamPort, sctp_port);
+  media_desc->AddOrReplaceCodec(codec);
+  return true;
+}
+
+bool AddOrModifySctpDataMaxMessageSize(DataContentDescription* media_desc,
+                                       int max_message_size) {
+  // Add the SCTP Max Message Size as a pseudo-parameter to the codec
+  auto codec = FindOrMakeSctpDataCodec(media_desc);
+  int dummy;
+  if (codec.GetParam(cricket::kCodecParamMaxMessageSize, &dummy)) {
+    return false;
+  }
+  codec.SetParam(cricket::kCodecParamMaxMessageSize, max_message_size);
+  media_desc->AddOrReplaceCodec(codec);
+  return true;
+}
+
 bool GetMinValue(const std::vector<int>& values, int* value) {
   if (values.empty()) {
     return false;
@@ -1919,17 +1960,14 @@
       AddAttributeLine(kCodecParamPTime, ptime, message);
     }
   } else if (media_type == cricket::MEDIA_TYPE_DATA) {
-    if (media_desc->as_rtp_data()) {
-      for (const cricket::RtpDataCodec& codec :
-           media_desc->as_rtp_data()->codecs()) {
-        // RFC 4566
-        // a=rtpmap:<payload type> <encoding name>/<clock rate>
-        // [/<encodingparameters>]
-        InitAttrLine(kAttributeRtpmap, &os);
-        os << kSdpDelimiterColon << codec.id << " " << codec.name << "/"
-           << codec.clockrate;
-        AddLine(os.str(), message);
-      }
+    for (const cricket::DataCodec& codec : media_desc->as_data()->codecs()) {
+      // RFC 4566
+      // a=rtpmap:<payload type> <encoding name>/<clock rate>
+      // [/<encodingparameters>]
+      InitAttrLine(kAttributeRtpmap, &os);
+      os << kSdpDelimiterColon << codec.id << " " << codec.name << "/"
+         << codec.clockrate;
+      AddLine(os.str(), message);
     }
   }
 }
@@ -2710,36 +2748,24 @@
           payload_types, pos, &content_name, &bundle_only,
           &section_msid_signaling, &transport, candidates, error);
     } else if (HasAttribute(line, kMediaTypeData)) {
-      if (IsDtlsSctp(protocol)) {
-        // The draft-03 format is:
-        // m=application <port> DTLS/SCTP <sctp-port>...
-        // use_sctpmap should be false.
-        // The draft-26 format is:
-        // m=application <port> UDP/DTLS/SCTP webrtc-datachannel
-        // use_sctpmap should be false.
-        auto data_desc = absl::make_unique<SctpDataContentDescription>();
+      std::unique_ptr<DataContentDescription> data_desc =
+          ParseContentDescription<DataContentDescription>(
+              message, cricket::MEDIA_TYPE_DATA, mline_index, protocol,
+              payload_types, pos, &content_name, &bundle_only,
+              &section_msid_signaling, &transport, candidates, error);
+
+      if (data_desc && IsDtlsSctp(protocol)) {
         int p;
         if (rtc::FromString(fields[3], &p)) {
-          data_desc->set_port(p);
+          if (!AddOrModifySctpDataCodecPort(data_desc.get(), p)) {
+            return false;
+          }
         } else if (fields[3] == kDefaultSctpmapProtocol) {
           data_desc->set_use_sctpmap(false);
         }
-        if (!ParseContent(message, cricket::MEDIA_TYPE_DATA, mline_index,
-                          protocol, payload_types, pos, &content_name,
-                          &bundle_only, &section_msid_signaling,
-                          data_desc.get(), &transport, candidates, error)) {
-          return false;
-        }
-        content = std::move(data_desc);
-      } else {
-        // RTP
-        std::unique_ptr<RtpDataContentDescription> data_desc =
-            ParseContentDescription<RtpDataContentDescription>(
-                message, cricket::MEDIA_TYPE_DATA, mline_index, protocol,
-                payload_types, pos, &content_name, &bundle_only,
-                &section_msid_signaling, &transport, candidates, error);
-        content = std::move(data_desc);
       }
+
+      content = std::move(data_desc);
     } else {
       RTC_LOG(LS_WARNING) << "Unsupported media type: " << line;
       continue;
@@ -3112,15 +3138,13 @@
             line, "sctp-port attribute found in non-data media description.",
             error);
       }
-      if (media_desc->as_sctp()->use_sctpmap()) {
-        return ParseFailed(
-            line, "sctp-port attribute can't be used with sctpmap.", error);
-      }
       int sctp_port;
       if (!ParseSctpPort(line, &sctp_port, error)) {
         return false;
       }
-      media_desc->as_sctp()->set_port(sctp_port);
+      if (!AddOrModifySctpDataCodecPort(media_desc->as_data(), sctp_port)) {
+        return false;
+      }
     } else if (IsDtlsSctp(protocol) &&
                HasAttribute(line, kAttributeMaxMessageSize)) {
       if (media_type != cricket::MEDIA_TYPE_DATA) {
@@ -3133,7 +3157,10 @@
       if (!ParseSctpMaxMessageSize(line, &max_message_size, error)) {
         return false;
       }
-      media_desc->as_sctp()->set_max_message_size(max_message_size);
+      if (!AddOrModifySctpDataMaxMessageSize(media_desc->as_data(),
+                                             max_message_size)) {
+        return false;
+      }
     } else if (IsRtp(protocol)) {
       //
       // RTP specific attrubtes
@@ -3594,8 +3621,8 @@
     UpdateCodec(payload_type, encoding_name, clock_rate, 0, channels,
                 audio_desc);
   } else if (media_type == cricket::MEDIA_TYPE_DATA) {
-    RtpDataContentDescription* data_desc = media_desc->as_rtp_data();
-    data_desc->AddCodec(cricket::RtpDataCodec(payload_type, encoding_name));
+    DataContentDescription* data_desc = media_desc->as_data();
+    data_desc->AddCodec(cricket::DataCodec(payload_type, encoding_name));
   }
   return true;
 }
diff --git a/pc/webrtc_sdp_unittest.cc b/pc/webrtc_sdp_unittest.cc
index 5b2bf29..7294cfc 100644
--- a/pc/webrtc_sdp_unittest.cc
+++ b/pc/webrtc_sdp_unittest.cc
@@ -56,6 +56,7 @@
 using cricket::ContentInfo;
 using cricket::CryptoParams;
 using cricket::DataCodec;
+using cricket::DataContentDescription;
 using cricket::ICE_CANDIDATE_COMPONENT_RTCP;
 using cricket::ICE_CANDIDATE_COMPONENT_RTP;
 using cricket::kFecSsrcGroupSemantics;
@@ -64,8 +65,6 @@
 using cricket::RELAY_PORT_TYPE;
 using cricket::RidDescription;
 using cricket::RidDirection;
-using cricket::RtpDataContentDescription;
-using cricket::SctpDataContentDescription;
 using cricket::SessionDescription;
 using cricket::SimulcastDescription;
 using cricket::SimulcastLayer;
@@ -276,7 +275,6 @@
     "a=ssrc:10 mslabel:data_channel\r\n"
     "a=ssrc:10 label:data_channeld0\r\n";
 
-// draft-ietf-mmusic-sctp-sdp-03
 static const char kSdpSctpDataChannelString[] =
     "m=application 9 DTLS/SCTP 5000\r\n"
     "c=IN IP4 0.0.0.0\r\n"
@@ -1445,17 +1443,10 @@
               simulcast2.receive_layers().size());
   }
 
-  void CompareRtpDataContentDescription(const RtpDataContentDescription* dcd1,
-                                        const RtpDataContentDescription* dcd2) {
-    CompareMediaContentDescription<RtpDataContentDescription>(dcd1, dcd2);
-  }
-
-  void CompareSctpDataContentDescription(
-      const SctpDataContentDescription* dcd1,
-      const SctpDataContentDescription* dcd2) {
+  void CompareDataContentDescription(const DataContentDescription* dcd1,
+                                     const DataContentDescription* dcd2) {
     EXPECT_EQ(dcd1->use_sctpmap(), dcd2->use_sctpmap());
-    EXPECT_EQ(dcd1->port(), dcd2->port());
-    EXPECT_EQ(dcd1->max_message_size(), dcd2->max_message_size());
+    CompareMediaContentDescription<DataContentDescription>(dcd1, dcd2);
   }
 
   void CompareSessionDescription(const SessionDescription& desc1,
@@ -1493,21 +1484,10 @@
       }
 
       ASSERT_EQ(IsDataContent(&c1), IsDataContent(&c2));
-      if (c1.media_description()->as_sctp()) {
-        ASSERT_TRUE(c2.media_description()->as_sctp());
-        const SctpDataContentDescription* scd1 =
-            c1.media_description()->as_sctp();
-        const SctpDataContentDescription* scd2 =
-            c2.media_description()->as_sctp();
-        CompareSctpDataContentDescription(scd1, scd2);
-      } else {
-        if (IsDataContent(&c1)) {
-          const RtpDataContentDescription* dcd1 =
-              c1.media_description()->as_rtp_data();
-          const RtpDataContentDescription* dcd2 =
-              c2.media_description()->as_rtp_data();
-          CompareRtpDataContentDescription(dcd1, dcd2);
-        }
+      if (IsDataContent(&c1)) {
+        const DataContentDescription* dcd1 = c1.media_description()->as_data();
+        const DataContentDescription* dcd2 = c2.media_description()->as_data();
+        CompareDataContentDescription(dcd1, dcd2);
       }
 
       CompareSimulcastDescription(
@@ -1780,12 +1760,14 @@
   }
 
   void AddSctpDataChannel(bool use_sctpmap) {
-    std::unique_ptr<SctpDataContentDescription> data(
-        new SctpDataContentDescription());
-    sctp_desc_ = data.get();
-    sctp_desc_->set_use_sctpmap(use_sctpmap);
-    sctp_desc_->set_protocol(cricket::kMediaProtocolDtlsSctp);
-    sctp_desc_->set_port(kDefaultSctpPort);
+    std::unique_ptr<DataContentDescription> data(new DataContentDescription());
+    data_desc_ = data.get();
+    data_desc_->set_use_sctpmap(use_sctpmap);
+    data_desc_->set_protocol(cricket::kMediaProtocolDtlsSctp);
+    DataCodec codec(cricket::kGoogleSctpDataCodecPlType,
+                    cricket::kGoogleSctpDataCodecName);
+    codec.SetParam(cricket::kCodecParamPort, kDefaultSctpPort);
+    data_desc_->AddCodec(codec);
     desc_.AddContent(kDataContentName, MediaProtocolType::kSctp,
                      data.release());
     desc_.AddTransportInfo(TransportInfo(
@@ -1793,8 +1775,7 @@
   }
 
   void AddRtpDataChannel() {
-    std::unique_ptr<RtpDataContentDescription> data(
-        new RtpDataContentDescription());
+    std::unique_ptr<DataContentDescription> data(new DataContentDescription());
     data_desc_ = data.get();
 
     data_desc_->AddCodec(DataCodec(101, "google-data"));
@@ -2062,8 +2043,7 @@
   SessionDescription desc_;
   AudioContentDescription* audio_desc_;
   VideoContentDescription* video_desc_;
-  RtpDataContentDescription* data_desc_;
-  SctpDataContentDescription* sctp_desc_;
+  DataContentDescription* data_desc_;
   Candidates candidates_;
   std::unique_ptr<IceCandidateInterface> jcandidate_;
   JsepSessionDescription jdesc_;
@@ -2235,26 +2215,21 @@
   EXPECT_EQ(message, expected_sdp);
 }
 
-void MutateJsepSctpPort(JsepSessionDescription* jdesc,
-                        const SessionDescription& desc,
-                        int port) {
-  // Take our pre-built session description and change the SCTP port.
-  std::unique_ptr<cricket::SessionDescription> mutant = desc.Clone();
-  SctpDataContentDescription* dcdesc =
-      mutant->GetContentDescriptionByName(kDataContentName)->as_sctp();
-  dcdesc->set_port(port);
-  ASSERT_TRUE(
-      jdesc->Initialize(std::move(mutant), kSessionId, kSessionVersion));
-}
-
 TEST_F(WebRtcSdpTest, SerializeWithSctpDataChannelAndNewPort) {
   bool use_sctpmap = true;
   AddSctpDataChannel(use_sctpmap);
   JsepSessionDescription jsep_desc(kDummyType);
   MakeDescriptionWithoutCandidates(&jsep_desc);
+  DataContentDescription* dcdesc =
+      jsep_desc.description()
+          ->GetContentDescriptionByName(kDataContentName)
+          ->as_data();
 
   const int kNewPort = 1234;
-  MutateJsepSctpPort(&jsep_desc, desc_, kNewPort);
+  cricket::DataCodec codec(cricket::kGoogleSctpDataCodecPlType,
+                           cricket::kGoogleSctpDataCodecName);
+  codec.SetParam(cricket::kCodecParamPort, kNewPort);
+  dcdesc->AddOrReplaceCodec(codec);
 
   std::string message = webrtc::SdpSerialize(jsep_desc);
 
@@ -2893,12 +2868,14 @@
 // Helper function to set the max-message-size parameter in the
 // SCTP data codec.
 void MutateJsepSctpMaxMessageSize(const SessionDescription& desc,
-                                  int new_value,
+                                  const std::string& new_value,
                                   JsepSessionDescription* jdesc) {
   std::unique_ptr<cricket::SessionDescription> mutant = desc.Clone();
-  SctpDataContentDescription* dcdesc =
-      mutant->GetContentDescriptionByName(kDataContentName)->as_sctp();
-  dcdesc->set_max_message_size(new_value);
+  DataContentDescription* dcdesc =
+      mutant->GetContentDescriptionByName(kDataContentName)->as_data();
+  std::vector<cricket::DataCodec> codecs(dcdesc->codecs());
+  codecs[0].SetParam(cricket::kCodecParamMaxMessageSize, new_value);
+  dcdesc->set_codecs(codecs);
   jdesc->Initialize(std::move(mutant), kSessionId, kSessionVersion);
 }
 
@@ -2910,7 +2887,7 @@
 
   sdp_with_data.append(kSdpSctpDataChannelStringWithSctpColonPort);
   sdp_with_data.append("a=max-message-size:12345\r\n");
-  MutateJsepSctpMaxMessageSize(desc_, 12345, &jdesc);
+  MutateJsepSctpMaxMessageSize(desc_, "12345", &jdesc);
   JsepSessionDescription jdesc_output(kDummyType);
 
   // Verify with DTLS/SCTP.
@@ -2960,13 +2937,29 @@
   // No crash is a pass.
 }
 
+void MutateJsepSctpPort(JsepSessionDescription* jdesc,
+                        const SessionDescription& desc) {
+  // take our pre-built session description and change the SCTP port.
+  std::unique_ptr<cricket::SessionDescription> mutant = desc.Clone();
+  DataContentDescription* dcdesc =
+      mutant->GetContentDescriptionByName(kDataContentName)->as_data();
+  std::vector<cricket::DataCodec> codecs(dcdesc->codecs());
+  EXPECT_EQ(1U, codecs.size());
+  EXPECT_EQ(cricket::kGoogleSctpDataCodecPlType, codecs[0].id);
+  codecs[0].SetParam(cricket::kCodecParamPort, kUnusualSctpPort);
+  dcdesc->set_codecs(codecs);
+
+  ASSERT_TRUE(
+      jdesc->Initialize(std::move(mutant), kSessionId, kSessionVersion));
+}
+
 TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelAndUnusualPort) {
   bool use_sctpmap = true;
   AddSctpDataChannel(use_sctpmap);
 
   // First setup the expected JsepSessionDescription.
   JsepSessionDescription jdesc(kDummyType);
-  MutateJsepSctpPort(&jdesc, desc_, kUnusualSctpPort);
+  MutateJsepSctpPort(&jdesc, desc_);
 
   // Then get the deserialized JsepSessionDescription.
   std::string sdp_with_data = kSdpString;
@@ -2986,7 +2979,7 @@
   AddSctpDataChannel(use_sctpmap);
 
   JsepSessionDescription jdesc(kDummyType);
-  MutateJsepSctpPort(&jdesc, desc_, kUnusualSctpPort);
+  MutateJsepSctpPort(&jdesc, desc_);
 
   // We need to test the deserialized JsepSessionDescription from
   // kSdpSctpDataChannelStringWithSctpPort for
@@ -3022,7 +3015,7 @@
   bool use_sctpmap = true;
   AddSctpDataChannel(use_sctpmap);
   JsepSessionDescription jdesc(kDummyType);
-  SctpDataContentDescription* dcd = GetFirstSctpDataContentDescription(&desc_);
+  DataContentDescription* dcd = GetFirstDataContentDescription(&desc_);
   dcd->set_bandwidth(100 * 1000);
   ASSERT_TRUE(jdesc.Initialize(desc_.Clone(), kSessionId, kSessionVersion));