Use PayloadTypePicker in WebRtcVoiceEngine

This entails passing in a PayloadTypeSuggester as a dependency. PT suggesting is still done according to the old method, but with new code.

Bug: webrtc:360058654
Change-Id: I12a7d2aa6aa482fb62ff3dfb34b9761ebb7dddef
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/361200
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42989}
diff --git a/call/BUILD.gn b/call/BUILD.gn
index a74e8ac..f53d0bd 100644
--- a/call/BUILD.gn
+++ b/call/BUILD.gn
@@ -39,7 +39,6 @@
   deps = [
     ":audio_sender_interface",
     ":payload_type",
-    ":payload_type",
     ":receive_stream_interface",
     ":rtp_interfaces",
     ":video_stream_api",
diff --git a/call/call.cc b/call/call.cc
index cf94cb8..2b77517 100644
--- a/call/call.cc
+++ b/call/call.cc
@@ -114,6 +114,11 @@
                                              cricket::Codec codec) override {
     return payload_type_picker_.SuggestMapping(codec, nullptr);
   }
+  RTCError AddLocalMapping(const std::string& mid,
+                           PayloadType payload_type,
+                           const cricket::Codec& codec) override {
+    return RTCError::OK();
+  }
 
  private:
   PayloadTypePicker payload_type_picker_;
diff --git a/call/payload_type.h b/call/payload_type.h
index 428096b..c0520e8 100644
--- a/call/payload_type.h
+++ b/call/payload_type.h
@@ -37,6 +37,11 @@
   // or a newly suggested one.
   virtual RTCErrorOr<PayloadType> SuggestPayloadType(const std::string& mid,
                                                      cricket::Codec codec) = 0;
+  // Register a payload type as mapped to a specific codec for this MID
+  // at this time.
+  virtual RTCError AddLocalMapping(const std::string& mid,
+                                   PayloadType payload_type,
+                                   const cricket::Codec& codec) = 0;
 };
 
 }  // namespace webrtc
diff --git a/call/payload_type_picker.cc b/call/payload_type_picker.cc
index 4c5936b..765d716 100644
--- a/call/payload_type_picker.cc
+++ b/call/payload_type_picker.cc
@@ -136,6 +136,14 @@
 RTCErrorOr<PayloadType> PayloadTypePicker::SuggestMapping(
     cricket::Codec codec,
     const PayloadTypeRecorder* excluder) {
+  // Test compatibility: If the codec contains a PT, and it is free, use it.
+  // This saves having to rewrite tests that set the codec ID themselves.
+  // Codecs with unassigned IDs should have -1 as their id.
+  if (codec.id >= 0 && codec.id <= kLastDynamicPayloadTypeUpperRange &&
+      seen_payload_types_.count(PayloadType(codec.id)) == 0) {
+    AddMapping(PayloadType(codec.id), codec);
+    return PayloadType(codec.id);
+  }
   // The first matching entry is returned, unless excluder
   // maps it to something different.
   for (auto entry : entries_) {
@@ -149,6 +157,7 @@
       return entry.payload_type();
     }
   }
+  // Assign the first free payload type.
   RTCErrorOr<PayloadType> found_pt = FindFreePayloadType(seen_payload_types_);
   if (found_pt.ok()) {
     AddMapping(found_pt.value(), codec);
diff --git a/media/BUILD.gn b/media/BUILD.gn
index 32af232..74d935d 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -344,6 +344,8 @@
     "../rtc_base:stringutils",
     "../rtc_base/network:sent_packet",
     "../video/config:encoder_config",
+    "//third_party/abseil-cpp/absl/functional:any_invocable",
+    "//third_party/abseil-cpp/absl/strings:string_view",
   ]
 }
 
@@ -592,6 +594,8 @@
     "../api/video_codecs:video_codecs_api",
     "../call",
     "../call:call_interfaces",
+    "../call:payload_type",
+    "../call:payload_type_picker",
     "../call:receive_stream_interface",
     "../call:rtp_interfaces",
     "../call:video_stream_api",
