Revert "Merge the codec types"

This reverts commit 49ace8b6548cda6d4ba74abfca9b616f56dbf9bc.

Reason for revert: Breaks downstream projects

Original change's description:
> Merge the codec types
>
> This allows simplifying code in the codebase to be able to remove a lot
> of templated code and special casing for either AudioCodec and VideoCodec.
> Code simplifications will come in later changes.
>
> Bug: webrtc:15214
> Change-Id: I6e75e6ea725163feb6cc4eb49f37b4722d6c6689
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/308501
> Reviewed-by: Henrik Boström <hbos@webrtc.org>
> Commit-Queue: Florent Castelli <orphis@webrtc.org>
> Cr-Commit-Position: refs/heads/main@{#40276}

Bug: webrtc:15214
Change-Id: I57778cccc3a13eb9f955f6ece054dee0ff5a7e92
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/308720
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
Owners-Override: Mirko Bonadei <mbonadei@webrtc.org>
Auto-Submit: Florent Castelli <orphis@webrtc.org>
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40278}
diff --git a/media/base/codec.cc b/media/base/codec.cc
index 7a238cf..a707a48 100644
--- a/media/base/codec.cc
+++ b/media/base/codec.cc
@@ -323,6 +323,20 @@
   return true;
 }
 
+AudioCodec::AudioCodec(int id,
+                       const std::string& name,
+                       int clockrate,
+                       int unused_bitrate,
+                       size_t channels)
+    : Codec(Type::kAudio, id, name, clockrate, channels) {}
+
+AudioCodec::AudioCodec() : Codec(Type::kAudio) {}
+
+AudioCodec::AudioCodec(const AudioCodec& c) = default;
+AudioCodec::AudioCodec(AudioCodec&& c) = default;
+AudioCodec& AudioCodec::operator=(const AudioCodec& c) = default;
+AudioCodec& AudioCodec::operator=(AudioCodec&& c) = default;
+
 std::string Codec::ToString() const {
   char buf[256];
 
@@ -345,16 +359,66 @@
   return sb.str();
 }
 
-Codec CreateAudioRtxCodec(int rtx_payload_type, int associated_payload_type) {
-  Codec rtx_codec = CreateAudioCodec(rtx_payload_type, kRtxCodecName, 0, 1);
+VideoCodec::VideoCodec(int id, const std::string& name)
+    : Codec(Type::kVideo, id, name, kVideoCodecClockrate) {
+  SetDefaultParameters();
+}
+
+VideoCodec::VideoCodec(const std::string& name) : VideoCodec(0 /* id */, name) {
+  SetDefaultParameters();
+}
+
+VideoCodec::VideoCodec() : Codec(Type::kVideo) {
+  clockrate = kVideoCodecClockrate;
+}
+
+VideoCodec::VideoCodec(const webrtc::SdpVideoFormat& c) : Codec(c) {}
+
+VideoCodec::VideoCodec(const VideoCodec& c) = default;
+VideoCodec::VideoCodec(VideoCodec&& c) = default;
+VideoCodec& VideoCodec::operator=(const VideoCodec& c) = default;
+VideoCodec& VideoCodec::operator=(VideoCodec&& c) = default;
+
+void VideoCodec::SetDefaultParameters() {
+  if (absl::EqualsIgnoreCase(kH264CodecName, name)) {
+    // This default is set for all H.264 codecs created because
+    // that was the default before packetization mode support was added.
+    // TODO(hta): Move this to the places that create VideoCodecs from
+    // SDP or from knowledge of implementation capabilities.
+    SetParam(kH264FmtpPacketizationMode, "1");
+  }
+}
+
+VideoCodec VideoCodec::CreateRtxCodec(int rtx_payload_type,
+                                      int associated_payload_type) {
+  return CreateVideoRtxCodec(rtx_payload_type, associated_payload_type);
+}
+
+VideoCodec CreateVideoRtxCodec(int rtx_payload_type,
+                               int associated_payload_type) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  VideoCodec rtx_codec(rtx_payload_type, kRtxCodecName);
+#pragma clang diagnostic pop
   rtx_codec.SetParam(kCodecParamAssociatedPayloadType, associated_payload_type);
   return rtx_codec;
 }
 
-Codec CreateVideoRtxCodec(int rtx_payload_type, int associated_payload_type) {
-  Codec rtx_codec = CreateVideoCodec(rtx_payload_type, kRtxCodecName);
-  rtx_codec.SetParam(kCodecParamAssociatedPayloadType, associated_payload_type);
-  return rtx_codec;
+VideoCodec::CodecType VideoCodec::GetCodecType() const {
+  if (absl::EqualsIgnoreCase(name, kRedCodecName)) {
+    return CODEC_RED;
+  }
+  if (absl::EqualsIgnoreCase(name, kUlpfecCodecName)) {
+    return CODEC_ULPFEC;
+  }
+  if (absl::EqualsIgnoreCase(name, kFlexfecCodecName)) {
+    return CODEC_FLEXFEC;
+  }
+  if (absl::EqualsIgnoreCase(name, kRtxCodecName)) {
+    return CODEC_RTX;
+  }
+
+  return CODEC_VIDEO;
 }
 
 bool HasLntf(const Codec& codec) {
@@ -435,31 +499,35 @@
   }
 }
 
-Codec CreateAudioCodec(int id,
-                       const std::string& name,
-                       int clockrate,
-                       size_t channels) {
-  return Codec(Codec::Type::kAudio, id, name, clockrate, channels);
+AudioCodec CreateAudioCodec(int id,
+                            const std::string& name,
+                            int clockrate,
+                            size_t channels) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  return AudioCodec(id, name, clockrate, 0, channels);
+#pragma clang diagnostic pop
 }
 
-Codec CreateVideoCodec(const std::string& name) {
-  return CreateVideoCodec(0, name);
+VideoCodec CreateVideoCodec(const std::string& name) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  return VideoCodec(name);
+#pragma clang diagnostic pop
 }
 
-Codec CreateVideoCodec(int id, const std::string& name) {
-  Codec c(Codec::Type::kVideo, id, name, kVideoCodecClockrate);
-  if (absl::EqualsIgnoreCase(kH264CodecName, name)) {
-    // This default is set for all H.264 codecs created because
-    // that was the default before packetization mode support was added.
-    // TODO(hta): Move this to the places that create VideoCodecs from
-    // SDP or from knowledge of implementation capabilities.
-    c.SetParam(kH264FmtpPacketizationMode, "1");
-  }
-  return c;
+VideoCodec CreateVideoCodec(int id, const std::string& name) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  return VideoCodec(id, name);
+#pragma clang diagnostic pop
 }
 
-Codec CreateVideoCodec(const webrtc::SdpVideoFormat& c) {
-  return Codec(c);
+VideoCodec CreateVideoCodec(const webrtc::SdpVideoFormat& c) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  return VideoCodec(c);
+#pragma clang diagnostic pop
 }
 
 }  // namespace cricket