@@ -652,8 +656,6 @@
   sources = [
     "engine/adm_helpers.cc",
     "engine/adm_helpers.h",
-    "engine/payload_type_mapper.cc",
-    "engine/payload_type_mapper.h",
     "engine/webrtc_media_engine.cc",
     "engine/webrtc_media_engine.h",
     "engine/webrtc_video_engine.cc",
@@ -786,12 +788,23 @@
       ":video_common",
       "../api:call_api",
       "../api:fec_controller_api",
+      "../api:frame_transformer_interface",
+      "../api:rtc_error",
+      "../api:rtp_headers",
       "../api:rtp_parameters",
+      "../api:rtp_sender_interface",
       "../api:scoped_refptr",
+      "../api/adaptation:resource_adaptation_api",
+      "../api/audio:audio_frame_api",
       "../api/audio:audio_processing",
+      "../api/audio_codecs:audio_codecs_api",
+      "../api/crypto:frame_decryptor_interface",
       "../api/environment",
       "../api/task_queue",
       "../api/task_queue:pending_task_safety_flag",
+      "../api/transport:bitrate_settings",
+      "../api/transport/rtp:rtp_source",
+      "../api/units:time_delta",
       "../api/units:timestamp",
       "../api/video:encoded_image",
       "../api/video:video_bitrate_allocation",
@@ -800,9 +813,13 @@
       "../api/video_codecs:video_codecs_api",
       "../call:call_interfaces",
       "../call:mock_rtp_interfaces",
+      "../call:payload_type",
+      "../call:payload_type_picker",
+      "../call:rtp_interfaces",
       "../call:video_stream_api",
       "../common_video",
       "../modules/audio_processing",
+      "../modules/rtp_rtcp",
       "../modules/rtp_rtcp:rtp_rtcp_format",
       "../modules/video_coding:video_codec_interface",
       "../modules/video_coding:video_coding_utility",
@@ -820,11 +837,13 @@
       "../rtc_base:stringutils",
       "../rtc_base:threading",
       "../rtc_base:timeutils",
+      "../rtc_base/network:sent_packet",
       "../rtc_base/synchronization:mutex",
       "../rtc_base/third_party/sigslot",
       "../test:explicit_key_value_config",
       "../test:scoped_key_value_config",
       "../test:test_support",
+      "../video/config:encoder_config",
       "../video/config:streams_config",
       "//testing/gtest",
       "//third_party/abseil-cpp/absl/algorithm:container",
@@ -882,6 +901,7 @@
         ":rtc_audio_video",
         ":rtc_internal_video_codecs",
         ":rtc_media",
+        ":rtc_media_config",
         ":rtc_media_tests_utils",
         ":rtc_sdp_video_format_utils",
         ":rtc_simulcast_encoder_adapter",
@@ -891,27 +911,38 @@
         ":video_adapter",
         ":video_broadcaster",
         ":video_common",
+        "../api:audio_options_api",
+        "../api:call_api",
         "../api:create_simulcast_test_fixture_api",
         "../api:field_trials_view",
         "../api:libjingle_peerconnection_api",
+        "../api:make_ref_counted",
         "../api:mock_encoder_selector",
         "../api:mock_video_bitrate_allocator",
         "../api:mock_video_bitrate_allocator_factory",
         "../api:mock_video_codec_factory",
         "../api:mock_video_encoder",
         "../api:priority",
+        "../api:ref_count",
+        "../api:rtc_error",
+        "../api:rtp_headers",
         "../api:rtp_parameters",
         "../api:scoped_refptr",
         "../api:simulcast_test_fixture_api",
+        "../api/audio:audio_processing",
+        "../api/audio_codecs:audio_codecs_api",
         "../api/audio_codecs:builtin_audio_decoder_factory",
         "../api/audio_codecs:builtin_audio_encoder_factory",
+        "../api/crypto:options",
         "../api/environment",
         "../api/environment:environment_factory",
         "../api/rtc_event_log",
         "../api/task_queue",
         "../api/task_queue:default_task_queue_factory",
         "../api/test/video:function_video_factory",
+        "../api/transport:bitrate_settings",
         "../api/transport:field_trial_based_config",
+        "../api/transport/rtp:rtp_source",
         "../api/units:time_delta",
         "../api/units:timestamp",
         "../api/video:builtin_video_bitrate_allocator_factory",
@@ -950,6 +981,8 @@
         "../rtc_base:async_packet_socket",
         "../rtc_base:byte_order",
         "../rtc_base:checks",
+        "../rtc_base:copy_on_write_buffer",
+        "../rtc_base:dscp",
         "../rtc_base:gunit_helpers",
         "../rtc_base:logging",
         "../rtc_base:macromagic",
@@ -995,7 +1028,6 @@
         "base/video_common_unittest.cc",
         "engine/internal_decoder_factory_unittest.cc",
         "engine/internal_encoder_factory_unittest.cc",
-        "engine/payload_type_mapper_unittest.cc",
         "engine/simulcast_encoder_adapter_unittest.cc",
         "engine/webrtc_media_engine_unittest.cc",
         "engine/webrtc_video_engine_unittest.cc",
diff --git a/media/DEPS b/media/DEPS
index bcdbcac..ffa3c11 100644
--- a/media/DEPS
+++ b/media/DEPS
@@ -34,8 +34,7 @@
   ".*fake_webrtc_call\.cc": [
     "+video/config",
   ],
-  # temporary
-  ".*webrtc_voice_engine\.cc": [
-    "+pc/payload_type_picker.h",
+  ".*fake_webrtc_call\.h": [
+    "+video/config",
   ],
 }
diff --git a/media/base/media_channel.h b/media/base/media_channel.h
index b7f5987..73d2b25 100644
--- a/media/base/media_channel.h
+++ b/media/base/media_channel.h
@@ -11,6 +11,9 @@
 #ifndef MEDIA_BASE_MEDIA_CHANNEL_H_
 #define MEDIA_BASE_MEDIA_CHANNEL_H_
 
+#include <cstddef>
+#include <cstdint>
+#include <functional>
 #include <map>
 #include <memory>
 #include <optional>
@@ -19,6 +22,8 @@
 #include <utility>
 #include <vector>
 
+#include "absl/functional/any_invocable.h"
+#include "absl/strings/string_view.h"
 #include "api/audio/audio_processing_statistics.h"
 #include "api/audio_codecs/audio_encoder.h"
 #include "api/audio_options.h"
@@ -27,37 +32,34 @@
 #include "api/crypto/frame_encryptor_interface.h"
 #include "api/frame_transformer_interface.h"
 #include "api/media_stream_interface.h"
+#include "api/media_types.h"
 #include "api/rtc_error.h"
+#include "api/rtp_headers.h"
 #include "api/rtp_parameters.h"
 #include "api/rtp_sender_interface.h"
-#include "api/task_queue/pending_task_safety_flag.h"
-#include "api/transport/data_channel_transport_interface.h"
+#include "api/scoped_refptr.h"
 #include "api/transport/rtp/rtp_source.h"
 #include "api/units/time_delta.h"
 #include "api/units/timestamp.h"
+#include "api/video/recordable_encoded_frame.h"
 #include "api/video/video_content_type.h"
 #include "api/video/video_sink_interface.h"
 #include "api/video/video_source_interface.h"
 #include "api/video/video_timing.h"
 #include "api/video_codecs/scalability_mode.h"
 #include "api/video_codecs/video_encoder_factory.h"
-#include "call/video_receive_stream.h"
 #include "common_video/include/quality_limitation_reason.h"
 #include "media/base/codec.h"
-#include "media/base/media_constants.h"
 #include "media/base/stream_params.h"
 #include "modules/rtp_rtcp/include/report_block_data.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "rtc_base/async_packet_socket.h"
-#include "rtc_base/buffer.h"
 #include "rtc_base/copy_on_write_buffer.h"
-#include "rtc_base/dscp.h"
-#include "rtc_base/logging.h"
+#include "rtc_base/network/sent_packet.h"
 #include "rtc_base/network_route.h"
 #include "rtc_base/socket.h"
 #include "rtc_base/string_encode.h"
 #include "rtc_base/strings/string_builder.h"
-#include "video/config/video_encoder_config.h"
 
 namespace rtc {
 class Timing;
diff --git a/media/engine/fake_webrtc_call.h b/media/engine/fake_webrtc_call.h
index 64baab7..c4e5f61 100644
--- a/media/engine/fake_webrtc_call.h
+++ b/media/engine/fake_webrtc_call.h
@@ -20,24 +20,56 @@
 #ifndef MEDIA_ENGINE_FAKE_WEBRTC_CALL_H_
 #define MEDIA_ENGINE_FAKE_WEBRTC_CALL_H_
 
+#include <cstddef>
+#include <cstdint>
 #include <map>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
 
 #include "absl/strings/string_view.h"
+#include "api/adaptation/resource.h"
+#include "api/audio/audio_frame.h"
+#include "api/audio_codecs/audio_format.h"
+#include "api/crypto/frame_decryptor_interface.h"
 #include "api/environment/environment.h"
+#include "api/frame_transformer_interface.h"
+#include "api/media_types.h"
+#include "api/rtc_error.h"
+#include "api/rtp_headers.h"
+#include "api/rtp_parameters.h"
+#include "api/rtp_sender_interface.h"
+#include "api/scoped_refptr.h"
+#include "api/task_queue/task_queue_base.h"
+#include "api/transport/bitrate_settings.h"
+#include "api/transport/rtp/rtp_source.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
 #include "api/video/video_frame.h"
+#include "api/video/video_sink_interface.h"
+#include "api/video/video_source_interface.h"
+#include "api/video_codecs/video_codec.h"
 #include "call/audio_receive_stream.h"
 #include "call/audio_send_stream.h"
 #include "call/call.h"
 #include "call/flexfec_receive_stream.h"
+#include "call/packet_receiver.h"
+#include "call/payload_type.h"
+#include "call/payload_type_picker.h"
+#include "call/rtp_transport_controller_send_interface.h"
 #include "call/test/mock_rtp_transport_controller_send.h"
 #include "call/video_receive_stream.h"
 #include "call/video_send_stream.h"
+#include "media/base/codec.h"
+#include "modules/rtp_rtcp/include/receive_statistics.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "rtc_base/buffer.h"
+#include "rtc_base/copy_on_write_buffer.h"
+#include "rtc_base/network/sent_packet.h"
+#include "test/gmock.h"
+#include "video/config/video_encoder_config.h"
 
 namespace cricket {
 class FakeAudioSendStream final : public webrtc::AudioSendStream {
@@ -363,6 +395,26 @@
   webrtc::FlexfecReceiveStream::Config config_;
 };
 
+// Fake payload type suggester.
+// This is injected into FakeCall at initialization.
+class FakePayloadTypeSuggester : public webrtc::PayloadTypeSuggester {
+ public:
+  webrtc::RTCErrorOr<webrtc::PayloadType> SuggestPayloadType(
+      const std::string& mid,
+      cricket::Codec codec) override {
+    // Ignores mid argument.
+    return pt_picker_.SuggestMapping(codec, nullptr);
+  }
+  webrtc::RTCError AddLocalMapping(const std::string& mid,
+                                   webrtc::PayloadType payload_type,
+                                   const cricket::Codec& codec) override {
+    return webrtc::RTCError::OK();
+  }
+
+ private:
+  webrtc::PayloadTypePicker pt_picker_;
+};
+
 class FakeCall final : public webrtc::Call, public webrtc::PacketReceiver {
  public:
   explicit FakeCall(const webrtc::Environment& env);
@@ -371,6 +423,10 @@
            webrtc::TaskQueueBase* network_thread);
   ~FakeCall() override;
 
+  webrtc::PayloadTypeSuggester* GetPayloadTypeSuggester() {
+    return &pt_suggester_;
+  }
+
   webrtc::MockRtpTransportControllerSend* GetMockTransportControllerSend() {
     return &transport_controller_send_;
   }
@@ -501,6 +557,8 @@
 
   int num_created_send_streams_;
   int num_created_receive_streams_;
+
+  FakePayloadTypeSuggester pt_suggester_;
 };
 
 }  // namespace cricket
diff --git a/media/engine/payload_type_mapper.cc b/media/engine/payload_type_mapper.cc
deleted file mode 100644
index 9db2281..0000000
--- a/media/engine/payload_type_mapper.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- *  Copyright (c) 2016 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 "media/engine/payload_type_mapper.h"
-
-#include <utility>
-
-#include "absl/strings/ascii.h"
-#include "api/audio_codecs/audio_format.h"
-#include "media/base/codec.h"
-#include "media/base/media_constants.h"
-
-namespace cricket {
-
-webrtc::SdpAudioFormat AudioCodecToSdpAudioFormat(const Codec& ac) {
-  return webrtc::SdpAudioFormat(ac.name, ac.clockrate, ac.channels, ac.params);
-}
-
-PayloadTypeMapper::PayloadTypeMapper()
-    // RFC 3551 reserves payload type numbers in the range 96-127 exclusively
-    // for dynamic assignment. Once those are used up, it is recommended that
-    // payload types unassigned by the RFC are used for dynamic payload type
-    // mapping, before any static payload ids. At this point, we only support
-    // mapping within the exclusive range.
-    : next_unused_payload_type_(96),
-      max_payload_type_(127),
-      mappings_(
-          {// Static payload type assignments according to RFC 3551.
-           {{kPcmuCodecName, 8000, 1}, 0},
-           {{"GSM", 8000, 1}, 3},
-           {{"G723", 8000, 1}, 4},
-           {{"DVI4", 8000, 1}, 5},
-           {{"DVI4", 16000, 1}, 6},
-           {{"LPC", 8000, 1}, 7},
-           {{kPcmaCodecName, 8000, 1}, 8},
-           {{kG722CodecName, 8000, 1}, 9},
-           {{kL16CodecName, 44100, 2}, 10},
-           {{kL16CodecName, 44100, 1}, 11},
-           {{"QCELP", 8000, 1}, 12},
-           {{kCnCodecName, 8000, 1}, 13},
-           // RFC 4566 is a bit ambiguous on the contents of the "encoding
-           // parameters" field, which, for audio, encodes the number of
-           // channels. It is "optional and may be omitted if the number of
-           // channels is one". Does that necessarily imply that an omitted
-           // encoding parameter means one channel?  Since RFC 3551 doesn't
-           // specify a value for this parameter for MPA, I've included both 0
-           // and 1 here, to increase the chances it will be correctly used if
-           // someone implements an MPEG audio encoder/decoder.
-           {{"MPA", 90000, 0}, 14},
-           {{"MPA", 90000, 1}, 14},
-           {{"G728", 8000, 1}, 15},
-           {{"DVI4", 11025, 1}, 16},
-           {{"DVI4", 22050, 1}, 17},
-           {{"G729", 8000, 1}, 18},
-
-           // Payload type assignments currently used by WebRTC.
-           // Includes data to reduce collisions (and thus reassignments)
-           {{kIlbcCodecName, 8000, 1}, 102},
-           {{kCnCodecName, 16000, 1}, 105},
-           {{kCnCodecName, 32000, 1}, 106},
-           {{kOpusCodecName,
-             48000,
-             2,
-             {{kCodecParamMinPTime, "10"},
-              {kCodecParamUseInbandFec, kParamValueTrue}}},
-            111},
-           // RED for opus is assigned in the lower range, starting at the top.
-           // Note that the FMTP refers to the opus payload type.
-           {{kRedCodecName,
-             48000,
-             2,
-             {{kCodecParamNotInNameValueFormat, "111/111"}}},
-            63},
-           // TODO(solenberg): Remove the hard coded 16k,32k,48k DTMF once we
-           // assign payload types dynamically for send side as well.
-           {{kDtmfCodecName, 48000, 1}, 110},
-           {{kDtmfCodecName, 32000, 1}, 112},
-           {{kDtmfCodecName, 16000, 1}, 113},
-           {{kDtmfCodecName, 8000, 1}, 126}}) {
-  // TODO(ossu): Try to keep this as change-proof as possible until we're able
-  // to remove the payload type constants from everywhere in the code.
-  for (const auto& mapping : mappings_) {
-    used_payload_types_.insert(mapping.second);
-  }
-}
-
-PayloadTypeMapper::~PayloadTypeMapper() = default;
-
-std::optional<int> PayloadTypeMapper::GetMappingFor(
-    const webrtc::SdpAudioFormat& format) {
-  auto iter = mappings_.find(format);
-  if (iter != mappings_.end())
-    return iter->second;
-
-  for (; next_unused_payload_type_ <= max_payload_type_;
-       ++next_unused_payload_type_) {
-    int payload_type = next_unused_payload_type_;
-    if (used_payload_types_.find(payload_type) == used_payload_types_.end()) {
-      used_payload_types_.insert(payload_type);
-      mappings_[format] = payload_type;
-      ++next_unused_payload_type_;
-      return payload_type;
-    }
-  }
-
-  return std::nullopt;
-}
-
-std::optional<int> PayloadTypeMapper::FindMappingFor(
-    const webrtc::SdpAudioFormat& format) const {
-  auto iter = mappings_.find(format);
-  if (iter != mappings_.end())
-    return iter->second;
-
-  return std::nullopt;
-}
-
-std::optional<Codec> PayloadTypeMapper::ToAudioCodec(
-    const webrtc::SdpAudioFormat& format) {
-  // TODO(ossu): We can safely set bitrate to zero here, since that field is
-  // not presented in the SDP. It is used to ferry around some target bitrate
-  // values for certain codecs (ISAC and Opus) and in ways it really
-  // shouldn't. It should be removed once we no longer use CodecInsts in the
-  // ACM or NetEq.
-  auto opt_payload_type = GetMappingFor(format);
-  if (opt_payload_type) {
-    Codec codec =
-        cricket::CreateAudioCodec(*opt_payload_type, format.name,
-                                  format.clockrate_hz, format.num_channels);
-    codec.params = format.parameters;
-    return std::move(codec);
-  }
-
-  return std::nullopt;
-}
-
-bool PayloadTypeMapper::SdpAudioFormatOrdering::operator()(
-    const webrtc::SdpAudioFormat& a,
-    const webrtc::SdpAudioFormat& b) const {
-  if (a.clockrate_hz == b.clockrate_hz) {
-    if (a.num_channels == b.num_channels) {
-      int name_cmp =
-          absl::AsciiStrToLower(a.name).compare(absl::AsciiStrToLower(b.name));
-      if (name_cmp == 0)
-        return a.parameters < b.parameters;
-      return name_cmp < 0;
-    }
-    return a.num_channels < b.num_channels;
-  }
-  return a.clockrate_hz < b.clockrate_hz;
-}
-
-}  // namespace cricket
diff --git a/media/engine/payload_type_mapper.h b/media/engine/payload_type_mapper.h
deleted file mode 100644
index 246b04e..0000000
--- a/media/engine/payload_type_mapper.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  Copyright (c) 2016 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 MEDIA_ENGINE_PAYLOAD_TYPE_MAPPER_H_
-#define MEDIA_ENGINE_PAYLOAD_TYPE_MAPPER_H_
-
-#include <map>
-#include <optional>
-#include <set>
-
-#include "api/audio_codecs/audio_format.h"
-#include "media/base/codec.h"
-
-namespace cricket {
-
-webrtc::SdpAudioFormat AudioCodecToSdpAudioFormat(const Codec& ac);
-
-class PayloadTypeMapper {
- public:
-  PayloadTypeMapper();
-  ~PayloadTypeMapper();
-
-  // Finds the current payload type for `format` or assigns a new one, if no
-  // current mapping exists. Will return an empty value if it was unable to
-  // create a mapping, i.e. if all dynamic payload type ids have been used up.
-  std::optional<int> GetMappingFor(const webrtc::SdpAudioFormat& format);
-
-  // Finds the current payload type for `format`, if any. Returns an empty value
-  // if no payload type mapping exists for the format.
-  std::optional<int> FindMappingFor(const webrtc::SdpAudioFormat& format) const;
-
-  // Like GetMappingFor, but fills in an AudioCodec structure with the necessary
-  // information instead.
-  std::optional<Codec> ToAudioCodec(const webrtc::SdpAudioFormat& format);
-
- private:
-  struct SdpAudioFormatOrdering {
-    bool operator()(const webrtc::SdpAudioFormat& a,
-                    const webrtc::SdpAudioFormat& b) const;
-  };
-
-  int next_unused_payload_type_;
-  int max_payload_type_;
-  std::map<webrtc::SdpAudioFormat, int, SdpAudioFormatOrdering> mappings_;
-  std::set<int> used_payload_types_;
-};
-
-}  // namespace cricket
-#endif  // MEDIA_ENGINE_PAYLOAD_TYPE_MAPPER_H_
diff --git a/media/engine/payload_type_mapper_unittest.cc b/media/engine/payload_type_mapper_unittest.cc
deleted file mode 100644
index 62cca1e..0000000
--- a/media/engine/payload_type_mapper_unittest.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- *  Copyright (c) 2016 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 "media/engine/payload_type_mapper.h"
-
-#include <set>
-#include <string>
-
-#include "absl/strings/string_view.h"
-#include "media/base/media_constants.h"
-#include "test/gmock.h"
-#include "test/gtest.h"
-
-namespace cricket {
-
-class PayloadTypeMapperTest : public ::testing::Test {
- protected:
-  PayloadTypeMapper mapper_;
-};
-
-TEST_F(PayloadTypeMapperTest, StaticPayloadTypes) {
-  EXPECT_EQ(0, mapper_.FindMappingFor({"pcmu", 8000, 1}));
-  EXPECT_EQ(3, mapper_.FindMappingFor({"gsm", 8000, 1}));
-  EXPECT_EQ(4, mapper_.FindMappingFor({"g723", 8000, 1}));
-  EXPECT_EQ(5, mapper_.FindMappingFor({"dvi4", 8000, 1}));
-  EXPECT_EQ(6, mapper_.FindMappingFor({"dvi4", 16000, 1}));
-  EXPECT_EQ(7, mapper_.FindMappingFor({"lpc", 8000, 1}));
-  EXPECT_EQ(8, mapper_.FindMappingFor({"pcma", 8000, 1}));
-  EXPECT_EQ(9, mapper_.FindMappingFor({"g722", 8000, 1}));
-  EXPECT_EQ(10, mapper_.FindMappingFor({"l16", 44100, 2}));
-  EXPECT_EQ(11, mapper_.FindMappingFor({"l16", 44100, 1}));
-  EXPECT_EQ(12, mapper_.FindMappingFor({"qcelp", 8000, 1}));
-  EXPECT_EQ(13, mapper_.FindMappingFor({"cn", 8000, 1}));
-  EXPECT_EQ(14, mapper_.FindMappingFor({"mpa", 90000, 0}));
-  EXPECT_EQ(14, mapper_.FindMappingFor({"mpa", 90000, 1}));
-  EXPECT_EQ(15, mapper_.FindMappingFor({"g728", 8000, 1}));
-  EXPECT_EQ(16, mapper_.FindMappingFor({"dvi4", 11025, 1}));
-  EXPECT_EQ(17, mapper_.FindMappingFor({"dvi4", 22050, 1}));
-  EXPECT_EQ(18, mapper_.FindMappingFor({"g729", 8000, 1}));
-}
-
-TEST_F(PayloadTypeMapperTest, WebRTCPayloadTypes) {
-  // Tests that the payload mapper knows about the audio formats we've
-  // been using in WebRTC, with their hard coded values.
-  EXPECT_EQ(102, mapper_.FindMappingFor({kIlbcCodecName, 8000, 1}));
-  EXPECT_EQ(105, mapper_.FindMappingFor({kCnCodecName, 16000, 1}));
-  EXPECT_EQ(106, mapper_.FindMappingFor({kCnCodecName, 32000, 1}));
-  EXPECT_EQ(111, mapper_.FindMappingFor(
-                     {kOpusCodecName,
-                      48000,
-                      2,
-                      {{"minptime", "10"}, {"useinbandfec", "1"}}}));
-  EXPECT_EQ(
-      63, mapper_.FindMappingFor({kRedCodecName, 48000, 2, {{"", "111/111"}}}));
-  // TODO(solenberg): Remove 16k, 32k, 48k DTMF checks once these payload types
-  // are dynamically assigned.
-  EXPECT_EQ(110, mapper_.FindMappingFor({kDtmfCodecName, 48000, 1}));
-  EXPECT_EQ(112, mapper_.FindMappingFor({kDtmfCodecName, 32000, 1}));
-  EXPECT_EQ(113, mapper_.FindMappingFor({kDtmfCodecName, 16000, 1}));
-  EXPECT_EQ(126, mapper_.FindMappingFor({kDtmfCodecName, 8000, 1}));
-}
-
-TEST_F(PayloadTypeMapperTest, ValidDynamicPayloadTypes) {
-  // RFC 3551 says:
-  // "This profile reserves payload type numbers in the range 96-127
-  // exclusively for dynamic assignment.  Applications SHOULD first use
-  // values in this range for dynamic payload types.  Those applications
-  // which need to define more than 32 dynamic payload types MAY bind
-  // codes below 96, in which case it is RECOMMENDED that unassigned
-  // payload type numbers be used first.  However, the statically assigned
-  // payload types are default bindings and MAY be dynamically bound to
-  // new encodings if needed."
-
-  // Tests that the payload mapper uses values in the dynamic payload type range
-  // (96 - 127) before any others and that the values returned are all valid.
-  bool has_been_below_96 = false;
-  std::set<int> used_payload_types;
-  for (int i = 0; i != 256; ++i) {
-    std::string format_name = "unknown_format_" + std::to_string(i);
-    webrtc::SdpAudioFormat format(format_name.c_str(), i * 100, (i % 2) + 1);
-    auto opt_payload_type = mapper_.GetMappingFor(format);
-    bool mapper_is_full = false;
-
-    // There's a limited number of slots for payload types. We're fine with not
-    // being able to map them all.
-    if (opt_payload_type) {
-      int payload_type = *opt_payload_type;
-      EXPECT_FALSE(mapper_is_full) << "Mapping should not fail sporadically";
-      EXPECT_EQ(used_payload_types.find(payload_type), used_payload_types.end())
-          << "Payload types must not be reused";
-      used_payload_types.insert(payload_type);
-      EXPECT_GE(payload_type, 0) << "Negative payload types are invalid";
-      EXPECT_LE(payload_type, 127) << "Payload types above 127 are invalid";
-      EXPECT_FALSE(payload_type >= 96 && has_been_below_96);
-      if (payload_type < 96)
-        has_been_below_96 = true;
-
-      EXPECT_EQ(payload_type, mapper_.FindMappingFor(format))
-          << "Mapping must be permanent after successful call to "
-             "GetMappingFor";
-      EXPECT_EQ(payload_type, mapper_.GetMappingFor(format))
-          << "Subsequent calls to GetMappingFor must return the same value";
-    } else {
-      mapper_is_full = true;
-    }
-  }
-
-  // Also, we must've been able to map at least one dynamic payload type.
-  EXPECT_FALSE(used_payload_types.empty())
-      << "Mapper must support at least one user-defined payload type";
-}
-
-TEST_F(PayloadTypeMapperTest, ToAudioCodec) {
-  webrtc::SdpAudioFormat format("unknown_format", 4711, 17);
-  auto opt_payload_type = mapper_.GetMappingFor(format);
-  EXPECT_TRUE(opt_payload_type);
-  auto opt_audio_codec = mapper_.ToAudioCodec(format);
-  EXPECT_TRUE(opt_audio_codec);
-
-  if (opt_payload_type && opt_audio_codec) {
-    int payload_type = *opt_payload_type;
-    const Codec& codec = *opt_audio_codec;
-
-    EXPECT_EQ(codec.id, payload_type);
-    EXPECT_EQ(codec.name, format.name);
-    EXPECT_EQ(codec.clockrate, format.clockrate_hz);
-    EXPECT_EQ(codec.channels, format.num_channels);
-    EXPECT_THAT(codec.params, ::testing::ContainerEq(format.parameters));
-  }
-}
-
-}  // namespace cricket
diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc
index e65d0eb..93533da 100644
--- a/media/engine/webrtc_voice_engine.cc
+++ b/media/engine/webrtc_voice_engine.cc
@@ -12,54 +12,77 @@
 
 #include <algorithm>
 #include <atomic>
+#include <cstddef>
 #include <cstdint>
 #include <functional>
 #include <initializer_list>
 #include <iterator>
+#include <map>
 #include <memory>
 #include <optional>
+#include <set>
 #include <string>
-#include <type_traits>
 #include <utility>
 #include <vector>
 
 #include "absl/algorithm/algorithm.h"
 #include "absl/algorithm/container.h"
+#include "absl/functional/any_invocable.h"
 #include "absl/functional/bind_front.h"
 #include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
 #include "api/audio/audio_frame.h"
 #include "api/audio/audio_frame_processor.h"
+#include "api/audio/audio_mixer.h"
 #include "api/audio/audio_processing.h"
 #include "api/audio/audio_processing_statistics.h"
 #include "api/audio_codecs/audio_codec_pair_id.h"
+#include "api/audio_codecs/audio_decoder_factory.h"
 #include "api/audio_codecs/audio_encoder.h"
+#include "api/audio_codecs/audio_encoder_factory.h"
+#include "api/audio_codecs/audio_format.h"
+#include "api/audio_options.h"
 #include "api/call/audio_sink.h"
+#include "api/crypto/crypto_options.h"
+#include "api/crypto/frame_decryptor_interface.h"
 #include "api/field_trials_view.h"
+#include "api/frame_transformer_interface.h"
 #include "api/make_ref_counted.h"
 #include "api/media_types.h"
 #include "api/priority.h"
+#include "api/rtc_error.h"
 #include "api/rtp_headers.h"
 #include "api/rtp_parameters.h"
+#include "api/rtp_sender_interface.h"
 #include "api/rtp_transceiver_direction.h"
+#include "api/scoped_refptr.h"
+#include "api/sequence_checker.h"
 #include "api/task_queue/pending_task_safety_flag.h"
 #include "api/transport/bitrate_settings.h"
+#include "api/transport/rtp/rtp_source.h"
 #include "api/units/data_rate.h"
 #include "api/units/time_delta.h"
 #include "api/units/timestamp.h"
 #include "call/audio_receive_stream.h"
+#include "call/audio_send_stream.h"
+#include "call/audio_state.h"
+#include "call/call.h"
 #include "call/packet_receiver.h"
+#include "call/payload_type_picker.h"
 #include "call/rtp_config.h"
 #include "call/rtp_transport_controller_send_interface.h"
 #include "media/base/audio_source.h"
 #include "media/base/codec.h"
+#include "media/base/media_channel.h"
+#include "media/base/media_channel_impl.h"
+#include "media/base/media_config.h"
 #include "media/base/media_constants.h"
+#include "media/base/media_engine.h"
 #include "media/base/stream_params.h"
 #include "media/engine/adm_helpers.h"
-#include "media/engine/payload_type_mapper.h"
 #include "media/engine/webrtc_media_engine.h"
 #include "modules/async_audio_processing/async_audio_processing.h"
 #include "modules/audio_mixer/audio_mixer_impl.h"
-#include "modules/rtp_rtcp/include/report_block_data.h"
 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "modules/rtp_rtcp/source/rtp_util.h"
@@ -72,6 +95,7 @@
 #include "rtc_base/strings/audio_format_to_string.h"
 #include "rtc_base/strings/string_builder.h"
 #include "rtc_base/strings/string_format.h"
+#include "rtc_base/system/file_wrapper.h"
 #include "rtc_base/thread_annotations.h"
 #include "rtc_base/time_utils.h"
 #include "rtc_base/trace_event.h"
@@ -332,6 +356,91 @@
   return true;
 }
 
+webrtc::SdpAudioFormat AudioCodecToSdpAudioFormat(const Codec& ac) {
+  return webrtc::SdpAudioFormat(ac.name, ac.clockrate, ac.channels, ac.params);
+}
+
+// Assign the payload types for the codecs of this voice engine.
+// This is a "preliminary" pass, done to prime the
+// payload type picker with a normal set of PTs.
+// TODO: https://issues.webrtc.org/360058654 - remove.
+std::vector<Codec> LegacyCollectCodecs(
+    const std::vector<webrtc::AudioCodecSpec>& specs) {
+  // Once payload assignment is done in the channel not in the factory,
+  // this needs to be a variable. But then this function should go away.
+  webrtc::PayloadTypePicker pt_mapper;
+  std::vector<Codec> out;
+
+  // Only generate CN payload types for these clockrates:
+  std::map<int, bool, std::greater<int>> generate_cn = {
+      {8000, false}, {16000, false}, {32000, false}};
+  // Only generate telephone-event payload types for these clockrates:
+  std::map<int, bool, std::greater<int>> generate_dtmf = {
+      {8000, false}, {16000, false}, {32000, false}, {48000, false}};
+
+  for (const auto& spec : specs) {
+    cricket::Codec codec = CreateAudioCodec(spec.format);
+    auto pt_or_error = pt_mapper.SuggestMapping(codec, nullptr);
+    // We need to do some extra stuff before adding the main codecs to out.
+    if (pt_or_error.ok()) {
+      codec.id = pt_or_error.value();
+      if (spec.info.supports_network_adaption) {
+        codec.AddFeedbackParam(
+            FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
+      }
+
+      if (spec.info.allow_comfort_noise) {
+        // Generate a CN entry if the decoder allows it and we support the
+        // clockrate.
+        auto cn = generate_cn.find(spec.format.clockrate_hz);
+        if (cn != generate_cn.end()) {
+          cn->second = true;
+        }
+      }
+
+      // Generate a telephone-event entry if we support the clockrate.
+      auto dtmf = generate_dtmf.find(spec.format.clockrate_hz);
+      if (dtmf != generate_dtmf.end()) {
+        dtmf->second = true;
+      }
+
+      out.push_back(codec);
+
+      // TODO(hta):  Don't assign RED codecs until we know that the PT for Opus
+      // is final
+      if (codec.name == kOpusCodecName) {
+        std::string red_fmtp =
+            rtc::ToString(codec.id) + "/" + rtc::ToString(codec.id);
+        cricket::Codec red_codec =
+            CreateAudioCodec({kRedCodecName, 48000, 2, {{"", red_fmtp}}});
+        red_codec.id = pt_mapper.SuggestMapping(red_codec, nullptr).value();
+        out.push_back(red_codec);
+      }
+    }
+  }
+
+  // Add CN codecs after "proper" audio codecs.
+  for (const auto& cn : generate_cn) {
+    if (cn.second) {
+      cricket::Codec cn_codec = CreateAudioCodec({kCnCodecName, cn.first, 1});
+      cn_codec.id = pt_mapper.SuggestMapping(cn_codec, nullptr).value();
+      out.push_back(cn_codec);
+    }
+  }
+
+  // Add telephone-event codecs last.
+  for (const auto& dtmf : generate_dtmf) {
+    if (dtmf.second) {
+      cricket::Codec dtmf_codec =
+          CreateAudioCodec({kDtmfCodecName, dtmf.first, 1});
+      dtmf_codec.id = pt_mapper.SuggestMapping(dtmf_codec, nullptr).value();
+      out.push_back(dtmf_codec);
+    }
+  }
+
+  return out;
+}
+
 }  // namespace
 
 WebRtcVoiceEngine::WebRtcVoiceEngine(
@@ -383,13 +492,13 @@
 
   // Load our audio codec lists.
   RTC_LOG(LS_VERBOSE) << "Supported send codecs in order of preference:";
-  send_codecs_ = CollectCodecs(encoder_factory_->GetSupportedEncoders());
+  send_codecs_ = LegacyCollectCodecs(encoder_factory_->GetSupportedEncoders());
   for (const Codec& codec : send_codecs_) {
     RTC_LOG(LS_VERBOSE) << ToString(codec);
   }
 
   RTC_LOG(LS_VERBOSE) << "Supported recv codecs in order of preference:";
-  recv_codecs_ = CollectCodecs(decoder_factory_->GetSupportedDecoders());
+  recv_codecs_ = LegacyCollectCodecs(decoder_factory_->GetSupportedDecoders());
   for (const Codec& codec : recv_codecs_) {
     RTC_LOG(LS_VERBOSE) << ToString(codec);
   }
@@ -708,84 +817,6 @@
   return audio_state_.get();
 }
 