diff --git a/media/base/codec.h b/media/base/codec.h
index 1ca0931..34f4506 100644
--- a/media/base/codec.h
+++ b/media/base/codec.h
@@ -38,7 +38,6 @@
       : id_(id), param_(kParamValueEmpty) {}
 
   bool operator==(const FeedbackParam& other) const;
-  bool operator!=(const FeedbackParam& c) const { return !(*this == c); }
 
   const std::string& id() const { return id_; }
   const std::string& param() const { return param_; }
@@ -53,7 +52,6 @@
   FeedbackParams();
   ~FeedbackParams();
   bool operator==(const FeedbackParams& other) const;
-  bool operator!=(const FeedbackParams& c) const { return !(*this == c); }
 
   bool Has(const FeedbackParam& param) const;
   void Add(const FeedbackParam& param);
@@ -165,34 +163,71 @@
         const std::string& name,
         int clockrate,
         size_t channels);
-
   explicit Codec(const webrtc::SdpVideoFormat& c);
-
-  friend Codec CreateAudioCodec(int id,
-                                const std::string& name,
-                                int clockrate,
-                                size_t channels);
-  friend Codec CreateAudioRtxCodec(int rtx_payload_type,
-                                   int associated_payload_type);
-  friend Codec CreateVideoCodec(int id, const std::string& name);
-  friend Codec CreateVideoCodec(const webrtc::SdpVideoFormat& c);
-  friend Codec CreateVideoRtxCodec(int rtx_payload_type,
-                                   int associated_payload_type);
 };
 
-// TODO(webrtc:15214): Compatibility names, to be migrated away and removed.
-using VideoCodec = Codec;
-using AudioCodec = Codec;
+struct AudioCodec : public Codec {
+  // Creates a codec with the given parameters.
+  [[deprecated("Use cricket::CreateAudioCodec")]] AudioCodec(
+      int id,
+      const std::string& name,
+      int clockrate,
+      int unused_bitrate,
+      size_t channels);
+  // Creates an empty codec.
+  [[deprecated("Do not create empty AudioCodec")]] AudioCodec();
+  AudioCodec(const AudioCodec& c);
+  AudioCodec(AudioCodec&& c);
+  ~AudioCodec() override = default;
 
-Codec CreateAudioCodec(int id,
-                       const std::string& name,
-                       int clockrate,
-                       size_t channels);
-Codec CreateAudioRtxCodec(int rtx_payload_type, int associated_payload_type);
-Codec CreateVideoCodec(const std::string& name);
-Codec CreateVideoCodec(int id, const std::string& name);
-Codec CreateVideoCodec(const webrtc::SdpVideoFormat& c);
-Codec CreateVideoRtxCodec(int rtx_payload_type, int associated_payload_type);
+  AudioCodec& operator=(const AudioCodec& c);
+  AudioCodec& operator=(AudioCodec&& c);
+};
+
+struct RTC_EXPORT VideoCodec : public Codec {
+  // Creates a codec with the given parameters.
+  [[deprecated("Use cricket::CreateVideoCodec")]] VideoCodec(
+      int id,
+      const std::string& name);
+  // Creates a codec with the given name and empty id.
+  [[deprecated("Use cricket::CreateVideoCodec")]] explicit VideoCodec(
+      const std::string& name);
+  // Creates an empty codec.
+  [[deprecated("Do not create empty VideoCodec")]] VideoCodec();
+  VideoCodec(const VideoCodec& c);
+  [[deprecated]] explicit VideoCodec(const webrtc::SdpVideoFormat& c);
+  VideoCodec(VideoCodec&& c);
+  ~VideoCodec() override = default;
+
+  VideoCodec& operator=(const VideoCodec& c);
+  VideoCodec& operator=(VideoCodec&& c);
+
+  [[deprecated]] static VideoCodec CreateRtxCodec(int rtx_payload_type,
+                                                  int associated_payload_type);
+
+  enum [[deprecated]] CodecType {
+    CODEC_VIDEO,
+    CODEC_RED,
+    CODEC_ULPFEC,
+    CODEC_FLEXFEC,
+    CODEC_RTX,
+  };
+
+  [[deprecated]] CodecType GetCodecType() const;
+
+ private:
+  void SetDefaultParameters();
+};
+
+AudioCodec CreateAudioCodec(int id,
+                            const std::string& name,
+                            int clockrate,
+                            size_t channels);
+VideoCodec CreateVideoCodec(const std::string& name);
+VideoCodec CreateVideoCodec(int id, const std::string& name);
+VideoCodec CreateVideoCodec(const webrtc::SdpVideoFormat& c);
+VideoCodec CreateVideoRtxCodec(int rtx_payload_type,
+                               int associated_payload_type);
 
 // Get the codec setting associated with `payload_type`. If there
 // is no codec associated with that payload type it returns nullptr.
diff --git a/media/base/codec_unittest.cc b/media/base/codec_unittest.cc
index eb34530..0d405be 100644
--- a/media/base/codec_unittest.cc
+++ b/media/base/codec_unittest.cc
@@ -82,8 +82,14 @@
   EXPECT_NE(c0, c4);
   EXPECT_NE(c0, c5);
 
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  AudioCodec c7;
+#pragma clang diagnostic pop
   AudioCodec c8 = cricket::CreateAudioCodec(0, "", 0, 0);
   AudioCodec c9 = c0;
+  EXPECT_EQ(c8, c7);
+  EXPECT_NE(c9, c7);
   EXPECT_EQ(c9, c0);
 
   AudioCodec c10(c0);
@@ -156,8 +162,14 @@
   EXPECT_TRUE(c0 != c1);
   EXPECT_TRUE(c0 != c2);
 
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  VideoCodec c7;
+#pragma clang diagnostic pop
   VideoCodec c8 = cricket::CreateVideoCodec(0, "");
   VideoCodec c9 = c0;
+  EXPECT_TRUE(c8 == c7);
+  EXPECT_TRUE(c9 != c7);
   EXPECT_TRUE(c9 == c0);
 
   VideoCodec c10(c0);