-std::vector<Codec> WebRtcVoiceEngine::CollectCodecs(
-    const std::vector<webrtc::AudioCodecSpec>& specs) const {
-  PayloadTypeMapper mapper;
-  std::vector<Codec> out;
-
-  // Only generate CN payload types for these clockrates:
-  std::map<int, bool, std::greater<int>> generate_cn = {
-      {8000, false}, {16000, false}, {32000, false}};
-  // Only generate telephone-event payload types for these clockrates:
-  std::map<int, bool, std::greater<int>> generate_dtmf = {
-      {8000, false}, {16000, false}, {32000, false}, {48000, false}};
-
-  auto map_format = [&mapper](const webrtc::SdpAudioFormat& format,
-                              std::vector<Codec>* out) {
-    std::optional<Codec> opt_codec = mapper.ToAudioCodec(format);
-    if (opt_codec) {
-      if (out) {
-        out->push_back(*opt_codec);
-      }
-    } else {
-      RTC_LOG(LS_ERROR) << "Unable to assign payload type to format: "
-                        << rtc::ToString(format);
-    }
-
-    return opt_codec;
-  };
-
-  for (const auto& spec : specs) {
-    // We need to do some extra stuff before adding the main codecs to out.
-    std::optional<Codec> opt_codec = map_format(spec.format, nullptr);
-    if (opt_codec) {
-      Codec& codec = *opt_codec;
-      if (spec.info.supports_network_adaption) {
-        codec.AddFeedbackParam(
-            FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
-      }
-
-      if (spec.info.allow_comfort_noise) {
-        // Generate a CN entry if the decoder allows it and we support the
-        // clockrate.
-        auto cn = generate_cn.find(spec.format.clockrate_hz);
-        if (cn != generate_cn.end()) {
-          cn->second = true;
-        }
-      }
-
-      // Generate a telephone-event entry if we support the clockrate.
-      auto dtmf = generate_dtmf.find(spec.format.clockrate_hz);
-      if (dtmf != generate_dtmf.end()) {
-        dtmf->second = true;
-      }
-
-      out.push_back(codec);
-
-      if (codec.name == kOpusCodecName) {
-        std::string red_fmtp =
-            rtc::ToString(codec.id) + "/" + rtc::ToString(codec.id);
-        map_format({kRedCodecName, 48000, 2, {{"", red_fmtp}}}, &out);
-      }
-    }
-  }
-
-  // Add CN codecs after "proper" audio codecs.
-  for (const auto& cn : generate_cn) {
-    if (cn.second) {
-      map_format({kCnCodecName, cn.first, 1}, &out);
-    }
-  }
-
-  // Add telephone-event codecs last.
-  for (const auto& dtmf : generate_dtmf) {
-    if (dtmf.second) {
-      map_format({kDtmfCodecName, dtmf.first, 1}, &out);
-    }
-  }
-
-  return out;
-}
 
 // --------------------------------- WebRtcVoiceSendChannel ------------------
 
@@ -2151,11 +2182,20 @@
 }
 
 bool WebRtcVoiceReceiveChannel::SetRecvCodecs(
-    const std::vector<Codec>& codecs) {
+    const std::vector<Codec>& codecs_in) {
   RTC_DCHECK_RUN_ON(worker_thread_);
 
-  // Set the payload types to be used for incoming media.
-  RTC_LOG(LS_INFO) << "Setting receive voice codecs.";
+  auto codecs = codecs_in;
+  // Record the payload types used in the payload type suggester.
+  RTC_LOG(LS_INFO) << "Setting receive voice codecs. Mid is " << mid_;
+  for (auto& codec : codecs) {
+    auto error = call_->GetPayloadTypeSuggester()->AddLocalMapping(
+        mid_, codec.id, codec);
+    if (!error.ok()) {
+      RTC_LOG(LS_ERROR) << "Failed to register PT for " << codec.ToString();
+      return false;
+    }
+  }
 
   if (!VerifyUniquePayloadTypes(codecs)) {
     RTC_LOG(LS_ERROR) << "Codec payload types overlap.";
diff --git a/media/engine/webrtc_voice_engine.h b/media/engine/webrtc_voice_engine.h
index 942c569..dd5b84b 100644
--- a/media/engine/webrtc_voice_engine.h
+++ b/media/engine/webrtc_voice_engine.h
@@ -34,13 +34,14 @@
 #include "api/audio_codecs/audio_format.h"
 #include "api/audio_options.h"
 #include "api/call/audio_sink.h"
-#include "api/call/transport.h"
 #include "api/crypto/crypto_options.h"
 #include "api/crypto/frame_decryptor_interface.h"
 #include "api/crypto/frame_encryptor_interface.h"
 #include "api/field_trials_view.h"
 #include "api/frame_transformer_interface.h"
+#include "api/media_types.h"
 #include "api/rtc_error.h"
+#include "api/rtp_headers.h"
 #include "api/rtp_parameters.h"
 #include "api/rtp_sender_interface.h"
 #include "api/scoped_refptr.h"
@@ -57,12 +58,11 @@
 #include "media/base/media_channel_impl.h"
 #include "media/base/media_config.h"
 #include "media/base/media_engine.h"
-#include "media/base/rtp_utils.h"
 #include "media/base/stream_params.h"
 #include "modules/async_audio_processing/async_audio_processing.h"
 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
-#include "rtc_base/buffer.h"
+#include "rtc_base/checks.h"
 #include "rtc_base/network/sent_packet.h"
 #include "rtc_base/network_route.h"
 #include "rtc_base/system/file_wrapper.h"
@@ -147,9 +147,6 @@
   webrtc::AudioProcessing* apm() const;
   webrtc::AudioState* audio_state();
 
-  std::vector<Codec> CollectCodecs(
-      const std::vector<webrtc::AudioCodecSpec>& specs) const;
-
   webrtc::SequenceChecker signal_thread_checker_{
       webrtc::SequenceChecker::kDetached};
   webrtc::SequenceChecker worker_thread_checker_{
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 5e11f04..f21f407 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -79,6 +79,7 @@
     "../api:scoped_refptr",
     "../api:sequence_checker",
     "../api/crypto:options",
+    "../api/task_queue",
     "../api/task_queue:pending_task_safety_flag",
     "../api/units:timestamp",
     "../call:rtp_interfaces",
@@ -1105,6 +1106,7 @@
     "../api:ice_transport_interface",
     "../api:libjingle_logging_api",
     "../api:libjingle_peerconnection_api",
+    "../api:make_ref_counted",
     "../api:media_stream_interface",
     "../api:rtc_error",
     "../api:rtc_stats_api",
@@ -1115,16 +1117,20 @@
     "../api:sequence_checker",
     "../api:turn_customizer",
     "../api/adaptation:resource_adaptation_api",
+    "../api/audio:audio_device",
     "../api/crypto:options",
     "../api/environment",
     "../api/rtc_event_log",
     "../api/task_queue:pending_task_safety_flag",
+    "../api/transport:bandwidth_estimation_settings",
     "../api/transport:bitrate_settings",
     "../api/transport:datagram_transport_interface",
     "../api/transport:enums",
+    "../api/units:time_delta",
     "../api/video:video_codec_constants",
     "../call:call_interfaces",
     "../call:payload_type_picker",
+    "../media:codec",
     "../media:media_channel",
     "../media:media_engine",
     "../media:rid_description",
diff --git a/pc/channel.cc b/pc/channel.cc
index 45c6e74..6e4a80b 100644
--- a/pc/channel.cc
+++ b/pc/channel.cc
@@ -12,28 +12,44 @@
 
 #include <algorithm>
 #include <cstdint>
+#include <functional>
+#include <memory>
+#include <optional>
 #include <string>
-#include <type_traits>
 #include <utility>
+#include <vector>
 
 #include "absl/algorithm/container.h"
 #include "absl/strings/string_view.h"
+#include "api/crypto/crypto_options.h"
+#include "api/jsep.h"
+#include "api/media_types.h"
 #include "api/rtp_parameters.h"
 #include "api/sequence_checker.h"
 #include "api/task_queue/pending_task_safety_flag.h"
-#include "api/units/timestamp.h"
+#include "api/task_queue/task_queue_base.h"
 #include "media/base/codec.h"
+#include "media/base/media_channel.h"
 #include "media/base/rid_description.h"
 #include "media/base/rtp_utils.h"
+#include "media/base/stream_params.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "p2p/base/dtls_transport_internal.h"
 #include "pc/rtp_media_utils.h"
+#include "pc/rtp_transport_internal.h"
+#include "pc/session_description.h"
+#include "rtc_base/async_packet_socket.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/containers/flat_set.h"
 #include "rtc_base/copy_on_write_buffer.h"
 #include "rtc_base/logging.h"
+#include "rtc_base/network/sent_packet.h"
 #include "rtc_base/network_route.h"
+#include "rtc_base/socket.h"
 #include "rtc_base/strings/string_format.h"
+#include "rtc_base/thread.h"
 #include "rtc_base/trace_event.h"
+#include "rtc_base/unique_id_generator.h"
 
 namespace cricket {
 namespace {
@@ -907,7 +923,9 @@
   set_local_content_direction(content->direction());
   UpdateMediaSendRecvState_w();
 
-  RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(0);
+  // Disabled because suggeting PTs takes thread jumps.
+  // TODO: https://issues.webrtc.org/360058654 - reenable after cleanup
+  // RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(0);
 
   bool success = MaybeUpdateDemuxerAndRtpExtensions_w(
       criteria_modified,
@@ -916,7 +934,7 @@
           : std::nullopt,
       error_desc);
 
-  RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(1);
+  // RTC_DCHECK_BLOCK_COUNT_NO_MORE_THAN(1);
 
   return success;
 }
diff --git a/pc/jsep_transport.h b/pc/jsep_transport.h
index 56840a3..4839ea7 100644
--- a/pc/jsep_transport.h
+++ b/pc/jsep_transport.h
@@ -17,7 +17,6 @@
 #include <string>
 #include <vector>
 
-#include "api/candidate.h"
 #include "api/ice_transport_interface.h"
 #include "api/jsep.h"
 #include "api/rtc_error.h"
@@ -243,6 +242,9 @@
   const webrtc::PayloadTypeRecorder& local_payload_types() const {
     return local_payload_types_;
   }
+  webrtc::PayloadTypeRecorder& local_payload_types() {
+    return local_payload_types_;
+  }
   void CommitPayloadTypes() {
     RTC_DCHECK_RUN_ON(network_thread_);
     local_payload_types_.Commit();
diff --git a/pc/jsep_transport_controller.cc b/pc/jsep_transport_controller.cc
index 2780196..cb79860 100644
--- a/pc/jsep_transport_controller.cc
+++ b/pc/jsep_transport_controller.cc
@@ -12,25 +12,58 @@
 
 #include <stddef.h>
 
+#include <cstdint>
 #include <functional>
+#include <map>
 #include <memory>
+#include <optional>
 #include <string>
-#include <type_traits>
 #include <utility>
+#include <vector>
 
 #include "absl/algorithm/container.h"
+#include "absl/strings/string_view.h"
+#include "api/async_dns_resolver.h"
+#include "api/candidate.h"
 #include "api/dtls_transport_interface.h"
 #include "api/environment/environment.h"
+#include "api/ice_transport_interface.h"
+#include "api/jsep.h"
+#include "api/peer_connection_interface.h"
+#include "api/rtc_error.h"
 #include "api/rtp_parameters.h"
+#include "api/scoped_refptr.h"
 #include "api/sequence_checker.h"
+#include "api/transport/data_channel_transport_interface.h"
 #include "api/transport/enums.h"
+#include "call/payload_type.h"
+#include "call/payload_type_picker.h"
+#include "media/base/codec.h"
 #include "media/sctp/sctp_transport_internal.h"
+#include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "p2p/base/dtls_transport.h"
+#include "p2p/base/dtls_transport_internal.h"
 #include "p2p/base/ice_transport_internal.h"
 #include "p2p/base/p2p_constants.h"
 #include "p2p/base/port.h"
+#include "p2p/base/port_allocator.h"
+#include "p2p/base/transport_description.h"
+#include "p2p/base/transport_info.h"
+#include "pc/dtls_srtp_transport.h"
+#include "pc/dtls_transport.h"
+#include "pc/jsep_transport.h"
+#include "pc/rtp_transport.h"
+#include "pc/rtp_transport_internal.h"
+#include "pc/sctp_transport.h"
+#include "pc/session_description.h"
+#include "pc/srtp_transport.h"
+#include "pc/transport_stats.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/copy_on_write_buffer.h"
 #include "rtc_base/logging.h"
+#include "rtc_base/rtc_certificate.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_stream_adapter.h"
 #include "rtc_base/thread.h"
 #include "rtc_base/trace_event.h"
 
@@ -225,6 +258,15 @@
 RTCErrorOr<webrtc::PayloadType> JsepTransportController::SuggestPayloadType(
     const std::string& mid,
     cricket::Codec codec) {
+  // Because SDP processing runs on the signal thread and Call processing
+  // runs on the worker thread, we allow cross thread invocation until we
+  // can clean up the thread work.
+  if (!network_thread_->IsCurrent()) {
+    return network_thread_->BlockingCall([&] {
+      RTC_DCHECK_RUN_ON(network_thread_);
+      return SuggestPayloadType(mid, codec);
+    });
+  }
   RTC_DCHECK_RUN_ON(network_thread_);
   const cricket::JsepTransport* transport = GetJsepTransportForMid(mid);
   if (transport) {
@@ -245,6 +287,27 @@
   return payload_type_picker_.SuggestMapping(codec, nullptr);
 }
 
+RTCError JsepTransportController::AddLocalMapping(const std::string& mid,
+                                                  PayloadType payload_type,
+                                                  const cricket::Codec& codec) {
+  // Because SDP processing runs on the signal thread and Call processing
+  // runs on the worker thread, we allow cross thread invocation until we
+  // can clean up the thread work.
+  if (!network_thread_->IsCurrent()) {
+    return network_thread_->BlockingCall([&] {
+      RTC_DCHECK_RUN_ON(network_thread_);
+      return AddLocalMapping(mid, payload_type, codec);
+    });
+  }
+  RTC_DCHECK_RUN_ON(network_thread_);
+  cricket::JsepTransport* transport = GetJsepTransportForMid(mid);
+  if (!transport) {
+    return RTCError(RTCErrorType::INVALID_PARAMETER,
+                    "AddLocalMapping: no transport for mid");
+  }
+  return transport->local_payload_types().AddMapping(payload_type, codec);
+}
+
 bool JsepTransportController::SetLocalCertificate(
     const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
   if (!network_thread_->IsCurrent()) {
diff --git a/pc/jsep_transport_controller.h b/pc/jsep_transport_controller.h
index 2846dab..b5e3ebf 100644
--- a/pc/jsep_transport_controller.h
+++ b/pc/jsep_transport_controller.h
@@ -243,6 +243,9 @@
   // or a newly suggested one.
   RTCErrorOr<PayloadType> SuggestPayloadType(const std::string& mid,
                                              cricket::Codec codec) override;
+  RTCError AddLocalMapping(const std::string& mid,
+                           PayloadType payload_type,
+                           const cricket::Codec& codec) override;
 
   // TODO(deadbeef): GetStats isn't const because all the way down to
   // OpenSSLStreamAdapter, GetSslCipherSuite and GetDtlsSrtpCryptoSuite are not
diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc
index 32f21cf..b125f9e 100644
--- a/pc/peer_connection.cc
+++ b/pc/peer_connection.cc
@@ -13,54 +13,110 @@
 #include <limits.h>
 #include <stddef.h>
 
-#include <algorithm>
+#include <cstdint>
+#include <functional>
+#include <map>
 #include <memory>
 #include <optional>
 #include <set>
 #include <string>
 #include <utility>
+#include <vector>
 
 #include "absl/algorithm/container.h"
 #include "absl/strings/match.h"
 #include "absl/strings/string_view.h"
+#include "api/adaptation/resource.h"
+#include "api/audio/audio_device.h"
+#include "api/candidate.h"
+#include "api/crypto/crypto_options.h"
+#include "api/data_channel_interface.h"
+#include "api/dtls_transport_interface.h"
 #include "api/environment/environment.h"
+#include "api/jsep.h"
 #include "api/jsep_ice_candidate.h"
+#include "api/make_ref_counted.h"
+#include "api/media_stream_interface.h"
 #include "api/media_types.h"
+#include "api/peer_connection_interface.h"
+#include "api/rtc_error.h"
+#include "api/rtc_event_log_output.h"
 #include "api/rtp_parameters.h"
+#include "api/rtp_receiver_interface.h"
+#include "api/rtp_sender_interface.h"
 #include "api/rtp_transceiver_direction.h"
+#include "api/rtp_transceiver_interface.h"
+#include "api/scoped_refptr.h"
+#include "api/sctp_transport_interface.h"
+#include "api/sequence_checker.h"
+#include "api/set_local_description_observer_interface.h"
+#include "api/set_remote_description_observer_interface.h"
+#include "api/stats/rtc_stats_collector_callback.h"
+#include "api/task_queue/pending_task_safety_flag.h"
+#include "api/transport/bandwidth_estimation_settings.h"
+#include "api/transport/bitrate_settings.h"
+#include "api/transport/data_channel_transport_interface.h"
+#include "api/transport/enums.h"
+#include "api/turn_customizer.h"
 #include "api/uma_metrics.h"
+#include "api/units/time_delta.h"
 #include "api/video/video_codec_constants.h"
 #include "call/audio_state.h"
 #include "call/packet_receiver.h"
-#include "media/base/media_channel.h"
+#include "media/base/codec.h"
 #include "media/base/media_config.h"
 #include "media/base/media_engine.h"
 #include "media/base/rid_description.h"
 #include "media/base/stream_params.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "p2p/base/basic_async_resolver_factory.h"
-#include "p2p/base/connection.h"
 #include "p2p/base/connection_info.h"
 #include "p2p/base/dtls_transport_internal.h"
+#include "p2p/base/ice_transport_internal.h"
 #include "p2p/base/p2p_constants.h"
 #include "p2p/base/p2p_transport_channel.h"
+#include "p2p/base/port.h"
+#include "p2p/base/port_allocator.h"
+#include "p2p/base/transport_description.h"
 #include "p2p/base/transport_info.h"
+#include "pc/channel_interface.h"
+#include "pc/connection_context.h"
+#include "pc/data_channel_utils.h"
+#include "pc/dtls_transport.h"
 #include "pc/ice_server_parsing.h"
+#include "pc/jsep_transport_controller.h"
+#include "pc/legacy_stats_collector.h"
+#include "pc/rtc_stats_collector.h"
 #include "pc/rtp_receiver.h"
 #include "pc/rtp_receiver_proxy.h"
 #include "pc/rtp_sender.h"
 #include "pc/rtp_sender_proxy.h"
+#include "pc/rtp_transceiver.h"
+#include "pc/rtp_transmission_manager.h"
+#include "pc/rtp_transport_internal.h"
+#include "pc/sctp_data_channel.h"
 #include "pc/sctp_transport.h"
+#include "pc/sdp_offer_answer.h"
+#include "pc/session_description.h"
 #include "pc/simulcast_description.h"
-#include "pc/webrtc_session_description_factory.h"
+#include "pc/transceiver_list.h"
+#include "pc/transport_stats.h"
+#include "pc/usage_pattern.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/copy_on_write_buffer.h"
 #include "rtc_base/crypto_random.h"
 #include "rtc_base/ip_address.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/net_helper.h"
 #include "rtc_base/network.h"
 #include "rtc_base/network_constants.h"
+#include "rtc_base/rtc_certificate.h"
 #include "rtc_base/socket_address.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_stream_adapter.h"
 #include "rtc_base/string_encode.h"
+#include "rtc_base/thread.h"
 #include "rtc_base/trace_event.h"
 #include "rtc_base/unique_id_generator.h"
 #include "system_wrappers/include/metrics.h"
@@ -695,6 +751,12 @@
                               kPeerConnectionAddressFamilyCounter_Max);
     return InitializeTransportController_n(configuration, dependencies);
   });
+  if (call_ptr_) {
+    worker_thread()->BlockingCall([this, tc = transport_controller_copy_] {
+      RTC_DCHECK_RUN_ON(worker_thread());
+      call_->SetPayloadTypeSuggester(tc);
+    });
+  }
 
   configuration_ = configuration;