diff --git a/pc/peer_connection_media_unittest.cc b/pc/peer_connection_media_unittest.cc
index 72bd9bd..dd497ba 100644
--- a/pc/peer_connection_media_unittest.cc
+++ b/pc/peer_connection_media_unittest.cc
@@ -573,7 +573,8 @@
 TEST_P(PeerConnectionMediaTest, RawPacketizationNotSetInOffer) {
   std::vector<cricket::VideoCodec> fake_codecs;
   fake_codecs.push_back(cricket::CreateVideoCodec(111, cricket::kVp8CodecName));
-  fake_codecs.push_back(cricket::CreateVideoRtxCodec(112, 111));
+  fake_codecs.push_back(cricket::CreateVideoCodec(112, cricket::kRtxCodecName));
+  fake_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "111";
   fake_codecs.push_back(cricket::CreateVideoCodec(113, cricket::kVp9CodecName));
   fake_codecs.push_back(
       cricket::CreateVideoCodec(114, cricket::kH264CodecName));
@@ -595,7 +596,8 @@
 TEST_P(PeerConnectionMediaTest, RawPacketizationSetInOfferAndAnswer) {
   std::vector<cricket::VideoCodec> fake_codecs;
   fake_codecs.push_back(cricket::CreateVideoCodec(111, cricket::kVp8CodecName));
-  fake_codecs.push_back(cricket::CreateVideoRtxCodec(112, 111));
+  fake_codecs.push_back(cricket::CreateVideoCodec(112, cricket::kRtxCodecName));
+  fake_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "111";
   fake_codecs.push_back(cricket::CreateVideoCodec(113, cricket::kVp9CodecName));
   fake_codecs.push_back(
       cricket::CreateVideoCodec(114, cricket::kH264CodecName));
@@ -638,7 +640,8 @@
        RawPacketizationNotSetInAnswerWhenNotSetInOffer) {
   std::vector<cricket::VideoCodec> fake_codecs;
   fake_codecs.push_back(cricket::CreateVideoCodec(111, cricket::kVp8CodecName));
-  fake_codecs.push_back(cricket::CreateVideoRtxCodec(112, 111));
+  fake_codecs.push_back(cricket::CreateVideoCodec(112, cricket::kRtxCodecName));
+  fake_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "111";
   fake_codecs.push_back(cricket::CreateVideoCodec(113, cricket::kVp9CodecName));
   fake_codecs.push_back(
       cricket::CreateVideoCodec(114, cricket::kH264CodecName));
@@ -1703,8 +1706,10 @@
        SetCodecPreferencesAudioRejectsOnlyRtxRedFec) {
   auto fake_engine = std::make_unique<FakeMediaEngine>();
   auto audio_codecs = fake_engine->voice().send_codecs();
-  audio_codecs.push_back(cricket::CreateAudioRtxCodec(
-      audio_codecs.back().id + 1, audio_codecs.back().id));
+  audio_codecs.push_back(cricket::CreateAudioCodec(
+      audio_codecs.back().id + 1, cricket::kRtxCodecName, 0, 1));
+  audio_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
+      std::to_string(audio_codecs.back().id - 1);
   audio_codecs.push_back(cricket::CreateAudioCodec(
       audio_codecs.back().id + 1, cricket::kRedCodecName, 0, 1));
   audio_codecs.push_back(cricket::CreateAudioCodec(
@@ -1798,8 +1803,10 @@
        SetCodecPreferencesVideoRejectsOnlyRtxRedFec) {
   auto fake_engine = std::make_unique<FakeMediaEngine>();
   auto video_codecs = fake_engine->video().send_codecs();
-  video_codecs.push_back(cricket::CreateVideoRtxCodec(
-      video_codecs.back().id + 1, video_codecs.back().id));
+  video_codecs.push_back(cricket::CreateVideoCodec(video_codecs.back().id + 1,
+                                                   cricket::kRtxCodecName));
+  video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
+      std::to_string(video_codecs.back().id - 1);
   video_codecs.push_back(cricket::CreateVideoCodec(video_codecs.back().id + 1,
                                                    cricket::kRedCodecName));
   video_codecs.push_back(cricket::CreateVideoCodec(video_codecs.back().id + 1,
@@ -1906,12 +1913,16 @@
   auto caller_video_codecs = caller_fake_engine->video().send_codecs();
   caller_video_codecs.push_back(cricket::CreateVideoCodec(
       caller_video_codecs.back().id + 1, cricket::kVp8CodecName));
-  caller_video_codecs.push_back(cricket::CreateVideoRtxCodec(
-      caller_video_codecs.back().id + 1, caller_video_codecs.back().id));
+  caller_video_codecs.push_back(cricket::CreateVideoCodec(
+      caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
+  caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
+      std::to_string(caller_video_codecs.back().id - 1);
   caller_video_codecs.push_back(cricket::CreateVideoCodec(
       caller_video_codecs.back().id + 1, cricket::kVp9CodecName));
-  caller_video_codecs.push_back(cricket::CreateVideoRtxCodec(
-      caller_video_codecs.back().id + 1, caller_video_codecs.back().id));
+  caller_video_codecs.push_back(cricket::CreateVideoCodec(
+      caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
+  caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
+      std::to_string(caller_video_codecs.back().id - 1);
   caller_fake_engine->SetVideoCodecs(caller_video_codecs);
 
   auto caller = CreatePeerConnectionWithVideo(std::move(caller_fake_engine));
@@ -1954,12 +1965,16 @@
   auto caller_video_codecs = caller_fake_engine->video().send_codecs();
   caller_video_codecs.push_back(cricket::CreateVideoCodec(
       caller_video_codecs.back().id + 1, cricket::kVp8CodecName));
-  caller_video_codecs.push_back(cricket::CreateVideoRtxCodec(
-      caller_video_codecs.back().id + 1, caller_video_codecs.back().id));
+  caller_video_codecs.push_back(cricket::CreateVideoCodec(
+      caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
+  caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
+      std::to_string(caller_video_codecs.back().id - 1);
   caller_video_codecs.push_back(cricket::CreateVideoCodec(
       caller_video_codecs.back().id + 1, cricket::kVp9CodecName));
-  caller_video_codecs.push_back(cricket::CreateVideoRtxCodec(
-      caller_video_codecs.back().id + 1, caller_video_codecs.back().id));
+  caller_video_codecs.push_back(cricket::CreateVideoCodec(
+      caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
+  caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
+      std::to_string(caller_video_codecs.back().id - 1);
   caller_fake_engine->SetVideoCodecs(caller_video_codecs);
 
   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
@@ -2024,12 +2039,16 @@
   auto caller_video_codecs = caller_fake_engine->video().send_codecs();
   caller_video_codecs.push_back(cricket::CreateVideoCodec(
       caller_video_codecs.back().id + 1, cricket::kVp8CodecName));
-  caller_video_codecs.push_back(cricket::CreateVideoRtxCodec(
-      caller_video_codecs.back().id + 1, caller_video_codecs.back().id));
+  caller_video_codecs.push_back(cricket::CreateVideoCodec(
+      caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
+  caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
+      std::to_string(caller_video_codecs.back().id - 1);
   caller_video_codecs.push_back(cricket::CreateVideoCodec(
       caller_video_codecs.back().id + 1, cricket::kVp9CodecName));
-  caller_video_codecs.push_back(cricket::CreateVideoRtxCodec(
-      caller_video_codecs.back().id + 1, caller_video_codecs.back().id));
+  caller_video_codecs.push_back(cricket::CreateVideoCodec(
+      caller_video_codecs.back().id + 1, cricket::kRtxCodecName));
+  caller_video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] =
+      std::to_string(caller_video_codecs.back().id - 1);
   caller_fake_engine->SetVideoCodecs(caller_video_codecs);
 
   auto callee_fake_engine = std::make_unique<FakeMediaEngine>();
@@ -2111,13 +2130,15 @@
   auto fake_engine = std::make_unique<cricket::FakeMediaEngine>();
 
   std::vector<cricket::AudioCodec> audio_codecs;
-  audio_codecs.emplace_back(cricket::CreateAudioCodec(100, "foo", 0, 1));
-  audio_codecs.emplace_back(cricket::CreateAudioRtxCodec(101, 100));
+  audio_codecs.emplace_back(100, "foo", 0, 0, 1);
+  audio_codecs.emplace_back(101, cricket::kRtxCodecName, 0, 0, 1);
+  audio_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "100";
   fake_engine->SetAudioCodecs(audio_codecs);
 
   std::vector<cricket::VideoCodec> video_codecs;
-  video_codecs.emplace_back(cricket::CreateVideoCodec(100, "bar"));
-  video_codecs.emplace_back(cricket::CreateVideoRtxCodec(101, 100));
+  video_codecs.emplace_back(100, "bar");
+  video_codecs.emplace_back(101, cricket::kRtxCodecName);
+  video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "100";
   fake_engine->SetVideoCodecs(video_codecs);
 
   auto caller = CreatePeerConnectionWithAudioVideo(std::move(fake_engine));
@@ -2152,13 +2173,15 @@
   auto fake_engine = std::make_unique<cricket::FakeMediaEngine>();
 
   std::vector<cricket::AudioCodec> audio_codecs;
-  audio_codecs.emplace_back(cricket::CreateAudioCodec(100, "foo", 0, 1));
-  audio_codecs.emplace_back(cricket::CreateAudioRtxCodec(101, 100));
+  audio_codecs.emplace_back(100, "foo", 0, 0, 1);
+  audio_codecs.emplace_back(101, cricket::kRtxCodecName, 0, 0, 1);
+  audio_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "100";
   fake_engine->SetAudioCodecs(audio_codecs);
 
   std::vector<cricket::VideoCodec> video_codecs;
-  video_codecs.emplace_back(cricket::CreateVideoCodec(100, "bar"));
-  video_codecs.emplace_back(cricket::CreateVideoRtxCodec(101, 100));
+  video_codecs.emplace_back(100, "bar");
+  video_codecs.emplace_back(101, cricket::kRtxCodecName);
+  video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "100";
   fake_engine->SetVideoCodecs(video_codecs);
 
   auto caller = CreatePeerConnectionWithAudioVideo(std::move(fake_engine));
@@ -2197,13 +2220,15 @@
   auto fake_engine = std::make_unique<cricket::FakeMediaEngine>();
 
   std::vector<cricket::AudioCodec> audio_codecs;
-  audio_codecs.emplace_back(cricket::CreateAudioCodec(100, "foo", 0, 1));
-  audio_codecs.emplace_back(cricket::CreateAudioRtxCodec(101, 100));
+  audio_codecs.emplace_back(100, "foo", 0, 0, 1);
+  audio_codecs.emplace_back(101, cricket::kRtxCodecName, 0, 0, 1);
+  audio_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "100";
   fake_engine->SetAudioCodecs(audio_codecs);
 
   std::vector<cricket::VideoCodec> video_codecs;
-  video_codecs.emplace_back(cricket::CreateVideoCodec(100, "bar"));
-  video_codecs.emplace_back(cricket::CreateVideoRtxCodec(101, 100));
+  video_codecs.emplace_back(100, "bar");
+  video_codecs.emplace_back(101, cricket::kRtxCodecName);
+  video_codecs.back().params[cricket::kCodecParamAssociatedPayloadType] = "100";
   fake_engine->SetVideoCodecs(video_codecs);
 
   auto caller = CreatePeerConnectionWithAudioVideo(std::move(fake_engine));
diff --git a/pc/rtp_parameters_conversion.cc b/pc/rtp_parameters_conversion.cc
index 2463cef..fa8599c 100644
--- a/pc/rtp_parameters_conversion.cc
+++ b/pc/rtp_parameters_conversion.cc
@@ -18,7 +18,6 @@
 
 #include "api/array_view.h"
 #include "api/media_types.h"
-#include "api/rtc_error.h"
 #include "media/base/codec.h"
 #include "media/base/media_constants.h"
 #include "media/base/rtp_utils.h"
@@ -81,71 +80,79 @@
   RTC_CHECK_NOTREACHED();
 }
 
-RTCErrorOr<cricket::Codec> ToCricketCodec(const RtpCodecParameters& codec) {
-  switch (codec.kind) {
-    case cricket::MEDIA_TYPE_AUDIO:
-      if (codec.kind != cricket::MEDIA_TYPE_AUDIO) {
-        LOG_AND_RETURN_ERROR(
-            RTCErrorType::INVALID_PARAMETER,
-            "Can't use video codec with audio sender or receiver.");
-      }
-      if (!codec.num_channels) {
-        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
-                             "Missing number of channels for audio codec.");
-      }
-      if (*codec.num_channels <= 0) {
-        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
-                             "Number of channels must be positive.");
-      }
-      if (!codec.clock_rate) {
-        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
-                             "Missing codec clock rate.");
-      }
-      if (*codec.clock_rate <= 0) {
-        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
-                             "Clock rate must be positive.");
-      }
-      break;
-    case cricket::MEDIA_TYPE_VIDEO:
-      if (codec.kind != cricket::MEDIA_TYPE_VIDEO) {
-        LOG_AND_RETURN_ERROR(
-            RTCErrorType::INVALID_PARAMETER,
-            "Can't use audio codec with video sender or receiver.");
-      }
-      if (codec.num_channels) {
-        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
-                             "Video codec shouldn't have num_channels.");
-      }
-      if (!codec.clock_rate) {
-        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
-                             "Missing codec clock rate.");
-      }
-      if (*codec.clock_rate != cricket::kVideoCodecClockrate) {
-        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
-                             "Video clock rate must be 90000.");
-      }
-      break;
-    default:
-      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
-                           "Unknown codec type");
-  }
+template <typename C>
+static RTCErrorOr<C> ToCricketCodecTypeSpecific(
+    const RtpCodecParameters& codec);
 
+template <>
+RTCErrorOr<cricket::AudioCodec> ToCricketCodecTypeSpecific<cricket::AudioCodec>(
+    const RtpCodecParameters& codec) {
+  if (codec.kind != cricket::MEDIA_TYPE_AUDIO) {
+    LOG_AND_RETURN_ERROR(
+        RTCErrorType::INVALID_PARAMETER,
+        "Can't use video codec with audio sender or receiver.");
+  }
+  if (!codec.num_channels) {
+    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
+                         "Missing number of channels for audio codec.");
+  }
+  if (*codec.num_channels <= 0) {
+    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
+                         "Number of channels must be positive.");
+  }
+  if (!codec.clock_rate) {
+    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
+                         "Missing codec clock rate.");
+  }
+  if (*codec.clock_rate <= 0) {
+    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE,
+                         "Clock rate must be positive.");
+  }
+  return cricket::CreateAudioCodec(0, codec.name, *codec.clock_rate,
+                                   *codec.num_channels);
+}
+
+// Video codecs don't use num_channels or clock_rate, but they should at least
+// be validated to ensure the application isn't trying to do something it
+// doesn't intend to.
+template <>
+RTCErrorOr<cricket::VideoCodec> ToCricketCodecTypeSpecific<cricket::VideoCodec>(
+    const RtpCodecParameters& codec) {
+  if (codec.kind != cricket::MEDIA_TYPE_VIDEO) {
+    LOG_AND_RETURN_ERROR(
+        RTCErrorType::INVALID_PARAMETER,
+        "Can't use audio codec with video sender or receiver.");
+  }
+  if (codec.num_channels) {
+    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
+                         "Video codec shouldn't have num_channels.");
+  }
+  if (!codec.clock_rate) {
+    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
+                         "Missing codec clock rate.");
+  }
+  if (*codec.clock_rate != cricket::kVideoCodecClockrate) {
+    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
+                         "Video clock rate must be 90000.");
+  }
+  return cricket::CreateVideoCodec(0, codec.name);
+}
+
+template <typename C>
+RTCErrorOr<C> ToCricketCodec(const RtpCodecParameters& codec) {
+  // Start with audio/video specific conversion.
+  RTCErrorOr<C> result = ToCricketCodecTypeSpecific<C>(codec);
+  if (!result.ok()) {
+    return result.MoveError();
+  }
+  C cricket_codec = result.MoveValue();
   if (!cricket::IsValidRtpPayloadType(codec.payload_type)) {
     char buf[40];
     rtc::SimpleStringBuilder sb(buf);
     sb << "Invalid payload type: " << codec.payload_type;
     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_RANGE, sb.str());
   }
-
-  cricket::Codec cricket_codec = [&]() {
-    if (codec.kind == cricket::MEDIA_TYPE_AUDIO) {
-      return cricket::CreateAudioCodec(codec.payload_type, codec.name,
-                                       *codec.clock_rate, *codec.num_channels);
-    }
-    RTC_DCHECK(codec.kind == cricket::MEDIA_TYPE_VIDEO);
-    return cricket::CreateVideoCodec(codec.payload_type, codec.name);
-  }();
-
+  cricket_codec.id = codec.payload_type;
   for (const RtcpFeedback& feedback : codec.rtcp_feedback) {
     auto result = ToCricketFeedbackParam(feedback);
     if (!result.ok()) {
@@ -157,12 +164,18 @@
   return std::move(cricket_codec);
 }
 
-RTCErrorOr<std::vector<cricket::Codec>> ToCricketCodecs(
+template RTCErrorOr<cricket::AudioCodec> ToCricketCodec(
+    const RtpCodecParameters& codec);
+template RTCErrorOr<cricket::VideoCodec> ToCricketCodec(
+    const RtpCodecParameters& codec);
+
+template <typename C>
+RTCErrorOr<std::vector<C>> ToCricketCodecs(
     const std::vector<RtpCodecParameters>& codecs) {
-  std::vector<cricket::Codec> cricket_codecs;
+  std::vector<C> cricket_codecs;
   std::set<int> seen_payload_types;
   for (const RtpCodecParameters& codec : codecs) {
-    auto result = ToCricketCodec(codec);
+    auto result = ToCricketCodec<C>(codec);
     if (!result.ok()) {
       return result.MoveError();
     }
@@ -177,6 +190,12 @@
   return std::move(cricket_codecs);
 }
 
+template RTCErrorOr<std::vector<cricket::AudioCodec>> ToCricketCodecs<
+    cricket::AudioCodec>(const std::vector<RtpCodecParameters>& codecs);
+
+template RTCErrorOr<std::vector<cricket::VideoCodec>> ToCricketCodecs<
+    cricket::VideoCodec>(const std::vector<RtpCodecParameters>& codecs);
+
 RTCErrorOr<cricket::StreamParamsVec> ToCricketStreamParamsVec(
     const std::vector<RtpEncodingParameters>& encodings) {
   if (encodings.size() > 1u) {
@@ -259,12 +278,51 @@
   return rtp_encodings;
 }
 
-RtpCodecCapability ToRtpCodecCapability(const cricket::Codec& cricket_codec) {
+template <typename C>
+cricket::MediaType KindOfCodec();
+
+template <>
+cricket::MediaType KindOfCodec<cricket::AudioCodec>() {
+  return cricket::MEDIA_TYPE_AUDIO;
+}
+
+template <>
+cricket::MediaType KindOfCodec<cricket::VideoCodec>() {
+  return cricket::MEDIA_TYPE_VIDEO;
+}
+
+template <typename C>
+static void ToRtpCodecCapabilityTypeSpecific(const C& cricket_codec,
+                                             RtpCodecCapability* codec);
+
+template <>
+void ToRtpCodecCapabilityTypeSpecific<cricket::AudioCodec>(
+    const cricket::AudioCodec& cricket_codec,
+    RtpCodecCapability* codec) {
+  codec->num_channels = static_cast<int>(cricket_codec.channels);
+}
+
+template <>
+void ToRtpCodecCapabilityTypeSpecific<cricket::VideoCodec>(
+    const cricket::VideoCodec& cricket_codec,
+    RtpCodecCapability* codec) {
+  if (cricket_codec.scalability_modes.empty() ||
+      (cricket_codec.scalability_modes.size() == 1 &&
+       cricket_codec.scalability_modes[0] == ScalabilityMode::kL1T1)) {
+    // https://w3c.github.io/webrtc-svc/#dom-rtcrtpcodeccapability-scalabilitymodes
+    // If a codec does not support encoding of scalability modes other than
+    // "L1T1", then the scalabilityModes member is not provided.
+    return;
+  }
+
+  codec->scalability_modes = cricket_codec.scalability_modes;
+}
+
+template <typename C>
+RtpCodecCapability ToRtpCodecCapability(const C& cricket_codec) {
   RtpCodecCapability codec;
   codec.name = cricket_codec.name;
-  codec.kind = cricket_codec.type == cricket::Codec::Type::kAudio
-                   ? cricket::MEDIA_TYPE_AUDIO
-                   : cricket::MEDIA_TYPE_VIDEO;
+  codec.kind = KindOfCodec<C>();
   codec.clock_rate.emplace(cricket_codec.clockrate);
   codec.preferred_payload_type.emplace(cricket_codec.id);
   for (const cricket::FeedbackParam& cricket_feedback :
@@ -274,25 +332,37 @@
       codec.rtcp_feedback.push_back(feedback.value());
     }
   }
-  switch (cricket_codec.type) {
-    case cricket::Codec::Type::kAudio:
-      codec.num_channels = static_cast<int>(cricket_codec.channels);
-      break;
-    case cricket::Codec::Type::kVideo:
-      codec.scalability_modes = cricket_codec.scalability_modes;
-      break;
-  }
+  ToRtpCodecCapabilityTypeSpecific(cricket_codec, &codec);
   codec.parameters.insert(cricket_codec.params.begin(),
                           cricket_codec.params.end());
   return codec;
 }
 
-RtpCodecParameters ToRtpCodecParameters(const cricket::Codec& cricket_codec) {
+template RtpCodecCapability ToRtpCodecCapability<cricket::AudioCodec>(
+    const cricket::AudioCodec& cricket_codec);
+template RtpCodecCapability ToRtpCodecCapability<cricket::VideoCodec>(
+    const cricket::VideoCodec& cricket_codec);
+
+template <typename C>
+static void ToRtpCodecParametersTypeSpecific(const C& cricket_codec,
+                                             RtpCodecParameters* codec);
+template <>
+void ToRtpCodecParametersTypeSpecific<cricket::AudioCodec>(
+    const cricket::AudioCodec& cricket_codec,
+    RtpCodecParameters* codec) {
+  codec->num_channels = static_cast<int>(cricket_codec.channels);
+}
+
+template <>
+void ToRtpCodecParametersTypeSpecific<cricket::VideoCodec>(
+    const cricket::VideoCodec& cricket_codec,
+    RtpCodecParameters* codec) {}
+
+template <typename C>
+RtpCodecParameters ToRtpCodecParameters(const C& cricket_codec) {
   RtpCodecParameters codec_param;
   codec_param.name = cricket_codec.name;
-  codec_param.kind = cricket_codec.type == cricket::Codec::Type::kAudio
-                         ? cricket::MEDIA_TYPE_AUDIO
-                         : cricket::MEDIA_TYPE_VIDEO;
+  codec_param.kind = KindOfCodec<C>();
   codec_param.clock_rate.emplace(cricket_codec.clockrate);
   codec_param.payload_type = cricket_codec.id;
   for (const cricket::FeedbackParam& cricket_feedback :
@@ -302,27 +372,26 @@
       codec_param.rtcp_feedback.push_back(feedback.value());
     }
   }
-  switch (cricket_codec.type) {
-    case cricket::Codec::Type::kAudio:
-      codec_param.num_channels = static_cast<int>(cricket_codec.channels);
-      break;
-    case cricket::Codec::Type::kVideo:
-      // Nothing to do.
-      break;
-  }
+  ToRtpCodecParametersTypeSpecific(cricket_codec, &codec_param);
   codec_param.parameters = cricket_codec.params;
   return codec_param;
 }
 
+template RtpCodecParameters ToRtpCodecParameters<cricket::AudioCodec>(
+    const cricket::AudioCodec& cricket_codec);
+template RtpCodecParameters ToRtpCodecParameters<cricket::VideoCodec>(
+    const cricket::VideoCodec& cricket_codec);
+
+template <class C>
 RtpCapabilities ToRtpCapabilities(
-    const std::vector<cricket::Codec>& cricket_codecs,
+    const std::vector<C>& cricket_codecs,
     const cricket::RtpHeaderExtensions& cricket_extensions) {
   RtpCapabilities capabilities;
   bool have_red = false;
   bool have_ulpfec = false;
   bool have_flexfec = false;
   bool have_rtx = false;
-  for (const cricket::Codec& cricket_codec : cricket_codecs) {
+  for (const C& cricket_codec : cricket_codecs) {
     if (cricket_codec.name == cricket::kRedCodecName) {
       have_red = true;
     } else if (cricket_codec.name == cricket::kUlpfecCodecName) {
@@ -359,12 +428,20 @@
   return capabilities;
 }
 
+template RtpCapabilities ToRtpCapabilities<cricket::AudioCodec>(
+    const std::vector<cricket::AudioCodec>& cricket_codecs,
+    const cricket::RtpHeaderExtensions& cricket_extensions);
+template RtpCapabilities ToRtpCapabilities<cricket::VideoCodec>(
+    const std::vector<cricket::VideoCodec>& cricket_codecs,
+    const cricket::RtpHeaderExtensions& cricket_extensions);
+
+template <class C>
 RtpParameters ToRtpParameters(
-    const std::vector<cricket::Codec>& cricket_codecs,
+    const std::vector<C>& cricket_codecs,
     const cricket::RtpHeaderExtensions& cricket_extensions,
     const cricket::StreamParamsVec& stream_params) {
   RtpParameters rtp_parameters;
-  for (const cricket::Codec& cricket_codec : cricket_codecs) {
+  for (const C& cricket_codec : cricket_codecs) {
     rtp_parameters.codecs.push_back(ToRtpCodecParameters(cricket_codec));
   }
   for (const RtpExtension& cricket_extension : cricket_extensions) {
@@ -375,4 +452,13 @@
   return rtp_parameters;
 }
 
+template RtpParameters ToRtpParameters<cricket::AudioCodec>(
+    const std::vector<cricket::AudioCodec>& cricket_codecs,
+    const cricket::RtpHeaderExtensions& cricket_extensions,
+    const cricket::StreamParamsVec& stream_params);
+template RtpParameters ToRtpParameters<cricket::VideoCodec>(
+    const std::vector<cricket::VideoCodec>& cricket_codecs,
+    const cricket::RtpHeaderExtensions& cricket_extensions,
+    const cricket::StreamParamsVec& stream_params);
+
 }  // namespace webrtc
diff --git a/pc/rtp_parameters_conversion.h b/pc/rtp_parameters_conversion.h
index 2cc39dd..959f3fd 100644
--- a/pc/rtp_parameters_conversion.h
+++ b/pc/rtp_parameters_conversion.h
@@ -48,11 +48,13 @@
 
 // Verifies that the codec kind is correct, and it has mandatory parameters
 // filled, with values in valid ranges.
-RTCErrorOr<cricket::Codec> ToCricketCodec(const RtpCodecParameters& codec);
+template <typename C>
+RTCErrorOr<C> ToCricketCodec(const RtpCodecParameters& codec);
 
 // Verifies that payload types aren't duplicated, in addition to normal
 // validation.
-RTCErrorOr<std::vector<cricket::Codec>> ToCricketCodecs(
+template <typename C>
+RTCErrorOr<std::vector<C>> ToCricketCodecs(
     const std::vector<RtpCodecParameters>& codecs);
 
 // SSRCs are allowed to be ommitted. This may be used for receive parameters
@@ -80,15 +82,20 @@
 std::vector<RtpEncodingParameters> ToRtpEncodings(
     const cricket::StreamParamsVec& stream_params);
 
-RtpCodecParameters ToRtpCodecParameters(const cricket::Codec& cricket_codec);
-RtpCodecCapability ToRtpCodecCapability(const cricket::Codec& cricket_codec);
+template <typename C>
+RtpCodecParameters ToRtpCodecParameters(const C& cricket_codec);
 
+template <typename C>
+RtpCodecCapability ToRtpCodecCapability(const C& cricket_codec);
+
+template <class C>
 RtpCapabilities ToRtpCapabilities(
-    const std::vector<cricket::Codec>& cricket_codecs,
+    const std::vector<C>& cricket_codecs,
     const cricket::RtpHeaderExtensions& cricket_extensions);
 
+template <class C>
 RtpParameters ToRtpParameters(
-    const std::vector<cricket::Codec>& cricket_codecs,
+    const std::vector<C>& cricket_codecs,
     const cricket::RtpHeaderExtensions& cricket_extensions,
     const cricket::StreamParamsVec& stream_params);
 
diff --git a/pc/rtp_parameters_conversion_unittest.cc b/pc/rtp_parameters_conversion_unittest.cc
index 9b48bfa..b1e6323 100644
--- a/pc/rtp_parameters_conversion_unittest.cc
+++ b/pc/rtp_parameters_conversion_unittest.cc
@@ -88,7 +88,7 @@
   codec.num_channels.emplace(6);
   codec.parameters["foo"] = "bar";
   codec.rtcp_feedback.emplace_back(RtcpFeedbackType::TRANSPORT_CC);
-  auto result = ToCricketCodec(codec);
+  auto result = ToCricketCodec<cricket::AudioCodec>(codec);
   ASSERT_TRUE(result.ok());
 
   EXPECT_EQ("AuDiO", result.value().name);
@@ -114,7 +114,7 @@
   codec.rtcp_feedback.emplace_back(RtcpFeedbackType::TRANSPORT_CC);
   codec.rtcp_feedback.emplace_back(RtcpFeedbackType::NACK,
                                    RtcpFeedbackMessageType::PLI);
-  auto result = ToCricketCodec(codec);
+  auto result = ToCricketCodec<cricket::VideoCodec>(codec);
   ASSERT_TRUE(result.ok());
 
   EXPECT_EQ("coolcodec", result.value().name);
@@ -147,18 +147,18 @@
   video_codec.payload_type = 102;
   video_codec.clock_rate.emplace(90000);
 
-  auto audio_result = ToCricketCodec(audio_codec);
+  auto audio_result = ToCricketCodec<cricket::AudioCodec>(audio_codec);
   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, audio_result.error().type());
 
-  auto video_result = ToCricketCodec(video_codec);
+  auto video_result = ToCricketCodec<cricket::VideoCodec>(video_codec);
   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, video_result.error().type());
 
   // Sanity check that if the kind is correct, the conversion succeeds.
   audio_codec.kind = cricket::MEDIA_TYPE_AUDIO;
   video_codec.kind = cricket::MEDIA_TYPE_VIDEO;
-  audio_result = ToCricketCodec(audio_codec);
+  audio_result = ToCricketCodec<cricket::AudioCodec>(audio_codec);
   EXPECT_TRUE(audio_result.ok());
-  video_result = ToCricketCodec(video_codec);
+  video_result = ToCricketCodec<cricket::VideoCodec>(video_codec);
   EXPECT_TRUE(video_result.ok());
 }
 
@@ -169,28 +169,28 @@
   codec.kind = cricket::MEDIA_TYPE_AUDIO;
   codec.payload_type = 111;
   codec.clock_rate.emplace(48000);
-  auto result = ToCricketCodec(codec);
+  auto result = ToCricketCodec<cricket::AudioCodec>(codec);
   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
 
   // Negative number of channels.
   codec.num_channels.emplace(-1);
-  result = ToCricketCodec(codec);
+  result = ToCricketCodec<cricket::AudioCodec>(codec);
   EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
 
   // Missing clock rate.
   codec.num_channels.emplace(2);
   codec.clock_rate.reset();
-  result = ToCricketCodec(codec);
+  result = ToCricketCodec<cricket::AudioCodec>(codec);
   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
 
   // Negative clock rate.
   codec.clock_rate.emplace(-48000);
-  result = ToCricketCodec(codec);
+  result = ToCricketCodec<cricket::AudioCodec>(codec);
   EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
 
   // Sanity check that conversion succeeds if these errors are fixed.
   codec.clock_rate.emplace(48000);
-  result = ToCricketCodec(codec);
+  result = ToCricketCodec<cricket::AudioCodec>(codec);
   EXPECT_TRUE(result.ok());
 }
 
@@ -200,23 +200,23 @@
   codec.name = "VP8";
   codec.kind = cricket::MEDIA_TYPE_VIDEO;
   codec.payload_type = 102;
-  auto result = ToCricketCodec(codec);
+  auto result = ToCricketCodec<cricket::VideoCodec>(codec);
   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
 
   // Invalid clock rate.
   codec.clock_rate.emplace(48000);
-  result = ToCricketCodec(codec);
+  result = ToCricketCodec<cricket::VideoCodec>(codec);
   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
 
   // Channels set (should be unset).
   codec.clock_rate.emplace(90000);
   codec.num_channels.emplace(2);
-  result = ToCricketCodec(codec);
+  result = ToCricketCodec<cricket::VideoCodec>(codec);
   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
 
   // Sanity check that conversion succeeds if these errors are fixed.
   codec.num_channels.reset();
-  result = ToCricketCodec(codec);
+  result = ToCricketCodec<cricket::VideoCodec>(codec);
   EXPECT_TRUE(result.ok());
 }
 
@@ -227,17 +227,17 @@
   codec.clock_rate.emplace(90000);
 
   codec.payload_type = -1000;
-  auto result = ToCricketCodec(codec);
+  auto result = ToCricketCodec<cricket::VideoCodec>(codec);
   EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
 
   // Max payload type is 127.
   codec.payload_type = 128;
-  result = ToCricketCodec(codec);
+  result = ToCricketCodec<cricket::VideoCodec>(codec);
   EXPECT_EQ(RTCErrorType::INVALID_RANGE, result.error().type());
 
   // Sanity check that conversion succeeds with a valid payload type.
   codec.payload_type = 127;
-  result = ToCricketCodec(codec);
+  result = ToCricketCodec<cricket::VideoCodec>(codec);
   EXPECT_TRUE(result.ok());
 }
 
@@ -252,12 +252,12 @@
   codec.rtcp_feedback.emplace_back(RtcpFeedbackType::CCM,
                                    RtcpFeedbackMessageType::PLI);
 
-  auto result = ToCricketCodec(codec);
+  auto result = ToCricketCodec<cricket::VideoCodec>(codec);
   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
 
   // Sanity check that conversion succeeds without invalid feedback.
   codec.rtcp_feedback.clear();
-  result = ToCricketCodec(codec);
+  result = ToCricketCodec<cricket::VideoCodec>(codec);
   EXPECT_TRUE(result.ok());
 }
 
@@ -274,7 +274,7 @@
   codec.payload_type = 100;
   codecs.push_back(codec);
 
-  auto result = ToCricketCodecs(codecs);
+  auto result = ToCricketCodecs<cricket::VideoCodec>(codecs);
   ASSERT_TRUE(result.ok());
   ASSERT_EQ(2u, result.value().size());
   EXPECT_EQ("VP8", result.value()[0].name);
@@ -296,12 +296,12 @@
   codec.payload_type = 99;
   codecs.push_back(codec);
 
-  auto result = ToCricketCodecs(codecs);
+  auto result = ToCricketCodecs<cricket::VideoCodec>(codecs);
   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
 
   // Sanity check that this succeeds without the duplicate payload type.
   codecs[1].payload_type = 120;
-  result = ToCricketCodecs(codecs);
+  result = ToCricketCodecs<cricket::VideoCodec>(codecs);
   EXPECT_TRUE(result.ok());
 }
 
@@ -541,8 +541,8 @@
 
   cricket::VideoCodec rtx2 = cricket::CreateVideoRtxCodec(105, 109);
 
-  RtpCapabilities capabilities =
-      ToRtpCapabilities({vp8, ulpfec, rtx, rtx2}, {{"uri", 1}, {"uri2", 3}});
+  RtpCapabilities capabilities = ToRtpCapabilities<cricket::VideoCodec>(
+      {vp8, ulpfec, rtx, rtx2}, {{"uri", 1}, {"uri2", 3}});
   ASSERT_EQ(3u, capabilities.codecs.size());
   EXPECT_EQ("VP8", capabilities.codecs[0].name);
   EXPECT_EQ("ulpfec", capabilities.codecs[1].name);
@@ -555,15 +555,15 @@
   EXPECT_EQ(3, capabilities.header_extensions[1].preferred_id);
   EXPECT_EQ(0u, capabilities.fec.size());
 
-  capabilities = ToRtpCapabilities({vp8, red, ulpfec, rtx},
-                                   cricket::RtpHeaderExtensions());
+  capabilities = ToRtpCapabilities<cricket::VideoCodec>(
+      {vp8, red, ulpfec, rtx}, cricket::RtpHeaderExtensions());
   EXPECT_EQ(4u, capabilities.codecs.size());
   EXPECT_THAT(
       capabilities.fec,
       UnorderedElementsAre(FecMechanism::RED, FecMechanism::RED_AND_ULPFEC));
 
-  capabilities =
-      ToRtpCapabilities({vp8, red, flexfec}, cricket::RtpHeaderExtensions());
+  capabilities = ToRtpCapabilities<cricket::VideoCodec>(
+      {vp8, red, flexfec}, cricket::RtpHeaderExtensions());
   EXPECT_EQ(3u, capabilities.codecs.size());
   EXPECT_THAT(capabilities.fec,
               UnorderedElementsAre(FecMechanism::RED, FecMechanism::FLEXFEC));
@@ -584,8 +584,8 @@
   stream.ssrcs.push_back(1234u);
   streams.push_back(stream);
 
-  RtpParameters rtp_parameters =
-      ToRtpParameters({vp8, red, ulpfec}, {{"uri", 1}, {"uri2", 3}}, streams);
+  RtpParameters rtp_parameters = ToRtpParameters<cricket::VideoCodec>(
+      {vp8, red, ulpfec}, {{"uri", 1}, {"uri2", 3}}, streams);
   ASSERT_EQ(3u, rtp_parameters.codecs.size());
   EXPECT_EQ("VP8", rtp_parameters.codecs[0].name);
   EXPECT_EQ("red", rtp_parameters.codecs[1].name);
diff --git a/pc/webrtc_sdp.cc b/pc/webrtc_sdp.cc
index 1e2f319..467b8c2 100644
--- a/pc/webrtc_sdp.cc
+++ b/pc/webrtc_sdp.cc
@@ -2897,16 +2897,14 @@
 // is no Codec associated with that payload type it returns an empty codec
 // with that payload type.
 template <class T>
-T GetCodecWithPayloadType(cricket::MediaType type,
-                          const std::vector<T>& codecs,
-                          int payload_type) {
+T GetCodecWithPayloadType(const std::vector<T>& codecs, int payload_type) {
   const T* codec = FindCodecById(codecs, payload_type);
   if (codec)
     return *codec;
   // Return empty codec with `payload_type`.
-  if (type == cricket::MEDIA_TYPE_AUDIO) {
+  if constexpr (std::is_same<T, cricket::AudioCodec>::value) {
     return cricket::CreateAudioCodec(payload_type, "", 0, 0);
-  } else {
+  } else if constexpr (std::is_same<T, cricket::VideoCodec>::value) {
     return cricket::CreateVideoCodec(payload_type, "");
   }
 }
@@ -2939,8 +2937,7 @@
                  int payload_type,
                  const cricket::CodecParameterMap& parameters) {
   // Codec might already have been populated (from rtpmap).
-  U new_codec = GetCodecWithPayloadType(content_desc->type(),
-                                        static_cast<T*>(content_desc)->codecs(),
+  U new_codec = GetCodecWithPayloadType(static_cast<T*>(content_desc)->codecs(),
                                         payload_type);
   AddParameters(parameters, &new_codec);
   AddOrReplaceCodec<T, U>(content_desc, new_codec);
@@ -2953,8 +2950,7 @@
                  int payload_type,
                  const cricket::FeedbackParam& feedback_param) {
   // Codec might already have been populated (from rtpmap).
-  U new_codec = GetCodecWithPayloadType(content_desc->type(),
-                                        static_cast<T*>(content_desc)->codecs(),
+  U new_codec = GetCodecWithPayloadType(static_cast<T*>(content_desc)->codecs(),
                                         payload_type);
   AddFeedbackParameter(feedback_param, &new_codec);
   AddOrReplaceCodec<T, U>(content_desc, new_codec);
@@ -2971,8 +2967,8 @@
   }
 
   // Codec might already have been populated (from rtpmap).
-  cricket::VideoCodec codec = GetCodecWithPayloadType(
-      video_desc->type(), video_desc->codecs(), payload_type);
+  cricket::VideoCodec codec =
+      GetCodecWithPayloadType(video_desc->codecs(), payload_type);
   codec.packetization = std::string(packetization);
   AddOrReplaceCodec<VideoContentDescription, cricket::VideoCodec>(video_desc,
                                                                   codec);
@@ -3596,8 +3592,8 @@
                  AudioContentDescription* audio_desc) {
   // Codec may already be populated with (only) optional parameters
   // (from an fmtp).
-  cricket::AudioCodec codec = GetCodecWithPayloadType(
-      audio_desc->type(), audio_desc->codecs(), payload_type);
+  cricket::AudioCodec codec =
+      GetCodecWithPayloadType(audio_desc->codecs(), payload_type);
   codec.name = std::string(name);
   codec.clockrate = clockrate;
   codec.bitrate = bitrate;
@@ -3613,8 +3609,8 @@
                  VideoContentDescription* video_desc) {
   // Codec may already be populated with (only) optional parameters
   // (from an fmtp).
-  cricket::VideoCodec codec = GetCodecWithPayloadType(
-      video_desc->type(), video_desc->codecs(), payload_type);
+  cricket::VideoCodec codec =
+      GetCodecWithPayloadType(video_desc->codecs(), payload_type);
   codec.name = std::string(name);
   AddOrReplaceCodec<VideoContentDescription, cricket::VideoCodec>(video_desc,
                                                                   codec);