Sync to webrtc ToT

Update to commit "AEC3: Parametrize the shadow filter output usage".

https://webrtc.googlesource.com/src/+/240215431ee21e85e415484d1d80f437850f2f8e

This update includes all parameters and codes for tuning
APM performance with CRAS.

BUG=chromium:874787
TEST=Apply all config files and test on nocturne
CQ-DEPEND=CL:1196304

Change-Id: Idf6da0c70ac1569d2567c2ab15f436731edb3f35
Reviewed-on: https://chromium-review.googlesource.com/1194561
Commit-Ready: Hsinyu Chao <hychao@chromium.org>
Tested-by: Hsinyu Chao <hychao@chromium.org>
Reviewed-by: Hsinyu Chao <hychao@chromium.org>
diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel
index 439addb..edd0274 100644
--- a/absl/BUILD.bazel
+++ b/absl/BUILD.bazel
@@ -18,11 +18,10 @@
 
 licenses(["notice"])  # Apache 2.0
 
-config_setting(
+load(":compiler_config_setting.bzl", "create_llvm_config")
+
+create_llvm_config(
     name = "llvm_compiler",
-    values = {
-        "compiler": "llvm",
-    },
     visibility = [":__subpackages__"],
 )
 
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index acddec4..6af8c09 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -314,7 +314,7 @@
 
 // c_mismatch()
 //
-// Container-based version of the <algorithm> `std::mismatchf()` function to
+// Container-based version of the <algorithm> `std::mismatch()` function to
 // return the first element where two ordered containers differ.
 template <typename C1, typename C2>
 container_algorithm_internal::ContainerIterPairType<C1, C2>
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 35414a2..06d092e 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -362,6 +362,7 @@
     copts = ABSL_TEST_COPTS,
     deps = [
         ":base",
+        "//absl/strings",
         "@com_google_googletest//:gtest_main",
     ],
 )
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index 303533e..01d2af0 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -310,7 +310,7 @@
 
 # test raw_logging_test
 set(RAW_LOGGING_TEST_SRC "raw_logging_test.cc")
-set(RAW_LOGGING_TEST_PUBLIC_LIBRARIES absl::base)
+set(RAW_LOGGING_TEST_PUBLIC_LIBRARIES absl::base absl::strings)
 
 absl_test(
   TARGET
diff --git a/absl/base/config.h b/absl/base/config.h
index 2f5f159..6890e31 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -268,7 +268,7 @@
 #error ABSL_HAVE_MMAP cannot be directly set
 #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) ||   \
     defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \
-    defined(__wasm__) || defined(__Fuchsia__)
+    defined(__wasm__) || defined(__Fuchsia__) || defined(__sun)
 #define ABSL_HAVE_MMAP 1
 #endif
 
diff --git a/absl/base/internal/endian_test.cc b/absl/base/internal/endian_test.cc
index f3ff4b3..e276915 100644
--- a/absl/base/internal/endian_test.cc
+++ b/absl/base/internal/endian_test.cc
@@ -33,32 +33,16 @@
 const int kNumValuesToTest = 1000000;
 const int kRandomSeed = 12345;
 
-#ifdef ABSL_IS_BIG_ENDIAN
+#if defined(ABSL_IS_BIG_ENDIAN)
 const uint64_t kInitialInNetworkOrder{kInitialNumber};
 const uint64_t k64ValueLE{0xefcdab8967452301};
 const uint32_t k32ValueLE{0x67452301};
 const uint16_t k16ValueLE{0x2301};
-const uint8_t k8ValueLE{k8Value};
-const uint64_t k64IValueLE{0xefcdab89674523a1};
-const uint32_t k32IValueLE{0x67452391};
-const uint16_t k16IValueLE{0x85ff};
-const uint8_t k8IValueLE{0xff};
-const uint64_t kDoubleValueLE{0x6e861bf0f9210940};
-const uint32_t kFloatValueLE{0xd00f4940};
-const uint8_t kBoolValueLE{0x1};
 
 const uint64_t k64ValueBE{kInitialNumber};
 const uint32_t k32ValueBE{k32Value};
 const uint16_t k16ValueBE{k16Value};
-const uint8_t k8ValueBE{k8Value};
-const uint64_t k64IValueBE{0xa123456789abcdef};
-const uint32_t k32IValueBE{0x91234567};
-const uint16_t k16IValueBE{0xff85};
-const uint8_t k8IValueBE{0xff};
-const uint64_t kDoubleValueBE{0x400921f9f01b866e};
-const uint32_t kFloatValueBE{0x40490fd0};
-const uint8_t kBoolValueBE{0x1};
-#elif defined ABSL_IS_LITTLE_ENDIAN
+#elif defined(ABSL_IS_LITTLE_ENDIAN)
 const uint64_t kInitialInNetworkOrder{0xefcdab8967452301};
 const uint64_t k64ValueLE{kInitialNumber};
 const uint32_t k32ValueLE{k32Value};
diff --git a/absl/base/internal/exception_testing.h b/absl/base/internal/exception_testing.h
index fd89a3f..0cf7918 100644
--- a/absl/base/internal/exception_testing.h
+++ b/absl/base/internal/exception_testing.h
@@ -35,7 +35,7 @@
   EXPECT_DEATH(expr, ".*")
 #else
 #define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \
-  EXPECT_DEATH(expr, text)
+  EXPECT_DEATH_IF_SUPPORTED(expr, text)
 
 #endif
 
diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc
index 1ce1388..d9485a6 100644
--- a/absl/base/internal/raw_logging.cc
+++ b/absl/base/internal/raw_logging.cc
@@ -139,7 +139,7 @@
 #endif
 
 #ifdef ABSL_MIN_LOG_LEVEL
-  if (static_cast<int>(severity) < ABSL_MIN_LOG_LEVEL &&
+  if (severity < static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
       severity < absl::LogSeverity::kFatal) {
     enabled = false;
   }
@@ -206,6 +206,15 @@
   va_end(ap);
 }
 
+// Non-formatting version of RawLog().
+//
+// TODO(gfalcon): When string_view no longer depends on base, change this
+// interface to take its message as a string_view instead.
+static void DefaultInternalLog(absl::LogSeverity severity, const char* file,
+                               int line, const std::string& message) {
+  RawLog(severity, file, line, "%s", message.c_str());
+}
+
 bool RawLoggingFullySupported() {
 #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
   return true;
@@ -214,5 +223,12 @@
 #endif  // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
 }
 
+ABSL_CONST_INIT absl::base_internal::AtomicHook<InternalLogFunction>
+    internal_log_function(DefaultInternalLog);
+
+void RegisterInternalLogFunction(InternalLogFunction func) {
+  internal_log_function.Store(func);
+}
+
 }  // namespace raw_logging_internal
 }  // namespace absl
diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h
index a2b7207..67abfd3 100644
--- a/absl/base/internal/raw_logging.h
+++ b/absl/base/internal/raw_logging.h
@@ -19,7 +19,10 @@
 #ifndef ABSL_BASE_INTERNAL_RAW_LOGGING_H_
 #define ABSL_BASE_INTERNAL_RAW_LOGGING_H_
 
+#include <string>
+
 #include "absl/base/attributes.h"
+#include "absl/base/internal/atomic_hook.h"
 #include "absl/base/log_severity.h"
 #include "absl/base/macros.h"
 #include "absl/base/port.h"
@@ -57,6 +60,34 @@
     }                                                                  \
   } while (0)
 
+// ABSL_INTERNAL_LOG and ABSL_INTERNAL_CHECK work like the RAW variants above,
+// except that if the richer log library is linked into the binary, we dispatch
+// to that instead.  This is potentially useful for internal logging and
+// assertions, where we are using RAW_LOG neither for its async-signal-safety
+// nor for its non-allocating nature, but rather because raw logging has very
+// few other dependencies.
+//
+// The API is a subset of the above: each macro only takes two arguments.  Use
+// StrCat if you need to build a richer message.
+#define ABSL_INTERNAL_LOG(severity, message)                          \
+  do {                                                                \
+    constexpr const char* absl_raw_logging_internal_basename =        \
+        ::absl::raw_logging_internal::Basename(__FILE__,              \
+                                               sizeof(__FILE__) - 1); \
+    ::absl::raw_logging_internal::internal_log_function(              \
+        ABSL_RAW_LOGGING_INTERNAL_##severity,                         \
+        absl_raw_logging_internal_basename, __LINE__, message);       \
+  } while (0)
+
+#define ABSL_INTERNAL_CHECK(condition, message)               \
+  do {                                                        \
+    if (ABSL_PREDICT_FALSE(!(condition))) {                   \
+      std::string death_message = "Check " #condition " failed: "; \
+      death_message += std::string(message);                       \
+      ABSL_INTERNAL_LOG(FATAL, death_message);                \
+    }                                                         \
+  } while (0)
+
 #define ABSL_RAW_LOGGING_INTERNAL_INFO ::absl::LogSeverity::kInfo
 #define ABSL_RAW_LOGGING_INTERNAL_WARNING ::absl::LogSeverity::kWarning
 #define ABSL_RAW_LOGGING_INTERNAL_ERROR ::absl::LogSeverity::kError
@@ -131,6 +162,18 @@
 using AbortHook = void (*)(const char* file, int line, const char* buf_start,
                            const char* prefix_end, const char* buf_end);
 
+// Internal logging function for ABSL_INTERNAL_LOG to dispatch to.
+//
+// TODO(gfalcon): When string_view no longer depends on base, change this
+// interface to take its message as a string_view instead.
+using InternalLogFunction = void (*)(absl::LogSeverity severity,
+                                     const char* file, int line,
+                                     const std::string& message);
+
+extern base_internal::AtomicHook<InternalLogFunction> internal_log_function;
+
+void RegisterInternalLogFunction(InternalLogFunction func);
+
 }  // namespace raw_logging_internal
 }  // namespace absl
 
diff --git a/absl/base/internal/unaligned_access.h b/absl/base/internal/unaligned_access.h
index c572436..5c7517a 100644
--- a/absl/base/internal/unaligned_access.h
+++ b/absl/base/internal/unaligned_access.h
@@ -103,6 +103,47 @@
 #define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
   (absl::UnalignedStore64(_p, _val))
 
+#elif defined(UNDEFINED_BEHAVIOR_SANITIZER)
+
+namespace absl {
+
+inline uint16_t UnalignedLoad16(const void *p) {
+  uint16_t t;
+  memcpy(&t, p, sizeof t);
+  return t;
+}
+
+inline uint32_t UnalignedLoad32(const void *p) {
+  uint32_t t;
+  memcpy(&t, p, sizeof t);
+  return t;
+}
+
+inline uint64_t UnalignedLoad64(const void *p) {
+  uint64_t t;
+  memcpy(&t, p, sizeof t);
+  return t;
+}
+
+inline void UnalignedStore16(void *p, uint16_t v) { memcpy(p, &v, sizeof v); }
+
+inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); }
+
+inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
+
+}  // namespace absl
+
+#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) (absl::UnalignedLoad16(_p))
+#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) (absl::UnalignedLoad32(_p))
+#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) (absl::UnalignedLoad64(_p))
+
+#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
+  (absl::UnalignedStore16(_p, _val))
+#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
+  (absl::UnalignedStore32(_p, _val))
+#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
+  (absl::UnalignedStore64(_p, _val))
+
 #elif defined(__x86_64__) || defined(_M_X64) || defined(__i386) || \
     defined(_M_IX86) || defined(__ppc__) || defined(__PPC__) ||    \
     defined(__ppc64__) || defined(__PPC64__)
diff --git a/absl/base/raw_logging_test.cc b/absl/base/raw_logging_test.cc
index dae4b35..ebbc5db 100644
--- a/absl/base/raw_logging_test.cc
+++ b/absl/base/raw_logging_test.cc
@@ -18,12 +18,20 @@
 
 #include "absl/base/internal/raw_logging.h"
 
+#include <tuple>
+
 #include "gtest/gtest.h"
+#include "absl/strings/str_cat.h"
 
 namespace {
 
 TEST(RawLoggingCompilationTest, Log) {
   ABSL_RAW_LOG(INFO, "RAW INFO: %d", 1);
+  ABSL_RAW_LOG(INFO, "RAW INFO: %d %d", 1, 2);
+  ABSL_RAW_LOG(INFO, "RAW INFO: %d %d %d", 1, 2, 3);
+  ABSL_RAW_LOG(INFO, "RAW INFO: %d %d %d %d", 1, 2, 3, 4);
+  ABSL_RAW_LOG(INFO, "RAW INFO: %d %d %d %d %d", 1, 2, 3, 4, 5);
+  ABSL_RAW_LOG(WARNING, "RAW WARNING: %d", 1);
   ABSL_RAW_LOG(ERROR, "RAW ERROR: %d", 1);
 }
 
@@ -47,4 +55,25 @@
                             kExpectedDeathOutput);
 }
 
+TEST(InternalLog, CompilationTest) {
+  ABSL_INTERNAL_LOG(INFO, "Internal Log");
+  std::string log_msg = "Internal Log";
+  ABSL_INTERNAL_LOG(INFO, log_msg);
+
+  ABSL_INTERNAL_LOG(INFO, log_msg + " 2");
+
+  float d = 1.1f;
+  ABSL_INTERNAL_LOG(INFO, absl::StrCat("Internal log ", 3, " + ", d));
+}
+
+TEST(InternalLogDeathTest, FailingCheck) {
+  EXPECT_DEATH_IF_SUPPORTED(ABSL_INTERNAL_CHECK(1 == 0, "explanation"),
+                            kExpectedDeathOutput);
+}
+
+TEST(InternalLogDeathTest, LogFatal) {
+  EXPECT_DEATH_IF_SUPPORTED(ABSL_INTERNAL_LOG(FATAL, "my dog has fleas"),
+                            kExpectedDeathOutput);
+}
+
 }  // namespace
diff --git a/absl/compiler_config_setting.bzl b/absl/compiler_config_setting.bzl
new file mode 100644
index 0000000..b77c4f5
--- /dev/null
+++ b/absl/compiler_config_setting.bzl
@@ -0,0 +1,39 @@
+#
+# Copyright 2018 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+"""Creates config_setting that allows selecting based on 'compiler' value."""
+
+def create_llvm_config(name, visibility):
+  # The "do_not_use_tools_cpp_compiler_present" attribute exists to
+  # distinguish between older versions of Bazel that do not support
+  # "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do.
+  # In the future, the only way to select on the compiler will be through
+  # flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can
+  # be removed.
+  if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"):
+    native.config_setting(
+      name = name,
+      flag_values = {
+          "@bazel_tools//tools/cpp:compiler": "llvm",
+      },
+      visibility = visibility,
+    )
+  else:
+    native.config_setting(
+        name = name,
+        values = {"compiler": "llvm"},
+        visibility = visibility,
+    )
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index 07df367..6d5c958 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -26,10 +26,30 @@
 licenses(["notice"])  # Apache 2.0
 
 cc_library(
+    name = "compressed_tuple",
+    hdrs = ["internal/compressed_tuple.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        "//absl/utility",
+    ],
+)
+
+cc_test(
+    name = "compressed_tuple_test",
+    srcs = ["internal/compressed_tuple_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    deps = [
+        ":compressed_tuple",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
     name = "fixed_array",
     hdrs = ["fixed_array.h"],
     copts = ABSL_DEFAULT_COPTS,
     deps = [
+        ":compressed_tuple",
         "//absl/algorithm",
         "//absl/base:core_headers",
         "//absl/base:dynamic_annotations",
diff --git a/absl/container/BUILD.gn b/absl/container/BUILD.gn
index a00eaf4..001a2a3 100644
--- a/absl/container/BUILD.gn
+++ b/absl/container/BUILD.gn
@@ -14,6 +14,21 @@
   visibility = [ "*" ]
 }
 
+source_set("compressed_tuple") {
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+    "//third_party/abseil-cpp:absl_default_cflags_cc",
+  ]
+  public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
+  public = [
+    "internal/compressed_tuple.h",
+  ]
+  deps = [
+    "../utility",
+  ]
+}
+
 source_set("fixed_array") {
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
@@ -25,6 +40,7 @@
     "fixed_array.h",
   ]
   deps = [
+    ":compressed_tuple",
     "../algorithm",
     "../base:core_headers",
     "../base:dynamic_annotations",
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index d580b48..123e4c4 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -52,7 +52,6 @@
     ${TEST_INSTANCE_TRACKER_LIB_SRC}
   PUBLIC_LIBRARIES
     absl::container
-  DISABLE_INSTALL
 )
 
 
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h
index 708c615..182258f 100644
--- a/absl/container/fixed_array.h
+++ b/absl/container/fixed_array.h
@@ -47,6 +47,7 @@
 #include "absl/base/macros.h"
 #include "absl/base/optimization.h"
 #include "absl/base/port.h"
+#include "absl/container/internal/compressed_tuple.h"
 #include "absl/memory/memory.h"
 
 namespace absl {
@@ -76,73 +77,99 @@
 // heap allocation, it will do so with global `::operator new[]()` and
 // `::operator delete[]()`, even if T provides class-scope overrides for these
 // operators.
-template <typename T, size_t inlined = kFixedArrayUseDefault>
+template <typename T, size_t N = kFixedArrayUseDefault,
+          typename A = std::allocator<T>>
 class FixedArray {
   static_assert(!std::is_array<T>::value || std::extent<T>::value > 0,
                 "Arrays with unknown bounds cannot be used with FixedArray.");
+
   static constexpr size_t kInlineBytesDefault = 256;
 
+  using AllocatorTraits = std::allocator_traits<A>;
   // std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17,
   // but this seems to be mostly pedantic.
   template <typename Iterator>
   using EnableIfForwardIterator = absl::enable_if_t<std::is_convertible<
       typename std::iterator_traits<Iterator>::iterator_category,
       std::forward_iterator_tag>::value>;
+  static constexpr bool NoexceptCopyable() {
+    return std::is_nothrow_copy_constructible<StorageElement>::value &&
+           absl::allocator_is_nothrow<allocator_type>::value;
+  }
+  static constexpr bool NoexceptMovable() {
+    return std::is_nothrow_move_constructible<StorageElement>::value &&
+           absl::allocator_is_nothrow<allocator_type>::value;
+  }
+  static constexpr bool DefaultConstructorIsNonTrivial() {
+    return !absl::is_trivially_default_constructible<StorageElement>::value;
+  }
 
  public:
-  using value_type = T;
-  using iterator = T*;
-  using const_iterator = const T*;
+  using allocator_type = typename AllocatorTraits::allocator_type;
+  using value_type = typename allocator_type::value_type;
+  using pointer = typename allocator_type::pointer;
+  using const_pointer = typename allocator_type::const_pointer;
+  using reference = typename allocator_type::reference;
+  using const_reference = typename allocator_type::const_reference;
+  using size_type = typename allocator_type::size_type;
+  using difference_type = typename allocator_type::difference_type;
+  using iterator = pointer;
+  using const_iterator = const_pointer;
   using reverse_iterator = std::reverse_iterator<iterator>;
   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
-  using reference = T&;
-  using const_reference = const T&;
-  using pointer = T*;
-  using const_pointer = const T*;
-  using difference_type = ptrdiff_t;
-  using size_type = size_t;
 
   static constexpr size_type inline_elements =
-      inlined == kFixedArrayUseDefault
-          ? kInlineBytesDefault / sizeof(value_type)
-          : inlined;
+      (N == kFixedArrayUseDefault ? kInlineBytesDefault / sizeof(value_type)
+                                  : static_cast<size_type>(N));
 
-  FixedArray(const FixedArray& other)
-      : FixedArray(other.begin(), other.end()) {}
+  FixedArray(
+      const FixedArray& other,
+      const allocator_type& a = allocator_type()) noexcept(NoexceptCopyable())
+      : FixedArray(other.begin(), other.end(), a) {}
 
-  FixedArray(FixedArray&& other) noexcept(
-      absl::conjunction<absl::allocator_is_nothrow<std::allocator<value_type>>,
-                        std::is_nothrow_move_constructible<value_type>>::value)
+  FixedArray(
+      FixedArray&& other,
+      const allocator_type& a = allocator_type()) noexcept(NoexceptMovable())
       : FixedArray(std::make_move_iterator(other.begin()),
-                   std::make_move_iterator(other.end())) {}
+                   std::make_move_iterator(other.end()), a) {}
 
   // Creates an array object that can store `n` elements.
   // Note that trivially constructible elements will be uninitialized.
-  explicit FixedArray(size_type n) : storage_(n) {
-    absl::memory_internal::uninitialized_default_construct_n(storage_.begin(),
-                                                             size());
+  explicit FixedArray(size_type n, const allocator_type& a = allocator_type())
+      : storage_(n, a) {
+    if (DefaultConstructorIsNonTrivial()) {
+      memory_internal::ConstructStorage(storage_.alloc(), storage_.begin(),
+                                        storage_.end());
+    }
   }
 
   // Creates an array initialized with `n` copies of `val`.
-  FixedArray(size_type n, const value_type& val) : storage_(n) {
-    std::uninitialized_fill_n(data(), size(), val);
+  FixedArray(size_type n, const value_type& val,
+             const allocator_type& a = allocator_type())
+      : storage_(n, a) {
+    memory_internal::ConstructStorage(storage_.alloc(), storage_.begin(),
+                                      storage_.end(), val);
   }
 
+  // Creates an array initialized with the size and contents of `init_list`.
+  FixedArray(std::initializer_list<value_type> init_list,
+             const allocator_type& a = allocator_type())
+      : FixedArray(init_list.begin(), init_list.end(), a) {}
+
   // Creates an array initialized with the elements from the input
   // range. The array's size will always be `std::distance(first, last)`.
   // REQUIRES: Iterator must be a forward_iterator or better.
   template <typename Iterator, EnableIfForwardIterator<Iterator>* = nullptr>
-  FixedArray(Iterator first, Iterator last)
-      : storage_(std::distance(first, last)) {
-    std::uninitialized_copy(first, last, data());
+  FixedArray(Iterator first, Iterator last,
+             const allocator_type& a = allocator_type())
+      : storage_(std::distance(first, last), a) {
+    memory_internal::CopyToStorageFromRange(storage_.alloc(), storage_.begin(),
+                                            first, last);
   }
 
-  FixedArray(std::initializer_list<value_type> init_list)
-      : FixedArray(init_list.begin(), init_list.end()) {}
-
   ~FixedArray() noexcept {
-    for (const StorageElement& cur : storage_) {
-      cur.~StorageElement();
+    for (auto* cur = storage_.begin(); cur != storage_.end(); ++cur) {
+      AllocatorTraits::destroy(*storage_.alloc(), cur);
     }
   }
 
@@ -332,7 +359,6 @@
   friend bool operator>=(const FixedArray& lhs, const FixedArray& rhs) {
     return !(lhs < rhs);
   }
-
  private:
   // StorageElement
   //
@@ -364,6 +390,8 @@
   using StorageElement =
       absl::conditional_t<std::is_array<value_type>::value,
                           StorageElementWrapper<value_type>, value_type>;
+  using StorageElementBuffer =
+      absl::aligned_storage_t<sizeof(StorageElement), alignof(StorageElement)>;
 
   static pointer AsValueType(pointer ptr) { return ptr; }
   static pointer AsValueType(StorageElementWrapper<value_type>* ptr) {
@@ -374,9 +402,6 @@
   static_assert(alignof(StorageElement) == alignof(value_type), "");
 
   struct NonEmptyInlinedStorage {
-    using StorageElementBuffer =
-        absl::aligned_storage_t<sizeof(StorageElement),
-                                alignof(StorageElement)>;
     StorageElement* data() {
       return reinterpret_cast<StorageElement*>(inlined_storage_.data());
     }
@@ -386,8 +411,8 @@
     void* RedzoneEnd() { return &redzone_end_ + 1; }
 #endif  // ADDRESS_SANITIZER
 
-    void AnnotateConstruct(size_t);
-    void AnnotateDestruct(size_t);
+    void AnnotateConstruct(size_type);
+    void AnnotateDestruct(size_type);
 
     ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_);
     std::array<StorageElementBuffer, inline_elements> inlined_storage_;
@@ -396,8 +421,8 @@
 
   struct EmptyInlinedStorage {
     StorageElement* data() { return nullptr; }
-    void AnnotateConstruct(size_t) {}
-    void AnnotateDestruct(size_t) {}
+    void AnnotateConstruct(size_type) {}
+    void AnnotateDestruct(size_type) {}
   };
 
   using InlinedStorage =
@@ -414,48 +439,57 @@
   //
   class Storage : public InlinedStorage {
    public:
-    explicit Storage(size_type n) : data_(CreateStorage(n)), size_(n) {}
+    Storage(size_type n, const allocator_type& a)
+        : size_alloc_(n, a), data_(InitializeData()) {}
+
     ~Storage() noexcept {
       if (UsingInlinedStorage(size())) {
-        this->AnnotateDestruct(size());
+        InlinedStorage::AnnotateDestruct(size());
       } else {
-        std::allocator<StorageElement>().deallocate(begin(), size());
+        AllocatorTraits::deallocate(*alloc(), AsValueType(begin()), size());
       }
     }
 
-    size_type size() const { return size_; }
+    size_type size() const { return size_alloc_.template get<0>(); }
     StorageElement* begin() const { return data_; }
     StorageElement* end() const { return begin() + size(); }
+    allocator_type* alloc() {
+      return std::addressof(size_alloc_.template get<1>());
+    }
 
    private:
     static bool UsingInlinedStorage(size_type n) {
       return n <= inline_elements;
     }
 
-    StorageElement* CreateStorage(size_type n) {
-      if (UsingInlinedStorage(n)) {
-        this->AnnotateConstruct(n);
+    StorageElement* InitializeData() {
+      if (UsingInlinedStorage(size())) {
+        InlinedStorage::AnnotateConstruct(size());
         return InlinedStorage::data();
       } else {
-        return std::allocator<StorageElement>().allocate(n);
+        return reinterpret_cast<StorageElement*>(
+            AllocatorTraits::allocate(*alloc(), size()));
       }
     }
 
-    StorageElement* const data_;
-    const size_type size_;
+    // `CompressedTuple` takes advantage of EBCO for stateless `allocator_type`s
+    container_internal::CompressedTuple<size_type, allocator_type> size_alloc_;
+    StorageElement* data_;
   };
 
-  const Storage storage_;
+  Storage storage_;
 };
 
-template <typename T, size_t N>
-constexpr size_t FixedArray<T, N>::inline_elements;
+template <typename T, size_t N, typename A>
+constexpr size_t FixedArray<T, N, A>::kInlineBytesDefault;
 
-template <typename T, size_t N>
-constexpr size_t FixedArray<T, N>::kInlineBytesDefault;
+template <typename T, size_t N, typename A>
+constexpr typename FixedArray<T, N, A>::size_type
+    FixedArray<T, N, A>::inline_elements;
 
-template <typename T, size_t N>
-void FixedArray<T, N>::NonEmptyInlinedStorage::AnnotateConstruct(size_t n) {
+template <typename T, size_t N, typename A>
+void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateConstruct(
+    typename FixedArray<T, N, A>::size_type n) {
 #ifdef ADDRESS_SANITIZER
   if (!n) return;
   ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(), data() + n);
@@ -464,8 +498,9 @@
   static_cast<void>(n);  // Mark used when not in asan mode
 }
 
-template <typename T, size_t N>
-void FixedArray<T, N>::NonEmptyInlinedStorage::AnnotateDestruct(size_t n) {
+template <typename T, size_t N, typename A>
+void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateDestruct(
+    typename FixedArray<T, N, A>::size_type n) {
 #ifdef ADDRESS_SANITIZER
   if (!n) return;
   ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n, RedzoneEnd());
@@ -473,6 +508,5 @@
 #endif                   // ADDRESS_SANITIZER
   static_cast<void>(n);  // Mark used when not in asan mode
 }
-
 }  // namespace absl
 #endif  // ABSL_CONTAINER_FIXED_ARRAY_H_
diff --git a/absl/container/fixed_array_test.cc b/absl/container/fixed_array_test.cc
index 2142132..b07ebcb 100644
--- a/absl/container/fixed_array_test.cc
+++ b/absl/container/fixed_array_test.cc
@@ -15,9 +15,11 @@
 #include "absl/container/fixed_array.h"
 
 #include <stdio.h>
+#include <cstring>
 #include <list>
 #include <memory>
 #include <numeric>
+#include <scoped_allocator>
 #include <stdexcept>
 #include <string>
 #include <vector>
@@ -607,6 +609,216 @@
   empty.fill(fill_val);
 }
 
+// TODO(johnsoncj): Investigate InlinedStorage default initialization in GCC 4.x
+#ifndef __GNUC__
+TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) {
+  using T = char;
+  constexpr auto capacity = 10;
+  using FixedArrType = absl::FixedArray<T, capacity>;
+  using FixedArrBuffType =
+      absl::aligned_storage_t<sizeof(FixedArrType), alignof(FixedArrType)>;
+  constexpr auto scrubbed_bits = 0x95;
+  constexpr auto length = capacity / 2;
+
+  FixedArrBuffType buff;
+  std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrBuffType));
+
+  FixedArrType* arr =
+      ::new (static_cast<void*>(std::addressof(buff))) FixedArrType(length);
+  EXPECT_THAT(*arr, testing::Each(scrubbed_bits));
+  arr->~FixedArrType();
+}
+#endif  // __GNUC__
+
+// This is a stateful allocator, but the state lives outside of the
+// allocator (in whatever test is using the allocator). This is odd
+// but helps in tests where the allocator is propagated into nested
+// containers - that chain of allocators uses the same state and is
+// thus easier to query for aggregate allocation information.
+template <typename T>
+class CountingAllocator : public std::allocator<T> {
+ public:
+  using Alloc = std::allocator<T>;
+  using pointer = typename Alloc::pointer;
+  using size_type = typename Alloc::size_type;
+
+  CountingAllocator() : bytes_used_(nullptr), instance_count_(nullptr) {}
+  explicit CountingAllocator(int64_t* b)
+      : bytes_used_(b), instance_count_(nullptr) {}
+  CountingAllocator(int64_t* b, int64_t* a)
+      : bytes_used_(b), instance_count_(a) {}
+
+  template <typename U>
+  explicit CountingAllocator(const CountingAllocator<U>& x)
+      : Alloc(x),
+        bytes_used_(x.bytes_used_),
+        instance_count_(x.instance_count_) {}
+
+  pointer allocate(size_type n, const void* const hint = nullptr) {
+    assert(bytes_used_ != nullptr);
+    *bytes_used_ += n * sizeof(T);
+    return Alloc::allocate(n, hint);
+  }
+
+  void deallocate(pointer p, size_type n) {
+    Alloc::deallocate(p, n);
+    assert(bytes_used_ != nullptr);
+    *bytes_used_ -= n * sizeof(T);
+  }
+
+  template <typename... Args>
+  void construct(pointer p, Args&&... args) {
+    Alloc::construct(p, absl::forward<Args>(args)...);
+    if (instance_count_) {
+      *instance_count_ += 1;
+    }
+  }
+
+  void destroy(pointer p) {
+    Alloc::destroy(p);
+    if (instance_count_) {
+      *instance_count_ -= 1;
+    }
+  }
+
+  template <typename U>
+  class rebind {
+   public:
+    using other = CountingAllocator<U>;
+  };
+
+  int64_t* bytes_used_;
+  int64_t* instance_count_;
+};
+
+TEST(AllocatorSupportTest, CountInlineAllocations) {
+  constexpr size_t inlined_size = 4;
+  using Alloc = CountingAllocator<int>;
+  using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
+
+  int64_t allocated = 0;
+  int64_t active_instances = 0;
+
+  {
+    const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
+
+    Alloc alloc(&allocated, &active_instances);
+
+    AllocFxdArr arr(ia, ia + inlined_size, alloc);
+    static_cast<void>(arr);
+  }
+
+  EXPECT_EQ(allocated, 0);
+  EXPECT_EQ(active_instances, 0);
+}
+
+TEST(AllocatorSupportTest, CountOutoflineAllocations) {
+  constexpr size_t inlined_size = 4;
+  using Alloc = CountingAllocator<int>;
+  using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
+
+  int64_t allocated = 0;
+  int64_t active_instances = 0;
+
+  {
+    const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
+    Alloc alloc(&allocated, &active_instances);
+
+    AllocFxdArr arr(ia, ia + ABSL_ARRAYSIZE(ia), alloc);
+
+    EXPECT_EQ(allocated, arr.size() * sizeof(int));
+    static_cast<void>(arr);
+  }
+
+  EXPECT_EQ(active_instances, 0);
+}
+
+TEST(AllocatorSupportTest, CountCopyInlineAllocations) {
+  constexpr size_t inlined_size = 4;
+  using Alloc = CountingAllocator<int>;
+  using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
+
+  int64_t allocated1 = 0;
+  int64_t allocated2 = 0;
+  int64_t active_instances = 0;
+  Alloc alloc(&allocated1, &active_instances);
+  Alloc alloc2(&allocated2, &active_instances);
+
+  {
+    int initial_value = 1;
+
+    AllocFxdArr arr1(inlined_size / 2, initial_value, alloc);
+
+    EXPECT_EQ(allocated1, 0);
+
+    AllocFxdArr arr2(arr1, alloc2);
+
+    EXPECT_EQ(allocated2, 0);
+    static_cast<void>(arr1);
+    static_cast<void>(arr2);
+  }
+
+  EXPECT_EQ(active_instances, 0);
+}
+
+TEST(AllocatorSupportTest, CountCopyOutoflineAllocations) {
+  constexpr size_t inlined_size = 4;
+  using Alloc = CountingAllocator<int>;
+  using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
+
+  int64_t allocated1 = 0;
+  int64_t allocated2 = 0;
+  int64_t active_instances = 0;
+  Alloc alloc(&allocated1, &active_instances);
+  Alloc alloc2(&allocated2, &active_instances);
+
+  {
+    int initial_value = 1;
+
+    AllocFxdArr arr1(inlined_size * 2, initial_value, alloc);
+
+    EXPECT_EQ(allocated1, arr1.size() * sizeof(int));
+
+    AllocFxdArr arr2(arr1, alloc2);
+
+    EXPECT_EQ(allocated2, inlined_size * 2 * sizeof(int));
+    static_cast<void>(arr1);
+    static_cast<void>(arr2);
+  }
+
+  EXPECT_EQ(active_instances, 0);
+}
+
+TEST(AllocatorSupportTest, SizeValAllocConstructor) {
+  using testing::AllOf;
+  using testing::Each;
+  using testing::SizeIs;
+
+  constexpr size_t inlined_size = 4;
+  using Alloc = CountingAllocator<int>;
+  using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
+
+  {
+    auto len = inlined_size / 2;
+    auto val = 0;
+    int64_t allocated = 0;
+    AllocFxdArr arr(len, val, Alloc(&allocated));
+
+    EXPECT_EQ(allocated, 0);
+    EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0)));
+  }
+
+  {
+    auto len = inlined_size * 2;
+    auto val = 0;
+    int64_t allocated = 0;
+    AllocFxdArr arr(len, val, Alloc(&allocated));
+
+    EXPECT_EQ(allocated, len * sizeof(int));
+    EXPECT_THAT(arr, AllOf(SizeIs(len), Each(0)));
+  }
+}
+
 #ifdef ADDRESS_SANITIZER
 TEST(FixedArrayTest, AddressSanitizerAnnotations1) {
   absl::FixedArray<int, 32> a(10);
@@ -655,5 +867,4 @@
   EXPECT_DEATH(raw[21] = ThreeInts(), "container-overflow");
 }
 #endif  // ADDRESS_SANITIZER
-
 }  // namespace
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index 03660f1..ca36fd3 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -626,14 +626,18 @@
   // It holds whether the vector is allocated or not in the lowest bit.
   // The size is held in the high bits:
   //   size_ = (size << 1) | is_allocated;
+  //
+  // Maintainer's Note: size_type is user defined. The contract is limited to
+  // arithmetic operators to avoid depending on compliant overloaded bitwise
+  // operators.
   class Tag {
    public:
     Tag() : size_(0) {}
-    size_type size() const { return size_ >> 1; }
-    void add_size(size_type n) { size_ += n << 1; }
-    void set_inline_size(size_type n) { size_ = n << 1; }
-    void set_allocated_size(size_type n) { size_ = (n << 1) | 1; }
-    bool allocated() const { return size_ & 1; }
+    size_type size() const { return size_ / 2; }
+    void add_size(size_type n) { size_ += n * 2; }
+    void set_inline_size(size_type n) { size_ = n * 2; }
+    void set_allocated_size(size_type n) { size_ = (n * 2) + 1; }
+    bool allocated() const { return size_ % 2; }
 
    private:
     size_type size_;
@@ -689,11 +693,14 @@
     new (&rep_.allocation_storage.allocation) Allocation(allocation);
   }
 
+  // TODO(absl-team): investigate whether the reinterpret_cast is appropriate.
   value_type* inlined_space() {
-    return reinterpret_cast<value_type*>(&rep_.inlined_storage.inlined);
+    return reinterpret_cast<value_type*>(
+        std::addressof(rep_.inlined_storage.inlined[0]));
   }
   const value_type* inlined_space() const {
-    return reinterpret_cast<const value_type*>(&rep_.inlined_storage.inlined);
+    return reinterpret_cast<const value_type*>(
+        std::addressof(rep_.inlined_storage.inlined[0]));
   }
 
   value_type* allocated_space() { return allocation().buffer(); }
diff --git a/absl/container/inlined_vector_test.cc b/absl/container/inlined_vector_test.cc
index f81fad5..196a1be 100644
--- a/absl/container/inlined_vector_test.cc
+++ b/absl/container/inlined_vector_test.cc
@@ -1788,5 +1788,4 @@
     EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));
   }
 }
-
 }  // anonymous namespace
diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h
new file mode 100644
index 0000000..cc52614
--- /dev/null
+++ b/absl/container/internal/compressed_tuple.h
@@ -0,0 +1,175 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Helper class to perform the Empty Base Optimization.
+// Ts can contain classes and non-classes, empty or not. For the ones that
+// are empty classes, we perform the optimization. If all types in Ts are empty
+// classes, then CompressedTuple<Ts...> is itself an empty class.
+//
+// To access the members, use member get<N>() function.
+//
+// Eg:
+//   absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,
+//                                                                    t3);
+//   assert(value.get<0>() == 7);
+//   T1& t1 = value.get<1>();
+//   const T2& t2 = value.get<2>();
+//   ...
+//
+// http://en.cppreference.com/w/cpp/language/ebo
+
+#ifndef ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
+#define ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
+
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "absl/utility/utility.h"
+
+#ifdef _MSC_VER
+// We need to mark these classes with this declspec to ensure that
+// CompressedTuple happens.
+#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases)
+#else  // _MSC_VER
+#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
+#endif  // _MSC_VER
+
+namespace absl {
+namespace container_internal {
+
+template <typename... Ts>
+class CompressedTuple;
+
+namespace internal_compressed_tuple {
+
+template <typename D, size_t I>
+struct Elem;
+template <typename... B, size_t I>
+struct Elem<CompressedTuple<B...>, I>
+    : std::tuple_element<I, std::tuple<B...>> {};
+template <typename D, size_t I>
+using ElemT = typename Elem<D, I>::type;
+
+// Use the __is_final intrinsic if available. Where it's not available, classes
+// declared with the 'final' specifier cannot be used as CompressedTuple
+// elements.
+// TODO(sbenza): Replace this with std::is_final in C++14.
+template <typename T>
+constexpr bool IsFinal() {
+#if defined(__clang__) || defined(__GNUC__)
+  return __is_final(T);
+#else
+  return false;
+#endif
+}
+
+template <typename T>
+constexpr bool ShouldUseBase() {
+  return std::is_class<T>::value && std::is_empty<T>::value && !IsFinal<T>();
+}
+
+// The storage class provides two specializations:
+//  - For empty classes, it stores T as a base class.
+//  - For everything else, it stores T as a member.
+template <typename D, size_t I, bool = ShouldUseBase<ElemT<D, I>>()>
+struct Storage {
+  using T = ElemT<D, I>;
+  T value;
+  constexpr Storage() = default;
+  explicit constexpr Storage(T&& v) : value(absl::forward<T>(v)) {}
+  constexpr const T& get() const { return value; }
+  T& get() { return value; }
+};
+
+template <typename D, size_t I>
+struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<D, I, true>
+    : ElemT<D, I> {
+  using T = internal_compressed_tuple::ElemT<D, I>;
+  constexpr Storage() = default;
+  explicit constexpr Storage(T&& v) : T(absl::forward<T>(v)) {}
+  constexpr const T& get() const { return *this; }
+  T& get() { return *this; }
+};
+
+template <typename D, typename I>
+struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl;
+
+template <typename... Ts, size_t... I>
+struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
+    CompressedTupleImpl<CompressedTuple<Ts...>, absl::index_sequence<I...>>
+    // We use the dummy identity function through std::integral_constant to
+    // convince MSVC of accepting and expanding I in that context. Without it
+    // you would get:
+    //   error C3548: 'I': parameter pack cannot be used in this context
+    : Storage<CompressedTuple<Ts...>,
+              std::integral_constant<size_t, I>::value>... {
+  constexpr CompressedTupleImpl() = default;
+  explicit constexpr CompressedTupleImpl(Ts&&... args)
+      : Storage<CompressedTuple<Ts...>, I>(absl::forward<Ts>(args))... {}
+};
+
+}  // namespace internal_compressed_tuple
+
+// Helper class to perform the Empty Base Class Optimization.
+// Ts can contain classes and non-classes, empty or not. For the ones that
+// are empty classes, we perform the CompressedTuple. If all types in Ts are
+// empty classes, then CompressedTuple<Ts...> is itself an empty class.
+//
+// To access the members, use member .get<N>() function.
+//
+// Eg:
+//   absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,
+//                                                                    t3);
+//   assert(value.get<0>() == 7);
+//   T1& t1 = value.get<1>();
+//   const T2& t2 = value.get<2>();
+//   ...
+//
+// http://en.cppreference.com/w/cpp/language/ebo
+template <typename... Ts>
+class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
+    : private internal_compressed_tuple::CompressedTupleImpl<
+          CompressedTuple<Ts...>, absl::index_sequence_for<Ts...>> {
+ private:
+  template <int I>
+  using ElemT = internal_compressed_tuple::ElemT<CompressedTuple, I>;
+
+ public:
+  constexpr CompressedTuple() = default;
+  explicit constexpr CompressedTuple(Ts... base)
+      : CompressedTuple::CompressedTupleImpl(absl::forward<Ts>(base)...) {}
+
+  template <int I>
+  ElemT<I>& get() {
+    return internal_compressed_tuple::Storage<CompressedTuple, I>::get();
+  }
+
+  template <int I>
+  constexpr const ElemT<I>& get() const {
+    return internal_compressed_tuple::Storage<CompressedTuple, I>::get();
+  }
+};
+
+// Explicit specialization for a zero-element tuple
+// (needed to avoid ambiguous overloads for the default constructor).
+template <>
+class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple<> {};
+
+}  // namespace container_internal
+}  // namespace absl
+
+#undef ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
+
+#endif  // ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
diff --git a/absl/container/internal/compressed_tuple_test.cc b/absl/container/internal/compressed_tuple_test.cc
new file mode 100644
index 0000000..45030c6
--- /dev/null
+++ b/absl/container/internal/compressed_tuple_test.cc
@@ -0,0 +1,166 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/container/internal/compressed_tuple.h"
+
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace absl {
+namespace container_internal {
+namespace {
+
+template <int>
+struct Empty {};
+
+template <typename T>
+struct NotEmpty {
+  T value;
+};
+
+template <typename T, typename U>
+struct TwoValues {
+  T value1;
+  U value2;
+};
+
+TEST(CompressedTupleTest, Sizeof) {
+  EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int>));
+  EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>>));
+  EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>, Empty<1>>));
+  EXPECT_EQ(sizeof(int),
+            sizeof(CompressedTuple<int, Empty<0>, Empty<1>, Empty<2>>));
+
+  EXPECT_EQ(sizeof(TwoValues<int, double>),
+            sizeof(CompressedTuple<int, NotEmpty<double>>));
+  EXPECT_EQ(sizeof(TwoValues<int, double>),
+            sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>>));
+  EXPECT_EQ(sizeof(TwoValues<int, double>),
+            sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>, Empty<1>>));
+}
+
+TEST(CompressedTupleTest, Access) {
+  struct S {
+    std::string x;
+  };
+  CompressedTuple<int, Empty<0>, S> x(7, {}, S{"ABC"});
+  EXPECT_EQ(sizeof(x), sizeof(TwoValues<int, S>));
+  EXPECT_EQ(7, x.get<0>());
+  EXPECT_EQ("ABC", x.get<2>().x);
+}
+
+TEST(CompressedTupleTest, NonClasses) {
+  CompressedTuple<int, const char*> x(7, "ABC");
+  EXPECT_EQ(7, x.get<0>());
+  EXPECT_STREQ("ABC", x.get<1>());
+}
+
+TEST(CompressedTupleTest, MixClassAndNonClass) {
+  CompressedTuple<int, const char*, Empty<0>, NotEmpty<double>> x(7, "ABC", {},
+                                                                  {1.25});
+  struct Mock {
+    int v;
+    const char* p;
+    double d;
+  };
+  EXPECT_EQ(sizeof(x), sizeof(Mock));
+  EXPECT_EQ(7, x.get<0>());
+  EXPECT_STREQ("ABC", x.get<1>());
+  EXPECT_EQ(1.25, x.get<3>().value);
+}
+
+TEST(CompressedTupleTest, Nested) {
+  CompressedTuple<int, CompressedTuple<int>,
+                  CompressedTuple<int, CompressedTuple<int>>>
+      x(1, CompressedTuple<int>(2),
+        CompressedTuple<int, CompressedTuple<int>>(3, CompressedTuple<int>(4)));
+  EXPECT_EQ(1, x.get<0>());
+  EXPECT_EQ(2, x.get<1>().get<0>());
+  EXPECT_EQ(3, x.get<2>().get<0>());
+  EXPECT_EQ(4, x.get<2>().get<1>().get<0>());
+
+  CompressedTuple<Empty<0>, Empty<0>,
+                  CompressedTuple<Empty<0>, CompressedTuple<Empty<0>>>>
+      y;
+  std::set<Empty<0>*> empties{&y.get<0>(), &y.get<1>(), &y.get<2>().get<0>(),
+                              &y.get<2>().get<1>().get<0>()};
+#ifdef _MSC_VER
+  // MSVC has a bug where many instances of the same base class are layed out in
+  // the same address when using __declspec(empty_bases).
+  // This will be fixed in a future version of MSVC.
+  int expected = 1;
+#else
+  int expected = 4;
+#endif
+  EXPECT_EQ(expected, sizeof(y));
+  EXPECT_EQ(expected, empties.size());
+  EXPECT_EQ(sizeof(y), sizeof(Empty<0>) * empties.size());
+
+  EXPECT_EQ(4 * sizeof(char),
+            sizeof(CompressedTuple<CompressedTuple<char, char>,
+                                   CompressedTuple<char, char>>));
+  EXPECT_TRUE(
+      (std::is_empty<CompressedTuple<CompressedTuple<Empty<0>>,
+                                     CompressedTuple<Empty<1>>>>::value));
+}
+
+TEST(CompressedTupleTest, Reference) {
+  int i = 7;
+  std::string s = "Very long std::string that goes in the heap";
+  CompressedTuple<int, int&, std::string, std::string&> x(i, i, s, s);
+
+  // Sanity check. We should have not moved from `s`
+  EXPECT_EQ(s, "Very long std::string that goes in the heap");
+
+  EXPECT_EQ(x.get<0>(), x.get<1>());
+  EXPECT_NE(&x.get<0>(), &x.get<1>());
+  EXPECT_EQ(&x.get<1>(), &i);
+
+  EXPECT_EQ(x.get<2>(), x.get<3>());
+  EXPECT_NE(&x.get<2>(), &x.get<3>());
+  EXPECT_EQ(&x.get<3>(), &s);
+}
+
+TEST(CompressedTupleTest, NoElements) {
+  CompressedTuple<> x;
+  static_cast<void>(x);  // Silence -Wunused-variable.
+  EXPECT_TRUE(std::is_empty<CompressedTuple<>>::value);
+}
+
+TEST(CompressedTupleTest, Constexpr) {
+  constexpr CompressedTuple<int, double, CompressedTuple<int>> x(
+      7, 1.25, CompressedTuple<int>(5));
+  constexpr int x0 = x.get<0>();
+  constexpr double x1 = x.get<1>();
+  constexpr int x2 = x.get<2>().get<0>();
+  EXPECT_EQ(x0, 7);
+  EXPECT_EQ(x1, 1.25);
+  EXPECT_EQ(x2, 5);
+}
+
+#if defined(__clang__) || defined(__GNUC__)
+TEST(CompressedTupleTest, EmptyFinalClass) {
+  struct S final {
+    int f() const { return 5; }
+  };
+  CompressedTuple<S> x;
+  EXPECT_EQ(x.get<0>().f(), 5);
+}
+#endif
+
+}  // namespace
+}  // namespace container_internal
+}  // namespace absl
diff --git a/absl/copts.bzl b/absl/copts.bzl
index 20c9b61..0168ac5 100644
--- a/absl/copts.bzl
+++ b/absl/copts.bzl
@@ -31,7 +31,6 @@
     "-Wno-unused-private-field",
 ]
 
-
 # Docs on single flags is preceded by a comment.
 # Docs on groups of flags is preceded by ###.
 
diff --git a/absl/debugging/failure_signal_handler.cc b/absl/debugging/failure_signal_handler.cc
index 4c131fe..d4b957b 100644
--- a/absl/debugging/failure_signal_handler.cc
+++ b/absl/debugging/failure_signal_handler.cc
@@ -252,7 +252,7 @@
       depth, min_dropped_frames, symbolize_stacktrace, writerfn, writerfn_arg);
 }
 
-// Called by FailureSignalHandler() to write the failure info. It is
+// Called by AbslFailureSignalHandler() to write the failure info. It is
 // called once with writerfn set to WriteToStderr() and then possibly
 // with writerfn set to the user provided function.
 static void WriteFailureInfo(int signo, void* ucontext,
@@ -278,9 +278,9 @@
 }
 
 #ifdef ABSL_HAVE_ALARM
-// FailureSignalHandler() installs this as a signal handler for
+// AbslFailureSignalHandler() installs this as a signal handler for
 // SIGALRM, then sets an alarm to be delivered to the program after a
-// set amount of time. If FailureSignalHandler() hangs for more than
+// set amount of time. If AbslFailureSignalHandler() hangs for more than
 // the alarm timeout, ImmediateAbortSignalHandler() will abort the
 // program.
 static void ImmediateAbortSignalHandler(int) {
@@ -294,11 +294,10 @@
 ABSL_CONST_INIT static std::atomic<GetTidType> failed_tid(0);
 
 #ifndef ABSL_HAVE_SIGACTION
-static void FailureSignalHandler(int signo) {
+static void AbslFailureSignalHandler(int signo) {
   void* ucontext = nullptr;
 #else
-static void FailureSignalHandler(int signo, siginfo_t*,
-                                 void* ucontext) {
+static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {
 #endif
 
   const GetTidType this_tid = absl::base_internal::GetTID();
@@ -308,10 +307,10 @@
           std::memory_order_acq_rel, std::memory_order_relaxed)) {
     ABSL_RAW_LOG(
         ERROR,
-        "Signal %d raised at PC=%p while already in FailureSignalHandler()",
+        "Signal %d raised at PC=%p while already in AbslFailureSignalHandler()",
         signo, absl::debugging_internal::GetProgramCounter(ucontext));
     if (this_tid != previous_failed_tid) {
-      // Another thread is already in FailureSignalHandler(), so wait
+      // Another thread is already in AbslFailureSignalHandler(), so wait
       // a bit for it to finish. If the other thread doesn't kill us,
       // we do so after sleeping.
       PortableSleepForSeconds(3);
@@ -349,7 +348,7 @@
 void InstallFailureSignalHandler(const FailureSignalHandlerOptions& options) {
   fsh_options = options;
   for (auto& it : failure_signal_data) {
-    InstallOneFailureHandler(&it, FailureSignalHandler);
+    InstallOneFailureHandler(&it, AbslFailureSignalHandler);
   }
 }
 
diff --git a/absl/debugging/internal/examine_stack.cc b/absl/debugging/internal/examine_stack.cc
index 8434709..faf8883 100644
--- a/absl/debugging/internal/examine_stack.cc
+++ b/absl/debugging/internal/examine_stack.cc
@@ -52,6 +52,10 @@
     return reinterpret_cast<void*>(context->uc_mcontext.gp_regs[32]);
 #elif defined(__powerpc__)
     return reinterpret_cast<void*>(context->uc_mcontext.regs->nip);
+#elif defined(__s390__) && !defined(__s390x__)
+    return reinterpret_cast<void*>(context->uc_mcontext.psw.addr & 0x7fffffff);
+#elif defined(__s390__) && defined(__s390x__)
+    return reinterpret_cast<void*>(context->uc_mcontext.psw.addr);
 #elif defined(__x86_64__)
     if (16 < ABSL_ARRAYSIZE(context->uc_mcontext.gregs))
       return reinterpret_cast<void*>(context->uc_mcontext.gregs[16]);
diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h
index 48adfcc..dd713da 100644
--- a/absl/debugging/internal/stacktrace_config.h
+++ b/absl/debugging/internal/stacktrace_config.h
@@ -21,26 +21,16 @@
 #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
 
-// First, test platforms which only support a stub.
-#if ABSL_STACKTRACE_INL_HEADER
+#if defined(ABSL_STACKTRACE_INL_HEADER)
 #error ABSL_STACKTRACE_INL_HEADER cannot be directly set
-#elif defined(__native_client__) || defined(__APPLE__) || \
-    defined(__FreeBSD__) || defined(__ANDROID__) || defined(__myriad2__) || \
-    defined(__asmjs__) || defined(__wasm__) || defined(__Fuchsia__)
-#define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
 
-// Next, test for Mips and Windows.
-// TODO(marmstrong): Mips case, remove the check for ABSL_STACKTRACE_INL_HEADER
-#elif defined(__mips__) && !defined(ABSL_STACKTRACE_INL_HEADER)
-#define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-#elif defined(_WIN32)  // windows
+#elif defined(_WIN32)
 #define ABSL_STACKTRACE_INL_HEADER \
     "absl/debugging/internal/stacktrace_win32-inl.inc"
 
-// Finally, test NO_FRAME_POINTER.
-#elif !defined(NO_FRAME_POINTER)
+#elif defined(__linux__) && !defined(__ANDROID__)
+
+#if !defined(NO_FRAME_POINTER)
 # if defined(__i386__) || defined(__x86_64__)
 #define ABSL_STACKTRACE_INL_HEADER \
     "absl/debugging/internal/stacktrace_x86-inl.inc"
@@ -53,22 +43,27 @@
 # elif defined(__arm__)
 #define ABSL_STACKTRACE_INL_HEADER \
     "absl/debugging/internal/stacktrace_arm-inl.inc"
+# else
+#define ABSL_STACKTRACE_INL_HEADER \
+   "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
 # endif
 #else  // defined(NO_FRAME_POINTER)
 # if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
 #define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
+    "absl/debugging/internal/stacktrace_generic-inl.inc"
 # elif defined(__ppc__) || defined(__PPC__)
-//  Use glibc's backtrace.
 #define ABSL_STACKTRACE_INL_HEADER \
     "absl/debugging/internal/stacktrace_generic-inl.inc"
-# elif defined(__arm__)
-#   error stacktrace without frame pointer is not supported on ARM
+# else
+#define ABSL_STACKTRACE_INL_HEADER \
+   "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
 # endif
 #endif  // NO_FRAME_POINTER
 
-#if !defined(ABSL_STACKTRACE_INL_HEADER)
-#error Not supported yet
+#else
+#define ABSL_STACKTRACE_INL_HEADER \
+  "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
+
 #endif
 
 #endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
diff --git a/absl/debugging/internal/stacktrace_powerpc-inl.inc b/absl/debugging/internal/stacktrace_powerpc-inl.inc
index 297bdad..860ac2b 100644
--- a/absl/debugging/internal/stacktrace_powerpc-inl.inc
+++ b/absl/debugging/internal/stacktrace_powerpc-inl.inc
@@ -31,6 +31,8 @@
 #include <cstdint>
 #include <cstdio>
 
+#include "absl/base/attributes.h"
+#include "absl/base/optimization.h"
 #include "absl/base/port.h"
 #include "absl/debugging/stacktrace.h"
 #include "absl/debugging/internal/address_is_readable.h"
@@ -150,8 +152,9 @@
 }
 
 // This ensures that absl::GetStackTrace sets up the Link Register properly.
-void StacktracePowerPCDummyFunction() __attribute__((noinline));
-void StacktracePowerPCDummyFunction() { __asm__ volatile(""); }
+ABSL_ATTRIBUTE_NOINLINE static void AbslStacktracePowerPCDummyFunction() {
+  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
+}
 
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
 ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
@@ -176,7 +179,7 @@
   // want here.  While the compiler will always(?) set up LR for
   // subroutine calls, it may not for leaf functions (such as this one).
   // This routine forces the compiler (at least gcc) to push it anyway.
-  StacktracePowerPCDummyFunction();
+  AbslStacktracePowerPCDummyFunction();
 
   // The LR save area is used by the callee, so the top entry is bogus.
   skip_count++;
diff --git a/absl/memory/memory.h b/absl/memory/memory.h
index c43e156..c7caf8b 100644
--- a/absl/memory/memory.h
+++ b/absl/memory/memory.h
@@ -83,7 +83,11 @@
 
 }  // namespace memory_internal
 
-#if __cplusplus >= 201402L || defined(_MSC_VER)
+// gcc 4.8 has __cplusplus at 201301 but doesn't define make_unique.  Other
+// supported compilers either just define __cplusplus as 201103 but have
+// make_unique (msvc), or have make_unique whenever __cplusplus > 201103 (clang)
+#if (__cplusplus > 201103L || defined(_MSC_VER)) && \
+    !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8)
 using std::make_unique;
 #else
 // -----------------------------------------------------------------------------
@@ -637,38 +641,56 @@
 #endif
 
 namespace memory_internal {
-// TODO(b110200014): Implement proper backports
-template <typename ForwardIt>
-void DefaultConstruct(ForwardIt it) {
-  using value_type = typename std::iterator_traits<ForwardIt>::value_type;
-  ::new (static_cast<void*>(std::addressof(*it))) value_type;
-}  // namespace memory_internal
-
 #ifdef ABSL_HAVE_EXCEPTIONS
-template <typename ForwardIt, typename Size>
-void uninitialized_default_construct_n(ForwardIt first, Size size) {
-  for (ForwardIt cur = first; size > 0; static_cast<void>(++cur), --size) {
+template <typename Allocator, typename StorageElement, typename... Args>
+void ConstructStorage(Allocator* alloc, StorageElement* first,
+                      StorageElement* last, const Args&... args) {
+  for (StorageElement* cur = first; cur != last; ++cur) {
     try {
-      absl::memory_internal::DefaultConstruct(cur);
+      std::allocator_traits<Allocator>::construct(*alloc, cur, args...);
     } catch (...) {
-      using value_type = typename std::iterator_traits<ForwardIt>::value_type;
-      for (; first != cur; ++first) {
-        first->~value_type();
+      while (cur != first) {
+        --cur;
+        std::allocator_traits<Allocator>::destroy(*alloc, cur);
+      }
+      throw;
+    }
+  }
+}
+template <typename Allocator, typename StorageElement, typename Iterator>
+void CopyToStorageFromRange(Allocator* alloc, StorageElement* destination,
+                            Iterator first, Iterator last) {
+  for (StorageElement* cur = destination; first != last;
+       static_cast<void>(++cur), static_cast<void>(++first)) {
+    try {
+      std::allocator_traits<Allocator>::construct(*alloc, cur, *first);
+    } catch (...) {
+      while (cur != destination) {
+        --cur;
+        std::allocator_traits<Allocator>::destroy(*alloc, cur);
       }
       throw;
     }
   }
 }
 #else   // ABSL_HAVE_EXCEPTIONS
-template <typename ForwardIt, typename Size>
-void uninitialized_default_construct_n(ForwardIt first, Size size) {
-  for (; size > 0; static_cast<void>(++first), --size) {
-    absl::memory_internal::DefaultConstruct(first);
+template <typename Allocator, typename StorageElement, typename... Args>
+void ConstructStorage(Allocator* alloc, StorageElement* first,
+                      StorageElement* last, const Args&... args) {
+  for (; first != last; ++first) {
+    std::allocator_traits<Allocator>::construct(*alloc, first, args...);
+  }
+}
+template <typename Allocator, typename StorageElement, typename Iterator>
+void CopyToStorageFromRange(Allocator* alloc, StorageElement* destination,
+                            Iterator first, Iterator last) {
+  for (; first != last;
+       static_cast<void>(++destination), static_cast<void>(++first)) {
+    std::allocator_traits<Allocator>::construct(*alloc, destination, *first);
   }
 }
 #endif  // ABSL_HAVE_EXCEPTIONS
 }  // namespace memory_internal
-
 }  // namespace absl
 
 #endif  // ABSL_MEMORY_MEMORY_H_
diff --git a/absl/memory/memory_exception_safety_test.cc b/absl/memory/memory_exception_safety_test.cc
index fb8b561..d1f6e84 100644
--- a/absl/memory/memory_exception_safety_test.cc
+++ b/absl/memory/memory_exception_safety_test.cc
@@ -48,16 +48,5 @@
   }));
 }
 
-TEST(MemoryInternal, UninitDefaultConstructNNonTrivial) {
-  EXPECT_TRUE(testing::MakeExceptionSafetyTester()
-                  .WithInitialValue(ThrowerList{})
-                  .WithOperation([&](ThrowerList* list_ptr) {
-                    absl::memory_internal::uninitialized_default_construct_n(
-                        list_ptr->data(), kLength);
-                  })
-                  .WithInvariants([&](...) { return true; })
-                  .Test());
-}
-
 }  // namespace
 }  // namespace absl
diff --git a/absl/memory/memory_test.cc b/absl/memory/memory_test.cc
index 8ff1945..dee9b48 100644
--- a/absl/memory/memory_test.cc
+++ b/absl/memory/memory_test.cc
@@ -611,47 +611,4 @@
   EXPECT_FALSE(absl::allocator_is_nothrow<UnspecifiedAllocator>::value);
 }
 
-TEST(MemoryInternal, UninitDefaultConstructNTrivial) {
-  constexpr int kInitialValue = 123;
-  constexpr int kExpectedValue = kInitialValue;  // Expect no-op behavior
-  constexpr int len = 5;
-
-  struct TestObj {
-    int val;
-  };
-  static_assert(absl::is_trivially_default_constructible<TestObj>::value, "");
-  static_assert(absl::is_trivially_destructible<TestObj>::value, "");
-
-  TestObj objs[len];
-  for (auto& obj : objs) {
-    obj.val = kInitialValue;
-  }
-
-  absl::memory_internal::uninitialized_default_construct_n(objs, len);
-  for (auto& obj : objs) {
-    EXPECT_EQ(obj.val, kExpectedValue);
-  }
-}
-
-TEST(MemoryInternal, UninitDefaultConstructNNonTrivial) {
-  constexpr int kInitialValue = 123;
-  constexpr int kExpectedValue = 0;  // Expect value-construction behavior
-  constexpr int len = 5;
-
-  struct TestObj {
-    int val{kExpectedValue};
-  };
-  static_assert(absl::is_trivially_destructible<TestObj>::value, "");
-
-  TestObj objs[len];
-  for (auto& obj : objs) {
-    obj.val = kInitialValue;
-  }
-
-  absl::memory_internal::uninitialized_default_construct_n(objs, len);
-  for (auto& obj : objs) {
-    EXPECT_EQ(obj.val, kExpectedValue);
-  }
-}
-
 }  // namespace
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index c3e01fe..457b890 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -44,6 +44,7 @@
 namespace absl {
 
 namespace type_traits_internal {
+
 template <typename... Ts>
 struct VoidTImpl {
   using type = void;
@@ -61,6 +62,49 @@
   static constexpr size_t value = Align;
 };
 
+////////////////////////////////
+// Library Fundamentals V2 TS //
+////////////////////////////////
+
+// NOTE: The `is_detected` family of templates here differ from the library
+// fundamentals specification in that for library fundamentals, `Op<Args...>` is
+// evaluated as soon as the type `is_detected<Op, Args...>` undergoes
+// substitution, regardless of whether or not the `::value` is accessed. That
+// is inconsistent with all other standard traits and prevents lazy evaluation
+// in larger contexts (such as if the `is_detected` check is a trailing argument
+// of a `conjunction`. This implementation opts to instead be lazy in the same
+// way that the standard traits are (this "defect" of the detection idiom
+// specifications has been reported).
+
+template <class Enabler, template <class...> class Op, class... Args>
+struct is_detected_impl {
+  using type = std::false_type;
+};
+
+template <template <class...> class Op, class... Args>
+struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {
+  using type = std::true_type;
+};
+
+template <template <class...> class Op, class... Args>
+struct is_detected : is_detected_impl<void, Op, Args...>::type {};
+
+template <class Enabler, class To, template <class...> class Op, class... Args>
+struct is_detected_convertible_impl {
+  using type = std::false_type;
+};
+
+template <class To, template <class...> class Op, class... Args>
+struct is_detected_convertible_impl<
+    typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type,
+    To, Op, Args...> {
+  using type = std::true_type;
+};
+
+template <class To, template <class...> class Op, class... Args>
+struct is_detected_convertible
+    : is_detected_convertible_impl<void, To, Op, Args...>::type {};
+
 }  // namespace type_traits_internal
 
 // void_t()
@@ -263,8 +307,9 @@
 // `is_trivially_assignable<T&, const T&>`.
 template <typename T>
 struct is_trivially_copy_assignable
-    : std::integral_constant<bool, __has_trivial_assign(T) &&
-                                   std::is_copy_assignable<T>::value> {
+    : std::integral_constant<
+          bool, __has_trivial_assign(typename std::remove_reference<T>::type) &&
+                    std::is_copy_assignable<T>::value> {
 #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
  private:
   static constexpr bool compliant =
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc
index c44d1c5..81b4bd3 100644
--- a/absl/meta/type_traits_test.cc
+++ b/absl/meta/type_traits_test.cc
@@ -34,6 +34,83 @@
 
 struct Dummy {};
 
+struct ReturnType {};
+struct ConvertibleToReturnType {
+  operator ReturnType() const;  // NOLINT
+};
+
+// Unique types used as parameter types for testing the detection idiom.
+struct StructA {};
+struct StructB {};
+struct StructC {};
+
+struct TypeWithBarFunction {
+  template <class T,
+            absl::enable_if_t<std::is_same<T&&, StructA&>::value, int> = 0>
+  ReturnType bar(T&&, const StructB&, StructC&&) &&;  // NOLINT
+};
+
+struct TypeWithBarFunctionAndConvertibleReturnType {
+  template <class T,
+            absl::enable_if_t<std::is_same<T&&, StructA&>::value, int> = 0>
+  ConvertibleToReturnType bar(T&&, const StructB&, StructC&&) &&;  // NOLINT
+};
+
+template <class Class, class... Ts>
+using BarIsCallableImpl =
+    decltype(std::declval<Class>().bar(std::declval<Ts>()...));
+
+template <class Class, class... T>
+using BarIsCallable =
+    absl::type_traits_internal::is_detected<BarIsCallableImpl, Class, T...>;
+
+template <class Class, class... T>
+using BarIsCallableConv = absl::type_traits_internal::is_detected_convertible<
+    ReturnType, BarIsCallableImpl, Class, T...>;
+
+// NOTE: Test of detail type_traits_internal::is_detected.
+TEST(IsDetectedTest, BasicUsage) {
+  EXPECT_TRUE((BarIsCallable<TypeWithBarFunction, StructA&, const StructB&,
+                             StructC>::value));
+  EXPECT_TRUE(
+      (BarIsCallable<TypeWithBarFunction, StructA&, StructB&, StructC>::value));
+  EXPECT_TRUE(
+      (BarIsCallable<TypeWithBarFunction, StructA&, StructB, StructC>::value));
+
+  EXPECT_FALSE((BarIsCallable<int, StructA&, const StructB&, StructC>::value));
+  EXPECT_FALSE((BarIsCallable<TypeWithBarFunction&, StructA&, const StructB&,
+                              StructC>::value));
+  EXPECT_FALSE((BarIsCallable<TypeWithBarFunction, StructA, const StructB&,
+                              StructC>::value));
+}
+
+// NOTE: Test of detail type_traits_internal::is_detected_convertible.
+TEST(IsDetectedConvertibleTest, BasicUsage) {
+  EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunction, StructA&, const StructB&,
+                                 StructC>::value));
+  EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunction, StructA&, StructB&,
+                                 StructC>::value));
+  EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunction, StructA&, StructB,
+                                 StructC>::value));
+  EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType,
+                                 StructA&, const StructB&, StructC>::value));
+  EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType,
+                                 StructA&, StructB&, StructC>::value));
+  EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType,
+                                 StructA&, StructB, StructC>::value));
+
+  EXPECT_FALSE(
+      (BarIsCallableConv<int, StructA&, const StructB&, StructC>::value));
+  EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunction&, StructA&,
+                                  const StructB&, StructC>::value));
+  EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunction, StructA, const StructB&,
+                                  StructC>::value));
+  EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType&,
+                                  StructA&, const StructB&, StructC>::value));
+  EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType,
+                                  StructA, const StructB&, StructC>::value));
+}
+
 TEST(VoidTTest, BasicUsage) {
   StaticAssertTypeEq<void, absl::void_t<Dummy>>();
   StaticAssertTypeEq<void, absl::void_t<Dummy, Dummy, Dummy>>();
@@ -528,6 +605,10 @@
   // Verify that arrays are not trivially copy assignable
   using int10 = int[10];
   EXPECT_FALSE(absl::is_trivially_copy_assignable<int10>::value);
+
+  // Verify that references are handled correctly
+  EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial&&>::value);
+  EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial&>::value);
 }
 
 #define ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(trait_name, ...)          \
@@ -714,8 +795,8 @@
   ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int[][1]);
 
   ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int());
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(float));
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(char, ...));
+  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(float));  // NOLINT
+  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(char, ...));  // NOLINT
 }
 
 struct TypeA {};
diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h
index e4f39c3..2d131b8 100644
--- a/absl/numeric/int128.h
+++ b/absl/numeric/int128.h
@@ -31,6 +31,7 @@
 #include <cstring>
 #include <iosfwd>
 #include <limits>
+#include <utility>
 
 #include "absl/base/config.h"
 #include "absl/base/macros.h"
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 3b1e067..3a5f133 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -159,6 +159,18 @@
 )
 
 cc_test(
+    name = "ascii_benchmark",
+    srcs = ["ascii_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    tags = ["benchmark"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":strings",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
+
+cc_test(
     name = "memutil_benchmark",
     srcs = [
         "internal/memutil.h",
diff --git a/absl/strings/ascii_benchmark.cc b/absl/strings/ascii_benchmark.cc
new file mode 100644
index 0000000..8dea4b8
--- /dev/null
+++ b/absl/strings/ascii_benchmark.cc
@@ -0,0 +1,120 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/ascii.h"
+
+#include <cctype>
+#include <string>
+#include <array>
+#include <random>
+
+#include "benchmark/benchmark.h"
+
+namespace {
+
+std::array<unsigned char, 256> MakeShuffledBytes() {
+  std::array<unsigned char, 256> bytes;
+  for (size_t i = 0; i < 256; ++i) bytes[i] = static_cast<unsigned char>(i);
+  std::random_device rd;
+  std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()});
+  std::mt19937 g(seed);
+  std::shuffle(bytes.begin(), bytes.end(), g);
+  return bytes;
+}
+
+template <typename Function>
+void AsciiBenchmark(benchmark::State& state, Function f) {
+  std::array<unsigned char, 256> bytes = MakeShuffledBytes();
+  size_t sum = 0;
+  for (auto _ : state) {
+    for (unsigned char b : bytes) sum += f(b) ? 1 : 0;
+  }
+  // Make a copy of `sum` before calling `DoNotOptimize` to make sure that `sum`
+  // can be put in a CPU register and not degrade performance in the loop above.
+  size_t sum2 = sum;
+  benchmark::DoNotOptimize(sum2);
+  state.SetBytesProcessed(state.iterations() * bytes.size());
+}
+
+using StdAsciiFunction = int (*)(int);
+template <StdAsciiFunction f>
+void BM_Ascii(benchmark::State& state) {
+  AsciiBenchmark(state, f);
+}
+
+using AbslAsciiIsFunction = bool (*)(unsigned char);
+template <AbslAsciiIsFunction f>
+void BM_Ascii(benchmark::State& state) {
+  AsciiBenchmark(state, f);
+}
+
+using AbslAsciiToFunction = char (*)(unsigned char);
+template <AbslAsciiToFunction f>
+void BM_Ascii(benchmark::State& state) {
+  AsciiBenchmark(state, f);
+}
+
+inline char Noop(unsigned char b) { return static_cast<char>(b); }
+
+BENCHMARK_TEMPLATE(BM_Ascii, Noop);
+BENCHMARK_TEMPLATE(BM_Ascii, std::isalpha);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isalpha);
+BENCHMARK_TEMPLATE(BM_Ascii, std::isdigit);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isdigit);
+BENCHMARK_TEMPLATE(BM_Ascii, std::isalnum);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isalnum);
+BENCHMARK_TEMPLATE(BM_Ascii, std::isspace);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isspace);
+BENCHMARK_TEMPLATE(BM_Ascii, std::ispunct);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_ispunct);
+BENCHMARK_TEMPLATE(BM_Ascii, std::isblank);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isblank);
+BENCHMARK_TEMPLATE(BM_Ascii, std::iscntrl);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_iscntrl);
+BENCHMARK_TEMPLATE(BM_Ascii, std::isxdigit);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isxdigit);
+BENCHMARK_TEMPLATE(BM_Ascii, std::isprint);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isprint);
+BENCHMARK_TEMPLATE(BM_Ascii, std::isgraph);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isgraph);
+BENCHMARK_TEMPLATE(BM_Ascii, std::isupper);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isupper);
+BENCHMARK_TEMPLATE(BM_Ascii, std::islower);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_islower);
+BENCHMARK_TEMPLATE(BM_Ascii, isascii);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_isascii);
+BENCHMARK_TEMPLATE(BM_Ascii, std::tolower);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_tolower);
+BENCHMARK_TEMPLATE(BM_Ascii, std::toupper);
+BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_toupper);
+
+static void BM_StrToLower(benchmark::State& state) {
+  const int size = state.range(0);
+  std::string s(size, 'X');
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(absl::AsciiStrToLower(s));
+  }
+}
+BENCHMARK(BM_StrToLower)->Range(1, 1 << 20);
+
+static void BM_StrToUpper(benchmark::State& state) {
+  const int size = state.range(0);
+  std::string s(size, 'x');
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(absl::AsciiStrToUpper(s));
+  }
+}
+BENCHMARK(BM_StrToUpper)->Range(1, 1 << 20);
+
+}  // namespace
diff --git a/absl/strings/escaping.h b/absl/strings/escaping.h
index 1af0afa..7f1ab96 100644
--- a/absl/strings/escaping.h
+++ b/absl/strings/escaping.h
@@ -139,7 +139,7 @@
 
 // WebSafeBase64Escape()
 //
-// Encodes a `src` std::string into a `dest` buffer using uses '-' instead of '+' and
+// Encodes a `src` std::string into a `dest` buffer using '-' instead of '+' and
 // '_' instead of '/', and without padding. This function conforms with RFC 4648
 // section 5 (base64url).
 void WebSafeBase64Escape(absl::string_view src, std::string* dest);
diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc
index 37952b4..6176db9 100644
--- a/absl/strings/internal/str_format/float_conversion.cc
+++ b/absl/strings/internal/str_format/float_conversion.cc
@@ -153,7 +153,14 @@
 
 template <typename Float, typename Int>
 constexpr bool CanFitMantissa() {
-  return std::numeric_limits<Float>::digits <= std::numeric_limits<Int>::digits;
+  return
+#if defined(__clang__) && !defined(__SSE3__)
+      // Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289
+      // Casting from long double to uint64_t is miscompiled and drops bits.
+      (!std::is_same<Float, long double>::value ||
+       !std::is_same<Int, uint64_t>::value) &&
+#endif
+      std::numeric_limits<Float>::digits <= std::numeric_limits<Int>::digits;
 }
 
 template <typename Float>
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index 24e7138..27cc047 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -56,16 +56,11 @@
 using testing::MatchesRegex;
 
 // Number of floats to test with.
-// 10,000,000 is a reasonable default for a test that only takes a few seconds.
+// 5,000,000 is a reasonable default for a test that only takes a few seconds.
 // 1,000,000,000+ triggers checking for all possible mantissa values for
 // double-precision tests. 2,000,000,000+ triggers checking for every possible
 // single-precision float.
-#ifdef _MSC_VER
-// Use a smaller number on MSVC to avoid test time out (1 min)
 const int kFloatNumCases = 5000000;
-#else
-const int kFloatNumCases = 10000000;
-#endif
 
 // This is a slow, brute-force routine to compute the exact base-10
 // representation of a double-precision floating-point number.  It
@@ -716,8 +711,9 @@
   }
 }
 
-// feenableexcept() and fedisableexcept() are missing on Mac OS X, MSVC.
-#if defined(_MSC_VER) || defined(__APPLE__)
+// feenableexcept() and fedisableexcept() are missing on Mac OS X, MSVC,
+// and WebAssembly.
+#if defined(_MSC_VER) || defined(__APPLE__) || defined(__EMSCRIPTEN__)
 #define ABSL_MISSING_FEENABLEEXCEPT 1
 #define ABSL_MISSING_FEDISABLEEXCEPT 1
 #endif
diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc
index fe742bf..fed75fa 100644
--- a/absl/strings/str_format_test.cc
+++ b/absl/strings/str_format_test.cc
@@ -384,8 +384,8 @@
   EXPECT_EQ(StrFormat("%G", 1e10), "1E+10");
   //     a/A - lower,upper case hex    Eg: -3.0 -> "-0x1.8p+1"/"-0X1.8P+1"
 
-// On NDK r16, there is a regression in hexfloat formatting.
-#if !defined(__NDK_MAJOR__) || __NDK_MAJOR__ != 16
+// On Android platform <=21, there is a regression in hexfloat formatting.
+#if !defined(__ANDROID_API__) || __ANDROID_API__ > 21
   EXPECT_EQ(StrFormat("%.1a", -3.0), "-0x1.8p+1");  // .1 to fix MSVC output
   EXPECT_EQ(StrFormat("%.1A", -3.0), "-0X1.8P+1");  // .1 to fix MSVC output
 #endif
diff --git a/absl/strings/str_split.h b/absl/strings/str_split.h
index 1f089b9..9a7be2b 100644
--- a/absl/strings/str_split.h
+++ b/absl/strings/str_split.h
@@ -373,11 +373,11 @@
 
 // StrSplit()
 //
-// Splits a given `std::string` based on the provided `Delimiter` object,
-// returning the elements within the type specified by the caller. Optionally,
-// you may also pass a `Predicate` to `StrSplit()` indicating whether to include
-// or exclude the resulting element within the final result set. (See the
-// overviews for Delimiters and Predicates above.)
+// Splits a given std::string based on the provided `Delimiter` object, returning the
+// elements within the type specified by the caller. Optionally, you may pass a
+// `Predicate` to `StrSplit()` indicating whether to include or exclude the
+// resulting element within the final result set. (See the overviews for
+// Delimiters and Predicates above.)
 //
 // Example:
 //
diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt
index c19f572..de0d7b7 100644
--- a/absl/synchronization/CMakeLists.txt
+++ b/absl/synchronization/CMakeLists.txt
@@ -34,7 +34,7 @@
 
 
 # synchronization library
-list(APPEND SYNCHRONIZATION_SRC 
+list(APPEND SYNCHRONIZATION_SRC
   "barrier.cc"
   "blocking_counter.cc"
   "internal/create_thread_identity.cc"
diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h
index 0d132d9..bb70800 100644
--- a/absl/synchronization/internal/kernel_timeout.h
+++ b/absl/synchronization/internal/kernel_timeout.h
@@ -25,9 +25,6 @@
 #ifndef ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
 #define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
 
-#ifdef _WIN32
-#include <intsafe.h>
-#endif
 #include <time.h>
 #include <algorithm>
 #include <limits>
@@ -117,9 +114,14 @@
   // Windows. Callers should recognize that the return value is a
   // relative duration (it should be recomputed by calling this method
   // in the case of a spurious wakeup).
-  DWORD InMillisecondsFromNow() const {
+  // This header file may be included transitively by public header files,
+  // so we define our own DWORD and INFINITE instead of getting them from
+  // <intsafe.h> and <WinBase.h>.
+  typedef unsigned long DWord;  // NOLINT
+  DWord InMillisecondsFromNow() const {
+    constexpr DWord kInfinite = std::numeric_limits<DWord>::max();
     if (!has_timeout()) {
-      return INFINITE;
+      return kInfinite;
     }
     // The use of absl::Now() to convert from absolute time to
     // relative time means that absl::Now() cannot use anything that
@@ -131,10 +133,10 @@
           std::numeric_limits<int64_t>::max() - 999999u;
       uint64_t ms_from_now =
           (std::min<uint64_t>(max_nanos, ns_ - now) + 999999u) / 1000000u;
-      if (ms_from_now > std::numeric_limits<DWORD>::max()) {
-        return INFINITE;
+      if (ms_from_now > kInfinite) {
+        return kInfinite;
       }
-      return static_cast<DWORD>(ms_from_now);
+      return static_cast<DWord>(ms_from_now);
     }
     return 0;
   }
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h
index 840b9d6..83c2148 100644
--- a/absl/synchronization/mutex.h
+++ b/absl/synchronization/mutex.h
@@ -24,7 +24,7 @@
 // Unlike a `std::mutex`, the Abseil `Mutex` provides the following additional
 // features:
 //   * Conditional predicates intrinsic to the `Mutex` object
-//   * Reader/writer locks, in addition to standard exclusive/writer locks
+//   * Shared/reader locks, in addition to standard exclusive/writer locks
 //   * Deadlock detection and debug support.
 //
 // The following helper classes are also defined within this file:
@@ -290,7 +290,7 @@
   // Mutex::ReaderLockWhen()
   // Mutex::WriterLockWhen()
   //
-  // Blocks until simultaneously both `cond` is `true` and this` Mutex` can
+  // Blocks until simultaneously both `cond` is `true` and this `Mutex` can
   // be acquired, then atomically acquires this `Mutex`. `LockWhen()` is
   // logically equivalent to `*Lock(); Await();` though they may have different
   // performance characteristics.
@@ -558,7 +558,7 @@
 // WriterMutexLock
 //
 // The `WriterMutexLock` is a helper class, like `MutexLock`, which acquires and
-// releases a write (exclusive) lock on a `Mutex` va RAII.
+// releases a write (exclusive) lock on a `Mutex` via RAII.
 class SCOPED_LOCKABLE WriterMutexLock {
  public:
   explicit WriterMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu)
diff --git a/absl/synchronization/mutex_benchmark.cc b/absl/synchronization/mutex_benchmark.cc
index 30a5235..1e019e0 100644
--- a/absl/synchronization/mutex_benchmark.cc
+++ b/absl/synchronization/mutex_benchmark.cc
@@ -74,11 +74,11 @@
   mu.Unlock();
 }
 
-#ifdef THREAD_SANITIZER
-// ThreadSanitizer can't handle 8192 threads.
-constexpr int kMaxConditionWaiters = 2048;
-#else
+// Some configurations have higher thread limits than others.
+#if defined(__linux__) && !defined(THREAD_SANITIZER)
 constexpr int kMaxConditionWaiters = 8192;
+#else
+constexpr int kMaxConditionWaiters = 1024;
 #endif
 BENCHMARK(BM_ConditionWaiters)->RangePair(0, 2, 1, kMaxConditionWaiters);
 
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc
index 53b9378..b2820e2 100644
--- a/absl/synchronization/mutex_test.cc
+++ b/absl/synchronization/mutex_test.cc
@@ -29,6 +29,7 @@
 #include <vector>
 
 #include "gtest/gtest.h"
+#include "absl/base/attributes.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/sysinfo.h"
 #include "absl/memory/memory.h"
@@ -54,8 +55,8 @@
 // Hack to schedule a function to run on a thread pool thread after a
 // duration has elapsed.
 static void ScheduleAfter(absl::synchronization_internal::ThreadPool *tp,
-                          const std::function<void()> &func,
-                          absl::Duration after) {
+                          absl::Duration after,
+                          const std::function<void()> &func) {
   tp->Schedule([func, after] {
     absl::SleepFor(after);
     func();
@@ -1150,249 +1151,369 @@
 // and so never expires/passes, and one that will expire/pass in the near
 // future.
 
-// Encapsulate a Mutex-protected bool with its associated Condition/CondVar.
-class Cond {
- public:
-  explicit Cond(bool use_deadline) : use_deadline_(use_deadline), c_(&b_) {}
+static absl::Duration TimeoutTestAllowedSchedulingDelay() {
+  // Note: we use a function here because Microsoft Visual Studio fails to
+  // properly initialize constexpr static absl::Duration variables.
+  return absl::Milliseconds(150);
+}
 
-  void Set(bool v) {
-    absl::MutexLock lock(&mu_);
-    b_ = v;
+// Returns true if `actual_delay` is close enough to `expected_delay` to pass
+// the timeouts/deadlines test.  Otherwise, logs warnings and returns false.
+ABSL_MUST_USE_RESULT
+static bool DelayIsWithinBounds(absl::Duration expected_delay,
+                                absl::Duration actual_delay) {
+  bool pass = true;
+  // Do not allow the observed delay to be less than expected.  This may occur
+  // in practice due to clock skew or when the synchronization primitives use a
+  // different clock than absl::Now(), but these cases should be handled by the
+  // the retry mechanism in each TimeoutTest.
+  if (actual_delay < expected_delay) {
+    ABSL_RAW_LOG(WARNING,
+                 "Actual delay %s was too short, expected %s (difference %s)",
+                 absl::FormatDuration(actual_delay).c_str(),
+                 absl::FormatDuration(expected_delay).c_str(),
+                 absl::FormatDuration(actual_delay - expected_delay).c_str());
+    pass = false;
   }
-
-  bool AwaitWithTimeout(absl::Duration timeout) {
-    absl::MutexLock lock(&mu_);
-    return use_deadline_ ? mu_.AwaitWithDeadline(c_, absl::Now() + timeout)
-                         : mu_.AwaitWithTimeout(c_, timeout);
+  // If the expected delay is <= zero then allow a small error tolerance, since
+  // we do not expect context switches to occur during test execution.
+  // Otherwise, thread scheduling delays may be substantial in rare cases, so
+  // tolerate up to kTimeoutTestAllowedSchedulingDelay of error.
+  absl::Duration tolerance = expected_delay <= absl::ZeroDuration()
+                                 ? absl::Milliseconds(10)
+                                 : TimeoutTestAllowedSchedulingDelay();
+  if (actual_delay > expected_delay + tolerance) {
+    ABSL_RAW_LOG(WARNING,
+                 "Actual delay %s was too long, expected %s (difference %s)",
+                 absl::FormatDuration(actual_delay).c_str(),
+                 absl::FormatDuration(expected_delay).c_str(),
+                 absl::FormatDuration(actual_delay - expected_delay).c_str());
+    pass = false;
   }
+  return pass;
+}
 
-  bool LockWhenWithTimeout(absl::Duration timeout) {
-    bool b = use_deadline_ ? mu_.LockWhenWithDeadline(c_, absl::Now() + timeout)
-                           : mu_.LockWhenWithTimeout(c_, timeout);
-    mu_.Unlock();
-    return b;
-  }
+// Parameters for TimeoutTest, below.
+struct TimeoutTestParam {
+  // The file and line number (used for logging purposes only).
+  const char *from_file;
+  int from_line;
 
-  bool ReaderLockWhenWithTimeout(absl::Duration timeout) {
-    bool b = use_deadline_
-                 ? mu_.ReaderLockWhenWithDeadline(c_, absl::Now() + timeout)
-                 : mu_.ReaderLockWhenWithTimeout(c_, timeout);
-    mu_.ReaderUnlock();
-    return b;
-  }
+  // Should the absolute deadline API based on absl::Time be tested?  If false,
+  // the relative deadline API based on absl::Duration is tested.
+  bool use_absolute_deadline;
 
-  void Await() {
-    absl::MutexLock lock(&mu_);
-    mu_.Await(c_);
-  }
+  // The deadline/timeout used when calling the API being tested
+  // (e.g. Mutex::LockWhenWithDeadline).
+  absl::Duration wait_timeout;
 
-  void Signal(bool v) {
-    absl::MutexLock lock(&mu_);
-    b_ = v;
-    cv_.Signal();
-  }
+  // The delay before the condition will be set true by the test code.  If zero
+  // or negative, the condition is set true immediately (before calling the API
+  // being tested).  Otherwise, if infinite, the condition is never set true.
+  // Otherwise a closure is scheduled for the future that sets the condition
+  // true.
+  absl::Duration satisfy_condition_delay;
 
-  bool WaitWithTimeout(absl::Duration timeout) {
-    absl::MutexLock lock(&mu_);
-    absl::Time deadline = absl::Now() + timeout;
-    if (use_deadline_) {
-      while (!b_ && !cv_.WaitWithDeadline(&mu_, deadline)) {
-      }
-    } else {
-      while (!b_ && !cv_.WaitWithTimeout(&mu_, timeout)) {
-        timeout = deadline - absl::Now();  // recompute timeout
-      }
-    }
-    return b_;
-  }
+  // The expected result of the condition after the call to the API being
+  // tested. Generally `true` means the condition was true when the API returns,
+  // `false` indicates an expected timeout.
+  bool expected_result;
 
-  void Wait() {
-    absl::MutexLock lock(&mu_);
-    while (!b_) cv_.Wait(&mu_);
-  }
-
- private:
-  const bool use_deadline_;
-
-  bool b_;
-  absl::Condition c_;
-  absl::CondVar cv_;
-  absl::Mutex mu_;
+  // The expected delay before the API under test returns.  This is inherently
+  // flaky, so some slop is allowed (see `DelayIsWithinBounds` above), and the
+  // test keeps trying indefinitely until this constraint passes.
+  absl::Duration expected_delay;
 };
 
-class OperationTimer {
- public:
-  OperationTimer() : start_(absl::Now()) {}
-  absl::Duration Get() const { return absl::Now() - start_; }
+// Print a `TimeoutTestParam` to a debug log.
+std::ostream &operator<<(std::ostream &os, const TimeoutTestParam &param) {
+  return os << "from: " << param.from_file << ":" << param.from_line
+            << " use_absolute_deadline: "
+            << (param.use_absolute_deadline ? "true" : "false")
+            << " wait_timeout: " << param.wait_timeout
+            << " satisfy_condition_delay: " << param.satisfy_condition_delay
+            << " expected_result: "
+            << (param.expected_result ? "true" : "false")
+            << " expected_delay: " << param.expected_delay;
+}
 
- private:
-  const absl::Time start_;
-};
+std::string FormatString(const TimeoutTestParam &param) {
+  std::ostringstream os;
+  os << param;
+  return os.str();
+}
 
-static void CheckResults(bool exp_result, bool act_result,
-                         absl::Duration exp_duration,
-                         absl::Duration act_duration) {
-  ABSL_RAW_CHECK(exp_result == act_result, "CheckResults failed");
-  // Allow for some worse-case scheduling delay and clock skew.
-  if ((exp_duration - absl::Milliseconds(40) > act_duration) ||
-      (exp_duration + absl::Milliseconds(150) < act_duration)) {
-    ABSL_RAW_LOG(FATAL, "CheckResults failed: operation took %s, expected %s",
-                 absl::FormatDuration(act_duration).c_str(),
-                 absl::FormatDuration(exp_duration).c_str());
+// Like `thread::Executor::ScheduleAt` except:
+// a) Delays zero or negative are executed immediately in the current thread.
+// b) Infinite delays are never scheduled.
+// c) Calls this test's `ScheduleAt` helper instead of using `pool` directly.
+static void RunAfterDelay(absl::Duration delay,
+                          absl::synchronization_internal::ThreadPool *pool,
+                          const std::function<void()> &callback) {
+  if (delay <= absl::ZeroDuration()) {
+    callback();  // immediate
+  } else if (delay != absl::InfiniteDuration()) {
+    ScheduleAfter(pool, delay, callback);
   }
 }
 
-static void TestAwaitTimeout(Cond *cp, absl::Duration timeout, bool exp_result,
-                             absl::Duration exp_duration) {
-  OperationTimer t;
-  bool act_result = cp->AwaitWithTimeout(timeout);
-  CheckResults(exp_result, act_result, exp_duration, t.Get());
-}
+class TimeoutTest : public ::testing::Test,
+                    public ::testing::WithParamInterface<TimeoutTestParam> {};
 
-static void TestLockWhenTimeout(Cond *cp, absl::Duration timeout,
-                                bool exp_result, absl::Duration exp_duration) {
-  OperationTimer t;
-  bool act_result = cp->LockWhenWithTimeout(timeout);
-  CheckResults(exp_result, act_result, exp_duration, t.Get());
-}
-
-static void TestReaderLockWhenTimeout(Cond *cp, absl::Duration timeout,
-                                      bool exp_result,
-                                      absl::Duration exp_duration) {
-  OperationTimer t;
-  bool act_result = cp->ReaderLockWhenWithTimeout(timeout);
-  CheckResults(exp_result, act_result, exp_duration, t.Get());
-}
-
-static void TestWaitTimeout(Cond *cp, absl::Duration timeout, bool exp_result,
-                            absl::Duration exp_duration) {
-  OperationTimer t;
-  bool act_result = cp->WaitWithTimeout(timeout);
-  CheckResults(exp_result, act_result, exp_duration, t.Get());
-}
-
-// Tests with a negative timeout (deadline in the past), which should
-// immediately return the current state of the condition.
-static void TestNegativeTimeouts(absl::synchronization_internal::ThreadPool *tp,
-                                 Cond *cp) {
+std::vector<TimeoutTestParam> MakeTimeoutTestParamValues() {
+  // The `finite` delay is a finite, relatively short, delay.  We make it larger
+  // than our allowed scheduling delay (slop factor) to avoid confusion when
+  // diagnosing test failures.  The other constants here have clear meanings.
+  const absl::Duration finite = 3 * TimeoutTestAllowedSchedulingDelay();
+  const absl::Duration never = absl::InfiniteDuration();
   const absl::Duration negative = -absl::InfiniteDuration();
   const absl::Duration immediate = absl::ZeroDuration();
 
-  // The condition is already true:
-  cp->Set(true);
-  TestAwaitTimeout(cp, negative, true, immediate);
-  TestLockWhenTimeout(cp, negative, true, immediate);
-  TestReaderLockWhenTimeout(cp, negative, true, immediate);
-  TestWaitTimeout(cp, negative, true, immediate);
+  // Every test case is run twice; once using the absolute deadline API and once
+  // using the relative timeout API.
+  std::vector<TimeoutTestParam> values;
+  for (bool use_absolute_deadline : {false, true}) {
+    // Tests with a negative timeout (deadline in the past), which should
+    // immediately return current state of the condition.
 
-  // The condition becomes true, but the timeout has already expired:
-  const absl::Duration delay = absl::Milliseconds(200);
-  cp->Set(false);
-  ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), 3 * delay);
-  TestAwaitTimeout(cp, negative, false, immediate);
-  TestLockWhenTimeout(cp, negative, false, immediate);
-  TestReaderLockWhenTimeout(cp, negative, false, immediate);
-  cp->Await();  // wait for the scheduled Set() to complete
-  cp->Set(false);
-  ScheduleAfter(tp, std::bind(&Cond::Signal, cp, true), delay);
-  TestWaitTimeout(cp, negative, false, immediate);
-  cp->Wait();  // wait for the scheduled Signal() to complete
+    // The condition is already true:
+    values.push_back(TimeoutTestParam{
+        __FILE__, __LINE__, use_absolute_deadline,
+        negative,   // wait_timeout
+        immediate,  // satisfy_condition_delay
+        true,       // expected_result
+        immediate,  // expected_delay
+    });
 
-  // The condition never becomes true:
-  cp->Set(false);
-  TestAwaitTimeout(cp, negative, false, immediate);
-  TestLockWhenTimeout(cp, negative, false, immediate);
-  TestReaderLockWhenTimeout(cp, negative, false, immediate);
-  TestWaitTimeout(cp, negative, false, immediate);
+    // The condition becomes true, but the timeout has already expired:
+    values.push_back(TimeoutTestParam{
+        __FILE__, __LINE__, use_absolute_deadline,
+        negative,  // wait_timeout
+        finite,    // satisfy_condition_delay
+        false,     // expected_result
+        immediate  // expected_delay
+    });
+
+    // The condition never becomes true:
+    values.push_back(TimeoutTestParam{
+        __FILE__, __LINE__, use_absolute_deadline,
+        negative,  // wait_timeout
+        never,     // satisfy_condition_delay
+        false,     // expected_result
+        immediate  // expected_delay
+    });
+
+    // Tests with an infinite timeout (deadline in the infinite future), which
+    // should only return when the condition becomes true.
+
+    // The condition is already true:
+    values.push_back(TimeoutTestParam{
+        __FILE__, __LINE__, use_absolute_deadline,
+        never,      // wait_timeout
+        immediate,  // satisfy_condition_delay
+        true,       // expected_result
+        immediate   // expected_delay
+    });
+
+    // The condition becomes true before the (infinite) expiry:
+    values.push_back(TimeoutTestParam{
+        __FILE__, __LINE__, use_absolute_deadline,
+        never,   // wait_timeout
+        finite,  // satisfy_condition_delay
+        true,    // expected_result
+        finite,  // expected_delay
+    });
+
+    // Tests with a (small) finite timeout (deadline soon), with the condition
+    // becoming true both before and after its expiry.
+
+    // The condition is already true:
+    values.push_back(TimeoutTestParam{
+        __FILE__, __LINE__, use_absolute_deadline,
+        never,      // wait_timeout
+        immediate,  // satisfy_condition_delay
+        true,       // expected_result
+        immediate   // expected_delay
+    });
+
+    // The condition becomes true before the expiry:
+    values.push_back(TimeoutTestParam{
+        __FILE__, __LINE__, use_absolute_deadline,
+        finite * 2,  // wait_timeout
+        finite,      // satisfy_condition_delay
+        true,        // expected_result
+        finite       // expected_delay
+    });
+
+    // The condition becomes true, but the timeout has already expired:
+    values.push_back(TimeoutTestParam{
+        __FILE__, __LINE__, use_absolute_deadline,
+        finite,      // wait_timeout
+        finite * 2,  // satisfy_condition_delay
+        false,       // expected_result
+        finite       // expected_delay
+    });
+
+    // The condition never becomes true:
+    values.push_back(TimeoutTestParam{
+        __FILE__, __LINE__, use_absolute_deadline,
+        finite,  // wait_timeout
+        never,   // satisfy_condition_delay
+        false,   // expected_result
+        finite   // expected_delay
+    });
+  }
+  return values;
 }
 
-// Tests with an infinite timeout (deadline in the infinite future), which
-// should only return when the condition becomes true.
-static void TestInfiniteTimeouts(absl::synchronization_internal::ThreadPool *tp,
-                                 Cond *cp) {
-  const absl::Duration infinite = absl::InfiniteDuration();
-  const absl::Duration immediate = absl::ZeroDuration();
+// Instantiate `TimeoutTest` with `MakeTimeoutTestParamValues()`.
+INSTANTIATE_TEST_CASE_P(All, TimeoutTest,
+                        testing::ValuesIn(MakeTimeoutTestParamValues()));
 
-  // The condition is already true:
-  cp->Set(true);
-  TestAwaitTimeout(cp, infinite, true, immediate);
-  TestLockWhenTimeout(cp, infinite, true, immediate);
-  TestReaderLockWhenTimeout(cp, infinite, true, immediate);
-  TestWaitTimeout(cp, infinite, true, immediate);
+TEST_P(TimeoutTest, Await) {
+  const TimeoutTestParam params = GetParam();
+  ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
 
-  // The condition becomes true before the (infinite) expiry:
-  const absl::Duration delay = absl::Milliseconds(200);
-  cp->Set(false);
-  ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), delay);
-  TestAwaitTimeout(cp, infinite, true, delay);
-  cp->Set(false);
-  ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), delay);
-  TestLockWhenTimeout(cp, infinite, true, delay);
-  cp->Set(false);
-  ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), delay);
-  TestReaderLockWhenTimeout(cp, infinite, true, delay);
-  cp->Set(false);
-  ScheduleAfter(tp, std::bind(&Cond::Signal, cp, true), delay);
-  TestWaitTimeout(cp, infinite, true, delay);
+  // Because this test asserts bounds on scheduling delays it is flaky.  To
+  // compensate it loops forever until it passes.  Failures express as test
+  // timeouts, in which case the test log can be used to diagnose the issue.
+  for (int attempt = 1;; ++attempt) {
+    ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
+
+    absl::Mutex mu;
+    bool value = false;  // condition value (under mu)
+
+    std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
+        CreateDefaultPool();
+    RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
+      absl::MutexLock l(&mu);
+      value = true;
+    });
+
+    absl::MutexLock lock(&mu);
+    absl::Time start_time = absl::Now();
+    absl::Condition cond(&value);
+    bool result =
+        params.use_absolute_deadline
+            ? mu.AwaitWithDeadline(cond, start_time + params.wait_timeout)
+            : mu.AwaitWithTimeout(cond, params.wait_timeout);
+    if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
+      EXPECT_EQ(params.expected_result, result);
+      break;
+    }
+  }
 }
 
-// Tests with a (small) finite timeout (deadline soon), with the condition
-// becoming true both before and after its expiry.
-static void TestFiniteTimeouts(absl::synchronization_internal::ThreadPool *tp,
-                               Cond *cp) {
-  const absl::Duration finite = absl::Milliseconds(400);
-  const absl::Duration immediate = absl::ZeroDuration();
+TEST_P(TimeoutTest, LockWhen) {
+  const TimeoutTestParam params = GetParam();
+  ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
 
-  // The condition is already true:
-  cp->Set(true);
-  TestAwaitTimeout(cp, finite, true, immediate);
-  TestLockWhenTimeout(cp, finite, true, immediate);
-  TestReaderLockWhenTimeout(cp, finite, true, immediate);
-  TestWaitTimeout(cp, finite, true, immediate);
+  // Because this test asserts bounds on scheduling delays it is flaky.  To
+  // compensate it loops forever until it passes.  Failures express as test
+  // timeouts, in which case the test log can be used to diagnose the issue.
+  for (int attempt = 1;; ++attempt) {
+    ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
 
-  // The condition becomes true before the expiry:
-  const absl::Duration delay1 = finite / 2;
-  cp->Set(false);
-  ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), delay1);
-  TestAwaitTimeout(cp, finite, true, delay1);
-  cp->Set(false);
-  ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), delay1);
-  TestLockWhenTimeout(cp, finite, true, delay1);
-  cp->Set(false);
-  ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), delay1);
-  TestReaderLockWhenTimeout(cp, finite, true, delay1);
-  cp->Set(false);
-  ScheduleAfter(tp, std::bind(&Cond::Signal, cp, true), delay1);
-  TestWaitTimeout(cp, finite, true, delay1);
+    absl::Mutex mu;
+    bool value = false;  // condition value (under mu)
 
-  // The condition becomes true, but the timeout has already expired:
-  const absl::Duration delay2 = finite * 2;
-  cp->Set(false);
-  ScheduleAfter(tp, std::bind(&Cond::Set, cp, true), 3 * delay2);
-  TestAwaitTimeout(cp, finite, false, finite);
-  TestLockWhenTimeout(cp, finite, false, finite);
-  TestReaderLockWhenTimeout(cp, finite, false, finite);
-  cp->Await();  // wait for the scheduled Set() to complete
-  cp->Set(false);
-  ScheduleAfter(tp, std::bind(&Cond::Signal, cp, true), delay2);
-  TestWaitTimeout(cp, finite, false, finite);
-  cp->Wait();  // wait for the scheduled Signal() to complete
+    std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
+        CreateDefaultPool();
+    RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
+      absl::MutexLock l(&mu);
+      value = true;
+    });
 
-  // The condition never becomes true:
-  cp->Set(false);
-  TestAwaitTimeout(cp, finite, false, finite);
-  TestLockWhenTimeout(cp, finite, false, finite);
-  TestReaderLockWhenTimeout(cp, finite, false, finite);
-  TestWaitTimeout(cp, finite, false, finite);
+    absl::Time start_time = absl::Now();
+    absl::Condition cond(&value);
+    bool result =
+        params.use_absolute_deadline
+            ? mu.LockWhenWithDeadline(cond, start_time + params.wait_timeout)
+            : mu.LockWhenWithTimeout(cond, params.wait_timeout);
+    mu.Unlock();
+
+    if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
+      EXPECT_EQ(params.expected_result, result);
+      break;
+    }
+  }
 }
 
-TEST(Mutex, Timeouts) {
-  auto tp = CreateDefaultPool();
-  for (bool use_deadline : {false, true}) {
-    Cond cond(use_deadline);
-    TestNegativeTimeouts(tp.get(), &cond);
-    TestInfiniteTimeouts(tp.get(), &cond);
-    TestFiniteTimeouts(tp.get(), &cond);
+TEST_P(TimeoutTest, ReaderLockWhen) {
+  const TimeoutTestParam params = GetParam();
+  ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
+
+  // Because this test asserts bounds on scheduling delays it is flaky.  To
+  // compensate it loops forever until it passes.  Failures express as test
+  // timeouts, in which case the test log can be used to diagnose the issue.
+  for (int attempt = 0;; ++attempt) {
+    ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
+
+    absl::Mutex mu;
+    bool value = false;  // condition value (under mu)
+
+    std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
+        CreateDefaultPool();
+    RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
+      absl::MutexLock l(&mu);
+      value = true;
+    });
+
+    absl::Time start_time = absl::Now();
+    bool result =
+        params.use_absolute_deadline
+            ? mu.ReaderLockWhenWithDeadline(absl::Condition(&value),
+                                            start_time + params.wait_timeout)
+            : mu.ReaderLockWhenWithTimeout(absl::Condition(&value),
+                                           params.wait_timeout);
+    mu.ReaderUnlock();
+
+    if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
+      EXPECT_EQ(params.expected_result, result);
+      break;
+    }
+  }
+}
+
+TEST_P(TimeoutTest, Wait) {
+  const TimeoutTestParam params = GetParam();
+  ABSL_RAW_LOG(INFO, "Params: %s", FormatString(params).c_str());
+
+  // Because this test asserts bounds on scheduling delays it is flaky.  To
+  // compensate it loops forever until it passes.  Failures express as test
+  // timeouts, in which case the test log can be used to diagnose the issue.
+  for (int attempt = 0;; ++attempt) {
+    ABSL_RAW_LOG(INFO, "Attempt %d", attempt);
+
+    absl::Mutex mu;
+    bool value = false;  // condition value (under mu)
+    absl::CondVar cv;    // signals a change of `value`
+
+    std::unique_ptr<absl::synchronization_internal::ThreadPool> pool =
+        CreateDefaultPool();
+    RunAfterDelay(params.satisfy_condition_delay, pool.get(), [&] {
+      absl::MutexLock l(&mu);
+      value = true;
+      cv.Signal();
+    });
+
+    absl::MutexLock lock(&mu);
+    absl::Time start_time = absl::Now();
+    absl::Duration timeout = params.wait_timeout;
+    absl::Time deadline = start_time + timeout;
+    while (!value) {
+      if (params.use_absolute_deadline ? cv.WaitWithDeadline(&mu, deadline)
+                                       : cv.WaitWithTimeout(&mu, timeout)) {
+        break;  // deadline/timeout exceeded
+      }
+      timeout = deadline - absl::Now();  // recompute
+    }
+    bool result = value;  // note: `mu` is still held
+
+    if (DelayIsWithinBounds(params.expected_delay, absl::Now() - start_time)) {
+      EXPECT_EQ(params.expected_result, result);
+      break;
+    }
   }
 }
 
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel
index e793da8..c7c16d4 100644
--- a/absl/time/BUILD.bazel
+++ b/absl/time/BUILD.bazel
@@ -30,9 +30,8 @@
         "clock.cc",
         "duration.cc",
         "format.cc",
-        "internal/get_current_time_ios.inc",
+        "internal/get_current_time_chrono.inc",
         "internal/get_current_time_posix.inc",
-        "internal/get_current_time_windows.inc",
         "time.cc",
     ],
     hdrs = [
diff --git a/absl/time/BUILD.gn b/absl/time/BUILD.gn
index 24de31c..9927af8 100644
--- a/absl/time/BUILD.gn
+++ b/absl/time/BUILD.gn
@@ -14,30 +14,19 @@
   visibility = [ "*" ]
 }
 
-config("suppress_unguarded_availability") {
-  # TODO(bugs.webrtc.org/9557): Remove -Wno-unguarded-availability when
-  # abseil will support Xcode 9.0+ (it currently supports Xcode 7.3.1+
-  # which doesn't have -Wunguarded-availability and __builtin_available).
-  cflags = [
-    "-Wno-unguarded-availability",
-  ]
-}
-
 source_set("time") {
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
     "//build/config/compiler:no_chromium_code",
     "//third_party/abseil-cpp:absl_default_cflags_cc",
-    ":suppress_unguarded_availability",
   ]
   public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
   sources = [
     "clock.cc",
     "duration.cc",
     "format.cc",
-    "internal/get_current_time_ios.inc",
+    "internal/get_current_time_chrono.inc",
     "internal/get_current_time_posix.inc",
-    "internal/get_current_time_windows.inc",
     "time.cc",
   ]
   public = [
diff --git a/absl/time/clock.cc b/absl/time/clock.cc
index 772f852..74ee140 100644
--- a/absl/time/clock.cc
+++ b/absl/time/clock.cc
@@ -57,10 +57,8 @@
 #endif
 #endif
 
-#if defined(__APPLE__)
-#include "absl/time/internal/get_current_time_ios.inc"
-#elif defined(_WIN32)
-#include "absl/time/internal/get_current_time_windows.inc"
+#if defined(__APPLE__) || defined(_WIN32)
+#include "absl/time/internal/get_current_time_chrono.inc"
 #else
 #include "absl/time/internal/get_current_time_posix.inc"
 #endif
diff --git a/absl/time/clock_test.cc b/absl/time/clock_test.cc
index f143c03..707166d 100644
--- a/absl/time/clock_test.cc
+++ b/absl/time/clock_test.cc
@@ -35,36 +35,84 @@
   EXPECT_GE(after, now);
 }
 
-TEST(SleepForTest, BasicSanity) {
-  absl::Duration sleep_time = absl::Milliseconds(2500);
-  absl::Time start = absl::Now();
-  absl::SleepFor(sleep_time);
-  absl::Time end = absl::Now();
-  EXPECT_LE(sleep_time - absl::Milliseconds(100), end - start);
-  EXPECT_GE(sleep_time + absl::Milliseconds(200), end - start);
-}
+enum class AlarmPolicy { kWithoutAlarm, kWithAlarm };
 
-#ifdef ABSL_HAVE_ALARM
-// Helper for test SleepFor.
+#if defined(ABSL_HAVE_ALARM)
 bool alarm_handler_invoked = false;
+
 void AlarmHandler(int signo) {
   ASSERT_EQ(signo, SIGALRM);
   alarm_handler_invoked = true;
 }
+#endif
 
-TEST(SleepForTest, AlarmSupport) {
-  alarm_handler_invoked = false;
-  sig_t old_alarm = signal(SIGALRM, AlarmHandler);
-  alarm(2);
-  absl::Duration sleep_time = absl::Milliseconds(3500);
-  absl::Time start = absl::Now();
-  absl::SleepFor(sleep_time);
-  absl::Time end = absl::Now();
-  EXPECT_TRUE(alarm_handler_invoked);
-  EXPECT_LE(sleep_time - absl::Milliseconds(100), end - start);
-  EXPECT_GE(sleep_time + absl::Milliseconds(200), end - start);
-  signal(SIGALRM, old_alarm);
+// Does SleepFor(d) take between lower_bound and upper_bound at least
+// once between now and (now + timeout)?  If requested (and supported),
+// add an alarm for the middle of the sleep period and expect it to fire.
+bool SleepForBounded(absl::Duration d, absl::Duration lower_bound,
+                     absl::Duration upper_bound, absl::Duration timeout,
+                     AlarmPolicy alarm_policy, int* attempts) {
+  const absl::Time deadline = absl::Now() + timeout;
+  while (absl::Now() < deadline) {
+#if defined(ABSL_HAVE_ALARM)
+    sig_t old_alarm = SIG_DFL;
+    if (alarm_policy == AlarmPolicy::kWithAlarm) {
+      alarm_handler_invoked = false;
+      old_alarm = signal(SIGALRM, AlarmHandler);
+      alarm(absl::ToInt64Seconds(d / 2));
+    }
+#else
+    EXPECT_EQ(alarm_policy, AlarmPolicy::kWithoutAlarm);
+#endif
+    ++*attempts;
+    absl::Time start = absl::Now();
+    absl::SleepFor(d);
+    absl::Duration actual = absl::Now() - start;
+#if defined(ABSL_HAVE_ALARM)
+    if (alarm_policy == AlarmPolicy::kWithAlarm) {
+      signal(SIGALRM, old_alarm);
+      if (!alarm_handler_invoked) continue;
+    }
+#endif
+    if (lower_bound <= actual && actual <= upper_bound) {
+      return true;  // yes, the SleepFor() was correctly bounded
+    }
+  }
+  return false;
 }
-#endif  // ABSL_HAVE_ALARM
+
+testing::AssertionResult AssertSleepForBounded(absl::Duration d,
+                                               absl::Duration early,
+                                               absl::Duration late,
+                                               absl::Duration timeout,
+                                               AlarmPolicy alarm_policy) {
+  const absl::Duration lower_bound = d - early;
+  const absl::Duration upper_bound = d + late;
+  int attempts = 0;
+  if (SleepForBounded(d, lower_bound, upper_bound, timeout, alarm_policy,
+                      &attempts)) {
+    return testing::AssertionSuccess();
+  }
+  return testing::AssertionFailure()
+         << "SleepFor(" << d << ") did not return within [" << lower_bound
+         << ":" << upper_bound << "] in " << attempts << " attempt"
+         << (attempts == 1 ? "" : "s") << " over " << timeout
+         << (alarm_policy == AlarmPolicy::kWithAlarm ? " with" : " without")
+         << " an alarm";
+}
+
+// Tests that SleepFor() returns neither too early nor too late.
+TEST(SleepFor, Bounded) {
+  const absl::Duration d = absl::Milliseconds(2500);
+  const absl::Duration early = absl::Milliseconds(100);
+  const absl::Duration late = absl::Milliseconds(300);
+  const absl::Duration timeout = 48 * d;
+  EXPECT_TRUE(AssertSleepForBounded(d, early, late, timeout,
+                                    AlarmPolicy::kWithoutAlarm));
+#if defined(ABSL_HAVE_ALARM)
+  EXPECT_TRUE(AssertSleepForBounded(d, early, late, timeout,
+                                    AlarmPolicy::kWithAlarm));
+#endif
+}
 
 }  // namespace
diff --git a/absl/time/duration.cc b/absl/time/duration.cc
index c13fa79..f402137 100644
--- a/absl/time/duration.cc
+++ b/absl/time/duration.cc
@@ -895,13 +895,10 @@
   *d = dur;
   return true;
 }
-
 bool ParseFlag(const std::string& text, Duration* dst, std::string* ) {
   return ParseDuration(text, dst);
 }
 
-std::string UnparseFlag(Duration d) {
-  return FormatDuration(d);
-}
+std::string UnparseFlag(Duration d) { return FormatDuration(d); }
 
 }  // namespace absl
diff --git a/absl/time/duration_benchmark.cc b/absl/time/duration_benchmark.cc
index 54f89a1..d5657bd 100644
--- a/absl/time/duration_benchmark.cc
+++ b/absl/time/duration_benchmark.cc
@@ -27,47 +27,113 @@
 //
 
 void BM_Duration_Factory_Nanoseconds(benchmark::State& state) {
+  int64_t i = 0;
   while (state.KeepRunning()) {
-    benchmark::DoNotOptimize(absl::Nanoseconds(1));
+    benchmark::DoNotOptimize(absl::Nanoseconds(i));
+    i += 314159;
   }
 }
 BENCHMARK(BM_Duration_Factory_Nanoseconds);
 
 void BM_Duration_Factory_Microseconds(benchmark::State& state) {
+  int64_t i = 0;
   while (state.KeepRunning()) {
-    benchmark::DoNotOptimize(absl::Microseconds(1));
+    benchmark::DoNotOptimize(absl::Microseconds(i));
+    i += 314;
   }
 }
 BENCHMARK(BM_Duration_Factory_Microseconds);
 
 void BM_Duration_Factory_Milliseconds(benchmark::State& state) {
+  int64_t i = 0;
   while (state.KeepRunning()) {
-    benchmark::DoNotOptimize(absl::Milliseconds(1));
+    benchmark::DoNotOptimize(absl::Milliseconds(i));
+    i += 1;
   }
 }
 BENCHMARK(BM_Duration_Factory_Milliseconds);
 
 void BM_Duration_Factory_Seconds(benchmark::State& state) {
+  int64_t i = 0;
   while (state.KeepRunning()) {
-    benchmark::DoNotOptimize(absl::Seconds(1));
+    benchmark::DoNotOptimize(absl::Seconds(i));
+    i += 1;
   }
 }
 BENCHMARK(BM_Duration_Factory_Seconds);
 
 void BM_Duration_Factory_Minutes(benchmark::State& state) {
+  int64_t i = 0;
   while (state.KeepRunning()) {
-    benchmark::DoNotOptimize(absl::Minutes(1));
+    benchmark::DoNotOptimize(absl::Minutes(i));
+    i += 1;
   }
 }
 BENCHMARK(BM_Duration_Factory_Minutes);
 
 void BM_Duration_Factory_Hours(benchmark::State& state) {
+  int64_t i = 0;
   while (state.KeepRunning()) {
-    benchmark::DoNotOptimize(absl::Hours(1));
+    benchmark::DoNotOptimize(absl::Hours(i));
+    i += 1;
   }
 }
 BENCHMARK(BM_Duration_Factory_Hours);
 
+void BM_Duration_Factory_DoubleNanoseconds(benchmark::State& state) {
+  double d = 1;
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(absl::Nanoseconds(d));
+    d = d * 1.00000001 + 1;
+  }
+}
+BENCHMARK(BM_Duration_Factory_DoubleNanoseconds);
+
+void BM_Duration_Factory_DoubleMicroseconds(benchmark::State& state) {
+  double d = 1e-3;
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(absl::Microseconds(d));
+    d = d * 1.00000001 + 1e-3;
+  }
+}
+BENCHMARK(BM_Duration_Factory_DoubleMicroseconds);
+
+void BM_Duration_Factory_DoubleMilliseconds(benchmark::State& state) {
+  double d = 1e-6;
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(absl::Milliseconds(d));
+    d = d * 1.00000001 + 1e-6;
+  }
+}
+BENCHMARK(BM_Duration_Factory_DoubleMilliseconds);
+
+void BM_Duration_Factory_DoubleSeconds(benchmark::State& state) {
+  double d = 1e-9;
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(absl::Seconds(d));
+    d = d * 1.00000001 + 1e-9;
+  }
+}
+BENCHMARK(BM_Duration_Factory_DoubleSeconds);
+
+void BM_Duration_Factory_DoubleMinutes(benchmark::State& state) {
+  double d = 1e-9;
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(absl::Minutes(d));
+    d = d * 1.00000001 + 1e-9;
+  }
+}
+BENCHMARK(BM_Duration_Factory_DoubleMinutes);
+
+void BM_Duration_Factory_DoubleHours(benchmark::State& state) {
+  double d = 1e-9;
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(absl::Hours(d));
+    d = d * 1.00000001 + 1e-9;
+  }
+}
+BENCHMARK(BM_Duration_Factory_DoubleHours);
+
 //
 // Arithmetic
 //
diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc
index 704684e..7ae25dc 100644
--- a/absl/time/duration_test.cc
+++ b/absl/time/duration_test.cc
@@ -16,7 +16,9 @@
 #include <cmath>
 #include <cstdint>
 #include <ctime>
+#include <iomanip>
 #include <limits>
+#include <random>
 #include <string>
 
 #include "gmock/gmock.h"
@@ -105,22 +107,22 @@
 }
 
 TEST(Duration, ToConversion) {
-#define TEST_DURATION_CONVERSION(UNIT)                              \
-  do {                                                              \
-    const absl::Duration d = absl::UNIT(1.5);                       \
-    const absl::Duration z = absl::ZeroDuration();                  \
-    const absl::Duration inf = absl::InfiniteDuration();            \
-    const double dbl_inf = std::numeric_limits<double>::infinity(); \
-    EXPECT_EQ(kint64min, absl::ToInt64##UNIT(-inf));                \
-    EXPECT_EQ(-1, absl::ToInt64##UNIT(-d));                         \
-    EXPECT_EQ(0, absl::ToInt64##UNIT(z));                           \
-    EXPECT_EQ(1, absl::ToInt64##UNIT(d));                           \
-    EXPECT_EQ(kint64max, absl::ToInt64##UNIT(inf));                 \
-    EXPECT_EQ(-dbl_inf, absl::ToDouble##UNIT(-inf));                \
-    EXPECT_EQ(-1.5, absl::ToDouble##UNIT(-d));                      \
-    EXPECT_EQ(0, absl::ToDouble##UNIT(z));                          \
-    EXPECT_EQ(1.5, absl::ToDouble##UNIT(d));                        \
-    EXPECT_EQ(dbl_inf, absl::ToDouble##UNIT(inf));                  \
+#define TEST_DURATION_CONVERSION(UNIT)                                  \
+  do {                                                                  \
+    const absl::Duration d = absl::UNIT(1.5);                           \
+    constexpr absl::Duration z = absl::ZeroDuration();                  \
+    constexpr absl::Duration inf = absl::InfiniteDuration();            \
+    constexpr double dbl_inf = std::numeric_limits<double>::infinity(); \
+    EXPECT_EQ(kint64min, absl::ToInt64##UNIT(-inf));                    \
+    EXPECT_EQ(-1, absl::ToInt64##UNIT(-d));                             \
+    EXPECT_EQ(0, absl::ToInt64##UNIT(z));                               \
+    EXPECT_EQ(1, absl::ToInt64##UNIT(d));                               \
+    EXPECT_EQ(kint64max, absl::ToInt64##UNIT(inf));                     \
+    EXPECT_EQ(-dbl_inf, absl::ToDouble##UNIT(-inf));                    \
+    EXPECT_EQ(-1.5, absl::ToDouble##UNIT(-d));                          \
+    EXPECT_EQ(0, absl::ToDouble##UNIT(z));                              \
+    EXPECT_EQ(1.5, absl::ToDouble##UNIT(d));                            \
+    EXPECT_EQ(dbl_inf, absl::ToDouble##UNIT(inf));                      \
   } while (0)
 
   TEST_DURATION_CONVERSION(Nanoseconds);
@@ -1284,6 +1286,16 @@
   EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(0.875e-9));
   EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(1.000e-9));
 
+  EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(-0.124999999e-9));
+  EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.125e-9));
+  EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.250e-9));
+  EXPECT_EQ(-absl::Nanoseconds(1) / 2, absl::Seconds(-0.375e-9));
+  EXPECT_EQ(-absl::Nanoseconds(1) / 2, absl::Seconds(-0.500e-9));
+  EXPECT_EQ(-absl::Nanoseconds(3) / 4, absl::Seconds(-0.625e-9));
+  EXPECT_EQ(-absl::Nanoseconds(3) / 4, absl::Seconds(-0.750e-9));
+  EXPECT_EQ(-absl::Nanoseconds(1), absl::Seconds(-0.875e-9));
+  EXPECT_EQ(-absl::Nanoseconds(1), absl::Seconds(-1.000e-9));
+
   timespec ts;
   ts.tv_sec = 0;
   ts.tv_nsec = 0;
@@ -1313,6 +1325,86 @@
   EXPECT_THAT(ToTimeval(absl::Nanoseconds(2000)), TimevalMatcher(tv));
 }
 
+void VerifySameAsMul(double time_as_seconds, int* const misses) {
+  auto direct_seconds = absl::Seconds(time_as_seconds);
+  auto mul_by_one_second = time_as_seconds * absl::Seconds(1);
+  if (direct_seconds != mul_by_one_second) {
+    if (*misses > 10) return;
+    ASSERT_LE(++(*misses), 10) << "Too many errors, not reporting more.";
+    EXPECT_EQ(direct_seconds, mul_by_one_second)
+        << "given double time_as_seconds = " << std::setprecision(17)
+        << time_as_seconds;
+  }
+}
+
+// For a variety of interesting durations, we find the exact point
+// where one double converts to that duration, and the very next double
+// converts to the next duration.  For both of those points, verify that
+// Seconds(point) returns the same duration as point * Seconds(1.0)
+TEST(Duration, ToDoubleSecondsCheckEdgeCases) {
+  constexpr uint32_t kTicksPerSecond = absl::time_internal::kTicksPerSecond;
+  constexpr auto duration_tick = absl::time_internal::MakeDuration(0, 1u);
+  int misses = 0;
+  for (int64_t seconds = 0; seconds < 99; ++seconds) {
+    uint32_t tick_vals[] = {0, +999, +999999, +999999999, kTicksPerSecond - 1,
+                            0, 1000, 1000000, 1000000000, kTicksPerSecond,
+                            1, 1001, 1000001, 1000000001, kTicksPerSecond + 1,
+                            2, 1002, 1000002, 1000000002, kTicksPerSecond + 2,
+                            3, 1003, 1000003, 1000000003, kTicksPerSecond + 3,
+                            4, 1004, 1000004, 1000000004, kTicksPerSecond + 4,
+                            5, 6,    7,       8,          9};
+    for (uint32_t ticks : tick_vals) {
+      absl::Duration s_plus_t = absl::Seconds(seconds) + ticks * duration_tick;
+      for (absl::Duration d : {s_plus_t, -s_plus_t}) {
+        absl::Duration after_d = d + duration_tick;
+        EXPECT_NE(d, after_d);
+        EXPECT_EQ(after_d - d, duration_tick);
+
+        double low_edge = ToDoubleSeconds(d);
+        EXPECT_EQ(d, absl::Seconds(low_edge));
+
+        double high_edge = ToDoubleSeconds(after_d);
+        EXPECT_EQ(after_d, absl::Seconds(high_edge));
+
+        for (;;) {
+          double midpoint = low_edge + (high_edge - low_edge) / 2;
+          if (midpoint == low_edge || midpoint == high_edge) break;
+          absl::Duration mid_duration = absl::Seconds(midpoint);
+          if (mid_duration == d) {
+            low_edge = midpoint;
+          } else {
+            EXPECT_EQ(mid_duration, after_d);
+            high_edge = midpoint;
+          }
+        }
+        // Now low_edge is the highest double that converts to Duration d,
+        // and high_edge is the lowest double that converts to Duration after_d.
+        VerifySameAsMul(low_edge, &misses);
+        VerifySameAsMul(high_edge, &misses);
+      }
+    }
+  }
+}
+
+TEST(Duration, ToDoubleSecondsCheckRandom) {
+  std::random_device rd;
+  std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()});
+  std::mt19937_64 gen(seed);
+  // We want doubles distributed from 1/8ns up to 2^63, where
+  // as many values are tested from 1ns to 2ns as from 1sec to 2sec,
+  // so even distribute along a log-scale of those values, and
+  // exponentiate before using them.  (9.223377e+18 is just slightly
+  // out of bounds for absl::Duration.)
+  std::uniform_real_distribution<double> uniform(std::log(0.125e-9),
+                                                 std::log(9.223377e+18));
+  int misses = 0;
+  for (int i = 0; i < 1000000; ++i) {
+    double d = std::exp(uniform(gen));
+    VerifySameAsMul(d, &misses);
+    VerifySameAsMul(-d, &misses);
+  }
+}
+
 TEST(Duration, ConversionSaturation) {
   absl::Duration d;
 
diff --git a/absl/time/internal/get_current_time_chrono.inc b/absl/time/internal/get_current_time_chrono.inc
new file mode 100644
index 0000000..cf884a1
--- /dev/null
+++ b/absl/time/internal/get_current_time_chrono.inc
@@ -0,0 +1,29 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <chrono>
+#include <cstdint>
+
+namespace absl {
+namespace time_internal {
+
+static int64_t GetCurrentTimeNanosFromSystem() {
+  return std::chrono::duration_cast<std::chrono::nanoseconds>(
+             std::chrono::system_clock::now() -
+             std::chrono::system_clock::from_time_t(0))
+      .count();
+}
+
+}  // namespace time_internal
+}  // namespace absl
diff --git a/absl/time/internal/get_current_time_ios.inc b/absl/time/internal/get_current_time_ios.inc
deleted file mode 100644
index f3db32b..0000000
--- a/absl/time/internal/get_current_time_ios.inc
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "absl/time/clock.h"
-
-#include <sys/time.h>
-#include <ctime>
-#include <cstdint>
-
-#include "absl/base/internal/raw_logging.h"
-
-// These are not defined in the Xcode 7.3.1 SDK Headers.
-// Once we are no longer supporting Xcode 7.3.1 we can
-// remove these.
-#ifndef __WATCHOS_3_0
-#define __WATCHOS_3_0 30000
-#endif
-
-#ifndef __TVOS_10_0
-#define __TVOS_10_0 100000
-#endif
-
-#ifndef __IPHONE_10_0
-#define __IPHONE_10_0 100000
-#endif
-
-#ifndef __MAC_10_12
-#define __MAC_10_12 101200
-#endif
-
-namespace absl {
-namespace time_internal {
-
-static int64_t GetCurrentTimeNanosFromSystem() {
-#if (__MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_12) ||    \
-    (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0) || \
-    (__WATCH_OS_VERSION_MAX_ALLOWED >= __WATCHOS_3_0) ||  \
-    (__TV_OS_VERSION_MAX_ALLOWED >= __TVOS_10_0)
-  // clock_gettime_nsec_np is not defined on SDKs before Xcode 8.0.
-  // This preprocessor logic is based upon __CLOCK_AVAILABILITY in
-  // usr/include/time.h. Once we are no longer supporting Xcode 7.3.1 we can
-  // remove this #if.
-  // We must continue to check if it is defined until we are sure that ALL the
-  // platforms we are shipping on support it.
-  // clock_gettime_nsec_np is preferred because it may give higher accuracy than
-  // gettimeofday in future Apple operating systems.
-  // Currently (macOS 10.12/iOS 10.2) clock_gettime_nsec_np accuracy is
-  // microsecond accuracy (i.e. equivalent to gettimeofday).
-  if (&clock_gettime_nsec_np != nullptr) {
-    return clock_gettime_nsec_np(CLOCK_REALTIME);
-  }
-#endif
-#if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) &&            \
-     (__MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_12)) ||    \
-    (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) &&           \
-     (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0)) || \
-    (defined(__WATCH_OS_VERSION_MIN_REQUIRED) &&            \
-     (__WATCH_OS_VERSION_MIN_REQUIRED < __WATCHOS_3_0)) ||  \
-    (defined(__TV_OS_VERSION_MIN_REQUIRED) &&               \
-     (__TV_OS_VERSION_MIN_REQUIRED < __TVOS_10_0))
-  // We need this block in 2 different cases:
-  // a) where we are compiling with Xcode 7 in which case the block above
-  //    will not be compiled in, and this is the only block executed.
-  // b) where we are compiling with Xcode 8+ but supporting operating systems
-  //    that do not define clock_gettime_nsec_np, so this is in effect
-  //    an else block to the block above.
-  // This block will not be compiled if the min supported version is
-  // guaranteed to supply clock_gettime_nsec_np.
-  //
-  // Once we know that clock_gettime_nsec_np is in the SDK *AND* exists on
-  // all the platforms we support, we can remove both this block and alter the
-  // block above to just call clock_gettime_nsec_np directly.
-  const int64_t kNanosPerSecond = 1000 * 1000 * 1000;
-  const int64_t kNanosPerMicrosecond = 1000;
-  struct timeval tp;
-  ABSL_RAW_CHECK(gettimeofday(&tp, nullptr) == 0, "Failed gettimeofday");
-  return (int64_t{tp.tv_sec} * kNanosPerSecond +
-          int64_t{tp.tv_usec} * kNanosPerMicrosecond);
-#endif
-}
-
-}  // namespace time_internal
-}  // namespace absl
diff --git a/absl/time/internal/get_current_time_windows.inc b/absl/time/internal/get_current_time_windows.inc
deleted file mode 100644
index b22a9c9..0000000
--- a/absl/time/internal/get_current_time_windows.inc
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "absl/time/clock.h"
-
-#include <chrono>
-#include <cstdint>
-
-namespace absl {
-namespace time_internal {
-
-static int64_t GetCurrentTimeNanosFromSystem() {
-  return std::chrono::duration_cast<std::chrono::nanoseconds>(
-             std::chrono::system_clock::now() -
-             std::chrono::system_clock::from_time_t(0))
-      .count();
-}
-
-}  // namespace time_internal
-}  // namespace absl
diff --git a/absl/time/time.h b/absl/time/time.h
index ceec2de..c41cb89 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -50,7 +50,7 @@
 #ifndef ABSL_TIME_TIME_H_
 #define ABSL_TIME_TIME_H_
 
-#if !defined(_WIN32)
+#if !defined(_MSC_VER)
 #include <sys/time.h>
 #else
 #include <winsock2.h>
@@ -81,6 +81,7 @@
 constexpr uint32_t GetRepLo(Duration d);
 constexpr Duration MakeDuration(int64_t hi, uint32_t lo);
 constexpr Duration MakeDuration(int64_t hi, int64_t lo);
+inline Duration MakePosDoubleDuration(double n);
 constexpr int64_t kTicksPerNanosecond = 4;
 constexpr int64_t kTicksPerSecond = 1000 * 1000 * 1000 * kTicksPerNanosecond;
 template <std::intmax_t N>
@@ -295,6 +296,39 @@
 //   absl::Duration c = absl::Ceil(d, absl::Microseconds(1));   // 123457us
 Duration Ceil(Duration d, Duration unit);
 
+// InfiniteDuration()
+//
+// Returns an infinite `Duration`.  To get a `Duration` representing negative
+// infinity, use `-InfiniteDuration()`.
+//
+// Duration arithmetic overflows to +/- infinity and saturates. In general,
+// arithmetic with `Duration` infinities is similar to IEEE 754 infinities
+// except where IEEE 754 NaN would be involved, in which case +/-
+// `InfiniteDuration()` is used in place of a "nan" Duration.
+//
+// Examples:
+//
+//   constexpr absl::Duration inf = absl::InfiniteDuration();
+//   const absl::Duration d = ... any finite duration ...
+//
+//   inf == inf + inf
+//   inf == inf + d
+//   inf == inf - inf
+//   -inf == d - inf
+//
+//   inf == d * 1e100
+//   inf == inf / 2
+//   0 == d / inf
+//   INT64_MAX == inf / d
+//
+//   // Division by zero returns infinity, or INT64_MIN/MAX where appropriate.
+//   inf == d / 0
+//   INT64_MAX == d / absl::ZeroDuration()
+//
+// The examples involving the `/` operator above also apply to `IDivDuration()`
+// and `FDivDuration()`.
+constexpr Duration InfiniteDuration();
+
 // Nanoseconds()
 // Microseconds()
 // Milliseconds()
@@ -344,7 +378,13 @@
 }
 template <typename T, time_internal::EnableIfFloat<T> = 0>
 Duration Seconds(T n) {
-  return n * Seconds(1);
+  if (n >= 0) {
+    if (n >= std::numeric_limits<int64_t>::max()) return InfiniteDuration();
+    return time_internal::MakePosDoubleDuration(n);
+  } else {
+    if (n <= std::numeric_limits<int64_t>::min()) return -InfiniteDuration();
+    return -time_internal::MakePosDoubleDuration(-n);
+  }
 }
 template <typename T, time_internal::EnableIfFloat<T> = 0>
 Duration Minutes(T n) {
@@ -439,39 +479,6 @@
 std::chrono::minutes ToChronoMinutes(Duration d);
 std::chrono::hours ToChronoHours(Duration d);
 
-// InfiniteDuration()
-//
-// Returns an infinite `Duration`.  To get a `Duration` representing negative
-// infinity, use `-InfiniteDuration()`.
-//
-// Duration arithmetic overflows to +/- infinity and saturates. In general,
-// arithmetic with `Duration` infinities is similar to IEEE 754 infinities
-// except where IEEE 754 NaN would be involved, in which case +/-
-// `InfiniteDuration()` is used in place of a "nan" Duration.
-//
-// Examples:
-//
-//   constexpr absl::Duration inf = absl::InfiniteDuration();
-//   const absl::Duration d = ... any finite duration ...
-//
-//   inf == inf + inf
-//   inf == inf + d
-//   inf == inf - inf
-//   -inf == d - inf
-//
-//   inf == d * 1e100
-//   inf == inf / 2
-//   0 == d / inf
-//   INT64_MAX == inf / d
-//
-//   // Division by zero returns infinity, or INT64_MIN/MAX where appropriate.
-//   inf == d / 0
-//   INT64_MAX == d / absl::ZeroDuration()
-//
-// The examples involving the `/` operator above also apply to `IDivDuration()`
-// and `FDivDuration()`.
-constexpr Duration InfiniteDuration();
-
 // FormatDuration()
 //
 // Returns a std::string representing the duration in the form "72h3m0.5s".
@@ -492,12 +499,9 @@
 // `ZeroDuration()`.  Parses "inf" and "-inf" as +/- `InfiniteDuration()`.
 bool ParseDuration(const std::string& dur_string, Duration* d);
 
-// ParseFlag()
-//
+// Support for flag values of type Duration. Duration flags must be specified
+// in a format that is valid input for absl::ParseDuration().
 bool ParseFlag(const std::string& text, Duration* dst, std::string* error);
-
-// UnparseFlag()
-//
 std::string UnparseFlag(Duration d);
 
 // Time
@@ -991,9 +995,6 @@
 bool ParseTime(const std::string& format, const std::string& input, TimeZone tz,
                Time* time, std::string* err);
 
-// ParseFlag()
-// UnparseFlag()
-//
 // Support for flag values of type Time. Time flags must be specified in a
 // format that matches absl::RFC3339_full. For example:
 //
@@ -1114,6 +1115,18 @@
   return MakeDuration(hi, static_cast<uint32_t>(lo));
 }
 
+// Make a Duration value from a floating-point number, as long as that number
+// is in the range [ 0 .. numeric_limits<int64_t>::max ), that is, as long as
+// it's positive and can be converted to int64_t without risk of UB.
+inline Duration MakePosDoubleDuration(double n) {
+  const int64_t int_secs = static_cast<int64_t>(n);
+  const uint32_t ticks =
+      static_cast<uint32_t>((n - int_secs) * kTicksPerSecond + 0.5);
+  return ticks < kTicksPerSecond
+             ? MakeDuration(int_secs, ticks)
+             : MakeDuration(int_secs + 1, ticks - kTicksPerSecond);
+}
+
 // Creates a normalized Duration from an almost-normalized (sec,ticks)
 // pair. sec may be positive or negative.  ticks must be in the range
 // -kTicksPerSecond < *ticks < kTicksPerSecond.  If ticks is negative it
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
index 7db5e05..7708e67 100644
--- a/absl/types/internal/variant.h
+++ b/absl/types/internal/variant.h
@@ -1062,32 +1062,6 @@
   static void Overload(...);
 };
 
-////////////////////////////////
-// Library Fundamentals V2 TS //
-////////////////////////////////
-
-// TODO(calabrese): Consider moving this to absl/meta/type_traits.h
-
-// The following is a rough implementation of parts of the detection idiom.
-// It is used for the comparison operator checks.
-
-template <class Enabler, class To, template <class...> class Op, class... Args>
-struct is_detected_convertible_impl {
-  using type = std::false_type;
-};
-
-template <class To, template <class...> class Op, class... Args>
-struct is_detected_convertible_impl<
-    absl::enable_if_t<std::is_convertible<Op<Args...>, To>::value>, To, Op,
-    Args...> {
-  using type = std::true_type;
-};
-
-// NOTE: This differs from library fundamentals by being lazy.
-template <class To, template <class...> class Op, class... Args>
-struct is_detected_convertible
-    : is_detected_convertible_impl<void, To, Op, Args...>::type {};
-
 template <class T>
 using LessThanResult = decltype(std::declval<T>() < std::declval<T>());
 
@@ -1107,6 +1081,8 @@
 template <class T>
 using NotEqualResult = decltype(std::declval<T>() != std::declval<T>());
 
+using type_traits_internal::is_detected_convertible;
+
 template <class... T>
 using RequireAllHaveEqualT = absl::enable_if_t<
     absl::conjunction<is_detected_convertible<bool, EqualResult, T>...>::value,
diff --git a/absl/types/span_test.cc b/absl/types/span_test.cc
index 5a4f001..fbce7e8 100644
--- a/absl/types/span_test.cc
+++ b/absl/types/span_test.cc
@@ -288,7 +288,7 @@
 #ifdef ABSL_HAVE_EXCEPTIONS
   EXPECT_THROW(absl::MakeSpan(ramp).subspan(11, 5), std::out_of_range);
 #else
-  EXPECT_DEATH(absl::MakeSpan(ramp).subspan(11, 5), "");
+  EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).subspan(11, 5), "");
 #endif
 }
 
diff --git a/absl/types/variant.h b/absl/types/variant.h
index fd1d49a..17e0634 100644
--- a/absl/types/variant.h
+++ b/absl/types/variant.h
@@ -248,7 +248,7 @@
 //
 // Example:
 //
-//   absl::variant<int, std::string> bar = 42;
+//   absl::variant<int, std::string> foo = 42;
 //   if (absl::holds_alternative<int>(foo)) {
 //       std::cout << "The variant holds an integer";
 //   }
@@ -449,14 +449,19 @@
 //------------------------------------------------------------------------------
 template <typename T0, typename... Tn>
 class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
+  static_assert(absl::conjunction<std::is_object<T0>,
+                                  std::is_object<Tn>...>::value,
+                "Attempted to instantiate a variant containing a non-object "
+                "type.");
   // Intentionally not qualifing `negation` with `absl::` to work around a bug
   // in MSVC 2015 with inline namespace and variadic template.
-  static_assert(absl::conjunction<std::is_object<T0>, std::is_object<Tn>...,
-                                  negation<std::is_array<T0> >,
-                                  negation<std::is_array<Tn> >...,
-                                  std::is_nothrow_destructible<T0>,
+  static_assert(absl::conjunction<negation<std::is_array<T0> >,
+                                  negation<std::is_array<Tn> >...>::value,
+                "Attempted to instantiate a variant containing an array type.");
+  static_assert(absl::conjunction<std::is_nothrow_destructible<T0>,
                                   std::is_nothrow_destructible<Tn>...>::value,
-                "Attempted to instantiate a variant with an unsupported type.");
+                "Attempted to instantiate a variant containing a non-nothrow "
+                "destructible type.");
 
   friend struct variant_internal::VariantCoreAccess;
 
diff --git a/api/asyncresolverfactory.h b/api/asyncresolverfactory.h
new file mode 100644
index 0000000..96abee4
--- /dev/null
+++ b/api/asyncresolverfactory.h
@@ -0,0 +1,32 @@
+/*
+ *  Copyright 2018 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 API_ASYNCRESOLVERFACTORY_H_
+#define API_ASYNCRESOLVERFACTORY_H_
+
+#include "rtc_base/asyncresolverinterface.h"
+
+namespace webrtc {
+
+// An abstract factory for creating AsyncResolverInterfaces. This allows
+// client applications to provide WebRTC with their own mechanism for
+// performing DNS resolution.
+class AsyncResolverFactory {
+ public:
+  AsyncResolverFactory() = default;
+  virtual ~AsyncResolverFactory() = default;
+
+  // The caller should call Destroy on the returned object to delete it.
+  virtual rtc::AsyncResolverInterface* Create() = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_ASYNCRESOLVERFACTORY_H_
diff --git a/api/audio/audio_frame.h b/api/audio/audio_frame.h
index 4c9aa9c..dd6ac02 100644
--- a/api/audio/audio_frame.h
+++ b/api/audio/audio_frame.h
@@ -12,13 +12,13 @@
 #define API_AUDIO_AUDIO_FRAME_H_
 
 #include <stddef.h>
+#include <stdint.h>
 
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
-/* This class holds up to 60 ms of super-wideband (32 kHz) stereo audio. It
+/* This class holds up to 120 ms of super-wideband (32 kHz) stereo audio. It
  * allows for adding and subtracting frames while keeping track of the resulting
  * states.
  *
@@ -38,8 +38,9 @@
   // variables which should allow us to switch to constexpr and keep this a
   // header-only class.
   enum : size_t {
-    // Stereo, 32 kHz, 60 ms (2 * 32 * 60)
-    kMaxDataSizeSamples = 3840,
+    // Stereo, 32 kHz, 120 ms (2 * 32 * 120)
+    // Stereo, 192 kHz, 20 ms (2 * 192 * 20)
+    kMaxDataSizeSamples = 7680,
     kMaxDataSizeBytes = kMaxDataSizeSamples * sizeof(int16_t),
   };
 
diff --git a/api/audio/echo_canceller3_config.cc b/api/audio/echo_canceller3_config.cc
index 9af7f11..3b03d13 100644
--- a/api/audio/echo_canceller3_config.cc
+++ b/api/audio/echo_canceller3_config.cc
@@ -14,6 +14,10 @@
 EchoCanceller3Config::EchoCanceller3Config() = default;
 EchoCanceller3Config::EchoCanceller3Config(const EchoCanceller3Config& e) =
     default;
+EchoCanceller3Config::Delay::Delay() = default;
+EchoCanceller3Config::Delay::Delay(const EchoCanceller3Config::Delay& e) =
+    default;
+
 EchoCanceller3Config::Mask::Mask() = default;
 EchoCanceller3Config::Mask::Mask(const EchoCanceller3Config::Mask& m) = default;
 
@@ -21,4 +25,30 @@
 EchoCanceller3Config::EchoModel::EchoModel(
     const EchoCanceller3Config::EchoModel& e) = default;
 
+EchoCanceller3Config::Suppressor::Suppressor() = default;
+EchoCanceller3Config::Suppressor::Suppressor(
+    const EchoCanceller3Config::Suppressor& e) = default;
+
+EchoCanceller3Config::Suppressor::MaskingThresholds::MaskingThresholds(
+    float enr_transparent,
+    float enr_suppress,
+    float emr_transparent)
+    : enr_transparent(enr_transparent),
+      enr_suppress(enr_suppress),
+      emr_transparent(emr_transparent) {}
+EchoCanceller3Config::Suppressor::Suppressor::MaskingThresholds::
+    MaskingThresholds(
+        const EchoCanceller3Config::Suppressor::MaskingThresholds& e) = default;
+
+EchoCanceller3Config::Suppressor::Tuning::Tuning(MaskingThresholds mask_lf,
+                                                 MaskingThresholds mask_hf,
+                                                 float max_inc_factor,
+                                                 float max_dec_factor_lf)
+    : mask_lf(mask_lf),
+      mask_hf(mask_hf),
+      max_inc_factor(max_inc_factor),
+      max_dec_factor_lf(max_dec_factor_lf) {}
+EchoCanceller3Config::Suppressor::Tuning::Tuning(
+    const EchoCanceller3Config::Suppressor::Tuning& e) = default;
+
 }  // namespace webrtc
diff --git a/api/audio/echo_canceller3_config.h b/api/audio/echo_canceller3_config.h
index d633d04..f4ba8e9 100644
--- a/api/audio/echo_canceller3_config.h
+++ b/api/audio/echo_canceller3_config.h
@@ -20,6 +20,8 @@
   EchoCanceller3Config();
   EchoCanceller3Config(const EchoCanceller3Config& e);
   struct Delay {
+    Delay();
+    Delay(const Delay& e);
     size_t default_delay = 5;
     size_t down_sampling_factor = 4;
     size_t num_filters = 6;
@@ -29,6 +31,7 @@
     size_t hysteresis_limit_1_blocks = 1;
     size_t hysteresis_limit_2_blocks = 1;
     size_t skew_hysteresis_blocks = 3;
+    size_t fixed_capture_delay_samples = 0;
   } delay;
 
   struct Filter {
@@ -53,12 +56,16 @@
     ShadowConfiguration shadow_initial = {12, 0.9f, 20075344.f};
 
     size_t config_change_duration_blocks = 250;
+    float initial_state_seconds = 2.5f;
+    bool conservative_initial_phase = false;
+    bool enable_shadow_filter_output_usage = true;
   } filter;
 
   struct Erle {
     float min = 1.f;
     float max_l = 4.f;
     float max_h = 1.5f;
+    bool onset_detection = true;
   } erle;
 
   struct EpStrength {
@@ -107,27 +114,6 @@
     float poor_excitation_render_limit_ds8 = 20.f;
   } render_levels;
 
-  struct GainUpdates {
-    struct GainChanges {
-      float max_inc;
-      float max_dec;
-      float rate_inc;
-      float rate_dec;
-      float min_inc;
-      float min_dec;
-    };
-
-    GainChanges low_noise = {2.f, 2.f, 1.4f, 1.4f, 1.1f, 1.1f};
-    GainChanges initial = {2.f, 2.f, 1.5f, 1.5f, 1.2f, 1.2f};
-    GainChanges normal = {2.f, 2.f, 1.5f, 1.5f, 1.2f, 1.2f};
-    GainChanges saturation = {1.2f, 1.2f, 1.5f, 1.5f, 1.f, 1.f};
-    GainChanges nonlinear = {1.5f, 1.5f, 1.2f, 1.2f, 1.1f, 1.1f};
-
-    float max_inc_factor = 2.0f;
-    float max_dec_factor_lf = 0.25f;
-    float floor_first_increase = 0.00001f;
-  } gain_updates;
-
   struct EchoRemovalControl {
     struct GainRampup {
       float initial_gain = 0.0f;
@@ -156,16 +142,57 @@
   } echo_model;
 
   struct Suppressor {
-    size_t bands_with_reliable_coherence = 5;
+    Suppressor();
+    Suppressor(const Suppressor& e);
+
     size_t nearend_average_blocks = 4;
 
     struct MaskingThresholds {
+      MaskingThresholds(float enr_transparent,
+                        float enr_suppress,
+                        float emr_transparent);
+      MaskingThresholds(const MaskingThresholds& e);
       float enr_transparent;
       float enr_suppress;
       float emr_transparent;
     };
-    MaskingThresholds mask_lf = {.2f, .3f, .3f};
-    MaskingThresholds mask_hf = {.07f, .1f, .3f};
+
+    struct Tuning {
+      Tuning(MaskingThresholds mask_lf,
+             MaskingThresholds mask_hf,
+             float max_inc_factor,
+             float max_dec_factor_lf);
+      Tuning(const Tuning& e);
+      MaskingThresholds mask_lf;
+      MaskingThresholds mask_hf;
+      float max_inc_factor;
+      float max_dec_factor_lf;
+    };
+
+    Tuning normal_tuning = Tuning(MaskingThresholds(.2f, .3f, .3f),
+                                  MaskingThresholds(.07f, .1f, .3f),
+                                  2.0f,
+                                  0.25f);
+    Tuning nearend_tuning = Tuning(MaskingThresholds(.2f, .3f, .3f),
+                                   MaskingThresholds(.07f, .1f, .3f),
+                                   2.0f,
+                                   0.25f);
+
+    struct DominantNearendDetection {
+      float enr_threshold = 10.f;
+      float snr_threshold = 10.f;
+      int hold_duration = 25;
+      int trigger_threshold = 15;
+    } dominant_nearend_detection;
+
+    struct HighBandsSuppression {
+      float enr_threshold = 1.f;
+      float max_gain_during_echo = 1.f;
+    } high_bands_suppression;
+
+    float floor_first_increase = 0.00001f;
+    bool enforce_transparent = false;
+    bool enforce_empty_higher_bands = false;
   } suppressor;
 };
 }  // namespace webrtc
diff --git a/api/audio_options.h b/api/audio_options.h
index df66d36..aefc7a1 100644
--- a/api/audio_options.h
+++ b/api/audio_options.h
@@ -44,7 +44,6 @@
     SetFrom(&extended_filter_aec, change.extended_filter_aec);
     SetFrom(&delay_agnostic_aec, change.delay_agnostic_aec);
     SetFrom(&experimental_ns, change.experimental_ns);
-    SetFrom(&intelligibility_enhancer, change.intelligibility_enhancer);
     SetFrom(&residual_echo_detector, change.residual_echo_detector);
     SetFrom(&tx_agc_target_dbov, change.tx_agc_target_dbov);
     SetFrom(&tx_agc_digital_compression_gain,
@@ -74,7 +73,6 @@
            extended_filter_aec == o.extended_filter_aec &&
            delay_agnostic_aec == o.delay_agnostic_aec &&
            experimental_ns == o.experimental_ns &&
-           intelligibility_enhancer == o.intelligibility_enhancer &&
            residual_echo_detector == o.residual_echo_detector &&
            tx_agc_target_dbov == o.tx_agc_target_dbov &&
            tx_agc_digital_compression_gain ==
@@ -108,7 +106,6 @@
     ost << ToStringIfSet("extended_filter_aec", extended_filter_aec);
     ost << ToStringIfSet("delay_agnostic_aec", delay_agnostic_aec);
     ost << ToStringIfSet("experimental_ns", experimental_ns);
-    ost << ToStringIfSet("intelligibility_enhancer", intelligibility_enhancer);
     ost << ToStringIfSet("residual_echo_detector", residual_echo_detector);
     ost << ToStringIfSet("tx_agc_target_dbov", tx_agc_target_dbov);
     ost << ToStringIfSet("tx_agc_digital_compression_gain",
@@ -153,7 +150,6 @@
   absl::optional<bool> extended_filter_aec;
   absl::optional<bool> delay_agnostic_aec;
   absl::optional<bool> experimental_ns;
-  absl::optional<bool> intelligibility_enhancer;
   // Note that tx_agc_* only applies to non-experimental AGC.
   absl::optional<bool> residual_echo_detector;
   absl::optional<uint16_t> tx_agc_target_dbov;
diff --git a/api/datachannelinterface.cc b/api/datachannelinterface.cc
new file mode 100644
index 0000000..141462d
--- /dev/null
+++ b/api/datachannelinterface.cc
@@ -0,0 +1,35 @@
+/*
+ *  Copyright 2018 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 "api/datachannelinterface.h"
+
+namespace webrtc {
+
+bool DataChannelInterface::ordered() const {
+  return false;
+}
+
+uint16_t DataChannelInterface::maxRetransmitTime() const {
+  return 0;
+}
+
+uint16_t DataChannelInterface::maxRetransmits() const {
+  return 0;
+}
+
+std::string DataChannelInterface::protocol() const {
+  return std::string();
+}
+
+bool DataChannelInterface::negotiated() const {
+  return false;
+}
+
+}  // namespace webrtc
diff --git a/api/datachannelinterface.h b/api/datachannelinterface.h
index 5cbe717..a0d2b3b 100644
--- a/api/datachannelinterface.h
+++ b/api/datachannelinterface.h
@@ -88,7 +88,7 @@
   virtual void OnBufferedAmountChange(uint64_t previous_amount) {}
 
  protected:
-  virtual ~DataChannelObserver() {}
+  virtual ~DataChannelObserver() = default;
 };
 
 class DataChannelInterface : public rtc::RefCountInterface {
@@ -134,11 +134,11 @@
   // TODO(deadbeef): Remove these dummy implementations when all classes have
   // implemented these APIs. They should all just return the values the
   // DataChannel was created with.
-  virtual bool ordered() const { return false; }
-  virtual uint16_t maxRetransmitTime() const { return 0; }
-  virtual uint16_t maxRetransmits() const { return 0; }
-  virtual std::string protocol() const { return std::string(); }
-  virtual bool negotiated() const { return false; }
+  virtual bool ordered() const;
+  virtual uint16_t maxRetransmitTime() const;
+  virtual uint16_t maxRetransmits() const;
+  virtual std::string protocol() const;
+  virtual bool negotiated() const;
 
   // Returns the ID from the DataChannelInit, if it was negotiated out-of-band.
   // If negotiated in-band, this ID will be populated once the DTLS role is
@@ -170,7 +170,7 @@
   virtual bool Send(const DataBuffer& buffer) = 0;
 
  protected:
-  virtual ~DataChannelInterface() {}
+  ~DataChannelInterface() override = default;
 };
 
 }  // namespace webrtc
diff --git a/api/dtmfsenderinterface.h b/api/dtmfsenderinterface.h
index 217f9d2..b79bb31 100644
--- a/api/dtmfsenderinterface.h
+++ b/api/dtmfsenderinterface.h
@@ -29,7 +29,7 @@
   virtual void OnToneChange(const std::string& tone) = 0;
 
  protected:
-  virtual ~DtmfSenderObserverInterface() {}
+  virtual ~DtmfSenderObserverInterface() = default;
 };
 
 // The interface of native implementation of the RTCDTMFSender defined by the
@@ -85,7 +85,7 @@
   virtual int inter_tone_gap() const = 0;
 
  protected:
-  virtual ~DtmfSenderInterface() {}
+  ~DtmfSenderInterface() override = default;
 };
 
 }  // namespace webrtc
diff --git a/api/jsep.cc b/api/jsep.cc
index 1f4afba..52a60f9 100644
--- a/api/jsep.cc
+++ b/api/jsep.cc
@@ -21,4 +21,21 @@
   return 0;
 }
 
+void CreateSessionDescriptionObserver::OnFailure(RTCError error) {
+  OnFailure(error.message());
+}
+
+void CreateSessionDescriptionObserver::OnFailure(const std::string& error) {
+  OnFailure(RTCError(RTCErrorType::INTERNAL_ERROR, std::string(error)));
+}
+
+void SetSessionDescriptionObserver::OnFailure(RTCError error) {
+  std::string message(error.message());
+  OnFailure(message);
+}
+
+void SetSessionDescriptionObserver::OnFailure(const std::string& error) {
+  OnFailure(RTCError(RTCErrorType::INTERNAL_ERROR, std::string(error)));
+}
+
 }  // namespace webrtc
diff --git a/api/jsep.h b/api/jsep.h
index dbf97f6..4d4bcc0 100644
--- a/api/jsep.h
+++ b/api/jsep.h
@@ -78,6 +78,12 @@
                                           const std::string& sdp,
                                           SdpParseError* error);
 
+// Creates an IceCandidateInterface based on a parsed candidate structure.
+std::unique_ptr<IceCandidateInterface> CreateIceCandidate(
+    const std::string& sdp_mid,
+    int sdp_mline_index,
+    const cricket::Candidate& candidate);
+
 // This class represents a collection of candidates for a specific m= section.
 // Used in SessionDescriptionInterface.
 class IceCandidateCollection {
@@ -191,6 +197,14 @@
     const std::string& sdp,
     SdpParseError* error_out);
 
+// Creates a SessionDescriptionInterface based on a parsed SDP structure and the
+// given type, ID and version.
+std::unique_ptr<SessionDescriptionInterface> CreateSessionDescription(
+    SdpType type,
+    const std::string& session_id,
+    const std::string& session_version,
+    std::unique_ptr<cricket::SessionDescription> description);
+
 // CreateOffer and CreateAnswer callback interface.
 class CreateSessionDescriptionObserver : public rtc::RefCountInterface {
  public:
@@ -205,10 +219,8 @@
   // is deprecated; in order to let clients remove the old version, it has a
   // default implementation. If both versions are unimplemented, the
   // result will be a runtime error (stack overflow). This is intentional.
-  virtual void OnFailure(RTCError error) { OnFailure(error.message()); }
-  virtual void OnFailure(const std::string& error) {
-    OnFailure(RTCError(RTCErrorType::INTERNAL_ERROR, std::string(error)));
-  }
+  virtual void OnFailure(RTCError error);
+  virtual void OnFailure(const std::string& error);
 
  protected:
   ~CreateSessionDescriptionObserver() override = default;
@@ -219,13 +231,9 @@
  public:
   virtual void OnSuccess() = 0;
   // See description in CreateSessionDescriptionObserver for OnFailure.
-  virtual void OnFailure(RTCError error) {
-    std::string message(error.message());
-    OnFailure(message);
-  }
-  virtual void OnFailure(const std::string& error) {
-    OnFailure(RTCError(RTCErrorType::INTERNAL_ERROR, std::string(error)));
-  }
+  virtual void OnFailure(RTCError error);
+
+  virtual void OnFailure(const std::string& error);
 
  protected:
   ~SetSessionDescriptionObserver() override = default;
diff --git a/api/jsepicecandidate.cc b/api/jsepicecandidate.cc
new file mode 100644
index 0000000..b9ba2fe
--- /dev/null
+++ b/api/jsepicecandidate.cc
@@ -0,0 +1,83 @@
+/*
+ *  Copyright 2018 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 "api/jsepicecandidate.h"
+
+namespace webrtc {
+
+std::string JsepIceCandidate::sdp_mid() const {
+  return sdp_mid_;
+}
+
+int JsepIceCandidate::sdp_mline_index() const {
+  return sdp_mline_index_;
+}
+
+const cricket::Candidate& JsepIceCandidate::candidate() const {
+  return candidate_;
+}
+
+std::string JsepIceCandidate::server_url() const {
+  return candidate_.url();
+}
+
+JsepCandidateCollection::JsepCandidateCollection() = default;
+
+JsepCandidateCollection::JsepCandidateCollection(JsepCandidateCollection&& o)
+    : candidates_(std::move(o.candidates_)) {}
+
+size_t JsepCandidateCollection::count() const {
+  return candidates_.size();
+}
+
+void JsepCandidateCollection::add(JsepIceCandidate* candidate) {
+  candidates_.push_back(candidate);
+}
+
+const IceCandidateInterface* JsepCandidateCollection::at(size_t index) const {
+  return candidates_[index];
+}
+
+JsepCandidateCollection::~JsepCandidateCollection() {
+  for (std::vector<JsepIceCandidate*>::iterator it = candidates_.begin();
+       it != candidates_.end(); ++it) {
+    delete *it;
+  }
+}
+
+bool JsepCandidateCollection::HasCandidate(
+    const IceCandidateInterface* candidate) const {
+  bool ret = false;
+  for (std::vector<JsepIceCandidate*>::const_iterator it = candidates_.begin();
+       it != candidates_.end(); ++it) {
+    if ((*it)->sdp_mid() == candidate->sdp_mid() &&
+        (*it)->sdp_mline_index() == candidate->sdp_mline_index() &&
+        (*it)->candidate().IsEquivalent(candidate->candidate())) {
+      ret = true;
+      break;
+    }
+  }
+  return ret;
+}
+
+size_t JsepCandidateCollection::remove(const cricket::Candidate& candidate) {
+  auto iter = std::find_if(candidates_.begin(), candidates_.end(),
+                           [candidate](JsepIceCandidate* c) {
+                             return candidate.MatchesForRemoval(c->candidate());
+                           });
+  if (iter != candidates_.end()) {
+    delete *iter;
+    candidates_.erase(iter);
+    return 1;
+  }
+  return 0;
+}
+
+}  // namespace webrtc
diff --git a/api/jsepicecandidate.h b/api/jsepicecandidate.h
index 4801a04..50520fe 100644
--- a/api/jsepicecandidate.h
+++ b/api/jsepicecandidate.h
@@ -31,20 +31,20 @@
   JsepIceCandidate(const std::string& sdp_mid,
                    int sdp_mline_index,
                    const cricket::Candidate& candidate);
-  ~JsepIceCandidate();
+  ~JsepIceCandidate() override;
   // |err| may be null.
   bool Initialize(const std::string& sdp, SdpParseError* err);
   void SetCandidate(const cricket::Candidate& candidate) {
     candidate_ = candidate;
   }
 
-  virtual std::string sdp_mid() const { return sdp_mid_; }
-  virtual int sdp_mline_index() const { return sdp_mline_index_; }
-  virtual const cricket::Candidate& candidate() const { return candidate_; }
+  std::string sdp_mid() const override;
+  int sdp_mline_index() const override;
+  const cricket::Candidate& candidate() const override;
 
-  virtual std::string server_url() const { return candidate_.url(); }
+  std::string server_url() const override;
 
-  virtual bool ToString(std::string* out) const;
+  bool ToString(std::string* out) const override;
 
  private:
   std::string sdp_mid_;
@@ -57,23 +57,18 @@
 // Implementation of IceCandidateCollection which stores JsepIceCandidates.
 class JsepCandidateCollection : public IceCandidateCollection {
  public:
-  JsepCandidateCollection() {}
+  JsepCandidateCollection();
   // Move constructor is defined so that a vector of JsepCandidateCollections
   // can be resized.
-  JsepCandidateCollection(JsepCandidateCollection&& o)
-      : candidates_(std::move(o.candidates_)) {}
-  ~JsepCandidateCollection();
-  virtual size_t count() const { return candidates_.size(); }
-  virtual bool HasCandidate(const IceCandidateInterface* candidate) const;
+  JsepCandidateCollection(JsepCandidateCollection&& o);
+  ~JsepCandidateCollection() override;
+  size_t count() const override;
+  bool HasCandidate(const IceCandidateInterface* candidate) const override;
   // Adds and takes ownership of the JsepIceCandidate.
   // TODO(deadbeef): Make this use an std::unique_ptr<>, so ownership logic is
   // more clear.
-  virtual void add(JsepIceCandidate* candidate) {
-    candidates_.push_back(candidate);
-  }
-  virtual const IceCandidateInterface* at(size_t index) const {
-    return candidates_[index];
-  }
+  virtual void add(JsepIceCandidate* candidate);
+  const IceCandidateInterface* at(size_t index) const override;
   // Removes the candidate that has a matching address and protocol.
   //
   // Returns the number of candidates that were removed.
diff --git a/api/mediaconstraintsinterface.cc b/api/mediaconstraintsinterface.cc
index fb4481f..5567786 100644
--- a/api/mediaconstraintsinterface.cc
+++ b/api/mediaconstraintsinterface.cc
@@ -104,8 +104,6 @@
     "googNoiseSuppression";
 const char MediaConstraintsInterface::kExperimentalNoiseSuppression[] =
     "googNoiseSuppression2";
-const char MediaConstraintsInterface::kIntelligibilityEnhancer[] =
-    "intelligibilityEnhancer";
 const char MediaConstraintsInterface::kHighpassFilter[] = "googHighpassFilter";
 const char MediaConstraintsInterface::kTypingNoiseDetection[] =
     "googTypingNoiseDetection";
@@ -146,6 +144,9 @@
     "googCpuOveruseDetection";
 const char MediaConstraintsInterface::kPayloadPadding[] = "googPayloadPadding";
 
+const char MediaConstraintsInterface::kNumSimulcastLayers[] =
+    "googNumSimulcastLayers";
+
 // Set |value| to the value associated with the first appearance of |key|, or
 // return false if |key| is not found.
 bool MediaConstraintsInterface::Constraints::FindFirst(
@@ -238,9 +239,6 @@
   ConstraintToOptional<bool>(
       constraints, MediaConstraintsInterface::kExperimentalNoiseSuppression,
       &options->experimental_ns);
-  ConstraintToOptional<bool>(
-      constraints, MediaConstraintsInterface::kIntelligibilityEnhancer,
-      &options->intelligibility_enhancer);
   ConstraintToOptional<bool>(constraints,
                              MediaConstraintsInterface::kHighpassFilter,
                              &options->highpass_filter);
@@ -260,4 +258,55 @@
   }
 }
 
+bool CopyConstraintsIntoOfferAnswerOptions(
+    const MediaConstraintsInterface* constraints,
+    PeerConnectionInterface::RTCOfferAnswerOptions* offer_answer_options) {
+  if (!constraints) {
+    return true;
+  }
+
+  bool value = false;
+  size_t mandatory_constraints_satisfied = 0;
+
+  if (FindConstraint(constraints,
+                     MediaConstraintsInterface::kOfferToReceiveAudio, &value,
+                     &mandatory_constraints_satisfied)) {
+    offer_answer_options->offer_to_receive_audio =
+        value ? PeerConnectionInterface::RTCOfferAnswerOptions::
+                    kOfferToReceiveMediaTrue
+              : 0;
+  }
+
+  if (FindConstraint(constraints,
+                     MediaConstraintsInterface::kOfferToReceiveVideo, &value,
+                     &mandatory_constraints_satisfied)) {
+    offer_answer_options->offer_to_receive_video =
+        value ? PeerConnectionInterface::RTCOfferAnswerOptions::
+                    kOfferToReceiveMediaTrue
+              : 0;
+  }
+  if (FindConstraint(constraints,
+                     MediaConstraintsInterface::kVoiceActivityDetection, &value,
+                     &mandatory_constraints_satisfied)) {
+    offer_answer_options->voice_activity_detection = value;
+  }
+  if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value,
+                     &mandatory_constraints_satisfied)) {
+    offer_answer_options->use_rtp_mux = value;
+  }
+  if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart,
+                     &value, &mandatory_constraints_satisfied)) {
+    offer_answer_options->ice_restart = value;
+  }
+
+  int layers;
+  if (FindConstraint(constraints,
+                     MediaConstraintsInterface::kNumSimulcastLayers,
+                     &layers, &mandatory_constraints_satisfied)) {
+    offer_answer_options->num_simulcast_layers = layers;
+  }
+
+  return mandatory_constraints_satisfied == constraints->GetMandatory().size();
+}
+
 }  // namespace webrtc
diff --git a/api/mediaconstraintsinterface.h b/api/mediaconstraintsinterface.h
index 54ab706..c6a914a 100644
--- a/api/mediaconstraintsinterface.h
+++ b/api/mediaconstraintsinterface.h
@@ -13,9 +13,10 @@
 // http://www.w3.org/TR/mediacapture-streams/#mediastreamconstraints and also
 // used in WebRTC: http://dev.w3.org/2011/webrtc/editor/webrtc.html#constraints.
 
-// This interface is being deprecated in Chrome, and may be removed
-// from WebRTC too.
-// https://bugs.chromium.org/p/webrtc/issues/detail?id=5617
+// Implementation of the w3c constraints spec is the responsibility of the
+// browser. Chrome no longer uses the constraints api declared here, and it will
+// be removed from WebRTC.
+// https://bugs.chromium.org/p/webrtc/issues/detail?id=9239
 
 #ifndef API_MEDIACONSTRAINTSINTERFACE_H_
 #define API_MEDIACONSTRAINTSINTERFACE_H_
@@ -72,7 +73,6 @@
   static const char kExperimentalAutoGainControl[];   // googAutoGainControl2
   static const char kNoiseSuppression[];              // googNoiseSuppression
   static const char kExperimentalNoiseSuppression[];  // googNoiseSuppression2
-  static const char kIntelligibilityEnhancer[];       // intelligibilityEnhancer
   static const char kHighpassFilter[];                // googHighpassFilter
   static const char kTypingNoiseDetection[];  // googTypingNoiseDetection
   static const char kAudioMirroring[];        // googAudioMirroring
@@ -118,6 +118,11 @@
   // stripped by Chrome before passed down to Libjingle.
   static const char kInternalConstraintPrefix[];
 
+  // Specifies number of simulcast layers for all video tracks
+  // with a Plan B offer/answer
+  // (see RTCOfferAnswerOptions::num_simulcast_layers).
+  static const char kNumSimulcastLayers[];
+
   virtual ~MediaConstraintsInterface() = default;
 
   virtual const Constraints& GetMandatory() const = 0;
@@ -144,6 +149,10 @@
     const MediaConstraintsInterface* constraints,
     cricket::AudioOptions* options);
 
+bool CopyConstraintsIntoOfferAnswerOptions(
+    const MediaConstraintsInterface* constraints,
+    PeerConnectionInterface::RTCOfferAnswerOptions* offer_answer_options);
+
 }  // namespace webrtc
 
 #endif  // API_MEDIACONSTRAINTSINTERFACE_H_
diff --git a/api/peerconnectionfactoryproxy.h b/api/peerconnectionfactoryproxy.h
index db52083..d885cc1 100644
--- a/api/peerconnectionfactoryproxy.h
+++ b/api/peerconnectionfactoryproxy.h
@@ -31,13 +31,6 @@
 // removed.
 using PeerConnectionFactoryInterface::CreateVideoSource;
 PROXY_METHOD1(void, SetOptions, const Options&)
-PROXY_METHOD5(rtc::scoped_refptr<PeerConnectionInterface>,
-              CreatePeerConnection,
-              const PeerConnectionInterface::RTCConfiguration&,
-              const MediaConstraintsInterface*,
-              std::unique_ptr<cricket::PortAllocator>,
-              std::unique_ptr<rtc::RTCCertificateGeneratorInterface>,
-              PeerConnectionObserver*);
 PROXY_METHOD4(rtc::scoped_refptr<PeerConnectionInterface>,
               CreatePeerConnection,
               const PeerConnectionInterface::RTCConfiguration&,
diff --git a/api/peerconnectioninterface.cc b/api/peerconnectioninterface.cc
new file mode 100644
index 0000000..05aa53f
--- /dev/null
+++ b/api/peerconnectioninterface.cc
@@ -0,0 +1,250 @@
+/*
+ *  Copyright 2018 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 "api/peerconnectioninterface.h"
+
+namespace webrtc {
+
+PeerConnectionInterface::IceServer::IceServer() = default;
+PeerConnectionInterface::IceServer::IceServer(const IceServer& rhs) = default;
+PeerConnectionInterface::IceServer::~IceServer() = default;
+
+PeerConnectionInterface::RTCConfiguration::RTCConfiguration() = default;
+
+PeerConnectionInterface::RTCConfiguration::RTCConfiguration(
+    const RTCConfiguration& rhs) = default;
+
+PeerConnectionInterface::RTCConfiguration::RTCConfiguration(
+    RTCConfigurationType type) {
+  if (type == RTCConfigurationType::kAggressive) {
+    // These parameters are also defined in Java and IOS configurations,
+    // so their values may be overwritten by the Java or IOS configuration.
+    bundle_policy = kBundlePolicyMaxBundle;
+    rtcp_mux_policy = kRtcpMuxPolicyRequire;
+    ice_connection_receiving_timeout = kAggressiveIceConnectionReceivingTimeout;
+
+    // These parameters are not defined in Java or IOS configuration,
+    // so their values will not be overwritten.
+    enable_ice_renomination = true;
+    redetermine_role_on_ice_restart = false;
+  }
+}
+
+PeerConnectionInterface::RTCConfiguration::~RTCConfiguration() = default;
+
+RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
+PeerConnectionInterface::AddTrack(
+    rtc::scoped_refptr<MediaStreamTrackInterface> track,
+    const std::vector<std::string>& stream_ids) {
+  return RTCError(RTCErrorType::UNSUPPORTED_OPERATION, "Not implemented");
+}
+
+bool PeerConnectionInterface::RemoveTrack(RtpSenderInterface* sender) {
+  return RemoveTrackNew(sender).ok();
+}
+
+RTCError PeerConnectionInterface::RemoveTrackNew(
+    rtc::scoped_refptr<RtpSenderInterface> sender) {
+  return RTCError(RemoveTrack(sender) ? RTCErrorType::NONE
+                                      : RTCErrorType::INTERNAL_ERROR);
+}
+
+RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+PeerConnectionInterface::AddTransceiver(
+    rtc::scoped_refptr<MediaStreamTrackInterface> track) {
+  return RTCError(RTCErrorType::INTERNAL_ERROR, "not implemented");
+}
+
+RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+PeerConnectionInterface::AddTransceiver(
+    rtc::scoped_refptr<MediaStreamTrackInterface> track,
+    const RtpTransceiverInit& init) {
+  return RTCError(RTCErrorType::INTERNAL_ERROR, "not implemented");
+}
+
+RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+PeerConnectionInterface::AddTransceiver(cricket::MediaType media_type) {
+  return RTCError(RTCErrorType::INTERNAL_ERROR, "not implemented");
+}
+
+RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+PeerConnectionInterface::AddTransceiver(cricket::MediaType media_type,
+                                        const RtpTransceiverInit& init) {
+  return RTCError(RTCErrorType::INTERNAL_ERROR, "not implemented");
+}
+
+rtc::scoped_refptr<RtpSenderInterface> PeerConnectionInterface::CreateSender(
+    const std::string& kind,
+    const std::string& stream_id) {
+  return rtc::scoped_refptr<RtpSenderInterface>();
+}
+
+std::vector<rtc::scoped_refptr<RtpSenderInterface>>
+PeerConnectionInterface::GetSenders() const {
+  return std::vector<rtc::scoped_refptr<RtpSenderInterface>>();
+}
+
+std::vector<rtc::scoped_refptr<RtpReceiverInterface>>
+PeerConnectionInterface::GetReceivers() const {
+  return std::vector<rtc::scoped_refptr<RtpReceiverInterface>>();
+}
+
+std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
+PeerConnectionInterface::GetTransceivers() const {
+  return std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>();
+}
+
+const SessionDescriptionInterface*
+PeerConnectionInterface::current_local_description() const {
+  return nullptr;
+}
+
+const SessionDescriptionInterface*
+PeerConnectionInterface::current_remote_description() const {
+  return nullptr;
+}
+
+const SessionDescriptionInterface*
+PeerConnectionInterface::pending_local_description() const {
+  return nullptr;
+}
+
+const SessionDescriptionInterface*
+PeerConnectionInterface::pending_remote_description() const {
+  return nullptr;
+}
+
+PeerConnectionInterface::RTCConfiguration
+PeerConnectionInterface::GetConfiguration() {
+  return PeerConnectionInterface::RTCConfiguration();
+}
+
+bool PeerConnectionInterface::SetConfiguration(
+    const PeerConnectionInterface::RTCConfiguration& config,
+    RTCError* error) {
+  return false;
+}
+
+bool PeerConnectionInterface::SetConfiguration(
+    const PeerConnectionInterface::RTCConfiguration& config) {
+  return false;
+}
+
+bool PeerConnectionInterface::RemoveIceCandidates(
+    const std::vector<cricket::Candidate>& candidates) {
+  return false;
+}
+
+RTCError PeerConnectionInterface::SetBitrate(const BitrateSettings& bitrate) {
+  BitrateParameters bitrate_parameters;
+  bitrate_parameters.min_bitrate_bps = bitrate.min_bitrate_bps;
+  bitrate_parameters.current_bitrate_bps = bitrate.start_bitrate_bps;
+  bitrate_parameters.max_bitrate_bps = bitrate.max_bitrate_bps;
+  return SetBitrate(bitrate_parameters);
+}
+
+RTCError PeerConnectionInterface::SetBitrate(
+    const BitrateParameters& bitrate_parameters) {
+  BitrateSettings bitrate;
+  bitrate.min_bitrate_bps = bitrate_parameters.min_bitrate_bps;
+  bitrate.start_bitrate_bps = bitrate_parameters.current_bitrate_bps;
+  bitrate.max_bitrate_bps = bitrate_parameters.max_bitrate_bps;
+  return SetBitrate(bitrate);
+}
+
+bool PeerConnectionInterface::StartRtcEventLog(rtc::PlatformFile file,
+                                               int64_t max_size_bytes) {
+  return false;
+}
+
+bool PeerConnectionInterface::StartRtcEventLog(
+    std::unique_ptr<RtcEventLogOutput> output,
+    int64_t output_period_ms) {
+  return false;
+}
+
+PeerConnectionInterface::BitrateParameters::BitrateParameters() = default;
+
+PeerConnectionInterface::BitrateParameters::~BitrateParameters() = default;
+
+PeerConnectionDependencies::PeerConnectionDependencies(
+    PeerConnectionObserver* observer_in)
+    : observer(observer_in) {}
+
+PeerConnectionDependencies::PeerConnectionDependencies(
+    PeerConnectionDependencies&&) = default;
+
+PeerConnectionDependencies::~PeerConnectionDependencies() = default;
+
+PeerConnectionFactoryDependencies::PeerConnectionFactoryDependencies() =
+    default;
+
+PeerConnectionFactoryDependencies::PeerConnectionFactoryDependencies(
+    PeerConnectionFactoryDependencies&&) = default;
+
+PeerConnectionFactoryDependencies::~PeerConnectionFactoryDependencies() =
+    default;
+
+rtc::scoped_refptr<PeerConnectionInterface>
+PeerConnectionFactoryInterface::CreatePeerConnection(
+    const PeerConnectionInterface::RTCConfiguration& configuration,
+    const MediaConstraintsInterface* constraints,
+    std::unique_ptr<cricket::PortAllocator> allocator,
+    std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
+    PeerConnectionObserver* observer) {
+  return nullptr;
+}
+
+rtc::scoped_refptr<PeerConnectionInterface>
+PeerConnectionFactoryInterface::CreatePeerConnection(
+    const PeerConnectionInterface::RTCConfiguration& configuration,
+    std::unique_ptr<cricket::PortAllocator> allocator,
+    std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
+    PeerConnectionObserver* observer) {
+  return nullptr;
+}
+
+rtc::scoped_refptr<PeerConnectionInterface>
+PeerConnectionFactoryInterface::CreatePeerConnection(
+    const PeerConnectionInterface::RTCConfiguration& configuration,
+    PeerConnectionDependencies dependencies) {
+  return nullptr;
+}
+
+RtpCapabilities PeerConnectionFactoryInterface::GetRtpSenderCapabilities(
+    cricket::MediaType kind) const {
+  return {};
+}
+
+RtpCapabilities PeerConnectionFactoryInterface::GetRtpReceiverCapabilities(
+    cricket::MediaType kind) const {
+  return {};
+}
+
+rtc::scoped_refptr<VideoTrackSourceInterface>
+PeerConnectionFactoryInterface::CreateVideoSource(
+    std::unique_ptr<cricket::VideoCapturer> capturer) {
+  return nullptr;
+}
+
+rtc::scoped_refptr<VideoTrackSourceInterface>
+PeerConnectionFactoryInterface::CreateVideoSource(
+    std::unique_ptr<cricket::VideoCapturer> capturer,
+    const MediaConstraintsInterface* constraints) {
+  return nullptr;
+}
+
+rtc::scoped_refptr<VideoTrackSourceInterface>
+PeerConnectionFactoryInterface::CreateVideoSource(
+    cricket::VideoCapturer* capturer) {
+  return CreateVideoSource(std::unique_ptr<cricket::VideoCapturer>(capturer));
+}
+
+}  // namespace webrtc
diff --git a/api/peerconnectioninterface.h b/api/peerconnectioninterface.h
index 90a99a6..2b94ee8 100644
--- a/api/peerconnectioninterface.h
+++ b/api/peerconnectioninterface.h
@@ -72,6 +72,7 @@
 #include <utility>
 #include <vector>
 
+#include "api/asyncresolverfactory.h"
 #include "api/audio/audio_mixer.h"
 #include "api/audio_codecs/audio_decoder_factory.h"
 #include "api/audio_codecs/audio_encoder_factory.h"
@@ -102,6 +103,7 @@
 // TODO(bugs.webrtc.org/7447): We plan to provide a way to let applications
 // inject a PacketSocketFactory and/or NetworkManager, and not expose
 // PortAllocator in the PeerConnection api.
+#include "media/base/mediaengine.h"  // nogncheck
 #include "p2p/base/portallocator.h"  // nogncheck
 // TODO(nisse): The interface for bitrate allocation strategy belongs in api/.
 #include "rtc_base/bitrateallocationstrategy.h"
@@ -119,7 +121,6 @@
 }  // namespace rtc
 
 namespace cricket {
-class MediaEngineInterface;
 class WebRtcVideoDecoderFactory;
 class WebRtcVideoEncoderFactory;
 }  // namespace cricket
@@ -144,7 +145,7 @@
 
  protected:
   // Dtor protected as objects shouldn't be deleted via this interface.
-  ~StreamCollectionInterface() {}
+  ~StreamCollectionInterface() override = default;
 };
 
 class StatsObserver : public rtc::RefCountInterface {
@@ -152,7 +153,7 @@
   virtual void OnComplete(const StatsReports& reports) = 0;
 
  protected:
-  virtual ~StatsObserver() {}
+  ~StatsObserver() override = default;
 };
 
 enum class SdpSemantics { kPlanB, kUnifiedPlan };
@@ -198,6 +199,10 @@
   };
 
   struct IceServer {
+    IceServer();
+    IceServer(const IceServer&);
+    ~IceServer();
+
     // TODO(jbauch): Remove uri when all code using it has switched to urls.
     // List of URIs associated with this server. Valid formats are described
     // in RFC7064 and RFC7065, and more may be added in the future. The "host"
@@ -284,22 +289,10 @@
     // methods for all settings which are of interest to applications,
     // Chrome in particular.
 
-    RTCConfiguration() = default;
-    explicit RTCConfiguration(RTCConfigurationType type) {
-      if (type == RTCConfigurationType::kAggressive) {
-        // These parameters are also defined in Java and IOS configurations,
-        // so their values may be overwritten by the Java or IOS configuration.
-        bundle_policy = kBundlePolicyMaxBundle;
-        rtcp_mux_policy = kRtcpMuxPolicyRequire;
-        ice_connection_receiving_timeout =
-            kAggressiveIceConnectionReceivingTimeout;
-
-        // These parameters are not defined in Java or IOS configuration,
-        // so their values will not be overwritten.
-        enable_ice_renomination = true;
-        redetermine_role_on_ice_restart = false;
-      }
-    }
+    RTCConfiguration();
+    RTCConfiguration(const RTCConfiguration&);
+    explicit RTCConfiguration(RTCConfigurationType type);
+    ~RTCConfiguration();
 
     bool operator==(const RTCConfiguration& o) const;
     bool operator!=(const RTCConfiguration& o) const;
@@ -603,6 +596,9 @@
     // confused with RTCP mux (multiplexing RTP and RTCP together).
     bool use_rtp_mux = true;
 
+    // This will apply to all video tracks with a Plan B SDP offer/answer.
+    int num_simulcast_layers = 1;
+
     RTCOfferAnswerOptions() = default;
 
     RTCOfferAnswerOptions(int offer_to_receive_video,
@@ -668,11 +664,25 @@
   // - INVALID_STATE: The PeerConnection is closed.
   virtual RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrack(
       rtc::scoped_refptr<MediaStreamTrackInterface> track,
-      const std::vector<std::string>& stream_ids) = 0;
+      const std::vector<std::string>& stream_ids);
 
   // Remove an RtpSender from this PeerConnection.
   // Returns true on success.
-  virtual bool RemoveTrack(RtpSenderInterface* sender) = 0;
+  // TODO(steveanton): Replace with signature that returns RTCError.
+  virtual bool RemoveTrack(RtpSenderInterface* sender);
+
+  // Plan B semantics: Removes the RtpSender from this PeerConnection.
+  // Unified Plan semantics: Stop sending on the RtpSender and mark the
+  // corresponding RtpTransceiver direction as no longer sending.
+  //
+  // Errors:
+  // - INVALID_PARAMETER: |sender| is null or (Plan B only) the sender is not
+  //       associated with this PeerConnection.
+  // - INVALID_STATE: PeerConnection is closed.
+  // TODO(bugs.webrtc.org/9534): Rename to RemoveTrack once the other signature
+  // is removed.
+  virtual RTCError RemoveTrackNew(
+      rtc::scoped_refptr<RtpSenderInterface> sender);
 
   // AddTransceiver creates a new RtpTransceiver and adds it to the set of
   // transceivers. Adding a transceiver will cause future calls to CreateOffer
@@ -701,14 +711,10 @@
   // Errors:
   // - INVALID_PARAMETER: |track| is null.
   virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
-  AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track) {
-    return RTCError(RTCErrorType::INTERNAL_ERROR, "not implemented");
-  }
+  AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track);
   virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
   AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track,
-                 const RtpTransceiverInit& init) {
-    return RTCError(RTCErrorType::INTERNAL_ERROR, "not implemented");
-  }
+                 const RtpTransceiverInit& init);
 
   // Adds a transceiver with the given kind. Can either be MEDIA_TYPE_AUDIO or
   // MEDIA_TYPE_VIDEO.
@@ -716,14 +722,9 @@
   // - INVALID_PARAMETER: |media_type| is not MEDIA_TYPE_AUDIO or
   //                      MEDIA_TYPE_VIDEO.
   virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
-  AddTransceiver(cricket::MediaType media_type) {
-    return RTCError(RTCErrorType::INTERNAL_ERROR, "not implemented");
-  }
+  AddTransceiver(cricket::MediaType media_type);
   virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
-  AddTransceiver(cricket::MediaType media_type,
-                 const RtpTransceiverInit& init) {
-    return RTCError(RTCErrorType::INTERNAL_ERROR, "not implemented");
-  }
+  AddTransceiver(cricket::MediaType media_type, const RtpTransceiverInit& init);
 
   // TODO(deadbeef): Make these pure virtual once all subclasses implement them.
 
@@ -743,9 +744,7 @@
   // AddTransceiver instead.
   virtual rtc::scoped_refptr<RtpSenderInterface> CreateSender(
       const std::string& kind,
-      const std::string& stream_id) {
-    return rtc::scoped_refptr<RtpSenderInterface>();
-  }
+      const std::string& stream_id);
 
   // If Plan B semantics are specified, gets all RtpSenders, created either
   // through AddStream, AddTrack, or CreateSender. All senders of a specific
@@ -754,9 +753,7 @@
   // If Unified Plan semantics are specified, gets the RtpSender for each
   // RtpTransceiver.
   virtual std::vector<rtc::scoped_refptr<RtpSenderInterface>> GetSenders()
-      const {
-    return std::vector<rtc::scoped_refptr<RtpSenderInterface>>();
-  }
+      const;
 
   // If Plan B semantics are specified, gets all RtpReceivers created when a
   // remote description is applied. All receivers of a specific media type share
@@ -767,9 +764,7 @@
   // If Unified Plan semantics are specified, gets the RtpReceiver for each
   // RtpTransceiver.
   virtual std::vector<rtc::scoped_refptr<RtpReceiverInterface>> GetReceivers()
-      const {
-    return std::vector<rtc::scoped_refptr<RtpReceiverInterface>>();
-  }
+      const;
 
   // Get all RtpTransceivers, created either through AddTransceiver, AddTrack or
   // by a remote description applied with SetRemoteDescription.
@@ -777,9 +772,7 @@
   // Note: This method is only available when Unified Plan is enabled (see
   // RTCConfiguration).
   virtual std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
-  GetTransceivers() const {
-    return {};
-  }
+  GetTransceivers() const;
 
   // The legacy non-compliant GetStats() API. This correspond to the
   // callback-based version of getStats() in JavaScript. The returned metrics
@@ -844,44 +837,24 @@
 
   // A "current" description the one currently negotiated from a complete
   // offer/answer exchange.
-  virtual const SessionDescriptionInterface* current_local_description() const {
-    return nullptr;
-  }
-  virtual const SessionDescriptionInterface* current_remote_description()
-      const {
-    return nullptr;
-  }
+  virtual const SessionDescriptionInterface* current_local_description() const;
+  virtual const SessionDescriptionInterface* current_remote_description() const;
 
   // A "pending" description is one that's part of an incomplete offer/answer
   // exchange (thus, either an offer or a pranswer). Once the offer/answer
   // exchange is finished, the "pending" description will become "current".
-  virtual const SessionDescriptionInterface* pending_local_description() const {
-    return nullptr;
-  }
-  virtual const SessionDescriptionInterface* pending_remote_description()
-      const {
-    return nullptr;
-  }
+  virtual const SessionDescriptionInterface* pending_local_description() const;
+  virtual const SessionDescriptionInterface* pending_remote_description() const;
 
   // Create a new offer.
   // The CreateSessionDescriptionObserver callback will be called when done.
   virtual void CreateOffer(CreateSessionDescriptionObserver* observer,
-                           const MediaConstraintsInterface* constraints) {}
-
-  // TODO(jiayl): remove the default impl and the old interface when chromium
-  // code is updated.
-  virtual void CreateOffer(CreateSessionDescriptionObserver* observer,
-                           const RTCOfferAnswerOptions& options) {}
+                           const RTCOfferAnswerOptions& options) = 0;
 
   // Create an answer to an offer.
   // The CreateSessionDescriptionObserver callback will be called when done.
   virtual void CreateAnswer(CreateSessionDescriptionObserver* observer,
-                            const RTCOfferAnswerOptions& options) {}
-  // Deprecated - use version above.
-  // TODO(hta): Remove and remove default implementations when all callers
-  // are updated.
-  virtual void CreateAnswer(CreateSessionDescriptionObserver* observer,
-                            const MediaConstraintsInterface* constraints) {}
+                            const RTCOfferAnswerOptions& options) = 0;
 
   // Sets the local session description.
   // The PeerConnection takes the ownership of |desc| even if it fails.
@@ -903,9 +876,7 @@
 
   // TODO(deadbeef): Make this pure virtual once all Chrome subclasses of
   // PeerConnectionInterface implement it.
-  virtual PeerConnectionInterface::RTCConfiguration GetConfiguration() {
-    return PeerConnectionInterface::RTCConfiguration();
-  }
+  virtual PeerConnectionInterface::RTCConfiguration GetConfiguration();
 
   // Sets the PeerConnection's global configuration to |config|.
   //
@@ -932,15 +903,12 @@
   // PeerConnectionInterface implement it.
   virtual bool SetConfiguration(
       const PeerConnectionInterface::RTCConfiguration& config,
-      RTCError* error) {
-    return false;
-  }
+      RTCError* error);
+
   // Version without error output param for backwards compatibility.
   // TODO(deadbeef): Remove once chromium is updated.
   virtual bool SetConfiguration(
-      const PeerConnectionInterface::RTCConfiguration& config) {
-    return false;
-  }
+      const PeerConnectionInterface::RTCConfiguration& config);
 
   // Provides a remote candidate to the ICE Agent.
   // A copy of the |candidate| will be created and added to the remote
@@ -952,21 +920,13 @@
   // continual gathering, to avoid an ever-growing list of candidates as
   // networks come and go.
   virtual bool RemoveIceCandidates(
-      const std::vector<cricket::Candidate>& candidates) {
-    return false;
-  }
-
-  // Register a metric observer (used by chromium). It's reference counted, and
-  // this method takes a reference. RegisterUMAObserver(nullptr) will release
-  // the reference.
-  // TODO(deadbeef): Take argument as scoped_refptr?
-  //
-  // This method is soon to be deprecated. This no-op default implementation
-  // allows the implementations of the interface to remove this method.
-  virtual void RegisterUMAObserver(UMAObserver* observer) {}
+      const std::vector<cricket::Candidate>& candidates);
 
   // 0 <= min <= current <= max should hold for set parameters.
   struct BitrateParameters {
+    BitrateParameters();
+    ~BitrateParameters();
+
     absl::optional<int> min_bitrate_bps;
     absl::optional<int> current_bitrate_bps;
     absl::optional<int> max_bitrate_bps;
@@ -978,24 +938,12 @@
   //
   // Setting |current_bitrate_bps| will reset the current bitrate estimate
   // to the provided value.
-  virtual RTCError SetBitrate(const BitrateSettings& bitrate) {
-    BitrateParameters bitrate_parameters;
-    bitrate_parameters.min_bitrate_bps = bitrate.min_bitrate_bps;
-    bitrate_parameters.current_bitrate_bps = bitrate.start_bitrate_bps;
-    bitrate_parameters.max_bitrate_bps = bitrate.max_bitrate_bps;
-    return SetBitrate(bitrate_parameters);
-  }
+  virtual RTCError SetBitrate(const BitrateSettings& bitrate);
 
   // TODO(nisse): Deprecated - use version above. These two default
   // implementations require subclasses to implement one or the other
   // of the methods.
-  virtual RTCError SetBitrate(const BitrateParameters& bitrate_parameters) {
-    BitrateSettings bitrate;
-    bitrate.min_bitrate_bps = bitrate_parameters.min_bitrate_bps;
-    bitrate.start_bitrate_bps = bitrate_parameters.current_bitrate_bps;
-    bitrate.max_bitrate_bps = bitrate_parameters.max_bitrate_bps;
-    return SetBitrate(bitrate);
-  }
+  virtual RTCError SetBitrate(const BitrateParameters& bitrate_parameters);
 
   // Sets current strategy. If not set default WebRTC allocator will be used.
   // May be changed during an active session. The strategy
@@ -1037,19 +985,14 @@
   // automatically after 10 minutes have passed, or when the StopRtcEventLog
   // function is called.
   // TODO(eladalon): Deprecate and remove this.
-  virtual bool StartRtcEventLog(rtc::PlatformFile file,
-                                int64_t max_size_bytes) {
-    return false;
-  }
+  virtual bool StartRtcEventLog(rtc::PlatformFile file, int64_t max_size_bytes);
 
   // Start RtcEventLog using an existing output-sink. Takes ownership of
   // |output| and passes it on to Call, which will take the ownership. If the
   // operation fails the output will be closed and deallocated. The event log
   // will send serialized events to the output object every |output_period_ms|.
   virtual bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output,
-                                int64_t output_period_ms) {
-    return false;
-  }
+                                int64_t output_period_ms);
 
   // Stops logging the RtcEventLog.
   // TODO(ivoc): Make this pure virtual when Chrome is updated.
@@ -1065,7 +1008,7 @@
 
  protected:
   // Dtor protected as objects shouldn't be deleted via this interface.
-  ~PeerConnectionInterface() {}
+  ~PeerConnectionInterface() override = default;
 };
 
 // PeerConnection callback interface, used for RTCPeerConnection events.
@@ -1149,6 +1092,14 @@
   // TODO(hbos,deadbeef): Make pure virtual when all subclasses implement it.
   virtual void OnRemoveTrack(
       rtc::scoped_refptr<RtpReceiverInterface> receiver) {}
+
+  // Called when an interesting usage is detected by WebRTC.
+  // An appropriate action is to add information about the context of the
+  // PeerConnection and write the event to some kind of "interesting events"
+  // log function.
+  // The heuristics for defining what constitutes "interesting" are
+  // implementation-defined.
+  virtual void OnInterestingUsage(int usage_pattern) {}
 };
 
 // PeerConnectionDependencies holds all of PeerConnections dependencies.
@@ -1159,19 +1110,20 @@
 // PeerConnection object to be the definitive owner of the dependencies
 // lifetime making injection safer.
 struct PeerConnectionDependencies final {
-  explicit PeerConnectionDependencies(PeerConnectionObserver* observer_in)
-      : observer(observer_in) {}
+  explicit PeerConnectionDependencies(PeerConnectionObserver* observer_in);
   // This object is not copyable or assignable.
   PeerConnectionDependencies(const PeerConnectionDependencies&) = delete;
   PeerConnectionDependencies& operator=(const PeerConnectionDependencies&) =
       delete;
   // This object is only moveable.
-  PeerConnectionDependencies(PeerConnectionDependencies&&) = default;
+  PeerConnectionDependencies(PeerConnectionDependencies&&);
   PeerConnectionDependencies& operator=(PeerConnectionDependencies&&) = default;
+  ~PeerConnectionDependencies();
   // Mandatory dependencies
   PeerConnectionObserver* observer = nullptr;
   // Optional dependencies
   std::unique_ptr<cricket::PortAllocator> allocator;
+  std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_factory;
   std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator;
   std::unique_ptr<rtc::SSLCertificateVerifier> tls_cert_verifier;
 };
@@ -1183,17 +1135,17 @@
 // connection factory to take ownership of the dependency by adding a unique_ptr
 // to this structure.
 struct PeerConnectionFactoryDependencies final {
-  PeerConnectionFactoryDependencies() = default;
+  PeerConnectionFactoryDependencies();
   // This object is not copyable or assignable.
   PeerConnectionFactoryDependencies(const PeerConnectionFactoryDependencies&) =
       delete;
   PeerConnectionFactoryDependencies& operator=(
       const PeerConnectionFactoryDependencies&) = delete;
   // This object is only moveable.
-  PeerConnectionFactoryDependencies(PeerConnectionFactoryDependencies&&) =
-      default;
+  PeerConnectionFactoryDependencies(PeerConnectionFactoryDependencies&&);
   PeerConnectionFactoryDependencies& operator=(
       PeerConnectionFactoryDependencies&&) = default;
+  ~PeerConnectionFactoryDependencies();
 
   // Optional dependencies
   rtc::Thread* network_thread = nullptr;
@@ -1264,9 +1216,7 @@
   // are updated.
   virtual rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
       const PeerConnectionInterface::RTCConfiguration& configuration,
-      PeerConnectionDependencies dependencies) {
-    return nullptr;
-  }
+      PeerConnectionDependencies dependencies);
 
   // Deprecated; |allocator| and |cert_generator| may be null, in which case
   // default implementations will be used.
@@ -1281,9 +1231,8 @@
       const PeerConnectionInterface::RTCConfiguration& configuration,
       std::unique_ptr<cricket::PortAllocator> allocator,
       std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
-      PeerConnectionObserver* observer) {
-    return nullptr;
-  }
+      PeerConnectionObserver* observer);
+
   // Deprecated; should use RTCConfiguration for everything that previously
   // used constraints.
   virtual rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
@@ -1291,25 +1240,19 @@
       const MediaConstraintsInterface* constraints,
       std::unique_ptr<cricket::PortAllocator> allocator,
       std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
-      PeerConnectionObserver* observer) {
-    return nullptr;
-  }
+      PeerConnectionObserver* observer);
 
   // Returns the capabilities of an RTP sender of type |kind|.
   // If for some reason you pass in MEDIA_TYPE_DATA, returns an empty structure.
   // TODO(orphis): Make pure virtual when all subclasses implement it.
   virtual RtpCapabilities GetRtpSenderCapabilities(
-      cricket::MediaType kind) const {
-    return {};
-  }
+      cricket::MediaType kind) const;
 
   // Returns the capabilities of an RTP receiver of type |kind|.
   // If for some reason you pass in MEDIA_TYPE_DATA, returns an empty structure.
   // TODO(orphis): Make pure virtual when all subclasses implement it.
   virtual RtpCapabilities GetRtpReceiverCapabilities(
-      cricket::MediaType kind) const {
-    return {};
-  }
+      cricket::MediaType kind) const;
 
   virtual rtc::scoped_refptr<MediaStreamInterface> CreateLocalMediaStream(
       const std::string& stream_id) = 0;
@@ -1327,9 +1270,7 @@
   // TODO(deadbeef): Make pure virtual once downstream mock PC factory classes
   // are updated.
   virtual rtc::scoped_refptr<VideoTrackSourceInterface> CreateVideoSource(
-      std::unique_ptr<cricket::VideoCapturer> capturer) {
-    return nullptr;
-  }
+      std::unique_ptr<cricket::VideoCapturer> capturer);
 
   // A video source creator that allows selection of resolution and frame rate.
   // |constraints| decides video resolution and frame rate but can be null.
@@ -1339,23 +1280,12 @@
   // safely be destroyed afterwards.
   virtual rtc::scoped_refptr<VideoTrackSourceInterface> CreateVideoSource(
       std::unique_ptr<cricket::VideoCapturer> capturer,
-      const MediaConstraintsInterface* constraints) {
-    return nullptr;
-  }
+      const MediaConstraintsInterface* constraints);
 
   // Deprecated; please use the versions that take unique_ptrs above.
   // TODO(deadbeef): Remove these once safe to do so.
   virtual rtc::scoped_refptr<VideoTrackSourceInterface> CreateVideoSource(
-      cricket::VideoCapturer* capturer) {
-    return CreateVideoSource(std::unique_ptr<cricket::VideoCapturer>(capturer));
-  }
-  virtual rtc::scoped_refptr<VideoTrackSourceInterface> CreateVideoSource(
-      cricket::VideoCapturer* capturer,
-      const MediaConstraintsInterface* constraints) {
-    return CreateVideoSource(std::unique_ptr<cricket::VideoCapturer>(capturer),
-                             constraints);
-  }
-
+      cricket::VideoCapturer* capturer);
   // Creates a new local VideoTrack. The same |source| can be used in several
   // tracks.
   virtual rtc::scoped_refptr<VideoTrackInterface> CreateVideoTrack(
@@ -1383,9 +1313,10 @@
   // Dtor and ctor protected as objects shouldn't be created or deleted via
   // this interface.
   PeerConnectionFactoryInterface() {}
-  ~PeerConnectionFactoryInterface() {}  // NOLINT
+  ~PeerConnectionFactoryInterface() override = default;
 };
 
+#if defined(USE_BUILTIN_SW_CODECS)
 // Create a new instance of PeerConnectionFactoryInterface.
 //
 // This method relies on the thread it's called on as the "signaling thread"
@@ -1462,6 +1393,7 @@
     std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory,
     std::unique_ptr<NetworkControllerFactoryInterface>
         network_controller_factory = nullptr);
+#endif
 
 // Create a new instance of PeerConnectionFactoryInterface with optional video
 // codec factories. These video factories represents all video codecs, i.e. no
@@ -1480,6 +1412,7 @@
     rtc::scoped_refptr<AudioMixer> audio_mixer,
     rtc::scoped_refptr<AudioProcessing> audio_processing);
 
+#if defined(USE_BUILTIN_SW_CODECS)
 // Create a new instance of PeerConnectionFactoryInterface with external audio
 // mixer.
 //
@@ -1512,6 +1445,7 @@
       default_adm, audio_encoder_factory, audio_decoder_factory,
       video_encoder_factory, video_decoder_factory);
 }
+#endif
 
 // This is a lower-level version of the CreatePeerConnectionFactory functions
 // above. It's implemented in the "peerconnection" build target, whereas the
diff --git a/api/peerconnectionproxy.h b/api/peerconnectionproxy.h
index 6855975..6b66bcc 100644
--- a/api/peerconnectionproxy.h
+++ b/api/peerconnectionproxy.h
@@ -88,14 +88,6 @@
 PROXY_METHOD2(void,
               CreateOffer,
               CreateSessionDescriptionObserver*,
-              const MediaConstraintsInterface*)
-PROXY_METHOD2(void,
-              CreateAnswer,
-              CreateSessionDescriptionObserver*,
-              const MediaConstraintsInterface*)
-PROXY_METHOD2(void,
-              CreateOffer,
-              CreateSessionDescriptionObserver*,
               const RTCOfferAnswerOptions&)
 PROXY_METHOD2(void,
               CreateAnswer,
@@ -127,7 +119,6 @@
               const std::vector<cricket::Candidate>&);
 PROXY_METHOD1(void, SetAudioPlayout, bool)
 PROXY_METHOD1(void, SetAudioRecording, bool)
-PROXY_METHOD1(void, RegisterUMAObserver, UMAObserver*)
 PROXY_METHOD1(RTCError, SetBitrate, const BitrateSettings&);
 PROXY_METHOD1(void,
               SetBitrateAllocationStrategy,
diff --git a/api/rtp_headers.h b/api/rtp_headers.h
index ded6c4b..c762534 100644
--- a/api/rtp_headers.h
+++ b/api/rtp_headers.h
@@ -25,7 +25,6 @@
 #include "common_types.h"  // NOLINT(build/include)
 #include "rtc_base/checks.h"
 #include "rtc_base/deprecation.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -40,7 +39,14 @@
   // maximum length that can be encoded with one-byte header extensions.
   static constexpr size_t kMaxSize = 16;
 
-  static bool IsLegalName(rtc::ArrayView<const char> name);
+  static bool IsLegalMidName(rtc::ArrayView<const char> name);
+  static bool IsLegalRsidName(rtc::ArrayView<const char> name);
+
+  // TODO(bugs.webrtc.org/9537): Deprecate and remove when third parties have
+  // migrated to "IsLegalRsidName".
+  static bool IsLegalName(rtc::ArrayView<const char> name) {
+    return IsLegalRsidName(name);
+  }
 
   StringRtpHeaderExtension() { value_[0] = 0; }
   explicit StringRtpHeaderExtension(rtc::ArrayView<const char> value) {
diff --git a/api/rtpparameters.cc b/api/rtpparameters.cc
index 5a873de..62ca3fc 100644
--- a/api/rtpparameters.cc
+++ b/api/rtpparameters.cc
@@ -19,17 +19,18 @@
 
 const double kDefaultBitratePriority = 1.0;
 
-RtcpFeedback::RtcpFeedback() {}
+RtcpFeedback::RtcpFeedback() = default;
 RtcpFeedback::RtcpFeedback(RtcpFeedbackType type) : type(type) {}
 RtcpFeedback::RtcpFeedback(RtcpFeedbackType type,
                            RtcpFeedbackMessageType message_type)
     : type(type), message_type(message_type) {}
-RtcpFeedback::~RtcpFeedback() {}
+RtcpFeedback::RtcpFeedback(const RtcpFeedback& rhs) = default;
+RtcpFeedback::~RtcpFeedback() = default;
 
-RtpCodecCapability::RtpCodecCapability() {}
-RtpCodecCapability::~RtpCodecCapability() {}
+RtpCodecCapability::RtpCodecCapability() = default;
+RtpCodecCapability::~RtpCodecCapability() = default;
 
-RtpHeaderExtensionCapability::RtpHeaderExtensionCapability() {}
+RtpHeaderExtensionCapability::RtpHeaderExtensionCapability() = default;
 RtpHeaderExtensionCapability::RtpHeaderExtensionCapability(
     const std::string& uri)
     : uri(uri) {}
@@ -37,39 +38,46 @@
     const std::string& uri,
     int preferred_id)
     : uri(uri), preferred_id(preferred_id) {}
-RtpHeaderExtensionCapability::~RtpHeaderExtensionCapability() {}
+RtpHeaderExtensionCapability::~RtpHeaderExtensionCapability() = default;
 
-RtpExtension::RtpExtension() {}
+RtpExtension::RtpExtension() = default;
 RtpExtension::RtpExtension(const std::string& uri, int id) : uri(uri), id(id) {}
 RtpExtension::RtpExtension(const std::string& uri, int id, bool encrypt)
     : uri(uri), id(id), encrypt(encrypt) {}
-RtpExtension::~RtpExtension() {}
+RtpExtension::~RtpExtension() = default;
 
-RtpFecParameters::RtpFecParameters() {}
+RtpFecParameters::RtpFecParameters() = default;
 RtpFecParameters::RtpFecParameters(FecMechanism mechanism)
     : mechanism(mechanism) {}
 RtpFecParameters::RtpFecParameters(FecMechanism mechanism, uint32_t ssrc)
     : ssrc(ssrc), mechanism(mechanism) {}
-RtpFecParameters::~RtpFecParameters() {}
+RtpFecParameters::RtpFecParameters(const RtpFecParameters& rhs) = default;
+RtpFecParameters::~RtpFecParameters() = default;
 
-RtpRtxParameters::RtpRtxParameters() {}
+RtpRtxParameters::RtpRtxParameters() = default;
 RtpRtxParameters::RtpRtxParameters(uint32_t ssrc) : ssrc(ssrc) {}
-RtpRtxParameters::~RtpRtxParameters() {}
+RtpRtxParameters::RtpRtxParameters(const RtpRtxParameters& rhs) = default;
+RtpRtxParameters::~RtpRtxParameters() = default;
 
-RtpEncodingParameters::RtpEncodingParameters() {}
-RtpEncodingParameters::~RtpEncodingParameters() {}
+RtpEncodingParameters::RtpEncodingParameters() = default;
+RtpEncodingParameters::RtpEncodingParameters(const RtpEncodingParameters& rhs) =
+    default;
+RtpEncodingParameters::~RtpEncodingParameters() = default;
 
-RtpCodecParameters::RtpCodecParameters() {}
-RtpCodecParameters::~RtpCodecParameters() {}
+RtpCodecParameters::RtpCodecParameters() = default;
+RtpCodecParameters::RtpCodecParameters(const RtpCodecParameters& rhs) = default;
+RtpCodecParameters::~RtpCodecParameters() = default;
 
-RtpCapabilities::RtpCapabilities() {}
-RtpCapabilities::~RtpCapabilities() {}
+RtpCapabilities::RtpCapabilities() = default;
+RtpCapabilities::~RtpCapabilities() = default;
 
-RtcpParameters::RtcpParameters() {}
-RtcpParameters::~RtcpParameters() {}
+RtcpParameters::RtcpParameters() = default;
+RtcpParameters::RtcpParameters(const RtcpParameters& rhs) = default;
+RtcpParameters::~RtcpParameters() = default;
 
-RtpParameters::RtpParameters() {}
-RtpParameters::~RtpParameters() {}
+RtpParameters::RtpParameters() = default;
+RtpParameters::RtpParameters(const RtpParameters& rhs) = default;
+RtpParameters::~RtpParameters() = default;
 
 std::string RtpExtension::ToString() const {
   char buf[256];
diff --git a/api/rtpparameters.h b/api/rtpparameters.h
index ba318ca..9a29c08 100644
--- a/api/rtpparameters.h
+++ b/api/rtpparameters.h
@@ -100,6 +100,7 @@
   RtcpFeedback();
   explicit RtcpFeedback(RtcpFeedbackType type);
   RtcpFeedback(RtcpFeedbackType type, RtcpFeedbackMessageType message_type);
+  RtcpFeedback(const RtcpFeedback&);
   ~RtcpFeedback();
 
   bool operator==(const RtcpFeedback& o) const {
@@ -321,6 +322,7 @@
   RtpFecParameters();
   explicit RtpFecParameters(FecMechanism mechanism);
   RtpFecParameters(FecMechanism mechanism, uint32_t ssrc);
+  RtpFecParameters(const RtpFecParameters&);
   ~RtpFecParameters();
 
   bool operator==(const RtpFecParameters& o) const {
@@ -337,6 +339,7 @@
   // Constructors for convenience.
   RtpRtxParameters();
   explicit RtpRtxParameters(uint32_t ssrc);
+  RtpRtxParameters(const RtpRtxParameters&);
   ~RtpRtxParameters();
 
   bool operator==(const RtpRtxParameters& o) const { return ssrc == o.ssrc; }
@@ -345,6 +348,7 @@
 
 struct RtpEncodingParameters {
   RtpEncodingParameters();
+  RtpEncodingParameters(const RtpEncodingParameters&);
   ~RtpEncodingParameters();
 
   // If unset, a value is chosen by the implementation.
@@ -460,6 +464,7 @@
 
 struct RtpCodecParameters {
   RtpCodecParameters();
+  RtpCodecParameters(const RtpCodecParameters&);
   ~RtpCodecParameters();
 
   // Build MIME "type/subtype" string from |name| and |kind|.
@@ -545,6 +550,7 @@
 
 struct RtcpParameters final {
   RtcpParameters();
+  RtcpParameters(const RtcpParameters&);
   ~RtcpParameters();
 
   // The SSRC to be used in the "SSRC of packet sender" field. If not set, one
@@ -579,6 +585,7 @@
 
 struct RtpParameters {
   RtpParameters();
+  RtpParameters(const RtpParameters&);
   ~RtpParameters();
 
   // Used when calling getParameters/setParameters with a PeerConnection
@@ -602,7 +609,9 @@
   // abstraction on which RTCP parameters are set.
   RtcpParameters rtcp;
 
-  // TODO(deadbeef): Not implemented.
+  // When bandwidth is constrained and the RtpSender needs to choose between
+  // degrading resolution or degrading framerate, degradationPreference
+  // indicates which is preferred. Only for video tracks.
   DegradationPreference degradation_preference =
       DegradationPreference::BALANCED;
 
diff --git a/api/rtpreceiverinterface.cc b/api/rtpreceiverinterface.cc
index fcdca69..216ed2e 100644
--- a/api/rtpreceiverinterface.cc
+++ b/api/rtpreceiverinterface.cc
@@ -45,4 +45,12 @@
   return {};
 }
 
+void RtpReceiverInterface::SetFrameDecryptor(
+    rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {}
+
+rtc::scoped_refptr<FrameDecryptorInterface>
+RtpReceiverInterface::GetFrameDecryptor() const {
+  return nullptr;
+}
+
 }  // namespace webrtc
diff --git a/api/rtpreceiverinterface.h b/api/rtpreceiverinterface.h
index b2499b4..266f6ac 100644
--- a/api/rtpreceiverinterface.h
+++ b/api/rtpreceiverinterface.h
@@ -17,6 +17,7 @@
 #include <string>
 #include <vector>
 
+#include "api/crypto/framedecryptorinterface.h"
 #include "api/mediastreaminterface.h"
 #include "api/mediatypes.h"
 #include "api/proxy.h"
@@ -124,6 +125,17 @@
   // content::FakeRtpReceiver in Chromium.
   virtual std::vector<RtpSource> GetSources() const;
 
+  // Sets a user defined frame decryptor that will decrypt the entire frame
+  // before it is sent across the network. This will decrypt the entire frame
+  // using the user provided decryption mechanism regardless of whether SRTP is
+  // enabled or not.
+  virtual void SetFrameDecryptor(
+      rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor);
+
+  // Returns a pointer to the frame decryptor set previously by the
+  // user. This can be used to update the state of the object.
+  virtual rtc::scoped_refptr<FrameDecryptorInterface> GetFrameDecryptor() const;
+
  protected:
   ~RtpReceiverInterface() override = default;
 };
@@ -142,6 +154,11 @@
 PROXY_METHOD1(bool, SetParameters, const RtpParameters&)
 PROXY_METHOD1(void, SetObserver, RtpReceiverObserverInterface*);
 PROXY_CONSTMETHOD0(std::vector<RtpSource>, GetSources);
+PROXY_METHOD1(void,
+              SetFrameDecryptor,
+              rtc::scoped_refptr<FrameDecryptorInterface>);
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<FrameDecryptorInterface>,
+                   GetFrameDecryptor);
 END_PROXY_MAP()
 
 }  // namespace webrtc
diff --git a/api/rtpsenderinterface.cc b/api/rtpsenderinterface.cc
new file mode 100644
index 0000000..bbf3901
--- /dev/null
+++ b/api/rtpsenderinterface.cc
@@ -0,0 +1,23 @@
+/*
+ *  Copyright 2018 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 "api/rtpsenderinterface.h"
+
+namespace webrtc {
+
+void RtpSenderInterface::SetFrameEncryptor(
+    rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {}
+
+rtc::scoped_refptr<FrameEncryptorInterface>
+RtpSenderInterface::GetFrameEncryptor() const {
+  return nullptr;
+}
+
+}  // namespace webrtc
diff --git a/api/rtpsenderinterface.h b/api/rtpsenderinterface.h
index 6003aa0..96c2669 100644
--- a/api/rtpsenderinterface.h
+++ b/api/rtpsenderinterface.h
@@ -17,6 +17,7 @@
 #include <string>
 #include <vector>
 
+#include "api/crypto/frameencryptorinterface.h"
 #include "api/dtmfsenderinterface.h"
 #include "api/mediastreaminterface.h"
 #include "api/mediatypes.h"
@@ -63,8 +64,19 @@
   // Returns null for a video sender.
   virtual rtc::scoped_refptr<DtmfSenderInterface> GetDtmfSender() const = 0;
 
+  // Sets a user defined frame encryptor that will encrypt the entire frame
+  // before it is sent across the network. This will encrypt the entire frame
+  // using the user provided encryption mechanism regardless of whether SRTP is
+  // enabled or not.
+  virtual void SetFrameEncryptor(
+      rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor);
+
+  // Returns a pointer to the frame encryptor set previously by the
+  // user. This can be used to update the state of the object.
+  virtual rtc::scoped_refptr<FrameEncryptorInterface> GetFrameEncryptor() const;
+
  protected:
-  virtual ~RtpSenderInterface() {}
+  ~RtpSenderInterface() override = default;
 };
 
 // Define proxy for RtpSenderInterface.
@@ -81,6 +93,11 @@
 PROXY_METHOD0(RtpParameters, GetParameters);
 PROXY_METHOD1(RTCError, SetParameters, const RtpParameters&)
 PROXY_CONSTMETHOD0(rtc::scoped_refptr<DtmfSenderInterface>, GetDtmfSender);
+PROXY_METHOD1(void,
+              SetFrameEncryptor,
+              rtc::scoped_refptr<FrameEncryptorInterface>);
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<FrameEncryptorInterface>,
+                   GetFrameEncryptor);
 END_PROXY_MAP()
 
 }  // namespace webrtc
diff --git a/api/rtptransceiverinterface.cc b/api/rtptransceiverinterface.cc
new file mode 100644
index 0000000..065ac04
--- /dev/null
+++ b/api/rtptransceiverinterface.cc
@@ -0,0 +1,26 @@
+/*
+ *  Copyright 2018 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 "api/rtptransceiverinterface.h"
+
+namespace webrtc {
+
+RtpTransceiverInit::RtpTransceiverInit() = default;
+
+RtpTransceiverInit::RtpTransceiverInit(const RtpTransceiverInit& rhs) = default;
+
+RtpTransceiverInit::~RtpTransceiverInit() = default;
+
+absl::optional<RtpTransceiverDirection>
+RtpTransceiverInterface::fired_direction() const {
+  return absl::nullopt;
+}
+
+}  // namespace webrtc
diff --git a/api/rtptransceiverinterface.h b/api/rtptransceiverinterface.h
index 26f1fdf..4c22957 100644
--- a/api/rtptransceiverinterface.h
+++ b/api/rtptransceiverinterface.h
@@ -34,6 +34,9 @@
 // PeerConnectionInterface::AddTransceiver.
 // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverinit
 struct RtpTransceiverInit final {
+  RtpTransceiverInit();
+  RtpTransceiverInit(const RtpTransceiverInit&);
+  ~RtpTransceiverInit();
   // Direction of the RtpTransceiver. See RtpTransceiverInterface::direction().
   RtpTransceiverDirection direction = RtpTransceiverDirection::kSendRecv;
 
@@ -112,9 +115,7 @@
   // OnAddTrack only get fired once even if the same session description is
   // applied again.
   // Exposed in the public interface for use by Chromium.
-  virtual absl::optional<RtpTransceiverDirection> fired_direction() const {
-    return absl::nullopt;
-  }
+  virtual absl::optional<RtpTransceiverDirection> fired_direction() const;
 
   // The Stop method irreversibly stops the RtpTransceiver. The sender of this
   // transceiver will no longer send, the receiver will no longer receive.
@@ -129,7 +130,7 @@
       rtc::ArrayView<RtpCodecCapability> codecs) = 0;
 
  protected:
-  virtual ~RtpTransceiverInterface() = default;
+  ~RtpTransceiverInterface() override = default;
 };
 
 }  // namespace webrtc
diff --git a/api/statstypes.cc b/api/statstypes.cc
index ceba28d..ad68894 100644
--- a/api/statstypes.cc
+++ b/api/statstypes.cc
@@ -99,7 +99,7 @@
 
   std::string ToString() const override {
     return std::string(InternalTypeToString(type_)) + kSeparator +
-           rtc::ToString<int>(id_);
+           rtc::ToString(id_);
   }
 
  protected:
@@ -165,7 +165,7 @@
     std::string ret(prefix);
     ret += content_name_;
     ret += '-';
-    ret += rtc::ToString<>(component_);
+    ret += rtc::ToString(component_);
     return ret;
   }
 
@@ -190,7 +190,7 @@
   std::string ToString() const override {
     std::string ret(ComponentId::ToString("Conn-"));
     ret += '-';
-    ret += rtc::ToString<>(index_);
+    ret += rtc::ToString(index_);
     return ret;
   }
 
diff --git a/api/transport/network_types.h b/api/transport/network_types.h
index a389716..8e9526b 100644
--- a/api/transport/network_types.h
+++ b/api/transport/network_types.h
@@ -45,6 +45,7 @@
   Timestamp at_time = Timestamp::Infinity();
   absl::optional<DataRate> min_data_rate;
   absl::optional<DataRate> max_data_rate;
+  absl::optional<DataRate> starting_rate;
 };
 
 // Send side information
@@ -62,7 +63,6 @@
   // The TargetRateConstraints are set here so they can be changed synchronously
   // when network route changes.
   TargetRateConstraints constraints;
-  absl::optional<DataRate> starting_rate;
 };
 
 struct PacedPacketInfo {
diff --git a/api/umametrics.h b/api/umametrics.h
index b999b64..88ab08c 100644
--- a/api/umametrics.h
+++ b/api/umametrics.h
@@ -17,38 +17,6 @@
 
 namespace webrtc {
 
-// Used to specify which enum counter type we're incrementing in
-// MetricsObserverInterface::IncrementEnumCounter.
-enum PeerConnectionEnumCounterType {
-  kEnumCounterAddressFamily,
-  // For the next 2 counters, we track them separately based on the "first hop"
-  // protocol used by the local candidate. "First hop" means the local candidate
-  // type in the case of non-TURN candidates, and the protocol used to connect
-  // to the TURN server in the case of TURN candidates.
-  kEnumCounterIceCandidatePairTypeUdp,
-  kEnumCounterIceCandidatePairTypeTcp,
-
-  kEnumCounterAudioSrtpCipher,
-  kEnumCounterAudioSslCipher,
-  kEnumCounterVideoSrtpCipher,
-  kEnumCounterVideoSslCipher,
-  kEnumCounterDataSrtpCipher,
-  kEnumCounterDataSslCipher,
-  kEnumCounterDtlsHandshakeError,
-  kEnumCounterIceRegathering,
-  kEnumCounterIceRestart,
-  kEnumCounterKeyProtocol,
-  kEnumCounterSdpSemanticRequested,
-  kEnumCounterSdpSemanticNegotiated,
-  kEnumCounterKeyProtocolMediaType,
-  kEnumCounterSdpFormatReceived,
-  // The next 2 counters log the value of srtp_err_status_t defined in libsrtp.
-  kEnumCounterSrtpUnprotectError,
-  kEnumCounterSrtcpUnprotectError,
-  kEnumCounterUsagePattern,
-  kPeerConnectionEnumCounterMax
-};
-
 // Currently this contains information related to WebRTC network/transport
 // information.
 
@@ -169,27 +137,19 @@
   kSdpFormatReceivedMax
 };
 
-class MetricsObserverInterface : public rtc::RefCountInterface {
- public:
-  // |type| is the type of the enum counter to be incremented. |counter|
-  // is the particular counter in that type. |counter_max| is the next sequence
-  // number after the highest counter.
-  virtual void IncrementEnumCounter(PeerConnectionEnumCounterType type,
-                                    int counter,
-                                    int counter_max) = 0;
-
-  // This is used to handle sparse counters like SSL cipher suites.
-  // TODO(guoweis): Remove the implementation once the dependency's interface
-  // definition is updated.
-  virtual void IncrementSparseEnumCounter(PeerConnectionEnumCounterType type,
-                                          int counter) = 0;
-
-  virtual void AddHistogramSample(PeerConnectionMetricsName type,
-                                  int value) = 0;
+// Metric for counting the outcome of adding an ICE candidate
+enum AddIceCandidateResult {
+  kAddIceCandidateSuccess,
+  kAddIceCandidateFailClosed,
+  kAddIceCandidateFailNoRemoteDescription,
+  kAddIceCandidateFailNullCandidate,
+  kAddIceCandidateFailNotValid,
+  kAddIceCandidateFailNotReady,
+  kAddIceCandidateFailInAddition,
+  kAddIceCandidateFailNotUsable,
+  kAddIceCandidateMax
 };
 
-typedef MetricsObserverInterface UMAObserver;
-
 }  // namespace webrtc
 
 #endif  // API_UMAMETRICS_H_
diff --git a/api/units/data_rate.cc b/api/units/data_rate.cc
index 4e31d51..9170627 100644
--- a/api/units/data_rate.cc
+++ b/api/units/data_rate.cc
@@ -20,7 +20,11 @@
   if (value.IsInfinite()) {
     sb << "inf bps";
   } else {
-    sb << value.bps() << " bps";
+    if (value.bps() == 0 || value.bps() % 1000 != 0) {
+      sb << value.bps() << " bps";
+    } else {
+      sb << value.kbps() << " kbps";
+    }
   }
   return sb.str();
 }
diff --git a/api/units/data_rate.h b/api/units/data_rate.h
index c7164e3..5c421d4 100644
--- a/api/units/data_rate.h
+++ b/api/units/data_rate.h
@@ -10,6 +10,11 @@
 
 #ifndef API_UNITS_DATA_RATE_H_
 #define API_UNITS_DATA_RATE_H_
+
+#ifdef UNIT_TEST
+#include <ostream>  // no-presubmit-check TODO(webrtc:8982)
+#endif              // UNIT_TEST
+
 #include <stdint.h>
 #include <cmath>
 #include <limits>
@@ -40,10 +45,22 @@
 class DataRate {
  public:
   DataRate() = delete;
-  static DataRate Zero() { return DataRate(0); }
-  static DataRate Infinity() {
+  static constexpr DataRate Zero() { return DataRate(0); }
+  static constexpr DataRate Infinity() {
     return DataRate(data_rate_impl::kPlusInfinityVal);
   }
+  template <int64_t bps>
+  static constexpr DataRate BitsPerSec() {
+    static_assert(bps >= 0, "");
+    static_assert(bps < data_rate_impl::kPlusInfinityVal, "");
+    return DataRate(bps);
+  }
+  template <int64_t kbps>
+  static constexpr DataRate KilobitsPerSec() {
+    static_assert(kbps >= 0, "");
+    static_assert(kbps < data_rate_impl::kPlusInfinityVal / 1000, "");
+    return DataRate(kbps * 1000);
+  }
 
   template <
       typename T,
@@ -89,56 +106,64 @@
   }
   template <typename T = int64_t>
   typename std::enable_if<std::is_integral<T>::value, T>::type kbps() const {
-    return rtc::dchecked_cast<T>((bps() + 500) / 1000);
+    RTC_DCHECK(IsFinite());
+    return rtc::dchecked_cast<T>(UnsafeKilobitsPerSec());
   }
 
   template <typename T>
-  typename std::enable_if<std::is_floating_point<T>::value, T>::type bps()
-      const {
-    if (IsInfinite()) {
-      return std::numeric_limits<T>::infinity();
-    } else {
-      return bits_per_sec_;
-    }
+  typename std::enable_if<std::is_floating_point<T>::value,
+                          T>::type constexpr bps() const {
+    return IsInfinite() ? std::numeric_limits<T>::infinity() : bits_per_sec_;
   }
   template <typename T>
-  typename std::enable_if<std::is_floating_point<T>::value, T>::type kbps()
-      const {
+  typename std::enable_if<std::is_floating_point<T>::value,
+                          T>::type constexpr kbps() const {
     return bps<T>() * 1e-3;
   }
 
-  bool IsZero() const { return bits_per_sec_ == 0; }
-  bool IsInfinite() const {
+  constexpr int64_t bps_or(int64_t fallback_value) const {
+    return IsFinite() ? bits_per_sec_ : fallback_value;
+  }
+  constexpr int64_t kbps_or(int64_t fallback_value) const {
+    return IsFinite() ? UnsafeKilobitsPerSec() : fallback_value;
+  }
+
+  constexpr bool IsZero() const { return bits_per_sec_ == 0; }
+  constexpr bool IsInfinite() const {
     return bits_per_sec_ == data_rate_impl::kPlusInfinityVal;
   }
-  bool IsFinite() const { return !IsInfinite(); }
+  constexpr bool IsFinite() const { return !IsInfinite(); }
 
-  double operator/(const DataRate& other) const {
+  constexpr double operator/(const DataRate& other) const {
     return bps<double>() / other.bps<double>();
   }
-  bool operator==(const DataRate& other) const {
+  constexpr bool operator==(const DataRate& other) const {
     return bits_per_sec_ == other.bits_per_sec_;
   }
-  bool operator!=(const DataRate& other) const {
+  constexpr bool operator!=(const DataRate& other) const {
     return bits_per_sec_ != other.bits_per_sec_;
   }
-  bool operator<=(const DataRate& other) const {
+  constexpr bool operator<=(const DataRate& other) const {
     return bits_per_sec_ <= other.bits_per_sec_;
   }
-  bool operator>=(const DataRate& other) const {
+  constexpr bool operator>=(const DataRate& other) const {
     return bits_per_sec_ >= other.bits_per_sec_;
   }
-  bool operator>(const DataRate& other) const {
+  constexpr bool operator>(const DataRate& other) const {
     return bits_per_sec_ > other.bits_per_sec_;
   }
-  bool operator<(const DataRate& other) const {
+  constexpr bool operator<(const DataRate& other) const {
     return bits_per_sec_ < other.bits_per_sec_;
   }
 
  private:
   // Bits per second used internally to simplify debugging by making the value
   // more recognizable.
-  explicit DataRate(int64_t bits_per_second) : bits_per_sec_(bits_per_second) {}
+  explicit constexpr DataRate(int64_t bits_per_second)
+      : bits_per_sec_(bits_per_second) {}
+  constexpr int64_t UnsafeKilobitsPerSec() const {
+    return (bits_per_sec_ + 500) / 1000;
+  }
   int64_t bits_per_sec_;
 };
 
@@ -177,6 +202,14 @@
 
 std::string ToString(const DataRate& value);
 
+#ifdef UNIT_TEST
+inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
+    std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
+    DataRate value) {
+  return stream << ToString(value);
+}
+#endif  // UNIT_TEST
+
 }  // namespace webrtc
 
 #endif  // API_UNITS_DATA_RATE_H_
diff --git a/api/units/data_rate_unittest.cc b/api/units/data_rate_unittest.cc
index 073e80e..9c91fd6 100644
--- a/api/units/data_rate_unittest.cc
+++ b/api/units/data_rate_unittest.cc
@@ -13,6 +13,23 @@
 
 namespace webrtc {
 namespace test {
+
+TEST(DataRateTest, ConstExpr) {
+  constexpr int64_t kValue = 12345;
+  constexpr DataRate kDataRateZero = DataRate::Zero();
+  constexpr DataRate kDataRateInf = DataRate::Infinity();
+  static_assert(kDataRateZero.IsZero(), "");
+  static_assert(kDataRateInf.IsInfinite(), "");
+  static_assert(kDataRateInf.bps_or(-1) == -1, "");
+  static_assert(kDataRateInf > kDataRateZero, "");
+
+  constexpr DataRate kDataRateBps = DataRate::BitsPerSec<kValue>();
+  constexpr DataRate kDataRateKbps = DataRate::KilobitsPerSec<kValue>();
+  static_assert(kDataRateBps.bps<double>() == kValue, "");
+  static_assert(kDataRateBps.bps_or(0) == kValue, "");
+  static_assert(kDataRateKbps.kbps_or(0) == kValue, "");
+}
+
 TEST(DataRateTest, GetBackSameValues) {
   const int64_t kValue = 123 * 8;
   EXPECT_EQ(DataRate::bps(kValue).bps(), kValue);
diff --git a/api/units/data_size.h b/api/units/data_size.h
index 8c35766..ac61a6f 100644
--- a/api/units/data_size.h
+++ b/api/units/data_size.h
@@ -11,6 +11,10 @@
 #ifndef API_UNITS_DATA_SIZE_H_
 #define API_UNITS_DATA_SIZE_H_
 
+#ifdef UNIT_TEST
+#include <ostream>  // no-presubmit-check TODO(webrtc:8982)
+#endif              // UNIT_TEST
+
 #include <stdint.h>
 #include <cmath>
 #include <limits>
@@ -29,10 +33,16 @@
 class DataSize {
  public:
   DataSize() = delete;
-  static DataSize Zero() { return DataSize(0); }
-  static DataSize Infinity() {
+  static constexpr DataSize Zero() { return DataSize(0); }
+  static constexpr DataSize Infinity() {
     return DataSize(data_size_impl::kPlusInfinityVal);
   }
+  template <int64_t bytes>
+  static constexpr DataSize Bytes() {
+    static_assert(bytes >= 0, "");
+    static_assert(bytes < data_size_impl::kPlusInfinityVal, "");
+    return DataSize(bytes);
+  }
 
   template <
       typename T,
@@ -64,18 +74,20 @@
   }
 
   template <typename T>
-  typename std::enable_if<std::is_floating_point<T>::value, T>::type bytes()
-      const {
-    if (IsInfinite()) {
-      return std::numeric_limits<T>::infinity();
-    } else {
-      return bytes_;
-    }
+  constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+  bytes() const {
+    return IsInfinite() ? std::numeric_limits<T>::infinity() : bytes_;
   }
 
-  bool IsZero() const { return bytes_ == 0; }
-  bool IsInfinite() const { return bytes_ == data_size_impl::kPlusInfinityVal; }
-  bool IsFinite() const { return !IsInfinite(); }
+  constexpr int64_t bytes_or(int64_t fallback_value) const {
+    return IsFinite() ? bytes_ : fallback_value;
+  }
+
+  constexpr bool IsZero() const { return bytes_ == 0; }
+  constexpr bool IsInfinite() const {
+    return bytes_ == data_size_impl::kPlusInfinityVal;
+  }
+  constexpr bool IsFinite() const { return !IsInfinite(); }
   DataSize operator-(const DataSize& other) const {
     return DataSize::bytes(bytes() - other.bytes());
   }
@@ -90,26 +102,30 @@
     bytes_ += other.bytes();
     return *this;
   }
-  double operator/(const DataSize& other) const {
+  constexpr double operator/(const DataSize& other) const {
     return bytes<double>() / other.bytes<double>();
   }
-  bool operator==(const DataSize& other) const {
+  constexpr bool operator==(const DataSize& other) const {
     return bytes_ == other.bytes_;
   }
-  bool operator!=(const DataSize& other) const {
+  constexpr bool operator!=(const DataSize& other) const {
     return bytes_ != other.bytes_;
   }
-  bool operator<=(const DataSize& other) const {
+  constexpr bool operator<=(const DataSize& other) const {
     return bytes_ <= other.bytes_;
   }
-  bool operator>=(const DataSize& other) const {
+  constexpr bool operator>=(const DataSize& other) const {
     return bytes_ >= other.bytes_;
   }
-  bool operator>(const DataSize& other) const { return bytes_ > other.bytes_; }
-  bool operator<(const DataSize& other) const { return bytes_ < other.bytes_; }
+  constexpr bool operator>(const DataSize& other) const {
+    return bytes_ > other.bytes_;
+  }
+  constexpr bool operator<(const DataSize& other) const {
+    return bytes_ < other.bytes_;
+  }
 
  private:
-  explicit DataSize(int64_t bytes) : bytes_(bytes) {}
+  explicit constexpr DataSize(int64_t bytes) : bytes_(bytes) {}
   int64_t bytes_;
 };
 
@@ -137,6 +153,14 @@
 
 std::string ToString(const DataSize& value);
 
+#ifdef UNIT_TEST
+inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
+    std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
+    DataSize value) {
+  return stream << ToString(value);
+}
+#endif  // UNIT_TEST
+
 }  // namespace webrtc
 
 #endif  // API_UNITS_DATA_SIZE_H_
diff --git a/api/units/data_size_unittest.cc b/api/units/data_size_unittest.cc
index 7747258..fe7f591 100644
--- a/api/units/data_size_unittest.cc
+++ b/api/units/data_size_unittest.cc
@@ -14,6 +14,21 @@
 namespace webrtc {
 namespace test {
 
+TEST(DataSizeTest, ConstExpr) {
+  constexpr int64_t kValue = 12345;
+  constexpr DataSize kDataSizeZero = DataSize::Zero();
+  constexpr DataSize kDataSizeInf = DataSize::Infinity();
+  static_assert(kDataSizeZero.IsZero(), "");
+  static_assert(kDataSizeInf.IsInfinite(), "");
+  static_assert(kDataSizeInf.bytes_or(-1) == -1, "");
+  static_assert(kDataSizeInf > kDataSizeZero, "");
+
+  constexpr DataSize kDataSize = DataSize::Bytes<kValue>();
+  static_assert(kDataSize.bytes_or(-1) == kValue, "");
+
+  EXPECT_EQ(kDataSize.bytes(), kValue);
+}
+
 TEST(DataSizeTest, GetBackSameValues) {
   const int64_t kValue = 123 * 8;
   EXPECT_EQ(DataSize::bytes(kValue).bytes(), kValue);
diff --git a/api/units/time_delta.cc b/api/units/time_delta.cc
index 398df77..d38387a 100644
--- a/api/units/time_delta.cc
+++ b/api/units/time_delta.cc
@@ -22,7 +22,12 @@
   } else if (value.IsMinusInfinity()) {
     sb << "-inf ms";
   } else {
-    sb << value.ms() << " ms";
+    if (value.us() == 0 || (value.us() % 1000) != 0)
+      sb << value.us() << " us";
+    else if (value.ms() % 1000 != 0)
+      sb << value.ms() << " ms";
+    else
+      sb << value.seconds() << " s";
   }
   return sb.str();
 }
diff --git a/api/units/time_delta.h b/api/units/time_delta.h
index 0f99e80..b820472 100644
--- a/api/units/time_delta.h
+++ b/api/units/time_delta.h
@@ -11,6 +11,10 @@
 #ifndef API_UNITS_TIME_DELTA_H_
 #define API_UNITS_TIME_DELTA_H_
 
+#ifdef UNIT_TEST
+#include <ostream>  // no-presubmit-check TODO(webrtc:8982)
+#endif              // UNIT_TEST
+
 #include <stdint.h>
 #include <cmath>
 #include <limits>
@@ -35,13 +39,31 @@
 class TimeDelta {
  public:
   TimeDelta() = delete;
-  static TimeDelta Zero() { return TimeDelta(0); }
-  static TimeDelta PlusInfinity() {
+  static constexpr TimeDelta Zero() { return TimeDelta(0); }
+  static constexpr TimeDelta PlusInfinity() {
     return TimeDelta(timedelta_impl::kPlusInfinityVal);
   }
-  static TimeDelta MinusInfinity() {
+  static constexpr TimeDelta MinusInfinity() {
     return TimeDelta(timedelta_impl::kMinusInfinityVal);
   }
+  template <int64_t seconds>
+  static constexpr TimeDelta Seconds() {
+    static_assert(seconds > timedelta_impl::kMinusInfinityVal / 1000000, "");
+    static_assert(seconds < timedelta_impl::kPlusInfinityVal / 1000000, "");
+    return TimeDelta(seconds * 1000000);
+  }
+  template <int64_t ms>
+  static constexpr TimeDelta Millis() {
+    static_assert(ms > timedelta_impl::kMinusInfinityVal / 1000, "");
+    static_assert(ms < timedelta_impl::kPlusInfinityVal / 1000, "");
+    return TimeDelta(ms * 1000);
+  }
+  template <int64_t us>
+  static constexpr TimeDelta Micros() {
+    static_assert(us > timedelta_impl::kMinusInfinityVal, "");
+    static_assert(us < timedelta_impl::kPlusInfinityVal, "");
+    return TimeDelta(us);
+  }
 
   template <
       typename T,
@@ -98,12 +120,13 @@
 
   template <typename T = int64_t>
   typename std::enable_if<std::is_integral<T>::value, T>::type seconds() const {
-    return rtc::dchecked_cast<T>((us() + (us() >= 0 ? 500000 : -500000)) /
-                                 1000000);
+    RTC_DCHECK(IsFinite());
+    return rtc::dchecked_cast<T>(UnsafeSeconds());
   }
   template <typename T = int64_t>
   typename std::enable_if<std::is_integral<T>::value, T>::type ms() const {
-    return rtc::dchecked_cast<T>((us() + (us() >= 0 ? 500 : -500)) / 1000);
+    RTC_DCHECK(IsFinite());
+    return rtc::dchecked_cast<T>(UnsafeMillis());
   }
   template <typename T = int64_t>
   typename std::enable_if<std::is_integral<T>::value, T>::type us() const {
@@ -118,43 +141,50 @@
   }
 
   template <typename T>
-  typename std::enable_if<std::is_floating_point<T>::value, T>::type seconds()
-      const {
+  constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+  seconds() const {
     return us<T>() * 1e-6;
   }
   template <typename T>
-  typename std::enable_if<std::is_floating_point<T>::value, T>::type ms()
-      const {
+  constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+  ms() const {
     return us<T>() * 1e-3;
   }
   template <typename T>
-  typename std::enable_if<std::is_floating_point<T>::value, T>::type us()
-      const {
-    if (IsPlusInfinity()) {
-      return std::numeric_limits<T>::infinity();
-    } else if (IsMinusInfinity()) {
-      return -std::numeric_limits<T>::infinity();
-    } else {
-      return microseconds_;
-    }
+  constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+  us() const {
+    return IsPlusInfinity()
+               ? std::numeric_limits<T>::infinity()
+               : IsMinusInfinity() ? -std::numeric_limits<T>::infinity()
+                                   : microseconds_;
   }
   template <typename T>
-  typename std::enable_if<std::is_floating_point<T>::value, T>::type ns()
-      const {
+  constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+  ns() const {
     return us<T>() * 1e3;
   }
 
+  constexpr int64_t seconds_or(int64_t fallback_value) const {
+    return IsFinite() ? UnsafeSeconds() : fallback_value;
+  }
+  constexpr int64_t ms_or(int64_t fallback_value) const {
+    return IsFinite() ? UnsafeMillis() : fallback_value;
+  }
+  constexpr int64_t us_or(int64_t fallback_value) const {
+    return IsFinite() ? microseconds_ : fallback_value;
+  }
+
   TimeDelta Abs() const { return TimeDelta::us(std::abs(us())); }
-  bool IsZero() const { return microseconds_ == 0; }
-  bool IsFinite() const { return !IsInfinite(); }
-  bool IsInfinite() const {
+  constexpr bool IsZero() const { return microseconds_ == 0; }
+  constexpr bool IsFinite() const { return !IsInfinite(); }
+  constexpr bool IsInfinite() const {
     return microseconds_ == timedelta_impl::kPlusInfinityVal ||
            microseconds_ == timedelta_impl::kMinusInfinityVal;
   }
-  bool IsPlusInfinity() const {
+  constexpr bool IsPlusInfinity() const {
     return microseconds_ == timedelta_impl::kPlusInfinityVal;
   }
-  bool IsMinusInfinity() const {
+  constexpr bool IsMinusInfinity() const {
     return microseconds_ == timedelta_impl::kMinusInfinityVal;
   }
   TimeDelta operator+(const TimeDelta& other) const {
@@ -171,30 +201,36 @@
     microseconds_ += other.us();
     return *this;
   }
-  double operator/(const TimeDelta& other) const {
+  constexpr double operator/(const TimeDelta& other) const {
     return us<double>() / other.us<double>();
   }
-  bool operator==(const TimeDelta& other) const {
+  constexpr bool operator==(const TimeDelta& other) const {
     return microseconds_ == other.microseconds_;
   }
-  bool operator!=(const TimeDelta& other) const {
+  constexpr bool operator!=(const TimeDelta& other) const {
     return microseconds_ != other.microseconds_;
   }
-  bool operator<=(const TimeDelta& other) const {
+  constexpr bool operator<=(const TimeDelta& other) const {
     return microseconds_ <= other.microseconds_;
   }
-  bool operator>=(const TimeDelta& other) const {
+  constexpr bool operator>=(const TimeDelta& other) const {
     return microseconds_ >= other.microseconds_;
   }
-  bool operator>(const TimeDelta& other) const {
+  constexpr bool operator>(const TimeDelta& other) const {
     return microseconds_ > other.microseconds_;
   }
-  bool operator<(const TimeDelta& other) const {
+  constexpr bool operator<(const TimeDelta& other) const {
     return microseconds_ < other.microseconds_;
   }
 
  private:
-  explicit TimeDelta(int64_t us) : microseconds_(us) {}
+  explicit constexpr TimeDelta(int64_t us) : microseconds_(us) {}
+  constexpr int64_t UnsafeSeconds() const {
+    return (microseconds_ + (microseconds_ >= 0 ? 500000 : -500000)) / 1000000;
+  }
+  constexpr int64_t UnsafeMillis() const {
+    return (microseconds_ + (microseconds_ >= 0 ? 500 : -500)) / 1000;
+  }
   int64_t microseconds_;
 };
 
@@ -220,8 +256,16 @@
 inline TimeDelta operator/(const TimeDelta& delta, const int64_t& scalar) {
   return TimeDelta::us(delta.us() / scalar);
 }
-
 std::string ToString(const TimeDelta& value);
+
+#ifdef UNIT_TEST
+inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
+    std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
+    TimeDelta value) {
+  return stream << ToString(value);
+}
+#endif  // UNIT_TEST
+
 }  // namespace webrtc
 
 #endif  // API_UNITS_TIME_DELTA_H_
diff --git a/api/units/time_delta_unittest.cc b/api/units/time_delta_unittest.cc
index 94a27f2..9eddee7 100644
--- a/api/units/time_delta_unittest.cc
+++ b/api/units/time_delta_unittest.cc
@@ -14,6 +14,26 @@
 
 namespace webrtc {
 namespace test {
+TEST(TimeDeltaTest, ConstExpr) {
+  constexpr int64_t kValue = -12345;
+  constexpr TimeDelta kTimeDeltaZero = TimeDelta::Zero();
+  constexpr TimeDelta kTimeDeltaPlusInf = TimeDelta::PlusInfinity();
+  constexpr TimeDelta kTimeDeltaMinusInf = TimeDelta::MinusInfinity();
+  static_assert(kTimeDeltaZero.IsZero(), "");
+  static_assert(kTimeDeltaPlusInf.IsPlusInfinity(), "");
+  static_assert(kTimeDeltaMinusInf.IsMinusInfinity(), "");
+  static_assert(kTimeDeltaPlusInf.ms_or(-1) == -1, "");
+
+  static_assert(kTimeDeltaPlusInf > kTimeDeltaZero, "");
+
+  constexpr TimeDelta kTimeDeltaSeconds = TimeDelta::Seconds<kValue>();
+  constexpr TimeDelta kTimeDeltaMs = TimeDelta::Millis<kValue>();
+  constexpr TimeDelta kTimeDeltaUs = TimeDelta::Micros<kValue>();
+
+  static_assert(kTimeDeltaSeconds.seconds_or(0) == kValue, "");
+  static_assert(kTimeDeltaMs.ms_or(0) == kValue, "");
+  static_assert(kTimeDeltaUs.us_or(0) == kValue, "");
+}
 
 TEST(TimeDeltaTest, GetBackSameValues) {
   const int64_t kValue = 499;
diff --git a/api/units/timestamp.cc b/api/units/timestamp.cc
index 4b2c44b..feb1447 100644
--- a/api/units/timestamp.cc
+++ b/api/units/timestamp.cc
@@ -19,7 +19,10 @@
   if (value.IsInfinite()) {
     sb << "inf ms";
   } else {
-    sb << value.ms() << " ms";
+    if (value.ms() % 1000 == 0)
+      sb << value.seconds() << " s";
+    else
+      sb << value.ms() << " ms";
   }
   return sb.str();
 }
diff --git a/api/units/timestamp.h b/api/units/timestamp.h
index a66e061..6e5e392 100644
--- a/api/units/timestamp.h
+++ b/api/units/timestamp.h
@@ -11,6 +11,10 @@
 #ifndef API_UNITS_TIMESTAMP_H_
 #define API_UNITS_TIMESTAMP_H_
 
+#ifdef UNIT_TEST
+#include <ostream>  // no-presubmit-check TODO(webrtc:8982)
+#endif              // UNIT_TEST
+
 #include <stdint.h>
 #include <limits>
 #include <string>
@@ -32,9 +36,27 @@
 class Timestamp {
  public:
   Timestamp() = delete;
-  static Timestamp Infinity() {
+  static constexpr Timestamp Infinity() {
     return Timestamp(timestamp_impl::kPlusInfinityVal);
   }
+  template <int64_t seconds>
+  static constexpr Timestamp Seconds() {
+    static_assert(seconds >= 0, "");
+    static_assert(seconds < timestamp_impl::kPlusInfinityVal / 1000000, "");
+    return Timestamp(seconds * 1000000);
+  }
+  template <int64_t ms>
+  static constexpr Timestamp Millis() {
+    static_assert(ms >= 0, "");
+    static_assert(ms < timestamp_impl::kPlusInfinityVal / 1000, "");
+    return Timestamp(ms * 1000);
+  }
+  template <int64_t us>
+  static constexpr Timestamp Micros() {
+    static_assert(us >= 0, "");
+    static_assert(us < timestamp_impl::kPlusInfinityVal, "");
+    return Timestamp(us);
+  }
 
   template <
       typename T,
@@ -92,11 +114,13 @@
 
   template <typename T = int64_t>
   typename std::enable_if<std::is_integral<T>::value, T>::type seconds() const {
-    return rtc::dchecked_cast<T>((us() + 500000) / 1000000);
+    RTC_DCHECK(IsFinite());
+    return rtc::dchecked_cast<T>(UnsafeSeconds());
   }
   template <typename T = int64_t>
   typename std::enable_if<std::is_integral<T>::value, T>::type ms() const {
-    return rtc::dchecked_cast<T>((us() + 500) / 1000);
+    RTC_DCHECK(IsFinite());
+    return rtc::dchecked_cast<T>(UnsafeMillis());
   }
   template <typename T = int64_t>
   typename std::enable_if<std::is_integral<T>::value, T>::type us() const {
@@ -105,29 +129,35 @@
   }
 
   template <typename T>
-  typename std::enable_if<std::is_floating_point<T>::value, T>::type seconds()
-      const {
+  constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+  seconds() const {
     return us<T>() * 1e-6;
   }
   template <typename T>
-  typename std::enable_if<std::is_floating_point<T>::value, T>::type ms()
-      const {
+  constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+  ms() const {
     return us<T>() * 1e-3;
   }
   template <typename T>
-  typename std::enable_if<std::is_floating_point<T>::value, T>::type us()
-      const {
-    if (IsInfinite()) {
-      return std::numeric_limits<T>::infinity();
-    } else {
-      return microseconds_;
-    }
+  constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+  us() const {
+    return IsInfinite() ? std::numeric_limits<T>::infinity() : microseconds_;
   }
 
-  bool IsInfinite() const {
+  constexpr int64_t seconds_or(int64_t fallback_value) const {
+    return IsFinite() ? UnsafeSeconds() : fallback_value;
+  }
+  constexpr int64_t ms_or(int64_t fallback_value) const {
+    return IsFinite() ? UnsafeMillis() : fallback_value;
+  }
+  constexpr int64_t us_or(int64_t fallback_value) const {
+    return IsFinite() ? microseconds_ : fallback_value;
+  }
+
+  constexpr bool IsInfinite() const {
     return microseconds_ == timestamp_impl::kPlusInfinityVal;
   }
-  bool IsFinite() const { return !IsInfinite(); }
+  constexpr bool IsFinite() const { return !IsInfinite(); }
   TimeDelta operator-(const Timestamp& other) const {
     return TimeDelta::us(us() - other.us());
   }
@@ -145,32 +175,46 @@
     microseconds_ += other.us();
     return *this;
   }
-  bool operator==(const Timestamp& other) const {
+  constexpr bool operator==(const Timestamp& other) const {
     return microseconds_ == other.microseconds_;
   }
-  bool operator!=(const Timestamp& other) const {
+  constexpr bool operator!=(const Timestamp& other) const {
     return microseconds_ != other.microseconds_;
   }
-  bool operator<=(const Timestamp& other) const {
+  constexpr bool operator<=(const Timestamp& other) const {
     return microseconds_ <= other.microseconds_;
   }
-  bool operator>=(const Timestamp& other) const {
+  constexpr bool operator>=(const Timestamp& other) const {
     return microseconds_ >= other.microseconds_;
   }
-  bool operator>(const Timestamp& other) const {
+  constexpr bool operator>(const Timestamp& other) const {
     return microseconds_ > other.microseconds_;
   }
-  bool operator<(const Timestamp& other) const {
+  constexpr bool operator<(const Timestamp& other) const {
     return microseconds_ < other.microseconds_;
   }
 
  private:
-  explicit Timestamp(int64_t us) : microseconds_(us) {}
+  explicit constexpr Timestamp(int64_t us) : microseconds_(us) {}
+  constexpr int64_t UnsafeSeconds() const {
+    return (microseconds_ + 500000) / 1000000;
+  }
+  constexpr int64_t UnsafeMillis() const {
+    return (microseconds_ + 500) / 1000;
+  }
   int64_t microseconds_;
 };
 
 std::string ToString(const Timestamp& value);
 
+#ifdef UNIT_TEST
+inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
+    std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
+    Timestamp value) {
+  return stream << ToString(value);
+}
+#endif  // UNIT_TEST
+
 }  // namespace webrtc
 
 #endif  // API_UNITS_TIMESTAMP_H_
diff --git a/api/units/timestamp_unittest.cc b/api/units/timestamp_unittest.cc
index eecfe02..db894cc 100644
--- a/api/units/timestamp_unittest.cc
+++ b/api/units/timestamp_unittest.cc
@@ -13,6 +13,27 @@
 
 namespace webrtc {
 namespace test {
+TEST(TimestampTest, ConstExpr) {
+  constexpr int64_t kValue = 12345;
+  constexpr Timestamp kTimestampInf = Timestamp::Infinity();
+  static_assert(kTimestampInf.IsInfinite(), "");
+  static_assert(kTimestampInf.ms_or(-1) == -1, "");
+
+  constexpr Timestamp kTimestampSeconds = Timestamp::Seconds<kValue>();
+  constexpr Timestamp kTimestampMs = Timestamp::Millis<kValue>();
+  constexpr Timestamp kTimestampUs = Timestamp::Micros<kValue>();
+
+  static_assert(kTimestampSeconds.seconds_or(0) == kValue, "");
+  static_assert(kTimestampMs.ms_or(0) == kValue, "");
+  static_assert(kTimestampUs.us_or(0) == kValue, "");
+
+  static_assert(kTimestampMs > kTimestampUs, "");
+
+  EXPECT_EQ(kTimestampSeconds.seconds(), kValue);
+  EXPECT_EQ(kTimestampMs.ms(), kValue);
+  EXPECT_EQ(kTimestampUs.us(), kValue);
+}
+
 TEST(TimestampTest, GetBackSameValues) {
   const int64_t kValue = 499;
   EXPECT_EQ(Timestamp::ms(kValue).ms(), kValue);
diff --git a/api/video/color_space.h b/api/video/color_space.h
index 736a170..8102647 100644
--- a/api/video/color_space.h
+++ b/api/video/color_space.h
@@ -30,27 +30,50 @@
   enum class PrimaryID {
     kInvalid,
     kBT709,
+    kBT470M,
+    kBT470BG,
     kSMPTE170M,  // Identical to BT601
     kSMPTE240M,
+    kFILM,
     kBT2020,
+    kSMPTEST428,
+    kSMPTEST431,
+    kSMPTEST432,
+    kJEDECP22,
   };
 
   enum class TransferID {
     kInvalid,
     kBT709,
+    kGAMMA22,
+    kGAMMA28,
     kSMPTE170M,
     kSMPTE240M,
-    kBT2020,
-    kBT2020_10,
+    kLINEAR,
+    kLOG,
+    kLOG_SQRT,
+    kIEC61966_2_4,
+    kBT1361_ECG,
     kIEC61966_2_1,
+    kBT2020_10,
+    kBT2020_12,
+    kSMPTEST2084,
+    kSMPTEST428,
+    kARIB_STD_B67,
   };
 
   enum class MatrixID {
     kInvalid,
+    kRGB,
     kBT709,
+    kFCC,
+    kBT470BG,
     kSMPTE170M,
     kSMPTE240M,
+    kYCOCG,
     kBT2020_NCL,
+    kBT2020_CL,
+    kSMPTE2085,
   };
 
   enum class RangeID {
diff --git a/api/video/encoded_frame.cc b/api/video/encoded_frame.cc
index f9152b2..26a794e 100644
--- a/api/video/encoded_frame.cc
+++ b/api/video/encoded_frame.cc
@@ -17,13 +17,5 @@
   return 0;
 }
 
-uint32_t EncodedFrame::Timestamp() const {
-  return timestamp;
-}
-
-void EncodedFrame::SetTimestamp(uint32_t rtp_timestamp) {
-  timestamp = rtp_timestamp;
-}
-
 }  // namespace video_coding
 }  // namespace webrtc
diff --git a/api/video/encoded_frame.h b/api/video/encoded_frame.h
index 1b0a26a..b8462c6 100644
--- a/api/video/encoded_frame.h
+++ b/api/video/encoded_frame.h
@@ -58,10 +58,6 @@
 
   virtual bool GetBitstream(uint8_t* destination) const = 0;
 
-  // The capture timestamp of this frame, using the 90 kHz RTP clock.
-  virtual uint32_t Timestamp() const;
-  virtual void SetTimestamp(uint32_t rtp_timestamp);
-
   // When this frame was received.
   virtual int64_t ReceivedTime() const = 0;
 
@@ -78,7 +74,6 @@
   bool is_keyframe() const { return num_references == 0; }
 
   VideoLayerFrameId id;
-  uint32_t timestamp = 0;
 
   // TODO(philipel): Add simple modify/access functions to prevent adding too
   // many |references|.
diff --git a/api/video/video_bitrate_allocation.h b/api/video/video_bitrate_allocation.h
index ce61734..9e2501d 100644
--- a/api/video/video_bitrate_allocation.h
+++ b/api/video/video_bitrate_allocation.h
@@ -16,7 +16,6 @@
 #include <vector>
 
 #include "absl/types/optional.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/api/video/video_bitrate_allocator.h b/api/video/video_bitrate_allocator.h
new file mode 100644
index 0000000..f85c633
--- /dev/null
+++ b/api/video/video_bitrate_allocator.h
@@ -0,0 +1,38 @@
+/*
+ *  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 API_VIDEO_VIDEO_BITRATE_ALLOCATOR_H_
+#define API_VIDEO_VIDEO_BITRATE_ALLOCATOR_H_
+
+#include "api/video/video_bitrate_allocation.h"
+
+namespace webrtc {
+
+class VideoBitrateAllocator {
+ public:
+  VideoBitrateAllocator() {}
+  virtual ~VideoBitrateAllocator() {}
+
+  virtual VideoBitrateAllocation GetAllocation(uint32_t total_bitrate_bps,
+                                               uint32_t framerate) = 0;
+};
+
+class VideoBitrateAllocationObserver {
+ public:
+  VideoBitrateAllocationObserver() {}
+  virtual ~VideoBitrateAllocationObserver() {}
+
+  virtual void OnBitrateAllocationUpdated(
+      const VideoBitrateAllocation& allocation) = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_VIDEO_VIDEO_BITRATE_ALLOCATOR_H_
diff --git a/api/video/video_bitrate_allocator_factory.h b/api/video/video_bitrate_allocator_factory.h
new file mode 100644
index 0000000..897c34f
--- /dev/null
+++ b/api/video/video_bitrate_allocator_factory.h
@@ -0,0 +1,32 @@
+/*
+ *  Copyright (c) 2018 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 API_VIDEO_VIDEO_BITRATE_ALLOCATOR_FACTORY_H_
+#define API_VIDEO_VIDEO_BITRATE_ALLOCATOR_FACTORY_H_
+
+#include <memory>
+#include "api/video/video_bitrate_allocator.h"
+#include "api/video_codecs/video_codec.h"
+
+namespace webrtc {
+
+// A factory that creates VideoBitrateAllocator.
+// NOTE: This class is still under development and may change without notice.
+class VideoBitrateAllocatorFactory {
+ public:
+  virtual ~VideoBitrateAllocatorFactory() = default;
+  // Creates a VideoBitrateAllocator for a specific video codec.
+  virtual std::unique_ptr<VideoBitrateAllocator> CreateVideoBitrateAllocator(
+      const VideoCodec& codec) = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_VIDEO_VIDEO_BITRATE_ALLOCATOR_FACTORY_H_
diff --git a/api/video/video_stream_encoder_create.cc b/api/video/video_stream_encoder_create.cc
new file mode 100644
index 0000000..3147d34
--- /dev/null
+++ b/api/video/video_stream_encoder_create.cc
@@ -0,0 +1,27 @@
+/*
+ *  Copyright (c) 2018 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 "api/video/video_stream_encoder_create.h"
+
+#include "absl/memory/memory.h"
+#include "video/video_stream_encoder.h"
+
+namespace webrtc {
+std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
+    uint32_t number_of_cores,
+    VideoStreamEncoderObserver* encoder_stats_observer,
+    const VideoStreamEncoderSettings& settings,
+    // Deprecated, used for tests only.
+    rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback) {
+  return absl::make_unique<VideoStreamEncoder>(
+      number_of_cores, encoder_stats_observer, settings, pre_encode_callback,
+      absl::make_unique<OveruseFrameDetector>(encoder_stats_observer));
+}
+}  // namespace webrtc
diff --git a/api/video/video_stream_encoder_create.h b/api/video/video_stream_encoder_create.h
new file mode 100644
index 0000000..9117273
--- /dev/null
+++ b/api/video/video_stream_encoder_create.h
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 2018 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 API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_
+#define API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_
+
+#include <map>
+#include <memory>
+#include <utility>
+
+#include "api/video/video_stream_encoder_interface.h"
+#include "api/video/video_stream_encoder_observer.h"
+#include "api/video/video_stream_encoder_settings.h"
+
+namespace webrtc {
+
+std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
+    uint32_t number_of_cores,
+    VideoStreamEncoderObserver* encoder_stats_observer,
+    const VideoStreamEncoderSettings& settings,
+    // Deprecated, used for tests only.
+    rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback);
+
+inline std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
+    uint32_t number_of_cores,
+    VideoStreamEncoderObserver* encoder_stats_observer,
+    const VideoStreamEncoderSettings& settings) {
+  return CreateVideoStreamEncoder(number_of_cores, encoder_stats_observer,
+                                  settings, nullptr);
+}
+
+}  // namespace webrtc
+
+#endif  // API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_
diff --git a/api/video/video_stream_encoder_interface.h b/api/video/video_stream_encoder_interface.h
index 44dc6f4..2f95e58 100644
--- a/api/video/video_stream_encoder_interface.h
+++ b/api/video/video_stream_encoder_interface.h
@@ -47,8 +47,6 @@
         int min_transmit_bitrate_bps) = 0;
   };
 
-  ~VideoStreamEncoderInterface() override = default;
-
   // Sets the source that will provide video frames to the VideoStreamEncoder's
   // OnFrame method. |degradation_preference| control whether or not resolution
   // or frame rate may be reduced. The VideoStreamEncoder registers itself with
diff --git a/api/video/video_stream_encoder_observer.cc b/api/video/video_stream_encoder_observer.cc
new file mode 100644
index 0000000..3b9bd52
--- /dev/null
+++ b/api/video/video_stream_encoder_observer.cc
@@ -0,0 +1,17 @@
+/*
+ *  Copyright (c) 2018 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 "api/video/video_stream_encoder_observer.h"
+
+namespace webrtc {
+
+VideoStreamEncoderObserver::AdaptationSteps::AdaptationSteps() = default;
+
+}  // namespace webrtc
diff --git a/api/video/video_stream_encoder_observer.h b/api/video/video_stream_encoder_observer.h
new file mode 100644
index 0000000..b940efd
--- /dev/null
+++ b/api/video/video_stream_encoder_observer.h
@@ -0,0 +1,95 @@
+/*
+ *  Copyright (c) 2018 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 API_VIDEO_VIDEO_STREAM_ENCODER_OBSERVER_H_
+#define API_VIDEO_VIDEO_STREAM_ENCODER_OBSERVER_H_
+
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/video_codecs/video_encoder.h"
+#include "api/video_codecs/video_encoder_config.h"
+
+namespace webrtc {
+
+// TODO(nisse): Used for the OnSendEncodedImage callback below. The callback
+// wants metadata such as size, encode timing, qp, but doesn't need actual
+// encoded data. So use some other type to represent that.
+class EncodedImage;
+
+// Broken out into a base class, with public inheritance below, only to ease
+// unit testing of the internal class OveruseFrameDetector.
+class CpuOveruseMetricsObserver {
+ public:
+  virtual ~CpuOveruseMetricsObserver() = default;
+  virtual void OnEncodedFrameTimeMeasured(int encode_duration_ms,
+                                          int encode_usage_percent) = 0;
+};
+
+class VideoStreamEncoderObserver : public CpuOveruseMetricsObserver {
+ public:
+  // Number of resolution and framerate reductions (unset if disabled).
+  struct AdaptationSteps {
+    AdaptationSteps();
+    absl::optional<int> num_resolution_reductions = 0;
+    absl::optional<int> num_framerate_reductions = 0;
+  };
+
+  // TODO(nisse): There are too many enums to represent this. Besides
+  // this one, see AdaptationObserverInterface::AdaptReason and
+  // WebRtcVideoChannel::AdaptReason.
+  enum class AdaptationReason {
+    kNone,  // Used for reset of counters.
+    kCpu,
+    kQuality,
+  };
+
+  // TODO(nisse): Duplicates enum EncodedImageCallback::DropReason.
+  enum class DropReason {
+    kSource,
+    kEncoderQueue,
+    kEncoder,
+    kMediaOptimization
+  };
+
+  ~VideoStreamEncoderObserver() override = default;
+
+  virtual void OnIncomingFrame(int width, int height) = 0;
+
+  // TODO(nisse): Merge into one callback per encoded frame.
+  using CpuOveruseMetricsObserver::OnEncodedFrameTimeMeasured;
+  virtual void OnSendEncodedImage(const EncodedImage& encoded_image,
+                                  const CodecSpecificInfo* codec_info) = 0;
+
+  virtual void OnFrameDropped(DropReason reason) = 0;
+
+  // Used to indicate change in content type, which may require a change in
+  // how stats are collected and set the configured preferred media bitrate.
+  virtual void OnEncoderReconfigured(
+      const VideoEncoderConfig& encoder_config,
+      const std::vector<VideoStream>& streams) = 0;
+
+  virtual void OnAdaptationChanged(AdaptationReason reason,
+                                   const AdaptationSteps& cpu_steps,
+                                   const AdaptationSteps& quality_steps) = 0;
+  virtual void OnMinPixelLimitReached() = 0;
+  virtual void OnInitialQualityResolutionAdaptDown() = 0;
+
+  virtual void OnSuspendChange(bool is_suspended) = 0;
+
+  // TODO(nisse): VideoStreamEncoder wants to query the stats, which makes this
+  // not a pure observer. GetInputFrameRate is needed for the cpu adaptation, so
+  // can be deleted if that responsibility is moved out to a VideoStreamAdaptor
+  // class.
+  virtual int GetInputFrameRate() const = 0;
+};
+
+}  // namespace webrtc
+#endif  // API_VIDEO_VIDEO_STREAM_ENCODER_OBSERVER_H_
diff --git a/api/video/video_stream_encoder_settings.h b/api/video/video_stream_encoder_settings.h
new file mode 100644
index 0000000..b67f33c
--- /dev/null
+++ b/api/video/video_stream_encoder_settings.h
@@ -0,0 +1,31 @@
+/*
+ *  Copyright (c) 2018 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 API_VIDEO_VIDEO_STREAM_ENCODER_SETTINGS_H_
+#define API_VIDEO_VIDEO_STREAM_ENCODER_SETTINGS_H_
+
+#include "api/video_codecs/video_encoder_factory.h"
+
+namespace webrtc {
+
+struct VideoStreamEncoderSettings {
+  VideoStreamEncoderSettings() = default;
+
+  // Enables the new method to estimate the cpu load from encoding, used for
+  // cpu adaptation.
+  bool experiment_cpu_load_estimator = false;
+
+  // Ownership stays with WebrtcVideoEngine (delegated from PeerConnection).
+  VideoEncoderFactory* encoder_factory = nullptr;
+};
+
+}  // namespace webrtc
+
+#endif  // API_VIDEO_VIDEO_STREAM_ENCODER_SETTINGS_H_
diff --git a/audio/BUILD.gn b/audio/BUILD.gn
index 22ceeb6..ae4c67e 100644
--- a/audio/BUILD.gn
+++ b/audio/BUILD.gn
@@ -54,7 +54,6 @@
     "../api/audio:audio_frame_api",
     "../api/audio:audio_mixer_api",
     "../api/audio_codecs:audio_codecs_api",
-    "../api/audio_codecs:builtin_audio_encoder_factory",
     "../call:bitrate_allocator",
     "../call:call_interfaces",
     "../call:rtp_interfaces",
@@ -100,6 +99,9 @@
     ]
     deps = [
       ":audio",
+      "../api:simulated_network_api",
+      "../call:fake_network",
+      "../call:simulated_network",
       "../system_wrappers:system_wrappers",
       "../test:test_common",
       "../test:test_support",
@@ -121,6 +123,7 @@
       "audio_state_unittest.cc",
       "mock_voe_channel_proxy.h",
       "remix_resample_unittest.cc",
+      "test/audio_stats_test.cc",
       "time_interval_unittest.cc",
       "transport_feedback_packet_loss_tracker_unittest.cc",
     ]
@@ -159,11 +162,6 @@
       "//third_party/abseil-cpp/absl/memory",
     ]
 
-    if (!rtc_use_memcheck) {
-      # This test is timing dependent, which rules out running on memcheck bots.
-      sources += [ "test/audio_stats_test.cc" ]
-    }
-
     if (!build_with_chromium && is_clang) {
       # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
       suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
@@ -180,6 +178,7 @@
 
       deps = [
         ":audio_end_to_end_test",
+        "../api:simulated_network_api",
         "../common_audio",
         "../rtc_base:rtc_base_approved",
         "../system_wrappers",
@@ -251,6 +250,9 @@
       "test/audio_bwe_integration_test.h",
     ]
     deps = [
+      "../api:simulated_network_api",
+      "../call:fake_network",
+      "../call:simulated_network",
       "../common_audio",
       "../rtc_base:rtc_base_approved",
       "../system_wrappers",
diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc
index 6f43576..b507afc 100644
--- a/audio/audio_receive_stream.cc
+++ b/audio/audio_receive_stream.cc
@@ -20,7 +20,6 @@
 #include "audio/conversion.h"
 #include "call/rtp_stream_receiver_controller_interface.h"
 #include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
-#include "modules/rtp_rtcp/include/rtp_receiver.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
@@ -66,16 +65,16 @@
 std::unique_ptr<voe::ChannelProxy> CreateChannelAndProxy(
     webrtc::AudioState* audio_state,
     ProcessThread* module_process_thread,
-    const webrtc::AudioReceiveStream::Config& config) {
+    const webrtc::AudioReceiveStream::Config& config,
+    RtcEventLog* event_log) {
   RTC_DCHECK(audio_state);
   internal::AudioState* internal_audio_state =
       static_cast<internal::AudioState*>(audio_state);
-  return std::unique_ptr<voe::ChannelProxy>(
-      new voe::ChannelProxy(std::unique_ptr<voe::Channel>(new voe::Channel(
-          module_process_thread, internal_audio_state->audio_device_module(),
-          nullptr /* RtcpRttStats */, config.jitter_buffer_max_packets,
-          config.jitter_buffer_fast_accelerate, config.decoder_factory,
-          config.codec_pair_id))));
+  return absl::make_unique<voe::ChannelProxy>(absl::make_unique<voe::Channel>(
+      module_process_thread, internal_audio_state->audio_device_module(),
+      nullptr /* RtcpRttStats */, event_log, config.rtp.remote_ssrc,
+      config.jitter_buffer_max_packets, config.jitter_buffer_fast_accelerate,
+      config.decoder_factory, config.codec_pair_id));
 }
 }  // namespace
 
@@ -93,7 +92,8 @@
                          event_log,
                          CreateChannelAndProxy(audio_state.get(),
                                                module_process_thread,
-                                               config)) {}
+                                               config,
+                                               event_log)) {}
 
 AudioReceiveStream::AudioReceiveStream(
     RtpStreamReceiverControllerInterface* receiver_controller,
@@ -112,7 +112,6 @@
 
   module_process_thread_checker_.DetachFromThread();
 
-  channel_proxy_->SetRtcEventLog(event_log);
   channel_proxy_->RegisterTransport(config.rtcp_send_transport);
 
   // Configure bandwidth estimation.
@@ -132,7 +131,6 @@
   channel_proxy_->DisassociateSendChannel();
   channel_proxy_->RegisterTransport(nullptr);
   channel_proxy_->ResetReceiverCongestionControlObjects();
-  channel_proxy_->SetRtcEventLog(nullptr);
 }
 
 void AudioReceiveStream::Reconfigure(
@@ -257,26 +255,12 @@
 
 absl::optional<Syncable::Info> AudioReceiveStream::GetInfo() const {
   RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
-  Syncable::Info info;
+  absl::optional<Syncable::Info> info = channel_proxy_->GetSyncInfo();
 
-  RtpRtcp* rtp_rtcp = nullptr;
-  RtpReceiver* rtp_receiver = nullptr;
-  channel_proxy_->GetRtpRtcp(&rtp_rtcp, &rtp_receiver);
-  RTC_DCHECK(rtp_rtcp);
-  RTC_DCHECK(rtp_receiver);
-
-  if (!rtp_receiver->GetLatestTimestamps(
-          &info.latest_received_capture_timestamp,
-          &info.latest_receive_time_ms)) {
+  if (!info)
     return absl::nullopt;
-  }
-  if (rtp_rtcp->RemoteNTP(&info.capture_time_ntp_secs,
-                          &info.capture_time_ntp_frac, nullptr, nullptr,
-                          &info.capture_time_source_clock) != 0) {
-    return absl::nullopt;
-  }
 
-  info.current_delay_ms = channel_proxy_->GetDelayEstimate();
+  info->current_delay_ms = channel_proxy_->GetDelayEstimate();
   return info;
 }
 
@@ -360,9 +344,7 @@
     channel_proxy->SetLocalSSRC(new_config.rtp.local_ssrc);
   }
 
-  if (first_time) {
-    channel_proxy->SetRemoteSSRC(new_config.rtp.remote_ssrc);
-  } else {
+  if (!first_time) {
     // Remote ssrc can't be changed mid-stream.
     RTC_DCHECK_EQ(old_config.rtp.remote_ssrc, new_config.rtp.remote_ssrc);
   }
diff --git a/audio/audio_receive_stream_unittest.cc b/audio/audio_receive_stream_unittest.cc
index 51635f6..eb93bd0 100644
--- a/audio/audio_receive_stream_unittest.cc
+++ b/audio/audio_receive_stream_unittest.cc
@@ -83,7 +83,6 @@
 
     channel_proxy_ = new testing::StrictMock<MockVoEChannelProxy>();
     EXPECT_CALL(*channel_proxy_, SetLocalSSRC(kLocalSsrc)).Times(1);
-    EXPECT_CALL(*channel_proxy_, SetRemoteSSRC(kRemoteSsrc)).Times(1);
     EXPECT_CALL(*channel_proxy_, SetNACKStatus(true, 15)).Times(1);
     EXPECT_CALL(*channel_proxy_,
                 RegisterReceiverCongestionControlObjects(&packet_router_))
@@ -91,11 +90,6 @@
     EXPECT_CALL(*channel_proxy_, ResetReceiverCongestionControlObjects())
         .Times(1);
     EXPECT_CALL(*channel_proxy_, RegisterTransport(nullptr)).Times(2);
-    testing::Expectation expect_set =
-        EXPECT_CALL(*channel_proxy_, SetRtcEventLog(&event_log_)).Times(1);
-    EXPECT_CALL(*channel_proxy_, SetRtcEventLog(testing::IsNull()))
-        .Times(1)
-        .After(expect_set);
     EXPECT_CALL(*channel_proxy_, DisassociateSendChannel()).Times(1);
     EXPECT_CALL(*channel_proxy_, SetReceiveCodecs(_))
         .WillRepeatedly(Invoke([](const std::map<int, SdpAudioFormat>& codecs) {
@@ -236,11 +230,11 @@
   const int kTransportSequenceNumberValue = 1234;
   std::vector<uint8_t> rtp_packet = CreateRtpHeaderWithOneByteExtension(
       kTransportSequenceNumberId, kTransportSequenceNumberValue, 2);
-  PacketTime packet_time(5678000, 0);
+  constexpr int64_t packet_time_us = 5678000;
 
   RtpPacketReceived parsed_packet;
   ASSERT_TRUE(parsed_packet.Parse(&rtp_packet[0], rtp_packet.size()));
-  parsed_packet.set_arrival_time_ms((packet_time.timestamp + 500) / 1000);
+  parsed_packet.set_arrival_time_ms((packet_time_us + 500) / 1000);
 
   EXPECT_CALL(*helper.channel_proxy(),
               OnRtpPacket(testing::Ref(parsed_packet)));
diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc
index de1be2c..0f725c4 100644
--- a/audio/audio_send_stream.cc
+++ b/audio/audio_send_stream.cc
@@ -14,6 +14,8 @@
 #include <utility>
 #include <vector>
 
+#include "absl/memory/memory.h"
+
 #include "audio/audio_state.h"
 #include "audio/channel_proxy.h"
 #include "audio/conversion.h"
@@ -48,14 +50,14 @@
     webrtc::AudioState* audio_state,
     rtc::TaskQueue* worker_queue,
     ProcessThread* module_process_thread,
-    RtcpRttStats* rtcp_rtt_stats) {
+    RtcpRttStats* rtcp_rtt_stats,
+    RtcEventLog* event_log) {
   RTC_DCHECK(audio_state);
   internal::AudioState* internal_audio_state =
       static_cast<internal::AudioState*>(audio_state);
-  return std::unique_ptr<voe::ChannelProxy>(
-      new voe::ChannelProxy(std::unique_ptr<voe::Channel>(new voe::Channel(
-          worker_queue, module_process_thread,
-          internal_audio_state->audio_device_module(), rtcp_rtt_stats))));
+  return absl::make_unique<voe::ChannelProxy>(absl::make_unique<voe::Channel>(
+      worker_queue, module_process_thread,
+      internal_audio_state->audio_device_module(), rtcp_rtt_stats, event_log));
 }
 }  // namespace
 
@@ -105,7 +107,8 @@
                       CreateChannelAndProxy(audio_state.get(),
                                             worker_queue,
                                             module_process_thread,
-                                            rtcp_rtt_stats)) {}
+                                            rtcp_rtt_stats,
+                                            event_log)) {}
 
 AudioSendStream::AudioSendStream(
     const webrtc::AudioSendStream::Config& config,
@@ -139,10 +142,8 @@
   RTC_DCHECK(transport);
   RTC_DCHECK(overall_call_lifetime_);
 
-  channel_proxy_->SetRtcEventLog(event_log_);
   channel_proxy_->SetRTCPStatus(true);
-  RtpReceiver* rtpReceiver = nullptr;  // Unused, but required for call.
-  channel_proxy_->GetRtpRtcp(&rtp_rtcp_module_, &rtpReceiver);
+  rtp_rtcp_module_ = channel_proxy_->GetRtpRtcp();
   RTC_DCHECK(rtp_rtcp_module_);
 
   ConfigureStream(this, config, true);
@@ -159,7 +160,6 @@
   transport_->DeRegisterPacketFeedbackObserver(this);
   channel_proxy_->RegisterTransport(nullptr);
   channel_proxy_->ResetSenderCongestionControlObjects();
-  channel_proxy_->SetRtcEventLog(nullptr);
   // Lifetime can only be updated after deregistering
   // |timed_send_transport_adapter_| in the underlying channel object to avoid
   // data races in |active_lifetime_|.
diff --git a/audio/audio_send_stream_unittest.cc b/audio/audio_send_stream_unittest.cc
index 2341d4e..f5d6796 100644
--- a/audio/audio_send_stream_unittest.cc
+++ b/audio/audio_send_stream_unittest.cc
@@ -189,12 +189,9 @@
   void SetupDefaultChannelProxy(bool audio_bwe_enabled) {
     EXPECT_TRUE(channel_proxy_ == nullptr);
     channel_proxy_ = new testing::StrictMock<MockVoEChannelProxy>();
-    EXPECT_CALL(*channel_proxy_, GetRtpRtcp(_, _))
-        .WillRepeatedly(Invoke(
-            [this](RtpRtcp** rtp_rtcp_module, RtpReceiver** rtp_receiver) {
-              *rtp_rtcp_module = &this->rtp_rtcp_;
-              *rtp_receiver = nullptr;  // Not deemed necessary for tests yet.
-            }));
+    EXPECT_CALL(*channel_proxy_, GetRtpRtcp()).WillRepeatedly(Invoke([this]() {
+      return &this->rtp_rtcp_;
+    }));
     EXPECT_CALL(*channel_proxy_, SetRTCPStatus(true)).Times(1);
     EXPECT_CALL(*channel_proxy_, SetLocalSSRC(kSsrc)).Times(1);
     EXPECT_CALL(*channel_proxy_, SetRTCP_CNAME(StrEq(kCName))).Times(1);
@@ -224,9 +221,6 @@
       EXPECT_CALL(*channel_proxy_, RegisterTransport(_)).Times(1);
       EXPECT_CALL(*channel_proxy_, RegisterTransport(nullptr)).Times(1);
     }
-    EXPECT_CALL(*channel_proxy_, SetRtcEventLog(testing::NotNull())).Times(1);
-    EXPECT_CALL(*channel_proxy_, SetRtcEventLog(testing::IsNull()))
-        .Times(1);  // Destructor resets the event log
   }
 
   void SetupMockForSetupSendCodec(bool expect_set_encoder_call) {
@@ -385,8 +379,7 @@
   EXPECT_EQ(kSsrc, stats.local_ssrc);
   EXPECT_EQ(static_cast<int64_t>(kCallStats.bytesSent), stats.bytes_sent);
   EXPECT_EQ(kCallStats.packetsSent, stats.packets_sent);
-  EXPECT_EQ(static_cast<int32_t>(kReportBlock.cumulative_num_packets_lost),
-            stats.packets_lost);
+  EXPECT_EQ(kReportBlock.cumulative_num_packets_lost, stats.packets_lost);
   EXPECT_EQ(Q8ToFloat(kReportBlock.fraction_lost), stats.fraction_lost);
   EXPECT_EQ(std::string(kIsacCodec.plname), stats.codec_name);
   EXPECT_EQ(static_cast<int32_t>(kReportBlock.extended_highest_sequence_number),
diff --git a/audio/audio_state.cc b/audio/audio_state.cc
index 35ea03d..7d473ae 100644
--- a/audio/audio_state.cc
+++ b/audio/audio_state.cc
@@ -39,6 +39,15 @@
   RTC_DCHECK(sending_streams_.empty());
 }
 
+AudioProcessing* AudioState::audio_processing() {
+  RTC_DCHECK(config_.audio_processing);
+  return config_.audio_processing.get();
+}
+
+AudioTransport* AudioState::audio_transport() {
+  return &audio_transport_;
+}
+
 bool AudioState::typing_noise_detected() const {
   RTC_DCHECK(thread_checker_.CalledOnValidThread());
   return audio_transport_.typing_noise_detected();
diff --git a/audio/audio_state.h b/audio/audio_state.h
index 689534b..9e302c4 100644
--- a/audio/audio_state.h
+++ b/audio/audio_state.h
@@ -35,11 +35,8 @@
   explicit AudioState(const AudioState::Config& config);
   ~AudioState() override;
 
-  AudioProcessing* audio_processing() override {
-    RTC_DCHECK(config_.audio_processing);
-    return config_.audio_processing.get();
-  }
-  AudioTransport* audio_transport() override { return &audio_transport_; }
+  AudioProcessing* audio_processing() override;
+  AudioTransport* audio_transport() override;
 
   void SetPlayout(bool enabled) override;
   void SetRecording(bool enabled) override;
diff --git a/audio/channel.cc b/audio/channel.cc
index 6acc65e..d884e03 100644
--- a/audio/channel.cc
+++ b/audio/channel.cc
@@ -29,8 +29,6 @@
 #include "modules/audio_processing/include/audio_processing.h"
 #include "modules/pacing/packet_router.h"
 #include "modules/rtp_rtcp/include/receive_statistics.h"
-#include "modules/rtp_rtcp/include/rtp_payload_registry.h"
-#include "modules/rtp_rtcp/include/rtp_receiver.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "modules/rtp_rtcp/source/rtp_receiver_strategy.h"
 #include "modules/utility/include/process_thread.h"
@@ -63,36 +61,6 @@
 
 const int kTelephoneEventAttenuationdB = 10;
 
-class RtcEventLogProxy final : public webrtc::RtcEventLog {
- public:
-  RtcEventLogProxy() : event_log_(nullptr) {}
-
-  bool StartLogging(std::unique_ptr<RtcEventLogOutput> output,
-                    int64_t output_period_ms) override {
-    RTC_NOTREACHED();
-    return false;
-  }
-
-  void StopLogging() override { RTC_NOTREACHED(); }
-
-  void Log(std::unique_ptr<RtcEvent> event) override {
-    rtc::CritScope lock(&crit_);
-    if (event_log_) {
-      event_log_->Log(std::move(event));
-    }
-  }
-
-  void SetEventLog(RtcEventLog* event_log) {
-    rtc::CritScope lock(&crit_);
-    event_log_ = event_log;
-  }
-
- private:
-  rtc::CriticalSection crit_;
-  RtcEventLog* event_log_ RTC_GUARDED_BY(crit_);
-  RTC_DISALLOW_COPY_AND_ASSIGN(RtcEventLogProxy);
-};
-
 class TransportFeedbackProxy : public TransportFeedbackObserver {
  public:
   TransportFeedbackProxy() : feedback_observer_(nullptr) {
@@ -374,8 +342,7 @@
   }
 
   int64_t round_trip_time = 0;
-  _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), &round_trip_time, NULL, NULL,
-                      NULL);
+  _rtpRtcpModule->RTT(remote_ssrc_, &round_trip_time, NULL, NULL, NULL);
 
   std::vector<uint16_t> nack_list = audio_coding_->GetNackList(round_trip_time);
   if (!nack_list.empty()) {
@@ -393,7 +360,7 @@
 
   unsigned int ssrc;
   RTC_CHECK_EQ(GetRemoteSSRC(ssrc), 0);
-  event_log_proxy_->Log(absl::make_unique<RtcEventAudioPlayout>(ssrc));
+  event_log_->Log(absl::make_unique<RtcEventAudioPlayout>(ssrc));
   // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
   bool muted;
   if (audio_coding_->PlayoutData10Ms(audio_frame->sample_rate_hz_, audio_frame,
@@ -502,10 +469,13 @@
 Channel::Channel(rtc::TaskQueue* encoder_queue,
                  ProcessThread* module_process_thread,
                  AudioDeviceModule* audio_device_module,
-                 RtcpRttStats* rtcp_rtt_stats)
+                 RtcpRttStats* rtcp_rtt_stats,
+                 RtcEventLog* rtc_event_log)
     : Channel(module_process_thread,
               audio_device_module,
               rtcp_rtt_stats,
+              rtc_event_log,
+              0,
               0,
               false,
               rtc::scoped_refptr<AudioDecoderFactory>(),
@@ -517,19 +487,16 @@
 Channel::Channel(ProcessThread* module_process_thread,
                  AudioDeviceModule* audio_device_module,
                  RtcpRttStats* rtcp_rtt_stats,
+                 RtcEventLog* rtc_event_log,
+                 uint32_t remote_ssrc,
                  size_t jitter_buffer_max_packets,
                  bool jitter_buffer_fast_playout,
                  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
                  absl::optional<AudioCodecPairId> codec_pair_id)
-    : event_log_proxy_(new RtcEventLogProxy()),
-      rtp_payload_registry_(new RTPPayloadRegistry()),
+    : event_log_(rtc_event_log),
       rtp_receive_statistics_(
           ReceiveStatistics::Create(Clock::GetRealTimeClock())),
-      rtp_receiver_(
-          RtpReceiver::CreateAudioReceiver(Clock::GetRealTimeClock(),
-                                           this,
-                                           rtp_payload_registry_.get())),
-      telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()),
+      remote_ssrc_(remote_ssrc),
       _outputAudioLevel(),
       _timeStamp(0),  // This is just an offset, RTP module will add it's own
                       // random offset
@@ -570,6 +537,7 @@
 
   _outputAudioLevel.Clear();
 
+  rtp_receive_statistics_->EnableRetransmitDetection(remote_ssrc_, true);
   RtpRtcp::Configuration configuration;
   configuration.audio = true;
   configuration.outgoing_transport = this;
@@ -582,14 +550,14 @@
         seq_num_allocator_proxy_.get();
     configuration.transport_feedback_callback = feedback_observer_proxy_.get();
   }
-  configuration.event_log = &(*event_log_proxy_);
+  configuration.event_log = event_log_;
   configuration.rtt_stats = rtcp_rtt_stats;
   configuration.retransmission_rate_limiter =
       retransmission_rate_limiter_.get();
 
   _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
   _rtpRtcpModule->SetSendingMediaStatus(false);
-
+  _rtpRtcpModule->SetRemoteSSRC(remote_ssrc_);
   Init();
 }
 
@@ -616,7 +584,6 @@
   // disabled by the user.
   // After StopListen (when no sockets exists), RTCP packets will no longer
   // be transmitted since the Transport object will then be invalid.
-  telephone_event_handler_->SetTelephoneEventForwardToDecoder(true);
   // RTCP is enabled by default.
   _rtpRtcpModule->SetRTCPStatus(RtcpMode::kCompound);
 
@@ -814,6 +781,22 @@
   });
 }
 
+std::vector<webrtc::RtpSource> Channel::GetSources() const {
+  int64_t now_ms = rtc::TimeMillis();
+  std::vector<RtpSource> sources;
+  {
+    rtc::CritScope cs(&rtp_sources_lock_);
+    sources = contributing_sources_.GetSources(now_ms);
+    if (last_received_rtp_system_time_ms_ >=
+        now_ms - ContributingSources::kHistoryMs) {
+      sources.emplace_back(*last_received_rtp_system_time_ms_, remote_ssrc_,
+                           RtpSourceType::SSRC);
+      sources.back().set_audio_level(last_received_rtp_audio_level_);
+    }
+  }
+  return sources;
+}
+
 void Channel::OnUplinkPacketLossRate(float packet_loss_rate) {
   if (use_twcc_plr_for_ana_)
     return;
@@ -825,7 +808,10 @@
 }
 
 void Channel::SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs) {
-  rtp_payload_registry_->SetAudioReceivePayloads(codecs);
+  for (const auto& kv : codecs) {
+    RTC_DCHECK_GE(kv.second.clockrate_hz, 1000);
+    payload_type_frequencies_[kv.first] = kv.second.clockrate_hz;
+  }
   audio_coding_->SetReceiveCodecs(codecs);
 }
 
@@ -833,8 +819,8 @@
   bool success = false;
   audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
     if (*encoder) {
-      success = (*encoder)->EnableAudioNetworkAdaptor(config_string,
-                                                      event_log_proxy_.get());
+      success =
+          (*encoder)->EnableAudioNetworkAdaptor(config_string, event_log_);
     }
   });
   return success;
@@ -862,21 +848,38 @@
   _transportPtr = transport;
 }
 
+// TODO(nisse): Move receive logic up to AudioReceiveStream.
 void Channel::OnRtpPacket(const RtpPacketReceived& packet) {
+  int64_t now_ms = rtc::TimeMillis();
+  uint8_t audio_level;
+  bool voice_activity;
+  bool has_audio_level =
+      packet.GetExtension<::webrtc::AudioLevel>(&voice_activity, &audio_level);
+
+  {
+    rtc::CritScope cs(&rtp_sources_lock_);
+    last_received_rtp_timestamp_ = packet.Timestamp();
+    last_received_rtp_system_time_ms_ = now_ms;
+    if (has_audio_level)
+      last_received_rtp_audio_level_ = audio_level;
+    std::vector<uint32_t> csrcs = packet.Csrcs();
+    contributing_sources_.Update(now_ms, csrcs);
+  }
+
   RTPHeader header;
   packet.GetHeader(&header);
 
   // Store playout timestamp for the received RTP packet
   UpdatePlayoutTimestamp(false);
 
-  header.payload_type_frequency =
-      rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
-  if (header.payload_type_frequency >= 0) {
-    rtp_receive_statistics_->IncomingPacket(header, packet.size(),
-                                            IsPacketRetransmitted(header));
+  const auto& it = payload_type_frequencies_.find(header.payloadType);
+  if (it == payload_type_frequencies_.end())
+    return;
+  header.payload_type_frequency = it->second;
 
-    ReceivePacket(packet.data(), packet.size(), header);
-  }
+  rtp_receive_statistics_->IncomingPacket(header, packet.size());
+
+  ReceivePacket(packet.data(), packet.size(), header);
 }
 
 bool Channel::ReceivePacket(const uint8_t* packet,
@@ -885,22 +888,16 @@
   const uint8_t* payload = packet + header.headerLength;
   assert(packet_length >= header.headerLength);
   size_t payload_length = packet_length - header.headerLength;
-  const auto pl =
-      rtp_payload_registry_->PayloadTypeToPayload(header.payloadType);
-  if (!pl) {
-    return false;
-  }
-  return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
-                                          pl->typeSpecific);
-}
+  WebRtcRTPHeader webrtc_rtp_header = {};
+  webrtc_rtp_header.header = header;
 
-bool Channel::IsPacketRetransmitted(const RTPHeader& header) const {
-  StreamStatistician* statistician =
-      rtp_receive_statistics_->GetStatistician(header.ssrc);
-  if (!statistician)
-    return false;
-  // Check if this is a retransmission.
-  return statistician->IsRetransmitOfOldPacket(header);
+  const size_t payload_data_length = payload_length - header.paddingLength;
+  if (payload_data_length == 0) {
+    webrtc_rtp_header.frameType = kEmptyFrame;
+    return OnReceivedPayloadData(nullptr, 0, &webrtc_rtp_header);
+  }
+  return OnReceivedPayloadData(payload, payload_data_length,
+                               &webrtc_rtp_header);
 }
 
 int32_t Channel::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
@@ -1018,19 +1015,15 @@
   return 0;
 }
 
-void Channel::SetRemoteSSRC(uint32_t ssrc) {
-  // Update ssrc so that NTP for AV sync can be updated.
-  _rtpRtcpModule->SetRemoteSSRC(ssrc);
-}
-
 void Channel::SetMid(const std::string& mid, int extension_id) {
   int ret = SetSendRtpHeaderExtension(true, kRtpExtensionMid, extension_id);
   RTC_DCHECK_EQ(0, ret);
   _rtpRtcpModule->SetMid(mid);
 }
 
+// TODO(nisse): Pass ssrc in return value instead.
 int Channel::GetRemoteSSRC(unsigned int& ssrc) {
-  ssrc = rtp_receiver_->SSRC();
+  ssrc = remote_ssrc_;
   return 0;
 }
 
@@ -1148,7 +1141,7 @@
   // based on received packets.
   RtcpStatistics statistics;
   StreamStatistician* statistician =
-      rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
+      rtp_receive_statistics_->GetStatistician(remote_ssrc_);
   if (statistician) {
     statistician->GetStatistics(&statistics,
                                 _rtpRtcpModule->RTCP() == RtcpMode::kOff);
@@ -1270,10 +1263,6 @@
   associated_send_channel_ = channel;
 }
 
-void Channel::SetRtcEventLog(RtcEventLog* event_log) {
-  event_log_proxy_->SetEventLog(event_log);
-}
-
 void Channel::UpdateOverheadForEncoder() {
   size_t overhead_per_packet =
       transport_overhead_per_packet_ + rtp_overhead_per_packet_;
@@ -1342,11 +1331,26 @@
   return 0;
 }
 
-int Channel::GetRtpRtcp(RtpRtcp** rtpRtcpModule,
-                        RtpReceiver** rtp_receiver) const {
-  *rtpRtcpModule = _rtpRtcpModule.get();
-  *rtp_receiver = rtp_receiver_.get();
-  return 0;
+RtpRtcp* Channel::GetRtpRtcp() const {
+  return _rtpRtcpModule.get();
+}
+
+absl::optional<Syncable::Info> Channel::GetSyncInfo() const {
+  Syncable::Info info;
+  if (_rtpRtcpModule->RemoteNTP(&info.capture_time_ntp_secs,
+                                &info.capture_time_ntp_frac, nullptr, nullptr,
+                                &info.capture_time_source_clock) != 0) {
+    return absl::nullopt;
+  }
+  {
+    rtc::CritScope cs(&rtp_sources_lock_);
+    if (!last_received_rtp_timestamp_ || !last_received_rtp_system_time_ms_) {
+      return absl::nullopt;
+    }
+    info.latest_received_capture_timestamp = *last_received_rtp_timestamp_;
+    info.latest_receive_time_ms = *last_received_rtp_system_time_ms_;
+  }
+  return info;
 }
 
 void Channel::UpdatePlayoutTimestamp(bool rtcp) {
@@ -1426,25 +1430,23 @@
     return rtt;
   }
 
-  uint32_t remoteSSRC = rtp_receiver_->SSRC();
   std::vector<RTCPReportBlock>::const_iterator it = report_blocks.begin();
   for (; it != report_blocks.end(); ++it) {
-    if (it->sender_ssrc == remoteSSRC)
+    if (it->sender_ssrc == remote_ssrc_)
       break;
   }
-  if (it == report_blocks.end()) {
-    // We have not received packets with SSRC matching the report blocks.
-    // To calculate RTT we try with the SSRC of the first report block.
-    // This is very important for send-only channels where we don't know
-    // the SSRC of the other end.
-    remoteSSRC = report_blocks[0].sender_ssrc;
-  }
+
+  // If we have not received packets with SSRC matching the report blocks, use
+  // the SSRC of the first report block for calculating the RTT. This is very
+  // important for send-only channels where we don't know the SSRC of the other
+  // end.
+  uint32_t ssrc =
+      (it == report_blocks.end()) ? report_blocks[0].sender_ssrc : remote_ssrc_;
 
   int64_t avg_rtt = 0;
   int64_t max_rtt = 0;
   int64_t min_rtt = 0;
-  if (_rtpRtcpModule->RTT(remoteSSRC, &rtt, &avg_rtt, &min_rtt, &max_rtt) !=
-      0) {
+  if (_rtpRtcpModule->RTT(ssrc, &rtt, &avg_rtt, &min_rtt, &max_rtt) != 0) {
     return 0;
   }
   return rtt;
diff --git a/audio/channel.h b/audio/channel.h
index 8d1a26b..562e79e 100644
--- a/audio/channel.h
+++ b/audio/channel.h
@@ -21,14 +21,16 @@
 #include "api/audio_codecs/audio_encoder.h"
 #include "api/call/audio_sink.h"
 #include "api/call/transport.h"
+#include "api/rtpreceiverinterface.h"
 #include "audio/audio_level.h"
+#include "call/syncable.h"
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/include/audio_coding_module.h"
 #include "modules/audio_processing/rms_level.h"
 #include "modules/rtp_rtcp/include/remote_ntp_time_estimator.h"
 #include "modules/rtp_rtcp/include/rtp_header_parser.h"
-#include "modules/rtp_rtcp/include/rtp_receiver.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp.h"
+#include "modules/rtp_rtcp/source/contributing_sources.h"
 #include "rtc_base/criticalsection.h"
 #include "rtc_base/event.h"
 #include "rtc_base/task_queue.h"
@@ -51,12 +53,9 @@
 class ReceiveStatistics;
 class RemoteNtpTimeEstimator;
 class RtcEventLog;
-class RTPPayloadRegistry;
-class RTPReceiverAudio;
 class RtpPacketReceived;
 class RtpRtcp;
 class RtpTransportControllerSendInterface;
-class TelephoneEventHandler;
 
 struct SenderInfo;
 
@@ -80,7 +79,7 @@
   uint32_t sender_SSRC;  // SSRC of sender
   uint32_t source_SSRC;
   uint8_t fraction_lost;
-  uint32_t cumulative_num_packets_lost;
+  int32_t cumulative_num_packets_lost;
   uint32_t extended_highest_sequence_number;
   uint32_t interarrival_jitter;
   uint32_t last_SR_timestamp;
@@ -89,7 +88,6 @@
 
 namespace voe {
 
-class RtcEventLogProxy;
 class RtpPacketSenderProxy;
 class TransportFeedbackProxy;
 class TransportSequenceNumberProxy;
@@ -150,11 +148,14 @@
   Channel(rtc::TaskQueue* encoder_queue,
           ProcessThread* module_process_thread,
           AudioDeviceModule* audio_device_module,
-          RtcpRttStats* rtcp_rtt_stats);
+          RtcpRttStats* rtcp_rtt_stats,
+          RtcEventLog* rtc_event_log);
   // Used for receive streams.
   Channel(ProcessThread* module_process_thread,
           AudioDeviceModule* audio_device_module,
           RtcpRttStats* rtcp_rtt_stats,
+          RtcEventLog* rtc_event_log,
+          uint32_t remote_ssrc,
           size_t jitter_buffer_max_packets,
           bool jitter_buffer_fast_playout,
           rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
@@ -210,15 +211,18 @@
   uint32_t GetDelayEstimate() const;
   int SetMinimumPlayoutDelay(int delayMs);
   int GetPlayoutTimestamp(unsigned int& timestamp);  // NOLINT
-  int GetRtpRtcp(RtpRtcp** rtpRtcpModule, RtpReceiver** rtp_receiver) const;
 
+  // Used by AudioSendStream.
+  RtpRtcp* GetRtpRtcp() const;
+
+  // Produces the transport-related timestamps; current_delay_ms is left unset.
+  absl::optional<Syncable::Info> GetSyncInfo() const;
   // DTMF.
   int SendTelephoneEventOutband(int event, int duration_ms);
   int SetSendTelephoneEventPayloadType(int payload_type, int payload_frequency);
 
   // RTP+RTCP
   int SetLocalSSRC(unsigned int ssrc);
-  void SetRemoteSSRC(uint32_t ssrc);
 
   void SetMid(const std::string& mid, int extension_id);
   int SetSendAudioLevelIndicationStatus(bool enable, unsigned char id);
@@ -281,9 +285,6 @@
   // Used for obtaining RTT for a receive-only channel.
   void SetAssociatedSendChannel(Channel* channel);
 
-  // Set a RtcEventLog logging object.
-  void SetRtcEventLog(RtcEventLog* event_log);
-
   void SetTransportOverhead(size_t transport_overhead_per_packet);
 
   // From OverheadObserver in the RTP/RTCP module
@@ -297,9 +298,7 @@
 
   void OnRecoverableUplinkPacketLossRate(float recoverable_packet_loss_rate);
 
-  std::vector<RtpSource> GetSources() const {
-    return rtp_receiver_->GetSources();
-  }
+  std::vector<RtpSource> GetSources() const;
 
  private:
   class ProcessAndEncodeAudioTask;
@@ -314,7 +313,6 @@
   bool ReceivePacket(const uint8_t* packet,
                      size_t packet_length,
                      const RTPHeader& header);
-  bool IsPacketRetransmitted(const RTPHeader& header) const;
   int ResendPackets(const uint16_t* sequence_numbers, int length);
   void UpdatePlayoutTimestamp(bool rtcp);
 
@@ -337,13 +335,26 @@
 
   ChannelState channel_state_;
 
-  std::unique_ptr<voe::RtcEventLogProxy> event_log_proxy_;
+  RtcEventLog* const event_log_;
 
-  std::unique_ptr<RTPPayloadRegistry> rtp_payload_registry_;
+  // Indexed by payload type.
+  std::map<uint8_t, int> payload_type_frequencies_;
+
   std::unique_ptr<ReceiveStatistics> rtp_receive_statistics_;
-  std::unique_ptr<RtpReceiver> rtp_receiver_;
-  TelephoneEventHandler* telephone_event_handler_;
   std::unique_ptr<RtpRtcp> _rtpRtcpModule;
+  const uint32_t remote_ssrc_;
+
+  // Info for GetSources and GetSyncInfo is updated on network or worker thread,
+  // queried on the worker thread.
+  rtc::CriticalSection rtp_sources_lock_;
+  ContributingSources contributing_sources_ RTC_GUARDED_BY(&rtp_sources_lock_);
+  absl::optional<uint32_t> last_received_rtp_timestamp_
+      RTC_GUARDED_BY(&rtp_sources_lock_);
+  absl::optional<int64_t> last_received_rtp_system_time_ms_
+      RTC_GUARDED_BY(&rtp_sources_lock_);
+  absl::optional<uint8_t> last_received_rtp_audio_level_
+      RTC_GUARDED_BY(&rtp_sources_lock_);
+
   std::unique_ptr<AudioCodingModule> audio_coding_;
   AudioSinkInterface* audio_sink_ = nullptr;
   AudioLevel _outputAudioLevel;
diff --git a/audio/channel_proxy.cc b/audio/channel_proxy.cc
index bac681f..5e8181a 100644
--- a/audio/channel_proxy.cc
+++ b/audio/channel_proxy.cc
@@ -53,11 +53,6 @@
   RTC_DCHECK_EQ(0, error);
 }
 
-void ChannelProxy::SetRemoteSSRC(uint32_t ssrc) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->SetRemoteSSRC(ssrc);
-}
-
 void ChannelProxy::SetMid(const std::string& mid, int extension_id) {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
   channel_->SetMid(mid, extension_id);
@@ -226,11 +221,6 @@
   channel_->SetChannelOutputVolumeScaling(scaling);
 }
 
-void ChannelProxy::SetRtcEventLog(RtcEventLog* event_log) {
-  RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_->SetRtcEventLog(event_log);
-}
-
 AudioMixer::Source::AudioFrameInfo ChannelProxy::GetAudioFrameWithInfo(
     int sample_rate_hz,
     AudioFrame* audio_frame) {
@@ -265,13 +255,14 @@
   channel_->SetAssociatedSendChannel(nullptr);
 }
 
-void ChannelProxy::GetRtpRtcp(RtpRtcp** rtp_rtcp,
-                              RtpReceiver** rtp_receiver) const {
+RtpRtcp* ChannelProxy::GetRtpRtcp() const {
   RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
-  RTC_DCHECK(rtp_rtcp);
-  RTC_DCHECK(rtp_receiver);
-  int error = channel_->GetRtpRtcp(rtp_rtcp, rtp_receiver);
-  RTC_DCHECK_EQ(0, error);
+  return channel_->GetRtpRtcp();
+}
+
+absl::optional<Syncable::Info> ChannelProxy::GetSyncInfo() const {
+  RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
+  return channel_->GetSyncInfo();
 }
 
 uint32_t ChannelProxy::GetPlayoutTimestamp() const {
diff --git a/audio/channel_proxy.h b/audio/channel_proxy.h
index 0029851..f82c1fd 100644
--- a/audio/channel_proxy.h
+++ b/audio/channel_proxy.h
@@ -34,7 +34,6 @@
 class RtcpRttStats;
 class RtpPacketSender;
 class RtpPacketReceived;
-class RtpReceiver;
 class RtpRtcp;
 class RtpTransportControllerSendInterface;
 class Transport;
@@ -62,7 +61,6 @@
 
   virtual void SetRTCPStatus(bool enable);
   virtual void SetLocalSSRC(uint32_t ssrc);
-  virtual void SetRemoteSSRC(uint32_t ssrc);
   virtual void SetMid(const std::string& mid, int extension_id);
   virtual void SetRTCP_CNAME(const std::string& c_name);
   virtual void SetNACKStatus(bool enable, int max_packets);
@@ -99,7 +97,6 @@
   void OnRtpPacket(const RtpPacketReceived& packet) override;
   virtual bool ReceivedRTCPPacket(const uint8_t* packet, size_t length);
   virtual void SetChannelOutputVolumeScaling(float scaling);
-  virtual void SetRtcEventLog(RtcEventLog* event_log);
   virtual AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo(
       int sample_rate_hz,
       AudioFrame* audio_frame);
@@ -108,7 +105,10 @@
   virtual void SetTransportOverhead(int transport_overhead_per_packet);
   virtual void AssociateSendChannel(const ChannelProxy& send_channel_proxy);
   virtual void DisassociateSendChannel();
-  virtual void GetRtpRtcp(RtpRtcp** rtp_rtcp, RtpReceiver** rtp_receiver) const;
+  virtual RtpRtcp* GetRtpRtcp() const;
+
+  // Produces the transport-related timestamps; current_delay_ms is left unset.
+  absl::optional<Syncable::Info> GetSyncInfo() const;
   virtual uint32_t GetPlayoutTimestamp() const;
   virtual void SetMinimumPlayoutDelay(int delay_ms);
   virtual bool GetRecCodec(CodecInst* codec_inst) const;
diff --git a/audio/mock_voe_channel_proxy.h b/audio/mock_voe_channel_proxy.h
index 7396dd1..f6a2637 100644
--- a/audio/mock_voe_channel_proxy.h
+++ b/audio/mock_voe_channel_proxy.h
@@ -37,7 +37,6 @@
       void(rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier));
   MOCK_METHOD1(SetRTCPStatus, void(bool enable));
   MOCK_METHOD1(SetLocalSSRC, void(uint32_t ssrc));
-  MOCK_METHOD1(SetRemoteSSRC, void(uint32_t ssrc));
   MOCK_METHOD1(SetRTCP_CNAME, void(const std::string& c_name));
   MOCK_METHOD2(SetNACKStatus, void(bool enable, int max_packets));
   MOCK_METHOD2(SetSendAudioLevelIndicationStatus, void(bool enable, int id));
@@ -68,7 +67,6 @@
   MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived& packet));
   MOCK_METHOD2(ReceivedRTCPPacket, bool(const uint8_t* packet, size_t length));
   MOCK_METHOD1(SetChannelOutputVolumeScaling, void(float scaling));
-  MOCK_METHOD1(SetRtcEventLog, void(RtcEventLog* event_log));
   MOCK_METHOD2(GetAudioFrameWithInfo,
                AudioMixer::Source::AudioFrameInfo(int sample_rate_hz,
                                                   AudioFrame* audio_frame));
@@ -83,8 +81,7 @@
   MOCK_METHOD1(AssociateSendChannel,
                void(const ChannelProxy& send_channel_proxy));
   MOCK_METHOD0(DisassociateSendChannel, void());
-  MOCK_CONST_METHOD2(GetRtpRtcp,
-                     void(RtpRtcp** rtp_rtcp, RtpReceiver** rtp_receiver));
+  MOCK_CONST_METHOD0(GetRtpRtcp, RtpRtcp*());
   MOCK_CONST_METHOD0(GetPlayoutTimestamp, uint32_t());
   MOCK_METHOD1(SetMinimumPlayoutDelay, void(int delay_ms));
   MOCK_CONST_METHOD1(GetRecCodec, bool(CodecInst* codec_inst));
diff --git a/audio/null_audio_poller.h b/audio/null_audio_poller.h
index b6ddf17..afb6edb 100644
--- a/audio/null_audio_poller.h
+++ b/audio/null_audio_poller.h
@@ -21,7 +21,7 @@
 class NullAudioPoller final : public rtc::MessageHandler {
  public:
   explicit NullAudioPoller(AudioTransport* audio_transport);
-  ~NullAudioPoller();
+  ~NullAudioPoller() override;
 
  protected:
   void OnMessage(rtc::Message* msg) override;
diff --git a/audio/transport_feedback_packet_loss_tracker.cc b/audio/transport_feedback_packet_loss_tracker.cc
index 7e0c5c5..c7acd76 100644
--- a/audio/transport_feedback_packet_loss_tracker.cc
+++ b/audio/transport_feedback_packet_loss_tracker.cc
@@ -47,6 +47,9 @@
   Reset();
 }
 
+TransportFeedbackPacketLossTracker::~TransportFeedbackPacketLossTracker() =
+    default;
+
 void TransportFeedbackPacketLossTracker::Reset() {
   acked_packets_ = 0;
   plr_state_.Reset();
diff --git a/audio/transport_feedback_packet_loss_tracker.h b/audio/transport_feedback_packet_loss_tracker.h
index 7d58d6c..180b64a 100644
--- a/audio/transport_feedback_packet_loss_tracker.h
+++ b/audio/transport_feedback_packet_loss_tracker.h
@@ -35,6 +35,7 @@
   TransportFeedbackPacketLossTracker(int64_t max_window_size_ms,
                                      size_t plr_min_num_acked_packets,
                                      size_t rplr_min_num_acked_pairs);
+  ~TransportFeedbackPacketLossTracker();
 
   void OnPacketAdded(uint16_t seq_num, int64_t send_time_ms);
 
diff --git a/audio/utility/BUILD.gn b/audio/utility/BUILD.gn
index fe39b7f..76c09a5 100644
--- a/audio/utility/BUILD.gn
+++ b/audio/utility/BUILD.gn
@@ -22,7 +22,6 @@
 
   deps = [
     "../..:webrtc_common",
-    "../../:typedefs",
     "../../api/audio:audio_frame_api",
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
diff --git a/audio/utility/audio_frame_operations.h b/audio/utility/audio_frame_operations.h
index 65a2bad..5993523 100644
--- a/audio/utility/audio_frame_operations.h
+++ b/audio/utility/audio_frame_operations.h
@@ -14,7 +14,6 @@
 #include <stddef.h>
 
 #include "api/audio/audio_frame.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/common_audio/BUILD.gn b/common_audio/BUILD.gn
index 57cf699..50bd0f4 100644
--- a/common_audio/BUILD.gn
+++ b/common_audio/BUILD.gn
@@ -10,14 +10,6 @@
 
 visibility = [ ":*" ]
 
-config("common_audio_config") {
-  include_dirs = [
-    "resampler/include",
-    "signal_processing/include",
-    "vad/include",
-  ]
-}
-
 rtc_static_library("common_audio") {
   visibility += [ "*" ]
   sources = [
@@ -60,17 +52,17 @@
 
   deps = [
     ":common_audio_c",
-    ":fft4g",
     ":sinc_resampler",
     "..:webrtc_common",
-    "../:typedefs",
     "../rtc_base:checks",
     "../rtc_base:gtest_prod",
     "../rtc_base:rtc_base_approved",
     "../rtc_base/memory:aligned_array",
     "../rtc_base/memory:aligned_malloc",
+    "../rtc_base/system:arch",
     "../system_wrappers",
     "../system_wrappers:cpu_features_api",
+    "third_party/fft4g:fft4g",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
 
@@ -80,8 +72,6 @@
     deps += [ ":common_audio_neon" ]
   }
 
-  public_configs = [ ":common_audio_config" ]
-
   if (current_cpu == "x86" || current_cpu == "x64") {
     deps += [ ":common_audio_sse2" ]
   }
@@ -104,10 +94,7 @@
   sources = []
   deps = []
   if (current_cpu == "arm") {
-    sources += [
-      "signal_processing/complex_bit_reverse_arm.S",
-      "signal_processing/spl_sqrt_floor_arm.S",
-    ]
+    sources += [ "signal_processing/complex_bit_reverse_arm.S" ]
 
     if (arm_version >= 7) {
       sources += [ "signal_processing/filter_ar_fast_q12_armv7.S" ]
@@ -180,7 +167,6 @@
       "signal_processing/include/spl_inl_mips.h",
       "signal_processing/min_max_operations_mips.c",
       "signal_processing/resample_by_2_mips.c",
-      "signal_processing/spl_sqrt_floor_mips.c",
     ]
     if (mips_dsp_rev > 0) {
       sources += [ "signal_processing/vector_scaling_operations_mips.c" ]
@@ -193,31 +179,22 @@
     sources += [
       "signal_processing/complex_bit_reverse.c",
       "signal_processing/filter_ar_fast_q12.c",
-      "signal_processing/spl_sqrt_floor.c",
     ]
   }
 
-  public_configs = [ ":common_audio_config" ]
   deps = [
     ":common_audio_c_arm_asm",
     ":common_audio_cc",
-    ":fft4g",
     "..:webrtc_common",
-    "../:typedefs",
     "../rtc_base:checks",
     "../rtc_base:compile_assert_c",
     "../rtc_base:rtc_base_approved",
     "../rtc_base:sanitizer",
+    "../rtc_base/system:arch",
     "../system_wrappers",
     "../system_wrappers:cpu_features_api",
-  ]
-}
-
-rtc_source_set("fft4g") {
-  visibility += webrtc_default_visibility
-  sources = [
-    "fft4g.c",
-    "fft4g.h",
+    "third_party/fft4g:fft4g",
+    "third_party/spl_sqrt_floor",
   ]
 }
 
@@ -227,10 +204,8 @@
     "signal_processing/dot_product_with_scale.h",
   ]
 
-  public_configs = [ ":common_audio_config" ]
   deps = [
     "..:webrtc_common",
-    "../:typedefs",
     "../rtc_base:rtc_base_approved",
     "../system_wrappers",
   ]
@@ -242,10 +217,10 @@
   ]
   deps = [
     "..:webrtc_common",
-    "../:typedefs",
     "../rtc_base:gtest_prod",
     "../rtc_base:rtc_base_approved",
     "../rtc_base/memory:aligned_malloc",
+    "../rtc_base/system:arch",
     "../system_wrappers",
   ]
 }
@@ -269,6 +244,7 @@
     ":fir_filter",
     "../rtc_base:checks",
     "../rtc_base:rtc_base_approved",
+    "../rtc_base/system:arch",
     "../system_wrappers:cpu_features_api",
   ]
   if (current_cpu == "x86" || current_cpu == "x64") {
@@ -310,9 +286,7 @@
     ]
 
     if (current_cpu != "arm64") {
-      # Enable compilation for the NEON instruction set. This is needed
-      # since //build/config/arm.gni only enables NEON for iOS, not Android.
-      # This provides the same functionality as webrtc/build/arm_neon.gypi.
+      # Enable compilation for the NEON instruction set.
       suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
       cflags = [ "-mfpu=neon" ]
     }
@@ -345,9 +319,7 @@
     ]
 
     if (current_cpu != "arm64") {
-      # Enable compilation for the NEON instruction set. This is needed
-      # since //build/config/arm.gni only enables NEON for iOS, not Android.
-      # This provides the same functionality as webrtc/build/arm_neon.gypi.
+      # Enable compilation for the NEON instruction set.
       suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
       cflags = [ "-mfpu=neon" ]
     }
@@ -365,6 +337,7 @@
       ":common_audio_c",
       "../rtc_base:checks",
       "../rtc_base:rtc_base_approved",
+      "../rtc_base/system:arch",
     ]
   }
 }
@@ -416,10 +389,10 @@
       ":fir_filter_factory",
       ":sinc_resampler",
       "..:webrtc_common",
-      "../:typedefs",
       "../rtc_base:checks",
       "../rtc_base:rtc_base_approved",
       "../rtc_base:rtc_base_tests_utils",
+      "../rtc_base/system:arch",
       "../system_wrappers:cpu_features_api",
       "../test:fileutils",
       "../test:test_main",
diff --git a/common_audio/audio_util.cc b/common_audio/audio_util.cc
index b442a14..735ba5f 100644
--- a/common_audio/audio_util.cc
+++ b/common_audio/audio_util.cc
@@ -10,8 +10,6 @@
 
 #include "common_audio/include/audio_util.h"
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 namespace webrtc {
 
 void FloatToS16(const float* src, size_t size, int16_t* dest) {
diff --git a/common_audio/audio_util_unittest.cc b/common_audio/audio_util_unittest.cc
index 230669e..cf85a2d 100644
--- a/common_audio/audio_util_unittest.cc
+++ b/common_audio/audio_util_unittest.cc
@@ -13,7 +13,6 @@
 #include "rtc_base/arraysize.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace {
diff --git a/common_audio/fir_filter_factory.cc b/common_audio/fir_filter_factory.cc
index c15c2e0..3243b27 100644
--- a/common_audio/fir_filter_factory.cc
+++ b/common_audio/fir_filter_factory.cc
@@ -12,6 +12,7 @@
 
 #include "common_audio/fir_filter_c.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/system/arch.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 
 #if defined(WEBRTC_HAS_NEON)
diff --git a/common_audio/include/audio_util.h b/common_audio/include/audio_util.h
index e4ea9a1..de242a4 100644
--- a/common_audio/include/audio_util.h
+++ b/common_audio/include/audio_util.h
@@ -17,7 +17,6 @@
 #include <limits>
 
 #include "rtc_base/checks.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/common_audio/module.mk b/common_audio/module.mk
index 65acd74..dab66c1 100644
--- a/common_audio/module.mk
+++ b/common_audio/module.mk
@@ -32,7 +32,7 @@
 # TODO(hychao): figure out if common_audio/real_fourier_openmax.o
 # is needed. Build it requires linking openmax dl library.
 common_audio_c_C_OBJECTS = \
-	common_audio/fft4g.o \
+	common_audio/third_party/fft4g/fft4g.o \
 	common_audio/ring_buffer.o \
 	common_audio/signal_processing/auto_corr_to_refl_coef.o \
 	common_audio/signal_processing/auto_correlation.o \
@@ -71,7 +71,7 @@
 	common_audio/signal_processing/complex_fft.o \
 	common_audio/signal_processing/complex_bit_reverse.o \
 	common_audio/signal_processing/filter_ar_fast_q12.o \
-	common_audio/signal_processing/spl_sqrt_floor.o
+	common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.o
 
 ifeq (${USE_NEON},1)
 common_audio_CXX_OBJECTS += \
diff --git a/common_audio/real_fourier_ooura.cc b/common_audio/real_fourier_ooura.cc
index db65d26..89694c1 100644
--- a/common_audio/real_fourier_ooura.cc
+++ b/common_audio/real_fourier_ooura.cc
@@ -13,7 +13,7 @@
 #include <algorithm>
 #include <cmath>
 
-#include "common_audio/fft4g.h"
+#include "common_audio/third_party/fft4g/fft4g.h"
 #include "rtc_base/checks.h"
 
 namespace webrtc {
diff --git a/common_audio/resampler/include/push_resampler.h b/common_audio/resampler/include/push_resampler.h
index 05b93d1..082cdc6 100644
--- a/common_audio/resampler/include/push_resampler.h
+++ b/common_audio/resampler/include/push_resampler.h
@@ -13,8 +13,6 @@
 
 #include <memory>
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 namespace webrtc {
 
 class PushSincResampler;
diff --git a/common_audio/resampler/include/resampler.h b/common_audio/resampler/include/resampler.h
index f923b46..04c487b 100644
--- a/common_audio/resampler/include/resampler.h
+++ b/common_audio/resampler/include/resampler.h
@@ -16,8 +16,7 @@
 #define COMMON_AUDIO_RESAMPLER_INCLUDE_RESAMPLER_H_
 
 #include <stddef.h>
-
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 namespace webrtc {
 
diff --git a/common_audio/resampler/push_sinc_resampler.h b/common_audio/resampler/push_sinc_resampler.h
index ad51471..1ffe73f 100644
--- a/common_audio/resampler/push_sinc_resampler.h
+++ b/common_audio/resampler/push_sinc_resampler.h
@@ -15,7 +15,6 @@
 
 #include "common_audio/resampler/sinc_resampler.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/common_audio/resampler/push_sinc_resampler_unittest.cc b/common_audio/resampler/push_sinc_resampler_unittest.cc
index 487a09f..2f53a74 100644
--- a/common_audio/resampler/push_sinc_resampler_unittest.cc
+++ b/common_audio/resampler/push_sinc_resampler_unittest.cc
@@ -19,7 +19,6 @@
 #include "rtc_base/timeutils.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace {
diff --git a/common_audio/resampler/sinc_resampler.cc b/common_audio/resampler/sinc_resampler.cc
index c3d1ea4..5aa2061 100644
--- a/common_audio/resampler/sinc_resampler.cc
+++ b/common_audio/resampler/sinc_resampler.cc
@@ -93,8 +93,8 @@
 #include <limits>
 
 #include "rtc_base/checks.h"
+#include "rtc_base/system/arch.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/common_audio/resampler/sinc_resampler.h b/common_audio/resampler/sinc_resampler.h
index 6306bc9..8a833ce 100644
--- a/common_audio/resampler/sinc_resampler.h
+++ b/common_audio/resampler/sinc_resampler.h
@@ -19,7 +19,7 @@
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/gtest_prod_util.h"
 #include "rtc_base/memory/aligned_malloc.h"
-#include "typedefs.h"  // NOLINT(build/include)
+#include "rtc_base/system/arch.h"
 
 namespace webrtc {
 
diff --git a/common_audio/resampler/sinc_resampler_unittest.cc b/common_audio/resampler/sinc_resampler_unittest.cc
index 90bdf31..eb5424d 100644
--- a/common_audio/resampler/sinc_resampler_unittest.cc
+++ b/common_audio/resampler/sinc_resampler_unittest.cc
@@ -23,6 +23,7 @@
 #include "common_audio/resampler/sinc_resampler.h"
 #include "common_audio/resampler/sinusoidal_linear_chirp_source.h"
 #include "rtc_base/stringize_macros.h"
+#include "rtc_base/system/arch.h"
 #include "rtc_base/timeutils.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 #include "test/gmock.h"
diff --git a/common_audio/signal_processing/complex_fft.c b/common_audio/signal_processing/complex_fft.c
index e2ac206..ddc9a97 100644
--- a/common_audio/signal_processing/complex_fft.c
+++ b/common_audio/signal_processing/complex_fft.c
@@ -17,6 +17,7 @@
 
 #include "common_audio/signal_processing/complex_fft_tables.h"
 #include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "rtc_base/system/arch.h"
 
 #define CFFTSFT 14
 #define CFFTRND 1
diff --git a/common_audio/signal_processing/complex_fft_tables.h b/common_audio/signal_processing/complex_fft_tables.h
index 5171040..90fac07 100644
--- a/common_audio/signal_processing/complex_fft_tables.h
+++ b/common_audio/signal_processing/complex_fft_tables.h
@@ -11,7 +11,7 @@
 #ifndef COMMON_AUDIO_SIGNAL_PROCESSING_COMPLEX_FFT_TABLES_H_
 #define COMMON_AUDIO_SIGNAL_PROCESSING_COMPLEX_FFT_TABLES_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 static const int16_t kSinTable1024[] = {
     0,      201,    402,    603,    804,    1005,   1206,   1406,   1607,
diff --git a/common_audio/signal_processing/cross_correlation_neon.c b/common_audio/signal_processing/cross_correlation_neon.c
index fdd03f1..f2afbdf 100644
--- a/common_audio/signal_processing/cross_correlation_neon.c
+++ b/common_audio/signal_processing/cross_correlation_neon.c
@@ -9,6 +9,7 @@
  */
 
 #include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "rtc_base/system/arch.h"
 
 #include <arm_neon.h>
 
diff --git a/common_audio/signal_processing/dot_product_with_scale.h b/common_audio/signal_processing/dot_product_with_scale.h
index ff3c525..bb892d4 100644
--- a/common_audio/signal_processing/dot_product_with_scale.h
+++ b/common_audio/signal_processing/dot_product_with_scale.h
@@ -11,10 +11,9 @@
 #ifndef COMMON_AUDIO_SIGNAL_PROCESSING_DOT_PRODUCT_WITH_SCALE_H_
 #define COMMON_AUDIO_SIGNAL_PROCESSING_DOT_PRODUCT_WITH_SCALE_H_
 
+#include <stdint.h>
 #include <string.h>
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/common_audio/signal_processing/include/real_fft.h b/common_audio/signal_processing/include/real_fft.h
index 8da243d..8445066 100644
--- a/common_audio/signal_processing/include/real_fft.h
+++ b/common_audio/signal_processing/include/real_fft.h
@@ -11,7 +11,7 @@
 #ifndef COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_
 #define COMMON_AUDIO_SIGNAL_PROCESSING_INCLUDE_REAL_FFT_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 // For ComplexFFT(), the maximum fft order is 10;
 // WebRTC APM uses orders of only 7 and 8.
diff --git a/common_audio/signal_processing/include/signal_processing_library.h b/common_audio/signal_processing/include/signal_processing_library.h
index 4d6edbf..33469d4 100644
--- a/common_audio/signal_processing/include/signal_processing_library.h
+++ b/common_audio/signal_processing/include/signal_processing_library.h
@@ -19,7 +19,6 @@
 
 #include <string.h>
 #include "common_audio/signal_processing/dot_product_with_scale.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 // Macros specific for the fixed point implementation
 #define WEBRTC_SPL_WORD16_MAX 32767
@@ -97,6 +96,9 @@
 // inline functions:
 #include "common_audio/signal_processing/include/spl_inl.h"
 
+// third party math functions
+#include "common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.h"
+
 // Initialize SPL. Currently it contains only function pointer initialization.
 // If the underlying platform is known to be ARM-Neon (WEBRTC_HAS_NEON defined),
 // the pointers will be assigned to code optimized for Neon; otherwise, generic
@@ -574,7 +576,6 @@
 
 // Math functions
 int32_t WebRtcSpl_Sqrt(int32_t value);
-int32_t WebRtcSpl_SqrtFloor(int32_t value);
 
 // Divisions. Implementations collected in division_operations.c and
 // descriptions at bottom of this file.
@@ -1336,23 +1337,6 @@
 //
 
 //
-// WebRtcSpl_SqrtFloor(...)
-//
-// Returns the square root of the input value |value|. The precision of this
-// function is rounding down integer precision, i.e., sqrt(8) gives 2 as answer.
-// If |value| is a negative number then 0 is returned.
-//
-// Algorithm:
-//
-// An iterative 4 cylce/bit routine
-//
-// Input:
-//      - value     : Value to calculate sqrt of
-//
-// Return value     : Result of the sqrt calculation
-//
-
-//
 // WebRtcSpl_DivU32U16(...)
 //
 // Divides a uint32_t |num| by a uint16_t |den|.
diff --git a/common_audio/signal_processing/real_fft_unittest.cc b/common_audio/signal_processing/real_fft_unittest.cc
index 2d6b7d1..3b43123 100644
--- a/common_audio/signal_processing/real_fft_unittest.cc
+++ b/common_audio/signal_processing/real_fft_unittest.cc
@@ -11,7 +11,6 @@
 #include "common_audio/signal_processing/include/real_fft.h"
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace {
diff --git a/common_audio/signal_processing/resample_by_2_internal.h b/common_audio/signal_processing/resample_by_2_internal.h
index 5483e2e..145395a 100644
--- a/common_audio/signal_processing/resample_by_2_internal.h
+++ b/common_audio/signal_processing/resample_by_2_internal.h
@@ -16,7 +16,7 @@
 #ifndef COMMON_AUDIO_SIGNAL_PROCESSING_RESAMPLE_BY_2_INTERNAL_H_
 #define COMMON_AUDIO_SIGNAL_PROCESSING_RESAMPLE_BY_2_INTERNAL_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 /*******************************************************************
  * resample_by_2_fast.c
diff --git a/common_audio/third_party/fft4g/BUILD.gn b/common_audio/third_party/fft4g/BUILD.gn
new file mode 100644
index 0000000..ae0d5f6
--- /dev/null
+++ b/common_audio/third_party/fft4g/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright (c) 2018 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.
+
+import("../../../webrtc.gni")
+
+rtc_source_set("fft4g") {
+  sources = [
+    "fft4g.c",
+    "fft4g.h",
+  ]
+}
diff --git a/common_audio/third_party/fft4g/LICENSE b/common_audio/third_party/fft4g/LICENSE
new file mode 100644
index 0000000..3bf870a
--- /dev/null
+++ b/common_audio/third_party/fft4g/LICENSE
@@ -0,0 +1,8 @@
+/*
+ * http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html
+ * Copyright Takuya OOURA, 1996-2001
+ *
+ * You may use, copy, modify and distribute this code for any purpose (include
+ * commercial use) and without fee. Please refer to this package when you modify
+ * this code.
+ */
diff --git a/common_audio/third_party/fft4g/README.chromium b/common_audio/third_party/fft4g/README.chromium
new file mode 100644
index 0000000..9df2ddb
--- /dev/null
+++ b/common_audio/third_party/fft4g/README.chromium
@@ -0,0 +1,13 @@
+Name: General Purpose FFT (Fast Fourier/Cosine/Sine Transform) Package
+Short Name: fft4g
+URL: http://www.kurims.kyoto-u.ac.jp/~ooura/fft.html
+Version: 0
+Date: 2018-06-19
+License: Custome license
+License File: LICENSE
+Security Critical: yes
+
+Description:
+This is a package to calculate Discrete Fourier/Cosine/Sine Transforms of
+1-dimensional sequences of length 2^N. This package contains C and Fortran
+FFT codes.
diff --git a/common_audio/fft4g.c b/common_audio/third_party/fft4g/fft4g.c
similarity index 100%
rename from common_audio/fft4g.c
rename to common_audio/third_party/fft4g/fft4g.c
diff --git a/common_audio/fft4g.h b/common_audio/third_party/fft4g/fft4g.h
similarity index 61%
rename from common_audio/fft4g.h
rename to common_audio/third_party/fft4g/fft4g.h
index 1750e27..f1f31a1 100644
--- a/common_audio/fft4g.h
+++ b/common_audio/third_party/fft4g/fft4g.h
@@ -1,15 +1,15 @@
 /*
- *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *  Copyright (c) 2018 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
+ *  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 COMMON_AUDIO_FFT4G_H_
-#define COMMON_AUDIO_FFT4G_H_
+#ifndef COMMON_AUDIO_THIRD_PARTY_FFT4G_FFT4G_H_
+#define COMMON_AUDIO_THIRD_PARTY_FFT4G_FFT4G_H_
 
 #if defined(__cplusplus)
 extern "C" {
@@ -22,4 +22,4 @@
 }
 #endif
 
-#endif  // COMMON_AUDIO_FFT4G_H_
+#endif  /* COMMON_AUDIO_THIRD_PARTY_FFT4G_FFT4G_H_ */
diff --git a/common_audio/third_party/fft4g/module.mk b/common_audio/third_party/fft4g/module.mk
new file mode 100644
index 0000000..37c23f4
--- /dev/null
+++ b/common_audio/third_party/fft4g/module.mk
@@ -0,0 +1,5 @@
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+include common.mk
diff --git a/common_audio/third_party/module.mk b/common_audio/third_party/module.mk
new file mode 100644
index 0000000..37c23f4
--- /dev/null
+++ b/common_audio/third_party/module.mk
@@ -0,0 +1,5 @@
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+include common.mk
diff --git a/common_audio/third_party/spl_sqrt_floor/BUILD.gn b/common_audio/third_party/spl_sqrt_floor/BUILD.gn
new file mode 100644
index 0000000..194899e
--- /dev/null
+++ b/common_audio/third_party/spl_sqrt_floor/BUILD.gn
@@ -0,0 +1,26 @@
+# Copyright (c) 2018 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.
+
+import("../../../webrtc.gni")
+
+rtc_source_set("spl_sqrt_floor") {
+  visibility = [ "../..:common_audio_c" ]
+  sources = [
+    "spl_sqrt_floor.h",
+  ]
+  deps = []
+  if (current_cpu == "arm") {
+    sources += [ "spl_sqrt_floor_arm.S" ]
+
+    deps += [ "../../../rtc_base/system:asm_defines" ]
+  } else if (current_cpu == "mipsel") {
+    sources += [ "spl_sqrt_floor_mips.c" ]
+  } else {
+    sources += [ "spl_sqrt_floor.c" ]
+  }
+}
diff --git a/common_audio/third_party/spl_sqrt_floor/LICENSE b/common_audio/third_party/spl_sqrt_floor/LICENSE
new file mode 100644
index 0000000..fdf17a2
--- /dev/null
+++ b/common_audio/third_party/spl_sqrt_floor/LICENSE
@@ -0,0 +1,27 @@
+/*
+ * Written by Wilco Dijkstra, 1996. The following email exchange establishes the
+ * license.
+ *
+ * From: Wilco Dijkstra <Wilco.Dijkstra@ntlworld.com>
+ * Date: Fri, Jun 24, 2011 at 3:20 AM
+ * Subject: Re: sqrt routine
+ * To: Kevin Ma <kma@google.com>
+ * Hi Kevin,
+ * Thanks for asking. Those routines are public domain (originally posted to
+ * comp.sys.arm a long time ago), so you can use them freely for any purpose.
+ * Cheers,
+ * Wilco
+ *
+ * ----- Original Message -----
+ * From: "Kevin Ma" <kma@google.com>
+ * To: <Wilco.Dijkstra@ntlworld.com>
+ * Sent: Thursday, June 23, 2011 11:44 PM
+ * Subject: Fwd: sqrt routine
+ * Hi Wilco,
+ * I saw your sqrt routine from several web sites, including
+ * http://www.finesse.demon.co.uk/steven/sqrt.html.
+ * Just wonder if there's any copyright information with your Successive
+ * approximation routines, or if I can freely use it for any purpose.
+ * Thanks.
+ * Kevin
+ */
diff --git a/common_audio/third_party/spl_sqrt_floor/README.chromium b/common_audio/third_party/spl_sqrt_floor/README.chromium
new file mode 100644
index 0000000..b226490
--- /dev/null
+++ b/common_audio/third_party/spl_sqrt_floor/README.chromium
@@ -0,0 +1,12 @@
+Name: sql sqrt floor
+Short Name: sql_sqrt_floor
+URL: http://www.pertinentdetail.org/sqrt
+Version: 0
+Date: 2018-03-22
+License: Custom license
+License File: LICENSE
+Security Critical: yes
+
+Description:
+Sqrt routine, originally was posted to the USENET group comp.sys.arm on
+20 Jun 1996.
diff --git a/common_audio/third_party/spl_sqrt_floor/module.mk b/common_audio/third_party/spl_sqrt_floor/module.mk
new file mode 100644
index 0000000..37c23f4
--- /dev/null
+++ b/common_audio/third_party/spl_sqrt_floor/module.mk
@@ -0,0 +1,5 @@
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+include common.mk
diff --git a/common_audio/signal_processing/spl_sqrt_floor.c b/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.c
similarity index 96%
rename from common_audio/signal_processing/spl_sqrt_floor.c
rename to common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.c
index 7141386..b478a41 100644
--- a/common_audio/signal_processing/spl_sqrt_floor.c
+++ b/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.c
@@ -28,7 +28,7 @@
 
 // Minor modifications in code style for WebRTC, 2012.
 
-#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.h"
 
 /*
  * Algorithm:
diff --git a/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.h b/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.h
new file mode 100644
index 0000000..eaa58e3
--- /dev/null
+++ b/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.h
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2018 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 <stdint.h>
+
+//
+// WebRtcSpl_SqrtFloor(...)
+//
+// Returns the square root of the input value |value|. The precision of this
+// function is rounding down integer precision, i.e., sqrt(8) gives 2 as answer.
+// If |value| is a negative number then 0 is returned.
+//
+// Algorithm:
+//
+// An iterative 4 cylce/bit routine
+//
+// Input:
+//      - value     : Value to calculate sqrt of
+//
+// Return value     : Result of the sqrt calculation
+//
+int32_t WebRtcSpl_SqrtFloor(int32_t value);
diff --git a/common_audio/signal_processing/spl_sqrt_floor_arm.S b/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor_arm.S
similarity index 100%
rename from common_audio/signal_processing/spl_sqrt_floor_arm.S
rename to common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor_arm.S
diff --git a/common_audio/signal_processing/spl_sqrt_floor_mips.c b/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor_mips.c
similarity index 98%
rename from common_audio/signal_processing/spl_sqrt_floor_mips.c
rename to common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor_mips.c
index 7128fbd..04033c1 100644
--- a/common_audio/signal_processing/spl_sqrt_floor_mips.c
+++ b/common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor_mips.c
@@ -29,7 +29,7 @@
 // Minor modifications in code style for WebRTC, 2012.
 // Code optimizations for MIPS, 2013.
 
-#include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "common_audio/third_party/spl_sqrt_floor/spl_sqrt_floor.h"
 
 /*
  * Algorithm:
diff --git a/common_audio/vad/include/vad.h b/common_audio/vad/include/vad.h
index bd10756..b15275b 100644
--- a/common_audio/vad/include/vad.h
+++ b/common_audio/vad/include/vad.h
@@ -15,7 +15,6 @@
 
 #include "common_audio/vad/include/webrtc_vad.h"
 #include "rtc_base/checks.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/common_audio/vad/include/webrtc_vad.h b/common_audio/vad/include/webrtc_vad.h
index a6c539c..f5bbadf 100644
--- a/common_audio/vad/include/webrtc_vad.h
+++ b/common_audio/vad/include/webrtc_vad.h
@@ -17,8 +17,7 @@
 #define COMMON_AUDIO_VAD_INCLUDE_WEBRTC_VAD_H_
 
 #include <stddef.h>
-
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 typedef struct WebRtcVadInst VadInst;
 
diff --git a/common_audio/vad/vad_core.c b/common_audio/vad/vad_core.c
index 7316b45..55927ce 100644
--- a/common_audio/vad/vad_core.c
+++ b/common_audio/vad/vad_core.c
@@ -15,7 +15,6 @@
 #include "common_audio/vad/vad_filterbank.h"
 #include "common_audio/vad/vad_gmm.h"
 #include "common_audio/vad/vad_sp.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 // Spectrum Weighting
 static const int16_t kSpectrumWeight[kNumChannels] = { 6, 8, 10, 12, 14, 16 };
diff --git a/common_audio/vad/vad_core.h b/common_audio/vad/vad_core.h
index 0eb8de3..e79696c 100644
--- a/common_audio/vad/vad_core.h
+++ b/common_audio/vad/vad_core.h
@@ -16,7 +16,6 @@
 #define COMMON_AUDIO_VAD_VAD_CORE_H_
 
 #include "common_audio/signal_processing/include/signal_processing_library.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 enum { kNumChannels = 6 };   // Number of frequency bands (named channels).
 enum { kNumGaussians = 2 };  // Number of Gaussians per channel in the GMM.
diff --git a/common_audio/vad/vad_core_unittest.cc b/common_audio/vad/vad_core_unittest.cc
index 0587878..3131a86 100644
--- a/common_audio/vad/vad_core_unittest.cc
+++ b/common_audio/vad/vad_core_unittest.cc
@@ -12,7 +12,6 @@
 
 #include "common_audio/vad/vad_unittest.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 extern "C" {
 #include "common_audio/vad/vad_core.h"
diff --git a/common_audio/vad/vad_filterbank.c b/common_audio/vad/vad_filterbank.c
index 82cff25..1513153 100644
--- a/common_audio/vad/vad_filterbank.c
+++ b/common_audio/vad/vad_filterbank.c
@@ -12,7 +12,6 @@
 
 #include "rtc_base/checks.h"
 #include "common_audio/signal_processing/include/signal_processing_library.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 // Constants used in LogOfEnergy().
 static const int16_t kLogConst = 24660;  // 160*log10(2) in Q9.
diff --git a/common_audio/vad/vad_filterbank.h b/common_audio/vad/vad_filterbank.h
index 60b785b..53bbbe1 100644
--- a/common_audio/vad/vad_filterbank.h
+++ b/common_audio/vad/vad_filterbank.h
@@ -16,7 +16,6 @@
 #define COMMON_AUDIO_VAD_VAD_FILTERBANK_H_
 
 #include "common_audio/vad/vad_core.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 // Takes |data_length| samples of |data_in| and calculates the logarithm of the
 // energy of each of the |kNumChannels| = 6 frequency bands used by the VAD:
diff --git a/common_audio/vad/vad_filterbank_unittest.cc b/common_audio/vad/vad_filterbank_unittest.cc
index b800044..51d8d0f 100644
--- a/common_audio/vad/vad_filterbank_unittest.cc
+++ b/common_audio/vad/vad_filterbank_unittest.cc
@@ -12,7 +12,6 @@
 
 #include "common_audio/vad/vad_unittest.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 extern "C" {
 #include "common_audio/vad/vad_core.h"
diff --git a/common_audio/vad/vad_gmm.c b/common_audio/vad/vad_gmm.c
index b746fd5..ddc87b6 100644
--- a/common_audio/vad/vad_gmm.c
+++ b/common_audio/vad/vad_gmm.c
@@ -11,7 +11,6 @@
 #include "common_audio/vad/vad_gmm.h"
 
 #include "common_audio/signal_processing/include/signal_processing_library.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 static const int32_t kCompVar = 22005;
 static const int16_t kLog2Exp = 5909;  // log2(exp(1)) in Q12.
diff --git a/common_audio/vad/vad_gmm.h b/common_audio/vad/vad_gmm.h
index 79f15c8..6b2d11b 100644
--- a/common_audio/vad/vad_gmm.h
+++ b/common_audio/vad/vad_gmm.h
@@ -13,7 +13,7 @@
 #ifndef COMMON_AUDIO_VAD_VAD_GMM_H_
 #define COMMON_AUDIO_VAD_VAD_GMM_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 // Calculates the probability for |input|, given that |input| comes from a
 // normal distribution with mean and standard deviation (|mean|, |std|).
diff --git a/common_audio/vad/vad_gmm_unittest.cc b/common_audio/vad/vad_gmm_unittest.cc
index e77603d..be61f7f 100644
--- a/common_audio/vad/vad_gmm_unittest.cc
+++ b/common_audio/vad/vad_gmm_unittest.cc
@@ -10,7 +10,6 @@
 
 #include "common_audio/vad/vad_unittest.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 extern "C" {
 #include "common_audio/vad/vad_gmm.h"
diff --git a/common_audio/vad/vad_sp.c b/common_audio/vad/vad_sp.c
index 915fb37..d367c8b 100644
--- a/common_audio/vad/vad_sp.c
+++ b/common_audio/vad/vad_sp.c
@@ -13,7 +13,6 @@
 #include "rtc_base/checks.h"
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 #include "common_audio/vad/vad_core.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 // Allpass filter coefficients, upper and lower, in Q13.
 // Upper: 0.64, Lower: 0.17.
diff --git a/common_audio/vad/vad_sp.h b/common_audio/vad/vad_sp.h
index 8586ccd..ff36760 100644
--- a/common_audio/vad/vad_sp.h
+++ b/common_audio/vad/vad_sp.h
@@ -14,7 +14,6 @@
 #define COMMON_AUDIO_VAD_VAD_SP_H_
 
 #include "common_audio/vad/vad_core.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 // Downsamples the signal by a factor 2, eg. 32->16 or 16->8.
 //
diff --git a/common_audio/vad/vad_sp_unittest.cc b/common_audio/vad/vad_sp_unittest.cc
index ebe25cf..cdde56d 100644
--- a/common_audio/vad/vad_sp_unittest.cc
+++ b/common_audio/vad/vad_sp_unittest.cc
@@ -12,7 +12,6 @@
 
 #include "common_audio/vad/vad_unittest.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 extern "C" {
 #include "common_audio/vad/vad_core.h"
diff --git a/common_audio/vad/vad_unittest.cc b/common_audio/vad/vad_unittest.cc
index 1cef8e9..c54014e 100644
--- a/common_audio/vad/vad_unittest.cc
+++ b/common_audio/vad/vad_unittest.cc
@@ -17,7 +17,6 @@
 #include "rtc_base/arraysize.h"
 #include "rtc_base/checks.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 VadTest::VadTest() {}
 
diff --git a/common_audio/vad/vad_unittest.h b/common_audio/vad/vad_unittest.h
index 5521983..ee64206 100644
--- a/common_audio/vad/vad_unittest.h
+++ b/common_audio/vad/vad_unittest.h
@@ -14,7 +14,6 @@
 #include <stddef.h>  // size_t
 
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace test {
diff --git a/common_audio/vad/webrtc_vad.c b/common_audio/vad/webrtc_vad.c
index 7fc4d65..d8457ee 100644
--- a/common_audio/vad/webrtc_vad.c
+++ b/common_audio/vad/webrtc_vad.c
@@ -15,7 +15,6 @@
 
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 #include "common_audio/vad/vad_core.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 static const int kInitCheck = 42;
 static const int kValidRates[] = { 8000, 16000, 32000, 48000 };
diff --git a/common_audio/wav_file.cc b/common_audio/wav_file.cc
index 21b64a8..008891f 100644
--- a/common_audio/wav_file.cc
+++ b/common_audio/wav_file.cc
@@ -19,6 +19,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/system/arch.h"
 
 namespace webrtc {
 
diff --git a/common_audio/wav_header.cc b/common_audio/wav_header.cc
index d093fa0..8fc5fef 100644
--- a/common_audio/wav_header.cc
+++ b/common_audio/wav_header.cc
@@ -21,6 +21,7 @@
 
 #include "common_audio/include/audio_util.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/system/arch.h"
 
 namespace webrtc {
 namespace {
diff --git a/common_types.h b/common_types.h
index 919a947..60d88b3 100644
--- a/common_types.h
+++ b/common_types.h
@@ -21,7 +21,6 @@
 #include "api/video/video_bitrate_allocation.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/deprecation.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 #if defined(_MSC_VER)
 // Disable "new behavior: elements of array will be default initialized"
@@ -60,14 +59,8 @@
         jitter(0) {}
 
   uint8_t fraction_lost;
-  union {
-    int32_t packets_lost;  // Defined as a 24 bit signed integer in RTCP
-    RTC_DEPRECATED uint32_t cumulative_lost;
-  };
-  union {
-    uint32_t extended_highest_sequence_number;
-    RTC_DEPRECATED uint32_t extended_max_sequence_number;
-  };
+  int32_t packets_lost;  // Defined as a 24 bit signed integer in RTCP
+  uint32_t extended_highest_sequence_number;
   uint32_t jitter;
 };
 
@@ -340,21 +333,13 @@
 // Video codec types
 enum VideoCodecType {
   // There are various memset(..., 0, ...) calls in the code that rely on
-  // kVideoCodecUnknown being zero.
-  kVideoCodecUnknown = 0,
+  // kVideoCodecGeneric being zero.
+  kVideoCodecGeneric = 0,
   kVideoCodecVP8,
   kVideoCodecVP9,
   kVideoCodecH264,
   kVideoCodecI420,
-  kVideoCodecGeneric,
   kVideoCodecMultiplex,
-
-  // TODO(nisse): Deprecated aliases, for code expecting RtpVideoCodecTypes.
-  kRtpVideoNone = kVideoCodecUnknown,
-  kRtpVideoGeneric = kVideoCodecGeneric,
-  kRtpVideoVp8 = kVideoCodecVP8,
-  kRtpVideoVp9 = kVideoCodecVP9,
-  kRtpVideoH264 = kVideoCodecH264,
 };
 
 // Translates from name of codec to codec type and vice versa.
@@ -367,6 +352,7 @@
 
   unsigned short width;
   unsigned short height;
+  float maxFramerate;  // fps.
   unsigned char numberOfTemporalLayers;
   unsigned int maxBitrate;     // kilobits/sec.
   unsigned int targetBitrate;  // kilobits/sec.
@@ -410,21 +396,6 @@
   double initial_var_noise;
 };
 
-// This structure will have the information about when packet is actually
-// received by socket.
-struct PacketTime {
-  PacketTime() : timestamp(-1), not_before(-1) {}
-  PacketTime(int64_t timestamp, int64_t not_before)
-      : timestamp(timestamp), not_before(not_before) {}
-
-  int64_t timestamp;   // Receive time after socket delivers the data.
-  int64_t not_before;  // Earliest possible time the data could have arrived,
-                       // indicating the potential error in the |timestamp|
-                       // value,in case the system is busy.
-                       // For example, the time of the last select() call.
-                       // If unknown, this value will be set to zero.
-};
-
 // Minimum and maximum playout delay values from capture to render.
 // These are best effort values.
 //
diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn
index 82cde8e..de2aeb7 100644
--- a/modules/audio_coding/BUILD.gn
+++ b/modules/audio_coding/BUILD.gn
@@ -66,7 +66,6 @@
     "acm2/rent_a_codec.h",
   ]
   deps = [
-           "../..:typedefs",
            "../../rtc_base:checks",
            "../../api:array_view",
            "//third_party/abseil-cpp/absl/types:optional",
@@ -84,19 +83,11 @@
   defines = audio_codec_defines
 }
 
-config("audio_coding_config") {
-  include_dirs = [
-    "include",
-    "../include",
-  ]
-}
-
 rtc_source_set("audio_coding_module_typedefs") {
   sources = [
     "include/audio_coding_module_typedefs.h",
   ]
   deps = [
-    "../..:typedefs",
     "../..:webrtc_common",
   ]
 }
@@ -119,8 +110,6 @@
 
   defines = []
 
-  public_configs = [ ":audio_coding_config" ]
-
   if (rtc_include_opus) {
     public_deps = [
       ":webrtc_opus",
@@ -131,7 +120,6 @@
            "../../api/audio:audio_frame_api",
            "..:module_api",
            "../../common_audio:common_audio_c",
-           "../..:typedefs",
            "../../rtc_base:deprecation",
            "../../rtc_base:checks",
            "../../system_wrappers:metrics_api",
@@ -160,10 +148,6 @@
   ]
 }
 
-config("cng_config") {
-  include_dirs = [ "codecs/cng/include" ]
-}
-
 rtc_static_library("cng") {
   visibility += [ "*" ]
   sources = [
@@ -173,10 +157,7 @@
     "codecs/cng/webrtc_cng.h",
   ]
 
-  public_configs = [ ":cng_config" ]
-
   deps = [
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../api:array_view",
     "../../api/audio_codecs:audio_codecs_api",
@@ -186,10 +167,6 @@
   ]
 }
 
-config("red_config") {
-  include_dirs = [ "codecs/red" ]
-}
-
 rtc_static_library("red") {
   visibility += [ "*" ]
   sources = [
@@ -197,8 +174,6 @@
     "codecs/red/audio_encoder_copy_red.h",
   ]
 
-  public_configs = [ ":red_config" ]
-
   deps = [
     "../../api/audio_codecs:audio_codecs_api",
     "../../common_audio",
@@ -207,10 +182,6 @@
   ]
 }
 
-config("g711_config") {
-  include_dirs = [ "codecs/g711/include" ]
-}
-
 rtc_static_library("g711") {
   visibility += [ "*" ]
   poisonous = [ "audio_codecs" ]
@@ -221,8 +192,6 @@
     "codecs/g711/audio_encoder_pcm.h",
   ]
 
-  public_configs = [ ":g711_config" ]
-
   deps = [
     ":legacy_encoded_audio_frame",
     "../..:webrtc_common",
@@ -242,24 +211,11 @@
     "codecs/g711/g711_interface.h",
   ]
   deps = [
-    ":g711_3p",
-    "../..:typedefs",
     "../..:webrtc_common",
+    "../third_party/g711:g711_3p",
   ]
 }
 
-rtc_source_set("g711_3p") {
-  poisonous = [ "audio_codecs" ]
-  sources = [
-    "codecs/g711/g711.c",
-    "codecs/g711/g711.h",
-  ]
-}
-
-config("g722_config") {
-  include_dirs = [ "codecs/g722/include" ]
-}
-
 rtc_static_library("g722") {
   visibility += [ "*" ]
   poisonous = [ "audio_codecs" ]
@@ -270,8 +226,6 @@
     "codecs/g722/audio_encoder_g722.h",
   ]
 
-  public_configs = [ ":g722_config" ]
-
   deps = [
     ":legacy_encoded_audio_frame",
     "../..:webrtc_common",
@@ -292,25 +246,11 @@
     "codecs/g722/g722_interface.h",
   ]
   deps = [
-    ":g722_3p",
-    "../..:typedefs",
     "../..:webrtc_common",
+    "../third_party/g722:g722_3p",
   ]
 }
 
-rtc_source_set("g722_3p") {
-  poisonous = [ "audio_codecs" ]
-  sources = [
-    "codecs/g722/g722_decode.c",
-    "codecs/g722/g722_enc_dec.h",
-    "codecs/g722/g722_encode.c",
-  ]
-}
-
-config("ilbc_config") {
-  include_dirs = [ "codecs/ilbc/include" ]
-}
-
 rtc_static_library("ilbc") {
   visibility += webrtc_default_visibility
   poisonous = [ "audio_codecs" ]
@@ -321,8 +261,6 @@
     "codecs/ilbc/audio_encoder_ilbc.h",
   ]
 
-  public_configs = [ ":ilbc_config" ]
-
   deps = [
     ":legacy_encoded_audio_frame",
     "../..:webrtc_common",
@@ -481,10 +419,7 @@
     "codecs/ilbc/xcorr_coef.h",
   ]
 
-  public_configs = [ ":ilbc_config" ]
-
   deps = [
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../api/audio_codecs:audio_codecs_api",
     "../../common_audio",
@@ -492,6 +427,8 @@
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
     "../../rtc_base:sanitizer",
+    "../../rtc_base/system:arch",
+    "../../rtc_base/system:unused",
   ]
 }
 
@@ -507,7 +444,6 @@
   ]
   deps = [
     ":isac_bwinfo",
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../api/audio_codecs:audio_codecs_api",
     "../../rtc_base:checks",
@@ -516,10 +452,6 @@
   ]
 }
 
-config("isac_config") {
-  include_dirs = [ "codecs/isac/main/include" ]
-}
-
 rtc_static_library("isac") {
   visibility += [ "*" ]
   poisonous = [ "audio_codecs" ]
@@ -543,9 +475,7 @@
   sources = [
     "codecs/isac/bandwidth_info.h",
   ]
-  deps = [
-    "../..:typedefs",
-  ]
+  deps = []
 }
 
 rtc_source_set("isac_vad") {
@@ -565,9 +495,10 @@
   ]
   deps = [
     ":isac_bwinfo",
-    "../..:typedefs",
     "../../rtc_base:compile_assert_c",
+    "../../rtc_base/system:arch",
     "../../rtc_base/system:ignore_warnings",
+    "../third_party/fft",
   ]
 }
 
@@ -619,37 +550,20 @@
     libs = [ "m" ]
   }
 
-  public_configs = [ ":isac_config" ]
-
   deps = [
-    ":fft",
     ":isac_bwinfo",
     ":isac_vad",
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../common_audio",
     "../../common_audio:common_audio_c",
     "../../rtc_base:checks",
     "../../rtc_base:compile_assert_c",
     "../../rtc_base:rtc_base_approved",
+    "../../rtc_base/system:arch",
+    "../third_party/fft",
   ]
 }
 
-rtc_source_set("fft") {
-  poisonous = [ "audio_codecs" ]
-  sources = [
-    "codecs/isac/main/source/fft.c",
-    "codecs/isac/main/source/fft.h",
-  ]
-  deps = [
-    ":isac_vad",
-  ]
-}
-
-config("isac_fix_config") {
-  include_dirs = [ "codecs/isac/fix/include" ]
-}
-
 rtc_static_library("isac_fix") {
   visibility += [ "*" ]
   poisonous = [ "audio_codecs" ]
@@ -658,8 +572,6 @@
     "codecs/isac/fix/source/audio_encoder_isacfix.cc",
   ]
 
-  public_configs = [ ":isac_fix_config" ]
-
   deps = [
     ":isac_common",
     "../../api/audio_codecs:audio_codecs_api",
@@ -687,10 +599,8 @@
     "codecs/isac/fix/source/structs.h",
     "codecs/isac/fix/source/transform_tables.c",
   ]
-  public_configs = [ ":isac_fix_config" ]
   deps = [
     ":isac_bwinfo",
-    "../..:typedefs",
     "../../common_audio",
     "../../common_audio:common_audio_c",
   ]
@@ -755,12 +665,9 @@
     "codecs/isac/fix/source/transform.c",
   ]
 
-  public_configs = [ ":isac_fix_config" ]
-
   deps = [
     ":isac_bwinfo",
     ":isac_common",
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../api/audio_codecs:audio_codecs_api",
     "../../common_audio",
@@ -770,6 +677,7 @@
     "../../rtc_base:rtc_base_approved",
     "../../rtc_base:sanitizer",
     "../../system_wrappers:cpu_features_api",
+    "../third_party/fft",
   ]
 
   public_deps = [
@@ -778,6 +686,13 @@
 
   if (rtc_build_with_neon) {
     deps += [ ":isac_neon" ]
+
+    # TODO(bugs.webrtc.org/9579): Consider moving the usage of NEON from
+    # pitch_estimator_c.c into the "isac_neon" target and delete this flag:
+    if (current_cpu != "arm64") {
+      suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
+      cflags = [ "-mfpu=neon" ]
+    }
   }
 
   if (current_cpu == "arm" && arm_version >= 7) {
@@ -825,9 +740,7 @@
     ]
 
     if (current_cpu != "arm64") {
-      # Enable compilation for the NEON instruction set. This is needed
-      # since //build/config/arm.gni only enables NEON for iOS, not Android.
-      # This provides the same functionality as webrtc/build/arm_neon.gypi.
+      # Enable compilation for the NEON instruction set.
       suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
       cflags = [ "-mfpu=neon" ]
     }
@@ -851,10 +764,6 @@
   }
 }
 
-config("pcm16b_config") {
-  include_dirs = [ "codecs/pcm16b/include" ]
-}
-
 rtc_static_library("pcm16b") {
   visibility += [ "*" ]
   poisonous = [ "audio_codecs" ]
@@ -878,7 +787,6 @@
   public_deps = [
     ":pcm16b_c",
   ]
-  public_configs = [ ":pcm16b_config" ]
 }
 
 rtc_source_set("pcm16b_c") {
@@ -888,9 +796,7 @@
     "codecs/pcm16b/pcm16b.h",
   ]
 
-  public_configs = [ ":pcm16b_config" ]
   deps = [
-    "../..:typedefs",
     "../..:webrtc_common",
   ]
 }
@@ -952,7 +858,6 @@
   }
 
   deps = [
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
@@ -1140,7 +1045,6 @@
     ":cng",
     ":neteq_decoder_enum",
     "..:module_api",
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../api:libjingle_peerconnection_api",
     "../../api/audio:audio_frame_api",
@@ -1181,14 +1085,8 @@
     "neteq/tools/packet_source.h",
   ]
 
-  if (!build_with_chromium && is_clang) {
-    # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-    suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-  }
-
   deps = [
     ":neteq",
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../api:libjingle_peerconnection_api",
     "../../api/audio:audio_frame_api",
@@ -1220,8 +1118,6 @@
     "neteq/tools/rtp_generator.h",
   ]
 
-  public_configs = [ ":neteq_tools_config" ]
-
   if (!build_with_chromium && is_clang) {
     # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
     suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
@@ -1229,7 +1125,6 @@
 
   deps = [
     ":pcm16b",
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../api:array_view",
     "../../api:libjingle_peerconnection_api",
@@ -1238,6 +1133,7 @@
     "../../rtc_base:rtc_base",
     "../../rtc_base:rtc_base_approved",
     "../../rtc_base:rtc_base_tests_utils",
+    "../../rtc_base/system:arch",
     "../../test:rtp_test_utils",
     "../rtp_rtcp",
     "../rtp_rtcp:rtp_rtcp_format",
@@ -1257,10 +1153,6 @@
   }
 }
 
-config("neteq_tools_config") {
-  include_dirs = [ "tools" ]
-}
-
 rtc_source_set("neteq_tools") {
   visibility += webrtc_default_visibility
   sources = [
@@ -1274,8 +1166,6 @@
     "neteq/tools/neteq_stats_getter.h",
   ]
 
-  public_configs = [ ":neteq_tools_config" ]
-
   if (!build_with_chromium && is_clang) {
     # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
     suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
@@ -1283,7 +1173,6 @@
 
   deps = [
     "..:module_api",
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../api:array_view",
     "../../api/audio_codecs:audio_codecs_api",
@@ -1310,7 +1199,6 @@
   ]
 
   deps = [
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../common_audio",
     "../../rtc_base:checks",
@@ -1436,10 +1324,10 @@
       ":audio_format_conversion",
       ":pcm16b_c",
       "..:module_api",
-      "../..:typedefs",
       "../..:webrtc_common",
       "../../api/audio:audio_frame_api",
       "../../api/audio_codecs:builtin_audio_decoder_factory",
+      "../../api/audio_codecs:builtin_audio_encoder_factory",
       "../../rtc_base:checks",
       "../../rtc_base:rtc_base_approved",
       "../../rtc_base/synchronization:rw_lock_wrapper",
@@ -1466,7 +1354,6 @@
     deps = [
       ":neteq_test_support",
       ":neteq_test_tools",
-      "../..:typedefs",
       "../..:webrtc_common",
       "../../api/audio_codecs/opus:audio_encoder_opus",
       "../../rtc_base:protobuf_utils",
@@ -1519,8 +1406,10 @@
              "../../api/audio:audio_frame_api",
              "../../rtc_base:checks",
              ":audio_coding",
+             ":audio_format_conversion",
              ":neteq_tools",
              "../../api/audio_codecs:builtin_audio_decoder_factory",
+             "../../api/audio_codecs:builtin_audio_encoder_factory",
              "../../api/audio_codecs:audio_codecs_api",
              "../../rtc_base:rtc_base_approved",
              "../../test:test_support",
@@ -1545,7 +1434,6 @@
       ":audio_coding_module_typedefs",
       ":audio_format_conversion",
       "..:module_api",
-      "../..:typedefs",
       "../../:webrtc_common",
       "../../api/audio:audio_frame_api",
       "../../api/audio_codecs:builtin_audio_decoder_factory",
@@ -1580,31 +1468,23 @@
       "neteq/audio_decoder_unittest.cc",
     ]
 
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
-
-    deps = [
-      "../../test:fileutils",
-    ]
-
     defines = neteq_defines
 
-    deps += audio_coding_deps
-    deps += [
-      ":ilbc",
-      ":isac",
-      ":isac_fix",
-      ":neteq",
-      ":neteq_tools",
-      "../../api/audio_codecs:audio_codecs_api",
-      "../../api/audio_codecs/opus:audio_encoder_opus",
-      "../../common_audio",
-      "../../rtc_base:protobuf_utils",
-      "../../test:test_main",
-      "//testing/gtest",
-    ]
+    deps = [
+             ":ilbc",
+             ":isac",
+             ":isac_fix",
+             ":neteq",
+             ":neteq_tools",
+             "../../test:fileutils",
+             "../../api/audio_codecs:audio_codecs_api",
+             "../../api/audio_codecs/opus:audio_encoder_opus",
+             "../../common_audio",
+             "../../rtc_base:protobuf_utils",
+             "../../rtc_base/system:arch",
+             "../../test:test_main",
+             "//testing/gtest",
+           ] + audio_coding_deps
 
     data = audio_decoder_unittests_resources
 
@@ -1615,7 +1495,7 @@
     if (is_ios) {
       deps += [ ":audio_decoder_unittests_bundle_data" ]
     }
-  }  # audio_decoder_unittests
+  }
 
   if (rtc_enable_protobuf) {
     proto_library("neteq_unittest_proto") {
@@ -1629,8 +1509,8 @@
       testonly = true
       defines = []
       deps = [
-        "../..:typedefs",
         "../../rtc_base:checks",
+        "../../test:field_trial",
         "../../test:fileutils",
       ]
       sources = [
@@ -1673,7 +1553,6 @@
     testonly = true
     defines = []
     deps = [
-      "../..:typedefs",
       "../../test:fileutils",
     ]
     sources = [
@@ -1732,7 +1611,6 @@
       ":neteq",
       ":neteq_test_tools",
       ":pcm16b",
-      "../..:typedefs",
       "../..:webrtc_common",
       "../../api/audio:audio_frame_api",
       "../../api/audio_codecs:audio_codecs_api",
@@ -1761,7 +1639,6 @@
     deps = [
       ":neteq",
       ":neteq_test_tools",
-      "../..:typedefs",
       "../..:webrtc_common",
       "../../api/audio_codecs:builtin_audio_decoder_factory",
       "../../rtc_base:checks",
@@ -1777,7 +1654,6 @@
 
     deps = audio_coding_deps + [
              "//third_party/abseil-cpp/absl/memory",
-             "../..:typedefs",
              ":audio_coding",
              ":neteq_input_audio_tools",
              "../../api/audio:audio_frame_api",
@@ -1802,7 +1678,6 @@
     testonly = true
 
     deps = audio_coding_deps + [
-             "../..:typedefs",
              "../../system_wrappers:system_wrappers_default",
              "../rtp_rtcp:rtp_rtcp_format",
              "../../api:array_view",
@@ -1847,11 +1722,6 @@
       "../../system_wrappers:system_wrappers_default",
       "//testing/gtest",
     ]
-
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
   }
 
   rtc_executable("neteq_opus_quality_test") {
@@ -1882,7 +1752,6 @@
     deps = [
       ":neteq",
       ":neteq_test_support",
-      "../..:typedefs",
       "../..:webrtc_common",
       "../../rtc_base:rtc_base_approved",
       "../../system_wrappers:system_wrappers_default",
@@ -2001,12 +1870,6 @@
       "codecs/isac/main/test/simpleKenny.c",
     ]
 
-    include_dirs = [
-      "codecs/isac/main/include",
-      "codecs/isac/main/test",
-      "codecs/isac/main/util",
-    ]
-
     deps = [
       ":isac",
       ":isac_test_util",
@@ -2035,7 +1898,6 @@
 
     deps = [
       ":g722",
-      "../..:typedefs",
       "../..:webrtc_common",
     ]
   }
@@ -2052,12 +1914,6 @@
       ":isac_test_util",
       "../../rtc_base:rtc_base_approved",
     ]
-
-    include_dirs = [
-      "codecs/isac/main/include",
-      "codecs/isac/main/test",
-      "codecs/isac/main/util",
-    ]
   }
 
   rtc_executable("isac_switch_samprate_test") {
@@ -2073,13 +1929,6 @@
       "../../common_audio",
       "../../common_audio:common_audio_c",
     ]
-
-    include_dirs = [
-      "codecs/isac/main/include",
-      "codecs/isac/main/test",
-      "codecs/isac/main/util",
-      "../../common_audio/signal_processing/include",
-    ]
   }
 
   rtc_executable("ilbc_test") {
@@ -2109,11 +1958,6 @@
       "../../test:test_main",
       "//testing/gtest",
     ]
-
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
   }
 
   rtc_source_set("audio_coding_unittests") {
@@ -2221,7 +2065,6 @@
       ":rent_a_codec",
       ":webrtc_opus",
       "..:module_api",
-      "../..:typedefs",
       "../..:webrtc_common",
       "../../api/audio:audio_frame_api",
       "../../api/audio_codecs:audio_codecs_api",
@@ -2241,6 +2084,7 @@
       "../../rtc_base:rtc_base_approved",
       "../../rtc_base:rtc_base_tests_utils",
       "../../rtc_base:sanitizer",
+      "../../rtc_base/system:arch",
       "../../system_wrappers",
       "../../system_wrappers:cpu_features_api",
       "../../test:audio_codec_mocks",
diff --git a/modules/audio_coding/acm2/acm_codec_database.h b/modules/audio_coding/acm2/acm_codec_database.h
index 8b7c68a..ee6bb46 100644
--- a/modules/audio_coding/acm2/acm_codec_database.h
+++ b/modules/audio_coding/acm2/acm_codec_database.h
@@ -18,7 +18,6 @@
 
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/acm2/rent_a_codec.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/acm2/acm_receiver.cc b/modules/audio_coding/acm2/acm_receiver.cc
index 0a88e70..892abe5 100644
--- a/modules/audio_coding/acm2/acm_receiver.cc
+++ b/modules/audio_coding/acm2/acm_receiver.cc
@@ -60,10 +60,6 @@
   return -1;
 }
 
-int AcmReceiver::LeastRequiredDelayMs() const {
-  return neteq_->LeastRequiredDelayMs();
-}
-
 absl::optional<int> AcmReceiver::last_packet_sample_rate_hz() const {
   rtc::CritScope lock(&crit_sect_);
   return last_packet_sample_rate_hz_;
diff --git a/modules/audio_coding/acm2/acm_receiver.h b/modules/audio_coding/acm2/acm_receiver.h
index c0afbb1..0731677 100644
--- a/modules/audio_coding/acm2/acm_receiver.h
+++ b/modules/audio_coding/acm2/acm_receiver.h
@@ -26,7 +26,6 @@
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "rtc_base/criticalsection.h"
 #include "rtc_base/thread_annotations.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -144,13 +143,6 @@
   int SetMaximumDelay(int delay_ms);
 
   //
-  // Get least required delay computed based on channel conditions. Note that
-  // this is before applying any user-defined limits (specified by calling
-  // (SetMinimumDelay() and/or SetMaximumDelay()).
-  //
-  int LeastRequiredDelayMs() const;
-
-  //
   // Resets the initial delay to zero.
   //
   void ResetInitialDelay();
diff --git a/modules/audio_coding/acm2/acm_resampler.h b/modules/audio_coding/acm2/acm_resampler.h
index d7d7bcf..904ea52 100644
--- a/modules/audio_coding/acm2/acm_resampler.h
+++ b/modules/audio_coding/acm2/acm_resampler.h
@@ -12,7 +12,6 @@
 #define MODULES_AUDIO_CODING_ACM2_ACM_RESAMPLER_H_
 
 #include "common_audio/resampler/include/push_resampler.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace acm2 {
diff --git a/modules/audio_coding/acm2/acm_send_test.cc b/modules/audio_coding/acm2/acm_send_test.cc
index b1a3e98..c5e010c 100644
--- a/modules/audio_coding/acm2/acm_send_test.cc
+++ b/modules/audio_coding/acm2/acm_send_test.cc
@@ -16,10 +16,13 @@
 
 #include "api/audio_codecs/audio_encoder.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
+#include "api/audio_codecs/builtin_audio_encoder_factory.h"
+#include "modules/audio_coding/codecs/audio_format_conversion.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "modules/audio_coding/neteq/tools/packet.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/stringencode.h"
 #include "test/gtest.h"
 
 namespace webrtc {
@@ -65,20 +68,26 @@
                                            sampling_freq_hz, channels));
   codec.pltype = payload_type;
   codec.pacsize = frame_size_samples;
-  codec_registered_ = (acm_->RegisterSendCodec(codec) == 0);
+  auto factory = CreateBuiltinAudioEncoderFactory();
+  SdpAudioFormat format = CodecInstToSdp(codec);
+  format.parameters["ptime"] = rtc::ToString(rtc::CheckedDivExact(
+      frame_size_samples, rtc::CheckedDivExact(sampling_freq_hz, 1000)));
+  acm_->SetEncoder(
+      factory->MakeAudioEncoder(payload_type, format, absl::nullopt));
+  codec_registered_ = true;
   input_frame_.num_channels_ = channels;
   assert(input_block_size_samples_ * input_frame_.num_channels_ <=
          AudioFrame::kMaxDataSizeSamples);
   return codec_registered_;
 }
 
-bool AcmSendTestOldApi::RegisterExternalCodec(
-    AudioEncoder* external_speech_encoder) {
-  acm_->RegisterExternalSendCodec(external_speech_encoder);
+void AcmSendTestOldApi::RegisterExternalCodec(
+    std::unique_ptr<AudioEncoder> external_speech_encoder) {
   input_frame_.num_channels_ = external_speech_encoder->NumChannels();
+  acm_->SetEncoder(std::move(external_speech_encoder));
   assert(input_block_size_samples_ * input_frame_.num_channels_ <=
          AudioFrame::kMaxDataSizeSamples);
-  return codec_registered_ = true;
+  codec_registered_ = true;
 }
 
 std::unique_ptr<Packet> AcmSendTestOldApi::NextPacket() {
diff --git a/modules/audio_coding/acm2/acm_send_test.h b/modules/audio_coding/acm2/acm_send_test.h
index 68ba9e1..3479de0 100644
--- a/modules/audio_coding/acm2/acm_send_test.h
+++ b/modules/audio_coding/acm2/acm_send_test.h
@@ -42,8 +42,9 @@
                      int payload_type,
                      int frame_size_samples);
 
-  // Registers an external send codec. Returns true on success, false otherwise.
-  bool RegisterExternalCodec(AudioEncoder* external_speech_encoder);
+  // Registers an external send codec.
+  void RegisterExternalCodec(
+      std::unique_ptr<AudioEncoder> external_speech_encoder);
 
   // Inherited from PacketSource.
   std::unique_ptr<Packet> NextPacket() override;
diff --git a/modules/audio_coding/acm2/audio_coding_module.cc b/modules/audio_coding/acm2/audio_coding_module.cc
index 7f652a2..f0b35ca 100644
--- a/modules/audio_coding/acm2/audio_coding_module.cc
+++ b/modules/audio_coding/acm2/audio_coding_module.cc
@@ -50,15 +50,9 @@
   void ModifyEncoder(rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)>
                          modifier) override;
 
-  void QueryEncoder(
-      rtc::FunctionView<void(const AudioEncoder*)> query) override;
-
   // Get current send codec.
   absl::optional<CodecInst> SendCodec() const override;
 
-  // Get current send frequency.
-  int SendFrequency() const override;
-
   // Sets the bitrate to the specified value in bits/sec. In case the codec does
   // not support the requested value it will choose an appropriate value
   // instead.
@@ -155,11 +149,6 @@
   // Maximum playout delay.
   int SetMaximumPlayoutDelay(int time_ms) override;
 
-  // Smallest latency NetEq will maintain.
-  int LeastRequiredDelayMs() const override;
-
-  RTC_DEPRECATED int32_t PlayoutTimestamp(uint32_t* timestamp) override;
-
   absl::optional<uint32_t> PlayoutTimestamp() override;
 
   int FilteredCurrentDelayMs() const override;
@@ -171,7 +160,6 @@
   int PlayoutData10Ms(int desired_freq_hz,
                       AudioFrame* audio_frame,
                       bool* muted) override;
-  int PlayoutData10Ms(int desired_freq_hz, AudioFrame* audio_frame) override;
 
   /////////////////////////////////////////
   //   Statistics
@@ -598,12 +586,6 @@
   modifier(&encoder_stack_);
 }
 
-void AudioCodingModuleImpl::QueryEncoder(
-    rtc::FunctionView<void(const AudioEncoder*)> query) {
-  rtc::CritScope lock(&acm_crit_sect_);
-  query(encoder_stack_.get());
-}
-
 // Get current send codec.
 absl::optional<CodecInst> AudioCodingModuleImpl::SendCodec() const {
   rtc::CritScope lock(&acm_crit_sect_);
@@ -627,18 +609,6 @@
   }
 }
 
-// Get current send frequency.
-int AudioCodingModuleImpl::SendFrequency() const {
-  rtc::CritScope lock(&acm_crit_sect_);
-
-  if (!encoder_stack_) {
-    RTC_LOG(LS_ERROR) << "SendFrequency Failed, no codec is registered";
-    return -1;
-  }
-
-  return encoder_stack_->SampleRateHz();
-}
-
 void AudioCodingModuleImpl::SetBitRate(int bitrate_bps) {
   rtc::CritScope lock(&acm_crit_sect_);
   if (encoder_stack_) {
@@ -1109,14 +1079,6 @@
   return 0;
 }
 
-int AudioCodingModuleImpl::PlayoutData10Ms(int desired_freq_hz,
-                                           AudioFrame* audio_frame) {
-  bool muted;
-  int ret = PlayoutData10Ms(desired_freq_hz, audio_frame, &muted);
-  RTC_DCHECK(!muted);
-  return ret;
-}
-
 /////////////////////////////////////////
 //   Statistics
 //
@@ -1181,14 +1143,6 @@
   return encoder_stack_->SetDtx(false) ? 0 : -1;
 }
 
-int32_t AudioCodingModuleImpl::PlayoutTimestamp(uint32_t* timestamp) {
-  absl::optional<uint32_t> ts = PlayoutTimestamp();
-  if (!ts)
-    return -1;
-  *timestamp = *ts;
-  return 0;
-}
-
 absl::optional<uint32_t> AudioCodingModuleImpl::PlayoutTimestamp() {
   return receiver_.GetPlayoutTimestamp();
 }
@@ -1226,10 +1180,6 @@
   return receiver_.GetNackList(round_trip_time_ms);
 }
 
-int AudioCodingModuleImpl::LeastRequiredDelayMs() const {
-  return receiver_.LeastRequiredDelayMs();
-}
-
 void AudioCodingModuleImpl::GetDecodingCallStatistics(
     AudioDecodingCallStats* call_stats) const {
   receiver_.GetDecodingCallStatistics(call_stats);
@@ -1310,12 +1260,4 @@
   return i ? *i : -1;
 }
 
-// Checks the validity of the parameters of the given codec
-bool AudioCodingModule::IsCodecValid(const CodecInst& codec) {
-  bool valid = acm2::RentACodec::IsCodecValid(codec);
-  if (!valid)
-    RTC_LOG(LS_ERROR) << "Invalid codec setting";
-  return valid;
-}
-
 }  // namespace webrtc
diff --git a/modules/audio_coding/acm2/audio_coding_module_unittest.cc b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
index ce2832a..924a4a6 100644
--- a/modules/audio_coding/acm2/audio_coding_module_unittest.cc
+++ b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
@@ -37,6 +37,7 @@
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/platform_thread.h"
 #include "rtc_base/refcountedobject.h"
+#include "rtc_base/system/arch.h"
 #include "rtc_base/thread_annotations.h"
 #include "system_wrappers/include/clock.h"
 #include "system_wrappers/include/event_wrapper.h"
@@ -1147,13 +1148,14 @@
                                      payload_type, frame_size_samples);
   }
 
-  bool RegisterExternalSendCodec(AudioEncoder* external_speech_encoder,
-                                 int payload_type) {
+  void RegisterExternalSendCodec(
+      std::unique_ptr<AudioEncoder> external_speech_encoder,
+      int payload_type) {
     payload_type_ = payload_type;
     frame_size_rtp_timestamps_ = rtc::checked_cast<uint32_t>(
         external_speech_encoder->Num10MsFramesInNextPacket() *
         external_speech_encoder->RtpTimestampRateHz() / 100);
-    return send_test_->RegisterExternalCodec(external_speech_encoder);
+    send_test_->RegisterExternalCodec(std::move(external_speech_encoder));
   }
 
   // Runs the test. SetUpSender() and RegisterSendCodec() must have been called
@@ -1248,11 +1250,11 @@
                                   codec_frame_size_rtp_timestamps));
   }
 
-  void SetUpTestExternalEncoder(AudioEncoder* external_speech_encoder,
-                                int payload_type) {
+  void SetUpTestExternalEncoder(
+      std::unique_ptr<AudioEncoder> external_speech_encoder,
+      int payload_type) {
     ASSERT_TRUE(SetUpSender());
-    ASSERT_TRUE(
-        RegisterExternalSendCodec(external_speech_encoder, payload_type));
+    RegisterExternalSendCodec(std::move(external_speech_encoder), payload_type);
   }
 
   std::unique_ptr<test::AcmSendTestOldApi> send_test_;
@@ -1459,8 +1461,8 @@
 TEST_F(AcmSenderBitExactnessNewApi, MAYBE_OpusFromFormat_stereo_20ms) {
   const auto config = AudioEncoderOpus::SdpToConfig(
       SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}}));
-  const auto encoder = AudioEncoderOpus::MakeAudioEncoder(*config, 120);
-  ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder(encoder.get(), 120));
+  ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder(
+      AudioEncoderOpus::MakeAudioEncoder(*config, 120), 120));
   Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
           "3e285b74510e62062fbd8142dacd16e9",
           "3e285b74510e62062fbd8142dacd16e9",
@@ -1498,8 +1500,8 @@
 TEST_F(AcmSenderBitExactnessNewApi, OpusFromFormat_stereo_20ms_voip) {
   const auto config = AudioEncoderOpus::SdpToConfig(
       SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}}));
-  const auto encoder = AudioEncoderOpus::MakeAudioEncoder(*config, 120);
-  ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder(encoder.get(), 120));
+  ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder(
+      AudioEncoderOpus::MakeAudioEncoder(*config, 120), 120));
   // If not set, default will be kAudio in case of stereo.
   EXPECT_EQ(0, send_test_->acm()->SetOpusApplication(kVoip));
   Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
@@ -1549,9 +1551,10 @@
                                      payload_type, frame_size_samples);
   }
 
-  bool RegisterExternalSendCodec(AudioEncoder* external_speech_encoder,
-                                 int payload_type) {
-    return send_test_->RegisterExternalCodec(external_speech_encoder);
+  void RegisterExternalSendCodec(
+      std::unique_ptr<AudioEncoder> external_speech_encoder,
+      int payload_type) {
+    send_test_->RegisterExternalCodec(std::move(external_speech_encoder));
   }
 
   void RunInner(int min_expected_total_bits, int max_expected_total_bits) {
@@ -1610,9 +1613,9 @@
 TEST_F(AcmSetBitRateNewApi, OpusFromFormat_48khz_20ms_10kbps) {
   const auto config = AudioEncoderOpus::SdpToConfig(
       SdpAudioFormat("opus", 48000, 2, {{"maxaveragebitrate", "10000"}}));
-  const auto encoder = AudioEncoderOpus::MakeAudioEncoder(*config, 107);
   ASSERT_TRUE(SetUpSender());
-  ASSERT_TRUE(RegisterExternalSendCodec(encoder.get(), 107));
+  RegisterExternalSendCodec(AudioEncoderOpus::MakeAudioEncoder(*config, 107),
+                            107);
   RunInner(8000, 12000);
 }
 
@@ -1624,9 +1627,9 @@
 TEST_F(AcmSetBitRateNewApi, OpusFromFormat_48khz_20ms_50kbps) {
   const auto config = AudioEncoderOpus::SdpToConfig(
       SdpAudioFormat("opus", 48000, 2, {{"maxaveragebitrate", "50000"}}));
-  const auto encoder = AudioEncoderOpus::MakeAudioEncoder(*config, 107);
   ASSERT_TRUE(SetUpSender());
-  ASSERT_TRUE(RegisterExternalSendCodec(encoder.get(), 107));
+  RegisterExternalSendCodec(AudioEncoderOpus::MakeAudioEncoder(*config, 107),
+                            107);
   RunInner(40000, 60000);
 }
 
@@ -1649,9 +1652,9 @@
 TEST_F(AcmSetBitRateNewApi, MAYBE_OpusFromFormat_48khz_20ms_100kbps) {
   const auto config = AudioEncoderOpus::SdpToConfig(
       SdpAudioFormat("opus", 48000, 2, {{"maxaveragebitrate", "100000"}}));
-  const auto encoder = AudioEncoderOpus::MakeAudioEncoder(*config, 107);
   ASSERT_TRUE(SetUpSender());
-  ASSERT_TRUE(RegisterExternalSendCodec(encoder.get(), 107));
+  RegisterExternalSendCodec(AudioEncoderOpus::MakeAudioEncoder(*config, 107),
+                            107);
   RunInner(80000, 120000);
 }
 
@@ -1723,17 +1726,17 @@
 
 TEST_F(AcmChangeBitRateOldApi, Opus_48khz_20ms_10kbps_2) {
   ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
-  Run(10000, 32200, 5208);
+  Run(10000, 14096, 4232);
 }
 
 TEST_F(AcmChangeBitRateOldApi, Opus_48khz_20ms_50kbps_2) {
   ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
-  Run(50000, 32200, 23928);
+  Run(50000, 14096, 22552);
 }
 
 TEST_F(AcmChangeBitRateOldApi, Opus_48khz_20ms_100kbps_2) {
   ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 1, 107, 960, 960));
-  Run(100000, 32200, 50448);
+  Run(100000, 14096, 49472);
 }
 
 // These next 2 tests ensure that the SetBitRate function has no effect on PCM
@@ -1753,36 +1756,33 @@
   codec_inst.pacsize = 160;
   codec_inst.pltype = 0;
   AudioEncoderPcmU encoder(codec_inst);
-  MockAudioEncoder mock_encoder;
+  auto mock_encoder = absl::make_unique<MockAudioEncoder>();
   // Set expectations on the mock encoder and also delegate the calls to the
   // real encoder.
-  EXPECT_CALL(mock_encoder, SampleRateHz())
+  EXPECT_CALL(*mock_encoder, SampleRateHz())
       .Times(AtLeast(1))
       .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::SampleRateHz));
-  EXPECT_CALL(mock_encoder, NumChannels())
+  EXPECT_CALL(*mock_encoder, NumChannels())
       .Times(AtLeast(1))
       .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::NumChannels));
-  EXPECT_CALL(mock_encoder, RtpTimestampRateHz())
+  EXPECT_CALL(*mock_encoder, RtpTimestampRateHz())
       .Times(AtLeast(1))
       .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::RtpTimestampRateHz));
-  EXPECT_CALL(mock_encoder, Num10MsFramesInNextPacket())
+  EXPECT_CALL(*mock_encoder, Num10MsFramesInNextPacket())
       .Times(AtLeast(1))
       .WillRepeatedly(
           Invoke(&encoder, &AudioEncoderPcmU::Num10MsFramesInNextPacket));
-  EXPECT_CALL(mock_encoder, GetTargetBitrate())
+  EXPECT_CALL(*mock_encoder, GetTargetBitrate())
       .Times(AtLeast(1))
       .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::GetTargetBitrate));
-  EXPECT_CALL(mock_encoder, EncodeImpl(_, _, _))
+  EXPECT_CALL(*mock_encoder, EncodeImpl(_, _, _))
       .Times(AtLeast(1))
       .WillRepeatedly(Invoke(
           &encoder, static_cast<AudioEncoder::EncodedInfo (AudioEncoder::*)(
                         uint32_t, rtc::ArrayView<const int16_t>, rtc::Buffer*)>(
                         &AudioEncoderPcmU::Encode)));
-  EXPECT_CALL(mock_encoder, SetFec(_))
-      .Times(AtLeast(1))
-      .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::SetFec));
   ASSERT_NO_FATAL_FAILURE(
-      SetUpTestExternalEncoder(&mock_encoder, codec_inst.pltype));
+      SetUpTestExternalEncoder(std::move(mock_encoder), codec_inst.pltype));
   Run("81a9d4c0bb72e9becc43aef124c981e9", "8f9b8750bd80fe26b6cbf6659b89f0f9",
       50, test::AcmReceiveTestOldApi::kMonoOutput);
 }
diff --git a/modules/audio_coding/acm2/codec_manager.cc b/modules/audio_coding/acm2/codec_manager.cc
index a101d3d..f29e0f1 100644
--- a/modules/audio_coding/acm2/codec_manager.cc
+++ b/modules/audio_coding/acm2/codec_manager.cc
@@ -14,7 +14,6 @@
 //#include "rtc_base/format_macros.h"
 #include "modules/audio_coding/acm2/rent_a_codec.h"
 #include "rtc_base/logging.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace acm2 {
diff --git a/modules/audio_coding/acm2/rent_a_codec.cc b/modules/audio_coding/acm2/rent_a_codec.cc
index 818e17f..264c2a8 100644
--- a/modules/audio_coding/acm2/rent_a_codec.cc
+++ b/modules/audio_coding/acm2/rent_a_codec.cc
@@ -80,10 +80,6 @@
   return ci;
 }
 
-bool RentACodec::IsCodecValid(const CodecInst& codec_inst) {
-  return ACMCodecDB::CodecNumber(codec_inst) >= 0;
-}
-
 absl::optional<bool> RentACodec::IsSupportedNumChannels(CodecId codec_id,
                                                         size_t num_channels) {
   auto i = CodecIndexFromId(codec_id);
diff --git a/modules/audio_coding/acm2/rent_a_codec.h b/modules/audio_coding/acm2/rent_a_codec.h
index 02f9d03..b0ad382 100644
--- a/modules/audio_coding/acm2/rent_a_codec.h
+++ b/modules/audio_coding/acm2/rent_a_codec.h
@@ -23,7 +23,6 @@
 #include "modules/audio_coding/neteq/neteq_decoder_enum.h"
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/scoped_ref_ptr.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -129,7 +128,6 @@
   static absl::optional<CodecInst> CodecInstByParams(const char* payload_name,
                                                      int sampling_freq_hz,
                                                      size_t channels);
-  static bool IsCodecValid(const CodecInst& codec_inst);
 
   static inline bool IsPayloadTypeValid(int payload_type) {
     return payload_type >= 0 && payload_type <= 127;
diff --git a/modules/audio_coding/audio_network_adaptor/parse_ana_dump.py b/modules/audio_coding/audio_network_adaptor/parse_ana_dump.py
index a52b065..1bd5f0c 100755
--- a/modules/audio_coding/audio_network_adaptor/parse_ana_dump.py
+++ b/modules/audio_coding/audio_network_adaptor/parse_ana_dump.py
@@ -66,9 +66,9 @@
     first_time_stamp = None
     while True:
       event = GetNextMessageFromFile(file_to_parse)
-      if event == None:
+      if event is None:
         break
-      if first_time_stamp == None:
+      if first_time_stamp is None:
         first_time_stamp = event.timestamp
       if event.type == debug_dump_pb2.Event.ENCODER_RUNTIME_CONFIG:
         for decision in event.encoder_runtime_config.DESCRIPTOR.fields:
@@ -110,7 +110,7 @@
       action='append')
 
   options = parser.parse_args()[0]
-  if options.dump_file_to_parse == None:
+  if options.dump_file_to_parse is None:
     print "No dump file to parse is set.\n"
     parser.print_help()
     exit()
diff --git a/modules/audio_coding/codecs/cng/webrtc_cng.h b/modules/audio_coding/codecs/cng/webrtc_cng.h
index 684480a..3f8fadc 100644
--- a/modules/audio_coding/codecs/cng/webrtc_cng.h
+++ b/modules/audio_coding/codecs/cng/webrtc_cng.h
@@ -15,7 +15,6 @@
 
 #include "api/array_view.h"
 #include "rtc_base/buffer.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 #define WEBRTC_CNG_MAX_LPC_ORDER 12
 
diff --git a/modules/audio_coding/codecs/g711/g711_interface.c b/modules/audio_coding/codecs/g711/g711_interface.c
index 9c31cbc..5fe1692 100644
--- a/modules/audio_coding/codecs/g711/g711_interface.c
+++ b/modules/audio_coding/codecs/g711/g711_interface.c
@@ -10,9 +10,8 @@
 
 #include <string.h>
 
-#include "modules/audio_coding/codecs/g711/g711.h"
+#include "modules/third_party/g711/g711.h"
 #include "modules/audio_coding/codecs/g711/g711_interface.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 size_t WebRtcG711_EncodeA(const int16_t* speechIn,
                           size_t len,
diff --git a/modules/audio_coding/codecs/g711/g711_interface.h b/modules/audio_coding/codecs/g711/g711_interface.h
index f206f30..83f9d37 100644
--- a/modules/audio_coding/codecs/g711/g711_interface.h
+++ b/modules/audio_coding/codecs/g711/g711_interface.h
@@ -11,7 +11,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_G711_G711_INTERFACE_H_
 #define MODULES_AUDIO_CODING_CODECS_G711_G711_INTERFACE_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 // Comfort noise constants
 #define G711_WEBRTC_SPEECH 1
diff --git a/modules/audio_coding/codecs/g722/g722_interface.c b/modules/audio_coding/codecs/g722/g722_interface.c
index fb25049..36ee6d9 100644
--- a/modules/audio_coding/codecs/g722/g722_interface.c
+++ b/modules/audio_coding/codecs/g722/g722_interface.c
@@ -11,9 +11,8 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "modules/audio_coding/codecs/g722/g722_enc_dec.h"
 #include "modules/audio_coding/codecs/g722/g722_interface.h"
-#include "typedefs.h"  // NOLINT(build/include)
+#include "modules/third_party/g722/g722_enc_dec.h"
 
 int16_t WebRtcG722_CreateEncoder(G722EncInst **G722enc_inst)
 {
diff --git a/modules/audio_coding/codecs/g722/g722_interface.h b/modules/audio_coding/codecs/g722/g722_interface.h
index 3b73f85..85c1cd0 100644
--- a/modules/audio_coding/codecs/g722/g722_interface.h
+++ b/modules/audio_coding/codecs/g722/g722_interface.h
@@ -11,7 +11,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_G722_G722_INTERFACE_H_
 #define MODULES_AUDIO_CODING_CODECS_G722_G722_INTERFACE_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 /*
  * Solution to support multiple instances
diff --git a/modules/audio_coding/codecs/ilbc/cb_construct.h b/modules/audio_coding/codecs/ilbc/cb_construct.h
index b200990..f4df387 100644
--- a/modules/audio_coding/codecs/ilbc/cb_construct.h
+++ b/modules/audio_coding/codecs/ilbc/cb_construct.h
@@ -20,7 +20,10 @@
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_CONSTRUCT_H_
 
 #include <stdbool.h>
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "rtc_base/system/unused.h"
 
 /*----------------------------------------------------------------*
  *  Construct decoded vector from codebook and gains.
diff --git a/modules/audio_coding/codecs/ilbc/constants.h b/modules/audio_coding/codecs/ilbc/constants.h
index 3c32c62..07369a3 100644
--- a/modules/audio_coding/codecs/ilbc/constants.h
+++ b/modules/audio_coding/codecs/ilbc/constants.h
@@ -20,7 +20,6 @@
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CONSTANTS_H_
 
 #include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 /* high pass filters */
 
diff --git a/modules/audio_coding/codecs/ilbc/decode.c b/modules/audio_coding/codecs/ilbc/decode.c
index 7cba418..3848bc7 100644
--- a/modules/audio_coding/codecs/ilbc/decode.c
+++ b/modules/audio_coding/codecs/ilbc/decode.c
@@ -16,6 +16,9 @@
 
 ******************************************************************/
 
+// Defines WEBRTC_ARCH_BIG_ENDIAN, used below.
+#include "rtc_base/system/arch.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h"
 #include "modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h"
diff --git a/modules/audio_coding/codecs/ilbc/decode.h b/modules/audio_coding/codecs/ilbc/decode.h
index c5f35f4..d73f798 100644
--- a/modules/audio_coding/codecs/ilbc/decode.h
+++ b/modules/audio_coding/codecs/ilbc/decode.h
@@ -19,7 +19,10 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_H_
 
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "rtc_base/system/unused.h"
 
 /*----------------------------------------------------------------*
  *  main decoder function
diff --git a/modules/audio_coding/codecs/ilbc/decode_residual.h b/modules/audio_coding/codecs/ilbc/decode_residual.h
index 7468e5f..d54aada 100644
--- a/modules/audio_coding/codecs/ilbc/decode_residual.h
+++ b/modules/audio_coding/codecs/ilbc/decode_residual.h
@@ -20,7 +20,10 @@
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_RESIDUAL_H_
 
 #include <stdbool.h>
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "rtc_base/system/unused.h"
 
 /*----------------------------------------------------------------*
  *  frame residual decoder function (subrutine to iLBC_decode)
diff --git a/modules/audio_coding/codecs/ilbc/defines.h b/modules/audio_coding/codecs/ilbc/defines.h
index 9a4a196..43948a2 100644
--- a/modules/audio_coding/codecs/ilbc/defines.h
+++ b/modules/audio_coding/codecs/ilbc/defines.h
@@ -21,7 +21,6 @@
 #include <string.h>
 
 #include "common_audio/signal_processing/include/signal_processing_library.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 /* general codec settings */
 
diff --git a/modules/audio_coding/codecs/ilbc/encode.c b/modules/audio_coding/codecs/ilbc/encode.c
index 3631c65..912e23c 100644
--- a/modules/audio_coding/codecs/ilbc/encode.c
+++ b/modules/audio_coding/codecs/ilbc/encode.c
@@ -18,6 +18,9 @@
 
 #include <string.h>
 
+// Defines WEBRTC_ARCH_BIG_ENDIAN, used below.
+#include "rtc_base/system/arch.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/lpc_encode.h"
 #include "modules/audio_coding/codecs/ilbc/frame_classify.h"
diff --git a/modules/audio_coding/codecs/ilbc/get_cd_vec.h b/modules/audio_coding/codecs/ilbc/get_cd_vec.h
index 76e1a56..647b063 100644
--- a/modules/audio_coding/codecs/ilbc/get_cd_vec.h
+++ b/modules/audio_coding/codecs/ilbc/get_cd_vec.h
@@ -20,8 +20,11 @@
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_CD_VEC_H_
 
 #include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
 
 #include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "rtc_base/system/unused.h"
 
 // Returns true on success, false on failure. In case of failure, the decoder
 // state may be corrupted and needs resetting.
diff --git a/modules/audio_coding/codecs/ilbc/ilbc.h b/modules/audio_coding/codecs/ilbc/ilbc.h
index 4c12665..de8cfde 100644
--- a/modules/audio_coding/codecs/ilbc/ilbc.h
+++ b/modules/audio_coding/codecs/ilbc/ilbc.h
@@ -19,12 +19,7 @@
 #define MODULES_AUDIO_CODING_CODECS_ILBC_ILBC_H_
 
 #include <stddef.h>
-
-/*
- * Define the fixpoint numeric formats
- */
-
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 /*
  * Solution to support multiple instances
diff --git a/modules/audio_coding/codecs/ilbc/vq3.h b/modules/audio_coding/codecs/ilbc/vq3.h
index ceaff8d..c946478 100644
--- a/modules/audio_coding/codecs/ilbc/vq3.h
+++ b/modules/audio_coding/codecs/ilbc/vq3.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_VQ3_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_VQ3_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  Vector quantization of order 3 (based on MSE)
diff --git a/modules/audio_coding/codecs/ilbc/vq4.h b/modules/audio_coding/codecs/ilbc/vq4.h
index 8dbedc9..6d14830 100644
--- a/modules/audio_coding/codecs/ilbc/vq4.h
+++ b/modules/audio_coding/codecs/ilbc/vq4.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_VQ4_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_VQ4_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  Vector quantization of order 4 (based on MSE)
diff --git a/modules/audio_coding/codecs/isac/bandwidth_info.h b/modules/audio_coding/codecs/isac/bandwidth_info.h
index 0539780..c3830a5 100644
--- a/modules/audio_coding/codecs/isac/bandwidth_info.h
+++ b/modules/audio_coding/codecs/isac/bandwidth_info.h
@@ -11,7 +11,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_BANDWIDTH_INFO_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_BANDWIDTH_INFO_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 typedef struct {
   int in_use;
diff --git a/modules/audio_coding/codecs/isac/fix/include/isacfix.h b/modules/audio_coding/codecs/isac/fix/include/isacfix.h
index 626b3c7..8fcfebb 100644
--- a/modules/audio_coding/codecs/isac/fix/include/isacfix.h
+++ b/modules/audio_coding/codecs/isac/fix/include/isacfix.h
@@ -14,7 +14,6 @@
 #include <stddef.h>
 
 #include "modules/audio_coding/codecs/isac/bandwidth_info.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 typedef struct { void* dummy; } ISACFIX_MainStruct;
 
diff --git a/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h b/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h
index 8d97347..6b99914 100644
--- a/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h
+++ b/modules/audio_coding/codecs/isac/fix/source/filterbank_internal.h
@@ -11,7 +11,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_INTERNAL_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
diff --git a/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h b/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h
index 55e1f44..01e5a7b 100644
--- a/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h
+++ b/modules/audio_coding/codecs/isac/fix/source/filterbank_tables.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_TABLES_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_FILTERBANK_TABLES_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
diff --git a/modules/audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc b/modules/audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc
index 0727d58..b7456a7 100644
--- a/modules/audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc
+++ b/modules/audio_coding/codecs/isac/fix/source/filterbanks_unittest.cc
@@ -15,7 +15,6 @@
 #include "rtc_base/sanitizer.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 class FilterBanksTest : public testing::Test {
  protected:
diff --git a/modules/audio_coding/codecs/isac/fix/source/filters_unittest.cc b/modules/audio_coding/codecs/isac/fix/source/filters_unittest.cc
index 2ab8d6a..471fa57 100644
--- a/modules/audio_coding/codecs/isac/fix/source/filters_unittest.cc
+++ b/modules/audio_coding/codecs/isac/fix/source/filters_unittest.cc
@@ -11,7 +11,6 @@
 #include "modules/audio_coding/codecs/isac/fix/source/codec.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 class FiltersTest : public testing::Test {
  protected:
diff --git a/modules/audio_coding/codecs/isac/fix/source/lattice_c.c b/modules/audio_coding/codecs/isac/fix/source/lattice_c.c
index d9849d6..4340661 100644
--- a/modules/audio_coding/codecs/isac/fix/source/lattice_c.c
+++ b/modules/audio_coding/codecs/isac/fix/source/lattice_c.c
@@ -16,7 +16,6 @@
 
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 #include "modules/audio_coding/codecs/isac/fix/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 /* Filter ar_g_Q0[] and ar_f_Q0[] through an AR filter with coefficients
  * cth_Q15[] and sth_Q15[].
diff --git a/modules/audio_coding/codecs/isac/fix/source/lattice_mips.c b/modules/audio_coding/codecs/isac/fix/source/lattice_mips.c
index 613c07c..3189726 100644
--- a/modules/audio_coding/codecs/isac/fix/source/lattice_mips.c
+++ b/modules/audio_coding/codecs/isac/fix/source/lattice_mips.c
@@ -9,9 +9,9 @@
  */
 
 #include <stddef.h>
+#include <stdint.h>
 
 #include "modules/audio_coding/codecs/isac/fix/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 // Filter ar_g_Q0[] and ar_f_Q0[] through an AR filter with coefficients
 // cth_Q15[] and sth_Q15[].
diff --git a/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_unittest.cc b/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_unittest.cc
index dbcf420..fab0a04 100644
--- a/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_unittest.cc
+++ b/modules/audio_coding/codecs/isac/fix/source/lpc_masking_model_unittest.cc
@@ -11,7 +11,6 @@
 #include "modules/audio_coding/codecs/isac/fix/source/lpc_masking_model.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 class LpcMaskingModelTest : public testing::Test {
  protected:
diff --git a/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h b/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h
index c51f2ca..2d68fa6 100644
--- a/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h
+++ b/modules/audio_coding/codecs/isac/fix/source/lpc_tables.h
@@ -18,7 +18,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_TABLES_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_LPC_TABLES_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 /* indices of KLT coefficients used */
 extern const uint16_t WebRtcIsacfix_kSelIndGain[12];
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h b/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h
index 2b5f54e..59e1738 100644
--- a/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_gain_tables.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_GAIN_TABLES_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_GAIN_TABLES_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 /********************* Pitch Filter Gain Coefficient Tables
  * ************************/
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h b/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h
index f834eab..228da26 100644
--- a/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_lag_tables.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_LAG_TABLES_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_PITCH_LAG_TABLES_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 /********************* Pitch Filter Lag Coefficient Tables
  * ************************/
diff --git a/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h b/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h
index 4ac5c0b..2282a36 100644
--- a/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h
+++ b/modules/audio_coding/codecs/isac/fix/source/spectrum_ar_model_tables.h
@@ -19,8 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_FIX_SOURCE_SPECTRUM_AR_MODEL_TABLES_H_
 
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/isac/fix/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 /********************* AR Coefficient Tables ************************/
 /* cdf for quantized reflection coefficient 1 */
diff --git a/modules/audio_coding/codecs/isac/fix/source/structs.h b/modules/audio_coding/codecs/isac/fix/source/structs.h
index 352eef0..59226ac 100644
--- a/modules/audio_coding/codecs/isac/fix/source/structs.h
+++ b/modules/audio_coding/codecs/isac/fix/source/structs.h
@@ -21,7 +21,6 @@
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 #include "modules/audio_coding/codecs/isac/bandwidth_info.h"
 #include "modules/audio_coding/codecs/isac/fix/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 /* Bitstream struct for decoder */
 typedef struct Bitstreamstruct_dec {
diff --git a/modules/audio_coding/codecs/isac/fix/source/transform.c b/modules/audio_coding/codecs/isac/fix/source/transform.c
index 2f1275d..80b244b 100644
--- a/modules/audio_coding/codecs/isac/fix/source/transform.c
+++ b/modules/audio_coding/codecs/isac/fix/source/transform.c
@@ -18,6 +18,7 @@
 #include "modules/audio_coding/codecs/isac/fix/source/codec.h"
 #include "modules/audio_coding/codecs/isac/fix/source/fft.h"
 #include "modules/audio_coding/codecs/isac/fix/source/settings.h"
+#include "modules/third_party/fft/fft.h"
 
 /* Tables are defined in transform_tables.c file or ARM assembly files. */
 /* Cosine table 1 in Q14 */
diff --git a/modules/audio_coding/codecs/isac/fix/source/transform_tables.c b/modules/audio_coding/codecs/isac/fix/source/transform_tables.c
index eed88e4..e661eff 100644
--- a/modules/audio_coding/codecs/isac/fix/source/transform_tables.c
+++ b/modules/audio_coding/codecs/isac/fix/source/transform_tables.c
@@ -13,8 +13,9 @@
  * transform functions WebRtcIsacfix_Time2Spec and WebRtcIsacfix_Spec2Time.
  */
 
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/isac/fix/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 /* Cosine table 1 in Q14. */
 const int16_t WebRtcIsacfix_kCosTab1[FRAMESAMPLES/2] = {
diff --git a/modules/audio_coding/codecs/isac/main/include/isac.h b/modules/audio_coding/codecs/isac/main/include/isac.h
index 1d7e075..6cd70a6 100644
--- a/modules/audio_coding/codecs/isac/main/include/isac.h
+++ b/modules/audio_coding/codecs/isac/main/include/isac.h
@@ -14,7 +14,6 @@
 #include <stddef.h>
 
 #include "modules/audio_coding/codecs/isac/bandwidth_info.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 typedef struct WebRtcISACStruct ISACStruct;
 
diff --git a/modules/audio_coding/codecs/isac/main/source/codec.h b/modules/audio_coding/codecs/isac/main/source/codec.h
index c386704..a7c7ddc 100644
--- a/modules/audio_coding/codecs/isac/main/source/codec.h
+++ b/modules/audio_coding/codecs/isac/main/source/codec.h
@@ -22,6 +22,7 @@
 #include <stddef.h>
 
 #include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#include "modules/third_party/fft/fft.h"
 
 void WebRtcIsac_ResetBitstream(Bitstr* bit_stream);
 
diff --git a/modules/audio_coding/codecs/isac/main/source/crc.h b/modules/audio_coding/codecs/isac/main/source/crc.h
index 19adbda..f031019 100644
--- a/modules/audio_coding/codecs/isac/main/source/crc.h
+++ b/modules/audio_coding/codecs/isac/main/source/crc.h
@@ -18,7 +18,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_CRC_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 /****************************************************************************
  * WebRtcIsac_GetCrc(...)
diff --git a/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c b/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c
index 0ab2dc1..7b02e64 100644
--- a/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c
+++ b/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.c
@@ -25,7 +25,6 @@
 #include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h"
 #include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
 #include "modules/audio_coding/codecs/isac/main/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 /******************************************************************************
  * WebRtcIsac_RemoveLarMean()
diff --git a/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h b/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h
index b8d918b..8bc3d75 100644
--- a/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h
+++ b/modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.h
@@ -21,7 +21,6 @@
 
 #include "modules/audio_coding/codecs/isac/main/source/settings.h"
 #include "modules/audio_coding/codecs/isac/main/source/structs.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 /******************************************************************************
  * WebRtcIsac_RemoveLarMean()
diff --git a/modules/audio_coding/codecs/isac/main/source/isac.c b/modules/audio_coding/codecs/isac/main/source/isac.c
index 45eb598..8669596 100644
--- a/modules/audio_coding/codecs/isac/main/source/isac.c
+++ b/modules/audio_coding/codecs/isac/main/source/isac.c
@@ -32,6 +32,7 @@
 #include "modules/audio_coding/codecs/isac/main/source/os_specific_inline.h"
 #include "modules/audio_coding/codecs/isac/main/source/structs.h"
 #include "modules/audio_coding/codecs/isac/main/source/isac_vad.h"
+#include "rtc_base/system/arch.h"
 
 #define BIT_MASK_DEC_INIT 0x0001
 #define BIT_MASK_ENC_INIT 0x0002
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c b/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c
index d6e65f3..6707540 100644
--- a/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.c
@@ -18,7 +18,6 @@
 
 #include "modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h"
 #include "modules/audio_coding/codecs/isac/main/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 const double WebRtcIsac_kQSizeLpcGain = 0.100000;
 
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h b/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h
index 84913dd..39c4a24 100644
--- a/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_gain_swb_tables.h
@@ -19,8 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_GAIN_SWB_TABLES_H_
 
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/isac/main/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 extern const double WebRtcIsac_kQSizeLpcGain;
 
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c
index 490866c..e3600a7 100644
--- a/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.c
@@ -18,7 +18,6 @@
 
 #include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h"
 #include "modules/audio_coding/codecs/isac/main/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 /*
 * Mean value of LAR
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h
index e21e15a..7448a1e 100644
--- a/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb12_tables.h
@@ -19,8 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB12_TABLES_H_
 
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/isac/main/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 extern const double WebRtcIsac_kMeanLarUb12[UB_LPC_ORDER];
 
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c
index d03c7b7..59617fd 100644
--- a/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.c
@@ -18,7 +18,6 @@
 
 #include "modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h"
 #include "modules/audio_coding/codecs/isac/main/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 /*
 * Mean value of LAR
diff --git a/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h
index 4d5403d..51101db 100644
--- a/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h
+++ b/modules/audio_coding/codecs/isac/main/source/lpc_shape_swb16_tables.h
@@ -19,8 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_LPC_SHAPE_SWB16_TABLES_H_
 
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/isac/main/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 extern const double WebRtcIsac_kMeanLarUb16[UB_LPC_ORDER];
 
diff --git a/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h b/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h
index f72236d..fe9afa4 100644
--- a/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h
+++ b/modules/audio_coding/codecs/isac/main/source/os_specific_inline.h
@@ -12,7 +12,8 @@
 #define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_OS_SPECIFIC_INLINE_H_
 
 #include <math.h>
-#include "typedefs.h"  // NOLINT(build/include)
+
+#include "rtc_base/system/arch.h"
 
 #if defined(WEBRTC_POSIX)
 #define WebRtcIsac_lrint lrint
diff --git a/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h b/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h
index 891bcef..145fd4e 100644
--- a/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h
+++ b/modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_GAIN_TABLES_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 /* header file for coding tables for the pitch filter side-info in the entropy
  * coder */
diff --git a/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h b/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h
index b662ab5..b48e358 100644
--- a/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h
+++ b/modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_PITCH_LAG_TABLES_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
+
 /* header file for coding tables for the pitch filter side-info in the entropy
  * coder */
 /********************* Pitch Filter Lag Coefficient Tables
diff --git a/modules/audio_coding/codecs/isac/main/source/settings.h b/modules/audio_coding/codecs/isac/main/source/settings.h
index 14a5be8..abce90c 100644
--- a/modules/audio_coding/codecs/isac/main/source/settings.h
+++ b/modules/audio_coding/codecs/isac/main/source/settings.h
@@ -24,9 +24,6 @@
 /* number of samples per frame (either 320 (20ms), 480 (30ms) or 960 (60ms)) */
 #define INITIAL_FRAMESAMPLES 960
 
-#define MAXFFTSIZE 2048
-#define NFACTOR 11
-
 /* do not modify the following; this will have to be modified if we
  * have a 20ms framesize option */
 /**********************************************************************/
diff --git a/modules/audio_coding/codecs/isac/main/source/structs.h b/modules/audio_coding/codecs/isac/main/source/structs.h
index f8ac9c7..1255d5b 100644
--- a/modules/audio_coding/codecs/isac/main/source/structs.h
+++ b/modules/audio_coding/codecs/isac/main/source/structs.h
@@ -20,7 +20,7 @@
 
 #include "modules/audio_coding/codecs/isac/bandwidth_info.h"
 #include "modules/audio_coding/codecs/isac/main/source/settings.h"
-#include "typedefs.h"  // NOLINT(build/include)
+#include "modules/third_party/fft/fft.h"
 
 typedef struct Bitstreamstruct {
   uint8_t stream[STREAM_SIZE_MAX];
@@ -229,18 +229,6 @@
 
 } RateModel;
 
-typedef struct {
-  unsigned int SpaceAlloced;
-  unsigned int MaxPermAlloced;
-  double Tmp0[MAXFFTSIZE];
-  double Tmp1[MAXFFTSIZE];
-  double Tmp2[MAXFFTSIZE];
-  double Tmp3[MAXFFTSIZE];
-  int Perm[MAXFFTSIZE];
-  int factor[NFACTOR];
-
-} FFTstr;
-
 /* The following strutc is used to store data from encoding, to make it
    fast and easy to construct a new bitstream with a different Bandwidth
    estimate. All values (except framelength and minBytes) is double size to
diff --git a/modules/audio_coding/codecs/isac/main/source/transform.c b/modules/audio_coding/codecs/isac/main/source/transform.c
index bfbfecb..082ad94 100644
--- a/modules/audio_coding/codecs/isac/main/source/transform.c
+++ b/modules/audio_coding/codecs/isac/main/source/transform.c
@@ -11,9 +11,9 @@
 #include <math.h>
 
 #include "modules/audio_coding/codecs/isac/main/source/settings.h"
-#include "modules/audio_coding/codecs/isac/main/source/fft.h"
 #include "modules/audio_coding/codecs/isac/main/source/codec.h"
 #include "modules/audio_coding/codecs/isac/main/source/os_specific_inline.h"
+#include "modules/third_party/fft/fft.h"
 
 void WebRtcIsac_InitTransform(TransformTables* tables) {
   int k;
diff --git a/modules/audio_coding/codecs/opus/opus_fec_test.cc b/modules/audio_coding/codecs/opus/opus_fec_test.cc
index f1983ae..4fab8a7 100644
--- a/modules/audio_coding/codecs/opus/opus_fec_test.cc
+++ b/modules/audio_coding/codecs/opus/opus_fec_test.cc
@@ -38,8 +38,8 @@
  protected:
   OpusFecTest();
 
-  virtual void SetUp();
-  virtual void TearDown();
+  void SetUp() override;
+  void TearDown() override;
 
   virtual void EncodeABlock();
 
diff --git a/modules/audio_coding/codecs/opus/opus_interface.h b/modules/audio_coding/codecs/opus/opus_interface.h
index 0b1c64d..ddb4ff9 100644
--- a/modules/audio_coding/codecs/opus/opus_interface.h
+++ b/modules/audio_coding/codecs/opus/opus_interface.h
@@ -12,9 +12,9 @@
 #define MODULES_AUDIO_CODING_CODECS_OPUS_OPUS_INTERFACE_H_
 
 #include <stddef.h>
+#include <stdint.h>
 
 #include "modules/audio_coding/codecs/opus/opus_inst.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/modules/audio_coding/codecs/pcm16b/pcm16b.c b/modules/audio_coding/codecs/pcm16b/pcm16b.c
index abcff4f..2f6dce5 100644
--- a/modules/audio_coding/codecs/pcm16b/pcm16b.c
+++ b/modules/audio_coding/codecs/pcm16b/pcm16b.c
@@ -10,8 +10,6 @@
 
 #include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 size_t WebRtcPcm16b_Encode(const int16_t* speech,
                            size_t len,
                            uint8_t* encoded) {
diff --git a/modules/audio_coding/codecs/pcm16b/pcm16b.h b/modules/audio_coding/codecs/pcm16b/pcm16b.h
index 9a3bfe9..75d1efd 100644
--- a/modules/audio_coding/codecs/pcm16b/pcm16b.h
+++ b/modules/audio_coding/codecs/pcm16b/pcm16b.h
@@ -15,8 +15,7 @@
  */
 
 #include <stddef.h>
-
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/modules/audio_coding/codecs/tools/audio_codec_speed_test.h b/modules/audio_coding/codecs/tools/audio_codec_speed_test.h
index 0214a7d..c626bfa 100644
--- a/modules/audio_coding/codecs/tools/audio_codec_speed_test.h
+++ b/modules/audio_coding/codecs/tools/audio_codec_speed_test.h
@@ -15,7 +15,6 @@
 #include <string>
 
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/include/audio_coding_module.h b/modules/audio_coding/include/audio_coding_module.h
index a5ad4ff..840a719 100644
--- a/modules/audio_coding/include/audio_coding_module.h
+++ b/modules/audio_coding/include/audio_coding_module.h
@@ -21,10 +21,8 @@
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/include/audio_coding_module_typedefs.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
-#include "rtc_base/deprecation.h"
 #include "rtc_base/function_view.h"
 #include "system_wrappers/include/clock.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -153,20 +151,6 @@
                    size_t channels);
 
   ///////////////////////////////////////////////////////////////////////////
-  // bool IsCodecValid()
-  // Checks the validity of the parameters of the given codec.
-  //
-  // Input:
-  //   -codec              : the structure which keeps the parameters of the
-  //                         codec.
-  //
-  // Return value:
-  //   true if the parameters are valid,
-  //   false if any parameter is not valid.
-  //
-  static bool IsCodecValid(const CodecInst& codec);
-
-  ///////////////////////////////////////////////////////////////////////////
   //   Sender
   //
 
@@ -212,11 +196,6 @@
   virtual void ModifyEncoder(
       rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) = 0;
 
-  // |modifier| is called exactly once with one argument: a const pointer to the
-  // current encoder (which is null if there is no current encoder).
-  virtual void QueryEncoder(
-      rtc::FunctionView<void(AudioEncoder const*)> query) = 0;
-
   // Utility method for simply replacing the existing encoder with a new one.
   void SetEncoder(std::unique_ptr<AudioEncoder> new_encoder) {
     ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
@@ -234,16 +213,6 @@
   virtual absl::optional<CodecInst> SendCodec() const = 0;
 
   ///////////////////////////////////////////////////////////////////////////
-  // int32_t SendFrequency()
-  // Get the sampling frequency of the current encoder in Hertz.
-  //
-  // Return value:
-  //   positive; sampling frequency [Hz] of the current encoder.
-  //   -1 if an error has happened.
-  //
-  virtual int32_t SendFrequency() const = 0;
-
-  ///////////////////////////////////////////////////////////////////////////
   // Sets the bitrate to the specified value in bits/sec. If the value is not
   // supported by the codec, it will choose another appropriate value.
   //
@@ -604,29 +573,6 @@
   //
   virtual int SetMaximumPlayoutDelay(int time_ms) = 0;
 
-  // TODO(kwiberg): Consider if this is needed anymore, now that voe::Channel
-  //                doesn't use it.
-  // The shortest latency, in milliseconds, required by jitter buffer. This
-  // is computed based on inter-arrival times and playout mode of NetEq. The
-  // actual delay is the maximum of least-required-delay and the minimum-delay
-  // specified by SetMinumumPlayoutDelay() API.
-  //
-  virtual int LeastRequiredDelayMs() const = 0;
-
-  // int32_t PlayoutTimestamp()
-  // The send timestamp of an RTP packet is associated with the decoded
-  // audio of the packet in question. This function returns the timestamp of
-  // the latest audio obtained by calling PlayoutData10ms().
-  //
-  // Input:
-  //   -timestamp          : a reference to a uint32_t to receive the
-  //                         timestamp.
-  // Return value:
-  //    0 if the output is a correct timestamp.
-  //   -1 if failed to output the correct timestamp.
-  //
-  RTC_DEPRECATED virtual int32_t PlayoutTimestamp(uint32_t* timestamp) = 0;
-
   ///////////////////////////////////////////////////////////////////////////
   // int32_t PlayoutTimestamp()
   // The send timestamp of an RTP packet is associated with the decoded
@@ -675,14 +621,6 @@
                                   AudioFrame* audio_frame,
                                   bool* muted) = 0;
 
-  /////////////////////////////////////////////////////////////////////////////
-  // Same as above, but without the muted parameter. This methods should not be
-  // used if enable_fast_accelerate was set to true in NetEq::Config.
-  // TODO(henrik.lundin) Remove this method when downstream dependencies are
-  // ready.
-  virtual int32_t PlayoutData10Ms(int32_t desired_freq_hz,
-                                  AudioFrame* audio_frame) = 0;
-
   ///////////////////////////////////////////////////////////////////////////
   //   Codec specific
   //
diff --git a/modules/audio_coding/include/audio_coding_module_typedefs.h b/modules/audio_coding/include/audio_coding_module_typedefs.h
index e8f80dc..cd4351b 100644
--- a/modules/audio_coding/include/audio_coding_module_typedefs.h
+++ b/modules/audio_coding/include/audio_coding_module_typedefs.h
@@ -13,8 +13,6 @@
 
 #include <map>
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 namespace webrtc {
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/modules/audio_coding/module.mk b/modules/audio_coding/module.mk
index b49e8aa..02f2a06 100644
--- a/modules/audio_coding/module.mk
+++ b/modules/audio_coding/module.mk
@@ -22,7 +22,6 @@
 	modules/audio_coding/codecs/isac/main/source/encode.o \
 	modules/audio_coding/codecs/isac/main/source/encode_lpc_swb.o \
 	modules/audio_coding/codecs/isac/main/source/entropy_coding.o \
-	modules/audio_coding/codecs/isac/main/source/fft.o \
 	modules/audio_coding/codecs/isac/main/source/filterbanks.o \
 	modules/audio_coding/codecs/isac/main/source/intialize.o \
 	modules/audio_coding/codecs/isac/main/source/isac.o \
@@ -35,7 +34,8 @@
 	modules/audio_coding/codecs/isac/main/source/pitch_gain_tables.o \
 	modules/audio_coding/codecs/isac/main/source/pitch_lag_tables.o \
 	modules/audio_coding/codecs/isac/main/source/spectrum_ar_model_tables.o \
-	modules/audio_coding/codecs/isac/main/source/transform.o
+	modules/audio_coding/codecs/isac/main/source/transform.o \
+	modules/third_party/fft/fft.o
 
 CC_STATIC_LIBRARY(modules/audio_coding/libaudio_coding.pic.a): \
 	$(isac_c_C_OBJECTS) $(isac_vad_c_OBJECTS)
diff --git a/modules/audio_coding/neteq/accelerate.h b/modules/audio_coding/neteq/accelerate.h
index 6d5b115..b0bab32 100644
--- a/modules/audio_coding/neteq/accelerate.h
+++ b/modules/audio_coding/neteq/accelerate.h
@@ -16,7 +16,6 @@
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "modules/audio_coding/neteq/time_stretch.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/audio_decoder_unittest.cc b/modules/audio_coding/neteq/audio_decoder_unittest.cc
index 54ede6f..1ad4835 100644
--- a/modules/audio_coding/neteq/audio_decoder_unittest.cc
+++ b/modules/audio_coding/neteq/audio_decoder_unittest.cc
@@ -100,16 +100,16 @@
         payload_type_(17),
         decoder_(NULL) {}
 
-  virtual ~AudioDecoderTest() {}
+  ~AudioDecoderTest() override {}
 
-  virtual void SetUp() {
+  void SetUp() override {
     if (audio_encoder_)
       codec_input_rate_hz_ = audio_encoder_->SampleRateHz();
     // Create arrays.
     ASSERT_GT(data_length_, 0u) << "The test must set data_length_ > 0";
   }
 
-  virtual void TearDown() {
+  void TearDown() override {
     delete decoder_;
     decoder_ = NULL;
   }
diff --git a/modules/audio_coding/neteq/audio_multi_vector.cc b/modules/audio_coding/neteq/audio_multi_vector.cc
index fee37cb..874633f 100644
--- a/modules/audio_coding/neteq/audio_multi_vector.cc
+++ b/modules/audio_coding/neteq/audio_multi_vector.cc
@@ -15,7 +15,6 @@
 #include <algorithm>
 
 #include "rtc_base/checks.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/audio_multi_vector.h b/modules/audio_coding/neteq/audio_multi_vector.h
index f54c98b..4a9ed48 100644
--- a/modules/audio_coding/neteq/audio_multi_vector.h
+++ b/modules/audio_coding/neteq/audio_multi_vector.h
@@ -17,7 +17,6 @@
 
 #include "modules/audio_coding/neteq/audio_vector.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/audio_multi_vector_unittest.cc b/modules/audio_coding/neteq/audio_multi_vector_unittest.cc
index 7272dc2..3f3283e 100644
--- a/modules/audio_coding/neteq/audio_multi_vector_unittest.cc
+++ b/modules/audio_coding/neteq/audio_multi_vector_unittest.cc
@@ -17,7 +17,6 @@
 
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/audio_vector.cc b/modules/audio_coding/neteq/audio_vector.cc
index 0486416..b3ad48f 100644
--- a/modules/audio_coding/neteq/audio_vector.cc
+++ b/modules/audio_coding/neteq/audio_vector.cc
@@ -16,7 +16,6 @@
 #include <memory>
 
 #include "rtc_base/checks.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/audio_vector.h b/modules/audio_coding/neteq/audio_vector.h
index 65939ce..825a3bc 100644
--- a/modules/audio_coding/neteq/audio_vector.h
+++ b/modules/audio_coding/neteq/audio_vector.h
@@ -16,7 +16,6 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/audio_vector_unittest.cc b/modules/audio_coding/neteq/audio_vector_unittest.cc
index e70178c..1a16bb3 100644
--- a/modules/audio_coding/neteq/audio_vector_unittest.cc
+++ b/modules/audio_coding/neteq/audio_vector_unittest.cc
@@ -17,7 +17,6 @@
 
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/background_noise.h b/modules/audio_coding/neteq/background_noise.h
index 26d42b5..58eecaa 100644
--- a/modules/audio_coding/neteq/background_noise.h
+++ b/modules/audio_coding/neteq/background_noise.h
@@ -17,7 +17,6 @@
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/comfort_noise.h b/modules/audio_coding/neteq/comfort_noise.h
index c8cc64a..5169124 100644
--- a/modules/audio_coding/neteq/comfort_noise.h
+++ b/modules/audio_coding/neteq/comfort_noise.h
@@ -13,7 +13,6 @@
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/decision_logic.h b/modules/audio_coding/neteq/decision_logic.h
index 20ba8af..00b8620 100644
--- a/modules/audio_coding/neteq/decision_logic.h
+++ b/modules/audio_coding/neteq/decision_logic.h
@@ -15,7 +15,6 @@
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/decoder_database.h b/modules/audio_coding/neteq/decoder_database.h
index 107d2f3..131e769 100644
--- a/modules/audio_coding/neteq/decoder_database.h
+++ b/modules/audio_coding/neteq/decoder_database.h
@@ -23,7 +23,6 @@
 #include "modules/audio_coding/neteq/packet.h"
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/scoped_ref_ptr.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc
index a945cdc..84d457c 100644
--- a/modules/audio_coding/neteq/delay_manager.cc
+++ b/modules/audio_coding/neteq/delay_manager.cc
@@ -40,7 +40,6 @@
       last_seq_no_(0),
       last_timestamp_(0),
       minimum_delay_ms_(0),
-      least_required_delay_ms_(target_level_),
       maximum_delay_ms_(target_level_),
       iat_cumulative_sum_(0),
       max_iat_cumulative_sum_(0),
@@ -234,8 +233,6 @@
 // |least_required_level_| while the above limits are applied.
 // TODO(hlundin): Move this check to the buffer logistics class.
 void DelayManager::LimitTargetLevel() {
-  least_required_delay_ms_ = (target_level_ * packet_len_ms_) >> 8;
-
   if (packet_len_ms_ > 0 && minimum_delay_ms_ > 0) {
     int minimum_delay_packet_q8 = (minimum_delay_ms_ << 8) / packet_len_ms_;
     target_level_ = std::max(target_level_, minimum_delay_packet_q8);
@@ -467,10 +464,6 @@
   return true;
 }
 
-int DelayManager::least_required_delay_ms() const {
-  return least_required_delay_ms_;
-}
-
 int DelayManager::base_target_level() const {
   return base_target_level_;
 }
diff --git a/modules/audio_coding/neteq/delay_manager.h b/modules/audio_coding/neteq/delay_manager.h
index 08004ea..00e39af 100644
--- a/modules/audio_coding/neteq/delay_manager.h
+++ b/modules/audio_coding/neteq/delay_manager.h
@@ -18,7 +18,6 @@
 
 #include "modules/audio_coding/neteq/tick_timer.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -110,7 +109,6 @@
   // Assuming |delay| is in valid range.
   virtual bool SetMinimumDelay(int delay_ms);
   virtual bool SetMaximumDelay(int delay_ms);
-  virtual int least_required_delay_ms() const;
   virtual int base_target_level() const;
   virtual void set_streaming_mode(bool value);
   virtual int last_pack_cng_or_dtmf() const;
@@ -162,10 +160,6 @@
   uint16_t last_seq_no_;         // Sequence number for last received packet.
   uint32_t last_timestamp_;      // Timestamp for the last received packet.
   int minimum_delay_ms_;         // Externally set minimum delay.
-  int least_required_delay_ms_;  // Smallest preferred buffer level (same unit
-                                 // as |target_level_|), before applying
-                                 // |minimum_delay_ms_| and/or
-                                 // |maximum_delay_ms_|.
   int maximum_delay_ms_;         // Externally set maximum allowed delay.
   int iat_cumulative_sum_;       // Cumulative sum of delta inter-arrival times.
   int max_iat_cumulative_sum_;   // Max of |iat_cumulative_sum_|.
diff --git a/modules/audio_coding/neteq/delay_manager_unittest.cc b/modules/audio_coding/neteq/delay_manager_unittest.cc
index f9c5680..6afed66 100644
--- a/modules/audio_coding/neteq/delay_manager_unittest.cc
+++ b/modules/audio_coding/neteq/delay_manager_unittest.cc
@@ -200,7 +200,7 @@
   EXPECT_EQ(lower + (20 << 8) / kFrameSizeMs, higher);
 }
 
-TEST_F(DelayManagerTest, MaxAndRequiredDelay) {
+TEST_F(DelayManagerTest, MaxDelay) {
   const int kExpectedTarget = 5;
   const int kTimeIncrement = kExpectedTarget * kFrameSizeMs;
   SetPacketAudioLength(kFrameSizeMs);
@@ -224,14 +224,13 @@
   EXPECT_TRUE(dm_->SetMaximumDelay(kMaxDelayMs));
   IncreaseTime(kTimeIncrement);
   InsertNextPacket();
-  EXPECT_EQ(kExpectedTarget * kFrameSizeMs, dm_->least_required_delay_ms());
   EXPECT_EQ(kMaxDelayPackets << 8, dm_->TargetLevel());
 
   // Target level at least should be one packet.
   EXPECT_FALSE(dm_->SetMaximumDelay(kFrameSizeMs - 1));
 }
 
-TEST_F(DelayManagerTest, MinAndRequiredDelay) {
+TEST_F(DelayManagerTest, MinDelay) {
   const int kExpectedTarget = 5;
   const int kTimeIncrement = kExpectedTarget * kFrameSizeMs;
   SetPacketAudioLength(kFrameSizeMs);
@@ -255,7 +254,6 @@
   dm_->SetMinimumDelay(kMinDelayMs);
   IncreaseTime(kTimeIncrement);
   InsertNextPacket();
-  EXPECT_EQ(kExpectedTarget * kFrameSizeMs, dm_->least_required_delay_ms());
   EXPECT_EQ(kMinDelayPackets << 8, dm_->TargetLevel());
 }
 
diff --git a/modules/audio_coding/neteq/dsp_helper.h b/modules/audio_coding/neteq/dsp_helper.h
index 8940acd..efa2f9c 100644
--- a/modules/audio_coding/neteq/dsp_helper.h
+++ b/modules/audio_coding/neteq/dsp_helper.h
@@ -15,7 +15,6 @@
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/dsp_helper_unittest.cc b/modules/audio_coding/neteq/dsp_helper_unittest.cc
index 9d5da5d..ec434a4 100644
--- a/modules/audio_coding/neteq/dsp_helper_unittest.cc
+++ b/modules/audio_coding/neteq/dsp_helper_unittest.cc
@@ -12,7 +12,6 @@
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/dtmf_buffer.h b/modules/audio_coding/neteq/dtmf_buffer.h
index 1035e87..6de5127 100644
--- a/modules/audio_coding/neteq/dtmf_buffer.h
+++ b/modules/audio_coding/neteq/dtmf_buffer.h
@@ -15,7 +15,6 @@
 #include <string>  // size_t
 
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/dtmf_tone_generator.h b/modules/audio_coding/neteq/dtmf_tone_generator.h
index b91d221..a773ff3 100644
--- a/modules/audio_coding/neteq/dtmf_tone_generator.h
+++ b/modules/audio_coding/neteq/dtmf_tone_generator.h
@@ -13,7 +13,6 @@
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/expand.h b/modules/audio_coding/neteq/expand.h
index 2fd4fae..4cfe7b9 100644
--- a/modules/audio_coding/neteq/expand.h
+++ b/modules/audio_coding/neteq/expand.h
@@ -16,7 +16,6 @@
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/include/neteq.h b/modules/audio_coding/neteq/include/neteq.h
index ce1448a..fdb73c5 100644
--- a/modules/audio_coding/neteq/include/neteq.h
+++ b/modules/audio_coding/neteq/include/neteq.h
@@ -24,7 +24,6 @@
 #include "modules/audio_coding/neteq/neteq_decoder_enum.h"
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/scoped_ref_ptr.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -97,7 +96,7 @@
     bool for_test_no_time_stretching = false;  // Use only for testing.
   };
 
-  enum ReturnCodes { kOK = 0, kFail = -1, kNotImplemented = -2 };
+  enum ReturnCodes { kOK = 0, kFail = -1 };
 
   // Creates a new NetEq object, with parameters set in |config|. The |config|
   // object will only have to be valid for the duration of the call to this
@@ -181,15 +180,6 @@
   // the |max_delay_ms| value in the NetEq::Config struct.
   virtual bool SetMaximumDelay(int delay_ms) = 0;
 
-  // The smallest latency required. This is computed bases on inter-arrival
-  // time and internal NetEq logic. Note that in computing this latency none of
-  // the user defined limits (applied by calling setMinimumDelay() and/or
-  // SetMaximumDelay()) are applied.
-  virtual int LeastRequiredDelayMs() const = 0;
-
-  // Not implemented.
-  virtual int SetTargetDelay() = 0;
-
   // Returns the current target delay in ms. This includes any extra delay
   // requested through SetMinimumDelay.
   virtual int TargetDelayMs() const = 0;
@@ -242,12 +232,6 @@
   virtual absl::optional<SdpAudioFormat> GetDecoderFormat(
       int payload_type) const = 0;
 
-  // Not implemented.
-  virtual int SetTargetNumberOfChannels() = 0;
-
-  // Not implemented.
-  virtual int SetTargetSampleRate() = 0;
-
   // Flushes both the packet buffer and the sync buffer.
   virtual void FlushBuffers() = 0;
 
diff --git a/modules/audio_coding/neteq/merge.h b/modules/audio_coding/neteq/merge.h
index 017e824..235c07f 100644
--- a/modules/audio_coding/neteq/merge.h
+++ b/modules/audio_coding/neteq/merge.h
@@ -15,7 +15,6 @@
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h b/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h
index 5aed6a9..1fb3db5 100644
--- a/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h
+++ b/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h
@@ -15,7 +15,6 @@
 #include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
 #include "rtc_base/constructormagic.h"
 #include "test/gmock.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/nack_tracker_unittest.cc b/modules/audio_coding/neteq/nack_tracker_unittest.cc
index 19adf30..a44f41b 100644
--- a/modules/audio_coding/neteq/nack_tracker_unittest.cc
+++ b/modules/audio_coding/neteq/nack_tracker_unittest.cc
@@ -17,7 +17,6 @@
 
 #include "modules/audio_coding/include/audio_coding_module_typedefs.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace {
diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc
index 0ef3263..ddcd221 100644
--- a/modules/audio_coding/neteq/neteq_impl.cc
+++ b/modules/audio_coding/neteq/neteq_impl.cc
@@ -307,16 +307,6 @@
   return false;
 }
 
-int NetEqImpl::LeastRequiredDelayMs() const {
-  rtc::CritScope lock(&crit_sect_);
-  assert(delay_manager_.get());
-  return delay_manager_->least_required_delay_ms();
-}
-
-int NetEqImpl::SetTargetDelay() {
-  return kNotImplemented;
-}
-
 int NetEqImpl::TargetDelayMs() const {
   rtc::CritScope lock(&crit_sect_);
   RTC_DCHECK(delay_manager_.get());
@@ -454,14 +444,6 @@
   return di->GetFormat();
 }
 
-int NetEqImpl::SetTargetNumberOfChannels() {
-  return kNotImplemented;
-}
-
-int NetEqImpl::SetTargetSampleRate() {
-  return kNotImplemented;
-}
-
 void NetEqImpl::FlushBuffers() {
   rtc::CritScope lock(&crit_sect_);
   RTC_LOG(LS_VERBOSE) << "FlushBuffers";
diff --git a/modules/audio_coding/neteq/neteq_impl.h b/modules/audio_coding/neteq/neteq_impl.h
index 6b8764d..68fdf3c 100644
--- a/modules/audio_coding/neteq/neteq_impl.h
+++ b/modules/audio_coding/neteq/neteq_impl.h
@@ -28,7 +28,6 @@
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/criticalsection.h"
 #include "rtc_base/thread_annotations.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -158,10 +157,6 @@
 
   bool SetMaximumDelay(int delay_ms) override;
 
-  int LeastRequiredDelayMs() const override;
-
-  int SetTargetDelay() override;
-
   int TargetDelayMs() const override;
 
   int CurrentDelayMs() const override;
@@ -197,10 +192,6 @@
   absl::optional<SdpAudioFormat> GetDecoderFormat(
       int payload_type) const override;
 
-  int SetTargetNumberOfChannels() override;
-
-  int SetTargetSampleRate() override;
-
   // Flushes both the packet buffer and the sync buffer.
   void FlushBuffers() override;
 
diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc
index 5d43fdb..96a392b 100644
--- a/modules/audio_coding/neteq/neteq_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_unittest.cc
@@ -33,10 +33,10 @@
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/protobuf_utils.h"
 #include "rtc_base/stringencode.h"
+#include "rtc_base/system/arch.h"
 #include "test/field_trial.h"
 #include "test/gtest.h"
 #include "test/testsupport/fileutils.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 // This must come after test/gtest.h
 #include "rtc_base/flags.h"  // NOLINT(build/include)
diff --git a/modules/audio_coding/neteq/normal.h b/modules/audio_coding/neteq/normal.h
index 41bd30a..b13f16e 100644
--- a/modules/audio_coding/neteq/normal.h
+++ b/modules/audio_coding/neteq/normal.h
@@ -20,7 +20,6 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/numerics/safe_conversions.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/packet.h b/modules/audio_coding/neteq/packet.h
index 61b0144..45c56e1 100644
--- a/modules/audio_coding/neteq/packet.h
+++ b/modules/audio_coding/neteq/packet.h
@@ -17,7 +17,6 @@
 #include "api/audio_codecs/audio_decoder.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
 #include "rtc_base/buffer.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/packet_buffer.h b/modules/audio_coding/neteq/packet_buffer.h
index 74f36a5..7e34c1e 100644
--- a/modules/audio_coding/neteq/packet_buffer.h
+++ b/modules/audio_coding/neteq/packet_buffer.h
@@ -16,7 +16,6 @@
 #include "modules/audio_coding/neteq/packet.h"
 #include "modules/include/module_common_types.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/post_decode_vad.h b/modules/audio_coding/neteq/post_decode_vad.h
index dac95f0..ad4f082 100644
--- a/modules/audio_coding/neteq/post_decode_vad.h
+++ b/modules/audio_coding/neteq/post_decode_vad.h
@@ -19,7 +19,6 @@
 #include "modules/audio_coding/neteq/defines.h"
 #include "modules/audio_coding/neteq/packet.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/preemptive_expand.h b/modules/audio_coding/neteq/preemptive_expand.h
index 197d3f1..4d72616 100644
--- a/modules/audio_coding/neteq/preemptive_expand.h
+++ b/modules/audio_coding/neteq/preemptive_expand.h
@@ -16,7 +16,6 @@
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "modules/audio_coding/neteq/time_stretch.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/random_vector.h b/modules/audio_coding/neteq/random_vector.h
index 2c6e06c..e8c7ba8 100644
--- a/modules/audio_coding/neteq/random_vector.h
+++ b/modules/audio_coding/neteq/random_vector.h
@@ -11,10 +11,10 @@
 #ifndef MODULES_AUDIO_CODING_NETEQ_RANDOM_VECTOR_H_
 #define MODULES_AUDIO_CODING_NETEQ_RANDOM_VECTOR_H_
 
-#include <string.h>  // size_t
+#include <stddef.h>
+#include <stdint.h>
 
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/rtcp.h b/modules/audio_coding/neteq/rtcp.h
index 45bb058..b1de7eb 100644
--- a/modules/audio_coding/neteq/rtcp.h
+++ b/modules/audio_coding/neteq/rtcp.h
@@ -13,7 +13,6 @@
 
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/statistics_calculator.h b/modules/audio_coding/neteq/statistics_calculator.h
index 42fd4c9..5f7d06a 100644
--- a/modules/audio_coding/neteq/statistics_calculator.h
+++ b/modules/audio_coding/neteq/statistics_calculator.h
@@ -16,7 +16,6 @@
 
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/sync_buffer.h b/modules/audio_coding/neteq/sync_buffer.h
index 8a35326..3833cb2 100644
--- a/modules/audio_coding/neteq/sync_buffer.h
+++ b/modules/audio_coding/neteq/sync_buffer.h
@@ -14,7 +14,6 @@
 #include "api/audio/audio_frame.h"
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/tick_timer.h b/modules/audio_coding/neteq/tick_timer.h
index 4a9ade5..520099e 100644
--- a/modules/audio_coding/neteq/tick_timer.h
+++ b/modules/audio_coding/neteq/tick_timer.h
@@ -15,7 +15,6 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/time_stretch.h b/modules/audio_coding/neteq/time_stretch.h
index 606d1d0..13ad2c8 100644
--- a/modules/audio_coding/neteq/time_stretch.h
+++ b/modules/audio_coding/neteq/time_stretch.h
@@ -16,7 +16,6 @@
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/timestamp_scaler.h b/modules/audio_coding/neteq/timestamp_scaler.h
index f0b05d6..62f535c 100644
--- a/modules/audio_coding/neteq/timestamp_scaler.h
+++ b/modules/audio_coding/neteq/timestamp_scaler.h
@@ -13,7 +13,6 @@
 
 #include "modules/audio_coding/neteq/packet.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/tools/audio_checksum.h b/modules/audio_coding/neteq/tools/audio_checksum.h
index db67edf..ee8c582 100644
--- a/modules/audio_coding/neteq/tools/audio_checksum.h
+++ b/modules/audio_coding/neteq/tools/audio_checksum.h
@@ -19,7 +19,7 @@
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/messagedigest.h"
 #include "rtc_base/stringencode.h"
-#include "typedefs.h"  // NOLINT(build/include)
+#include "rtc_base/system/arch.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/audio_loop.h b/modules/audio_coding/neteq/tools/audio_loop.h
index 876c2d7..c7788a6 100644
--- a/modules/audio_coding/neteq/tools/audio_loop.h
+++ b/modules/audio_coding/neteq/tools/audio_loop.h
@@ -16,7 +16,6 @@
 
 #include "api/array_view.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/audio_sink.h b/modules/audio_coding/neteq/tools/audio_sink.h
index 05e6fe8..be2a315 100644
--- a/modules/audio_coding/neteq/tools/audio_sink.h
+++ b/modules/audio_coding/neteq/tools/audio_sink.h
@@ -13,7 +13,6 @@
 
 #include "api/audio/audio_frame.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/encode_neteq_input.cc b/modules/audio_coding/neteq/tools/encode_neteq_input.cc
index f0d5b6f..c576670 100644
--- a/modules/audio_coding/neteq/tools/encode_neteq_input.cc
+++ b/modules/audio_coding/neteq/tools/encode_neteq_input.cc
@@ -27,6 +27,8 @@
   CreatePacket();
 }
 
+EncodeNetEqInput::~EncodeNetEqInput() = default;
+
 absl::optional<int64_t> EncodeNetEqInput::NextPacketTime() const {
   RTC_DCHECK(packet_data_);
   return static_cast<int64_t>(packet_data_->time_ms);
@@ -50,6 +52,10 @@
   next_output_event_ms_ += kOutputPeriodMs;
 }
 
+bool EncodeNetEqInput::ended() const {
+  return next_output_event_ms_ <= input_duration_ms_;
+}
+
 absl::optional<RTPHeader> EncodeNetEqInput::NextHeader() const {
   RTC_DCHECK(packet_data_);
   return packet_data_->header;
diff --git a/modules/audio_coding/neteq/tools/encode_neteq_input.h b/modules/audio_coding/neteq/tools/encode_neteq_input.h
index a75262b..caa9ac7 100644
--- a/modules/audio_coding/neteq/tools/encode_neteq_input.h
+++ b/modules/audio_coding/neteq/tools/encode_neteq_input.h
@@ -35,6 +35,7 @@
   EncodeNetEqInput(std::unique_ptr<Generator> generator,
                    std::unique_ptr<AudioEncoder> encoder,
                    int64_t input_duration_ms);
+  ~EncodeNetEqInput() override;
 
   absl::optional<int64_t> NextPacketTime() const override;
 
@@ -44,9 +45,7 @@
 
   void AdvanceOutputEvent() override;
 
-  bool ended() const override {
-    return next_output_event_ms_ <= input_duration_ms_;
-  }
+  bool ended() const override;
 
   absl::optional<RTPHeader> NextHeader() const override;
 
diff --git a/modules/audio_coding/neteq/tools/input_audio_file.h b/modules/audio_coding/neteq/tools/input_audio_file.h
index db5a944..b36dc24 100644
--- a/modules/audio_coding/neteq/tools/input_audio_file.h
+++ b/modules/audio_coding/neteq/tools/input_audio_file.h
@@ -16,7 +16,6 @@
 #include <string>
 
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/neteq_delay_analyzer.h b/modules/audio_coding/neteq/tools/neteq_delay_analyzer.h
index 5099e03..f6b895a 100644
--- a/modules/audio_coding/neteq/tools/neteq_delay_analyzer.h
+++ b/modules/audio_coding/neteq/tools/neteq_delay_analyzer.h
@@ -19,7 +19,6 @@
 #include "absl/types/optional.h"
 #include "modules/audio_coding/neteq/tools/neteq_input.h"
 #include "modules/audio_coding/neteq/tools/neteq_test.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/neteq_input.cc b/modules/audio_coding/neteq/tools/neteq_input.cc
index fed3ecc..bb2a01e 100644
--- a/modules/audio_coding/neteq/tools/neteq_input.cc
+++ b/modules/audio_coding/neteq/tools/neteq_input.cc
@@ -15,6 +15,9 @@
 namespace webrtc {
 namespace test {
 
+NetEqInput::PacketData::PacketData() = default;
+NetEqInput::PacketData::~PacketData() = default;
+
 std::string NetEqInput::PacketData::ToString() const {
   std::stringstream ss;
   ss << "{"
@@ -34,6 +37,8 @@
       start_time_ms_(input_->NextEventTime()),
       duration_ms_(duration_ms) {}
 
+TimeLimitedNetEqInput::~TimeLimitedNetEqInput() = default;
+
 absl::optional<int64_t> TimeLimitedNetEqInput::NextPacketTime() const {
   return ended_ ? absl::nullopt : input_->NextPacketTime();
 }
diff --git a/modules/audio_coding/neteq/tools/neteq_input.h b/modules/audio_coding/neteq/tools/neteq_input.h
index 1691585..b9cba09 100644
--- a/modules/audio_coding/neteq/tools/neteq_input.h
+++ b/modules/audio_coding/neteq/tools/neteq_input.h
@@ -28,6 +28,8 @@
 class NetEqInput {
  public:
   struct PacketData {
+    PacketData();
+    ~PacketData();
     std::string ToString() const;
 
     RTPHeader header;
@@ -84,6 +86,7 @@
 class TimeLimitedNetEqInput : public NetEqInput {
  public:
   TimeLimitedNetEqInput(std::unique_ptr<NetEqInput> input, int64_t duration_ms);
+  ~TimeLimitedNetEqInput() override;
   absl::optional<int64_t> NextPacketTime() const override;
   absl::optional<int64_t> NextOutputEventTime() const override;
   std::unique_ptr<PacketData> PopPacket() override;
diff --git a/modules/audio_coding/neteq/tools/neteq_performance_test.cc b/modules/audio_coding/neteq/tools/neteq_performance_test.cc
index e0dfebf..52524fe 100644
--- a/modules/audio_coding/neteq/tools/neteq_performance_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_performance_test.cc
@@ -20,7 +20,6 @@
 #include "rtc_base/checks.h"
 #include "system_wrappers/include/clock.h"
 #include "test/testsupport/fileutils.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 using webrtc::NetEq;
 using webrtc::test::AudioLoop;
diff --git a/modules/audio_coding/neteq/tools/neteq_performance_test.h b/modules/audio_coding/neteq/tools/neteq_performance_test.h
index dcf0314..d2212f0 100644
--- a/modules/audio_coding/neteq/tools/neteq_performance_test.h
+++ b/modules/audio_coding/neteq/tools/neteq_performance_test.h
@@ -11,7 +11,7 @@
 #ifndef MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_PERFORMANCE_TEST_H_
 #define MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_PERFORMANCE_TEST_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/neteq_quality_test.h b/modules/audio_coding/neteq/tools/neteq_quality_test.h
index b19460c..3d7760e 100644
--- a/modules/audio_coding/neteq/tools/neteq_quality_test.h
+++ b/modules/audio_coding/neteq/tools/neteq_quality_test.h
@@ -21,7 +21,6 @@
 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
 #include "rtc_base/flags.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/neteq_replacement_input.cc b/modules/audio_coding/neteq/tools/neteq_replacement_input.cc
index 6aa7581..362eb89 100644
--- a/modules/audio_coding/neteq/tools/neteq_replacement_input.cc
+++ b/modules/audio_coding/neteq/tools/neteq_replacement_input.cc
@@ -28,7 +28,6 @@
   RTC_CHECK(source_);
   packet_ = source_->PopPacket();
   ReplacePacket();
-  RTC_CHECK(packet_);
 }
 
 absl::optional<int64_t> NetEqReplacementInput::NextPacketTime() const {
diff --git a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
index 7f1263c..bf782bf 100644
--- a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
+++ b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
@@ -31,8 +31,8 @@
 #include "modules/audio_coding/neteq/tools/rtp_file_source.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/flags.h"
+#include "test/field_trial.h"
 #include "test/testsupport/fileutils.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace test {
@@ -133,6 +133,12 @@
             "Generates a python script for plotting the delay profile");
 DEFINE_bool(help, false, "Prints this message");
 DEFINE_bool(concealment_events, false, "Prints concealment events");
+DEFINE_string(
+    force_fieldtrials,
+    "",
+    "Field trials control experimental feature code which can be forced. "
+    "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/"
+    " will assign the group Enable to field trial WebRTC-FooFeature.");
 
 // Maps a codec type to a printable name string.
 std::string CodecName(NetEqDecoder codec) {
@@ -293,6 +299,10 @@
     std::cout << usage;
     return 0;
   }
+
+  ValidateFieldTrialsStringOrDie(FLAG_force_fieldtrials);
+  ScopedFieldTrials field_trials(FLAG_force_fieldtrials);
+
   RTC_CHECK(ValidatePayloadType(FLAG_pcmu));
   RTC_CHECK(ValidatePayloadType(FLAG_pcma));
   RTC_CHECK(ValidatePayloadType(FLAG_ilbc));
@@ -398,32 +408,38 @@
   std::cout << "Output file: " << output_file_name << std::endl;
 
   NetEqTest::DecoderMap codecs = {
-      {FLAG_pcmu, std::make_pair(NetEqDecoder::kDecoderPCMu, "pcmu")},
-      {FLAG_pcma, std::make_pair(NetEqDecoder::kDecoderPCMa, "pcma")},
-      {FLAG_ilbc, std::make_pair(NetEqDecoder::kDecoderILBC, "ilbc")},
-      {FLAG_isac, std::make_pair(NetEqDecoder::kDecoderISAC, "isac")},
-      {FLAG_isac_swb,
-       std::make_pair(NetEqDecoder::kDecoderISACswb, "isac-swb")},
-      {FLAG_opus, std::make_pair(NetEqDecoder::kDecoderOpus, "opus")},
-      {FLAG_pcm16b, std::make_pair(NetEqDecoder::kDecoderPCM16B, "pcm16-nb")},
-      {FLAG_pcm16b_wb,
-       std::make_pair(NetEqDecoder::kDecoderPCM16Bwb, "pcm16-wb")},
-      {FLAG_pcm16b_swb32,
-       std::make_pair(NetEqDecoder::kDecoderPCM16Bswb32kHz, "pcm16-swb32")},
-      {FLAG_pcm16b_swb48,
-       std::make_pair(NetEqDecoder::kDecoderPCM16Bswb48kHz, "pcm16-swb48")},
-      {FLAG_g722, std::make_pair(NetEqDecoder::kDecoderG722, "g722")},
-      {FLAG_avt, std::make_pair(NetEqDecoder::kDecoderAVT, "avt")},
-      {FLAG_avt_16, std::make_pair(NetEqDecoder::kDecoderAVT16kHz, "avt-16")},
-      {FLAG_avt_32, std::make_pair(NetEqDecoder::kDecoderAVT32kHz, "avt-32")},
-      {FLAG_avt_48, std::make_pair(NetEqDecoder::kDecoderAVT48kHz, "avt-48")},
-      {FLAG_red, std::make_pair(NetEqDecoder::kDecoderRED, "red")},
-      {FLAG_cn_nb, std::make_pair(NetEqDecoder::kDecoderCNGnb, "cng-nb")},
-      {FLAG_cn_wb, std::make_pair(NetEqDecoder::kDecoderCNGwb, "cng-wb")},
-      {FLAG_cn_swb32,
-       std::make_pair(NetEqDecoder::kDecoderCNGswb32kHz, "cng-swb32")},
-      {FLAG_cn_swb48,
-       std::make_pair(NetEqDecoder::kDecoderCNGswb48kHz, "cng-swb48")}};
+    {FLAG_pcmu, std::make_pair(NetEqDecoder::kDecoderPCMu, "pcmu")},
+    {FLAG_pcma, std::make_pair(NetEqDecoder::kDecoderPCMa, "pcma")},
+#ifdef WEBRTC_CODEC_ILBC
+    {FLAG_ilbc, std::make_pair(NetEqDecoder::kDecoderILBC, "ilbc")},
+#endif
+    {FLAG_isac, std::make_pair(NetEqDecoder::kDecoderISAC, "isac")},
+#if !defined(WEBRTC_ANDROID)
+    {FLAG_isac_swb, std::make_pair(NetEqDecoder::kDecoderISACswb, "isac-swb")},
+#endif
+#ifdef WEBRTC_CODEC_OPUS
+    {FLAG_opus, std::make_pair(NetEqDecoder::kDecoderOpus, "opus")},
+#endif
+    {FLAG_pcm16b, std::make_pair(NetEqDecoder::kDecoderPCM16B, "pcm16-nb")},
+    {FLAG_pcm16b_wb,
+     std::make_pair(NetEqDecoder::kDecoderPCM16Bwb, "pcm16-wb")},
+    {FLAG_pcm16b_swb32,
+     std::make_pair(NetEqDecoder::kDecoderPCM16Bswb32kHz, "pcm16-swb32")},
+    {FLAG_pcm16b_swb48,
+     std::make_pair(NetEqDecoder::kDecoderPCM16Bswb48kHz, "pcm16-swb48")},
+    {FLAG_g722, std::make_pair(NetEqDecoder::kDecoderG722, "g722")},
+    {FLAG_avt, std::make_pair(NetEqDecoder::kDecoderAVT, "avt")},
+    {FLAG_avt_16, std::make_pair(NetEqDecoder::kDecoderAVT16kHz, "avt-16")},
+    {FLAG_avt_32, std::make_pair(NetEqDecoder::kDecoderAVT32kHz, "avt-32")},
+    {FLAG_avt_48, std::make_pair(NetEqDecoder::kDecoderAVT48kHz, "avt-48")},
+    {FLAG_red, std::make_pair(NetEqDecoder::kDecoderRED, "red")},
+    {FLAG_cn_nb, std::make_pair(NetEqDecoder::kDecoderCNGnb, "cng-nb")},
+    {FLAG_cn_wb, std::make_pair(NetEqDecoder::kDecoderCNGwb, "cng-wb")},
+    {FLAG_cn_swb32,
+     std::make_pair(NetEqDecoder::kDecoderCNGswb32kHz, "cng-swb32")},
+    {FLAG_cn_swb48,
+     std::make_pair(NetEqDecoder::kDecoderCNGswb48kHz, "cng-swb48")}
+  };
 
   // Check if a replacement audio file was provided.
   std::unique_ptr<AudioDecoder> replacement_decoder;
diff --git a/modules/audio_coding/neteq/tools/neteq_test.cc b/modules/audio_coding/neteq/tools/neteq_test.cc
index e2bed56..3448f4e 100644
--- a/modules/audio_coding/neteq/tools/neteq_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_test.cc
@@ -46,6 +46,8 @@
   RegisterExternalDecoders(ext_codecs);
 }
 
+NetEqTest::~NetEqTest() = default;
+
 int64_t NetEqTest::Run() {
   const int64_t start_time_ms = *input_->NextEventTime();
   int64_t time_now_ms = start_time_ms;
diff --git a/modules/audio_coding/neteq/tools/neteq_test.h b/modules/audio_coding/neteq/tools/neteq_test.h
index 9c05fc4..ada6bab 100644
--- a/modules/audio_coding/neteq/tools/neteq_test.h
+++ b/modules/audio_coding/neteq/tools/neteq_test.h
@@ -82,7 +82,7 @@
             std::unique_ptr<AudioSink> output,
             Callbacks callbacks);
 
-  ~NetEqTest() = default;
+  ~NetEqTest();
 
   // Runs the test. Returns the duration of the produced audio in ms.
   int64_t Run();
diff --git a/modules/audio_coding/neteq/tools/packet.h b/modules/audio_coding/neteq/tools/packet.h
index 2c9a26f..623c5cb 100644
--- a/modules/audio_coding/neteq/tools/packet.h
+++ b/modules/audio_coding/neteq/tools/packet.h
@@ -17,7 +17,6 @@
 #include "api/rtp_headers.h"  // NOLINT(build/include)
 #include "common_types.h"     // NOLINT(build/include)
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/tools/packet_source.h b/modules/audio_coding/neteq/tools/packet_source.h
index 3f98ba1..fb689e3 100644
--- a/modules/audio_coding/neteq/tools/packet_source.h
+++ b/modules/audio_coding/neteq/tools/packet_source.h
@@ -16,7 +16,6 @@
 
 #include "modules/audio_coding/neteq/tools/packet.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/resample_input_audio_file.h b/modules/audio_coding/neteq/tools/resample_input_audio_file.h
index 13c419d..4e2e9b0 100644
--- a/modules/audio_coding/neteq/tools/resample_input_audio_file.h
+++ b/modules/audio_coding/neteq/tools/resample_input_audio_file.h
@@ -16,7 +16,6 @@
 #include "common_audio/resampler/include/resampler.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/rtp_encode.cc b/modules/audio_coding/neteq/tools/rtp_encode.cc
index abbb621..5065ca1 100644
--- a/modules/audio_coding/neteq/tools/rtp_encode.cc
+++ b/modules/audio_coding/neteq/tools/rtp_encode.cc
@@ -34,7 +34,6 @@
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "rtc_base/flags.h"
 #include "rtc_base/numerics/safe_conversions.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/rtp_file_source.h b/modules/audio_coding/neteq/tools/rtp_file_source.h
index b44bc64..013333b 100644
--- a/modules/audio_coding/neteq/tools/rtp_file_source.h
+++ b/modules/audio_coding/neteq/tools/rtp_file_source.h
@@ -39,7 +39,7 @@
   static bool ValidRtpDump(const std::string& file_name);
   static bool ValidPcap(const std::string& file_name);
 
-  virtual ~RtpFileSource();
+  ~RtpFileSource() override;
 
   // Registers an RTP header extension and binds it to |id|.
   virtual bool RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id);
diff --git a/modules/audio_coding/neteq/tools/rtp_generator.h b/modules/audio_coding/neteq/tools/rtp_generator.h
index 04fdbdd..ca7b04f 100644
--- a/modules/audio_coding/neteq/tools/rtp_generator.h
+++ b/modules/audio_coding/neteq/tools/rtp_generator.h
@@ -14,7 +14,6 @@
 #include "api/rtp_headers.h"
 #include "common_types.h"  // NOLINT(build/include)
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/rtp_jitter.cc b/modules/audio_coding/neteq/tools/rtp_jitter.cc
index d92fed0..3c49443 100644
--- a/modules/audio_coding/neteq/tools/rtp_jitter.cc
+++ b/modules/audio_coding/neteq/tools/rtp_jitter.cc
@@ -18,7 +18,6 @@
 #include "modules/rtp_rtcp/source/byte_io.h"
 #include "rtc_base/buffer.h"
 #include "rtc_base/flags.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_processing/BUILD.gn b/modules/audio_processing/BUILD.gn
index 4be7d8f..052bb47 100644
--- a/modules/audio_processing/BUILD.gn
+++ b/modules/audio_processing/BUILD.gn
@@ -37,8 +37,12 @@
     "common.h",
     "echo_cancellation_impl.cc",
     "echo_cancellation_impl.h",
+    "echo_cancellation_proxy.cc",
+    "echo_cancellation_proxy.h",
     "echo_control_mobile_impl.cc",
     "echo_control_mobile_impl.h",
+    "echo_control_mobile_proxy.cc",
+    "echo_control_mobile_proxy.h",
     "echo_detector/circular_buffer.cc",
     "echo_detector/circular_buffer.h",
     "echo_detector/mean_variance_estimator.cc",
@@ -101,7 +105,6 @@
     ":audio_processing_c",
     ":audio_processing_statistics",
     ":gain_control_interface",
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../api:array_view",
     "../../api/audio:aec3_config",
@@ -109,12 +112,13 @@
     "../../api/audio:echo_control",
     "../../audio/utility:audio_frame_operations",
     "../../common_audio:common_audio_c",
-    "../../common_audio:fft4g",
+    "../../common_audio/third_party/fft4g:fft4g",
     "../../rtc_base:checks",
     "../../rtc_base:deprecation",
     "../../rtc_base:gtest_prod",
     "../../rtc_base:safe_minmax",
     "../../rtc_base:sanitizer",
+    "../../rtc_base/system:arch",
     "../../system_wrappers:cpu_features_api",
     "../../system_wrappers:field_trial_api",
     "../../system_wrappers:metrics_api",
@@ -134,18 +138,6 @@
     defines += [ "WEBRTC_UNTRUSTED_DELAY" ]
   }
 
-  if (rtc_enable_intelligibility_enhancer) {
-    defines += [ "WEBRTC_INTELLIGIBILITY_ENHANCER=1" ]
-    sources += [
-      "intelligibility/intelligibility_enhancer.cc",
-      "intelligibility/intelligibility_enhancer.h",
-      "intelligibility/intelligibility_utils.cc",
-      "intelligibility/intelligibility_utils.h",
-    ]
-  } else {
-    defines += [ "WEBRTC_INTELLIGIBILITY_ENHANCER=0" ]
-  }
-
   if (rtc_prefer_fixed_point) {
     defines += [ "WEBRTC_NS_FIXED" ]
   } else {
@@ -257,11 +249,10 @@
   }
 
   deps = [
-    "../..:typedefs",
     "../..:webrtc_common",
     "../../common_audio",
     "../../common_audio:common_audio_c",
-    "../../common_audio:fft4g",
+    "../../common_audio/third_party/fft4g:fft4g",
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
     "../../system_wrappers:cpu_features_api",
@@ -272,9 +263,7 @@
     sources += [ "ns/nsx_core_neon.c" ]
 
     if (current_cpu != "arm64") {
-      # Enable compilation for the NEON instruction set. This is needed
-      # since //build/config/arm.gni only enables NEON for iOS, not Android.
-      # This provides the same functionality as webrtc/build/arm_neon.gypi.
+      # Enable compilation for the NEON instruction set.
       suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
       cflags = [ "-mfpu=neon" ]
     }
@@ -336,10 +325,6 @@
       ":transient_suppression_test",
     ]
 
-    if (rtc_enable_intelligibility_enhancer) {
-      deps += [ ":intelligibility_proc" ]
-    }
-
     if (rtc_enable_protobuf) {
       deps += [
         ":audioproc_f",
@@ -382,7 +367,6 @@
       ":audioproc_test_utils",
       ":file_audio_generator_unittests",
       ":mocks",
-      "../..:typedefs",
       "../..:webrtc_common",
       "../../api:array_view",
       "../../api/audio:aec3_config",
@@ -395,6 +379,7 @@
       "../../rtc_base:rtc_base",
       "../../rtc_base:rtc_base_approved",
       "../../rtc_base:safe_minmax",
+      "../../rtc_base/system:arch",
       "../../rtc_base/system:file_wrapper",
       "../../system_wrappers",
       "../../system_wrappers:cpu_features_api",
@@ -421,16 +406,6 @@
 
     defines = []
 
-    if (rtc_enable_intelligibility_enhancer) {
-      defines += [ "WEBRTC_INTELLIGIBILITY_ENHANCER=1" ]
-      sources += [
-        "intelligibility/intelligibility_enhancer_unittest.cc",
-        "intelligibility/intelligibility_utils_unittest.cc",
-      ]
-    } else {
-      defines += [ "WEBRTC_INTELLIGIBILITY_ENHANCER=0" ]
-    }
-
     if (rtc_prefer_fixed_point) {
       defines += [ "WEBRTC_AUDIOPROC_FIXED_PROFILE" ]
     } else {
@@ -445,6 +420,7 @@
         ":audioproc_test_utils",
         ":audioproc_unittest_proto",
         "../../api/audio:audio_frame_api",
+        "../../rtc_base:rtc_base_tests_utils",
         "../../rtc_base:rtc_task_queue",
         "aec_dump",
         "aec_dump:aec_dump_unittests",
@@ -498,12 +474,6 @@
       "../../test:perf_test",
       "../../test:test_support",
     ]
-
-    if (rtc_enable_intelligibility_enhancer) {
-      defines = [ "WEBRTC_INTELLIGIBILITY_ENHANCER=1" ]
-    } else {
-      defines = [ "WEBRTC_INTELLIGIBILITY_ENHANCER=0" ]
-    }
   }
 
   rtc_source_set("file_audio_generator_unittests") {
@@ -616,6 +586,7 @@
       "../../common_audio",
       "../../rtc_base:checks",
       "../../rtc_base:rtc_base_approved",
+      "../../rtc_base/system:arch",
       "../../system_wrappers",
       "../../test:fileutils",
       "../../test:test_support",
@@ -634,7 +605,6 @@
     ]
     deps = [
       ":audio_processing",
-      "../..:typedefs",
       "../..:webrtc_common",
       "../../common_audio:common_audio",
       "../../rtc_base:rtc_base_approved",
@@ -657,7 +627,6 @@
     ]
     deps = [
       ":audio_processing",
-      "../..:typedefs",
       "../..:webrtc_common",
       "../../rtc_base/system:file_wrapper",
       "../../system_wrappers",
@@ -665,24 +634,6 @@
     ]
   }
 
-  if (rtc_enable_intelligibility_enhancer) {
-    rtc_executable("intelligibility_proc") {
-      testonly = true
-      sources = [
-        "intelligibility/test/intelligibility_proc.cc",
-      ]
-      deps = [
-        ":audio_processing",
-        ":audioproc_test_utils",
-        "../../common_audio",
-        "../../rtc_base:rtc_base_approved",
-        "../../system_wrappers:metrics_default",
-        "../../test:test_support",
-        "//testing/gtest",
-      ]
-    }
-  }
-
   if (rtc_enable_protobuf) {
     proto_library("audioproc_unittest_proto") {
       sources = [
@@ -699,10 +650,10 @@
 
       deps = [
         ":audioproc_debug_proto",
-        "../..:typedefs",
         "../..:webrtc_common",
         "../../rtc_base:protobuf_utils",
         "../../rtc_base:rtc_base_approved",
+        "../../rtc_base/system:arch",
       ]
     }
   }
diff --git a/modules/audio_processing/aec/BUILD.gn b/modules/audio_processing/aec/BUILD.gn
index 5a858f5..52441d7 100644
--- a/modules/audio_processing/aec/BUILD.gn
+++ b/modules/audio_processing/aec/BUILD.gn
@@ -19,7 +19,6 @@
   deps = [
     ":aec_core",
     "..:apm_logging",
-    "../../..:typedefs",
     "../../../common_audio:common_audio_c",
     "../../../rtc_base:checks",
     "../../../rtc_base:rtc_base_approved",
@@ -36,10 +35,10 @@
   ]
   deps = [
     "..:apm_logging",
-    "../../..:typedefs",
     "../../../common_audio:common_audio_c",
     "../../../rtc_base:checks",
     "../../../rtc_base:rtc_base_approved",
+    "../../../rtc_base/system:arch",
     "../../../system_wrappers:cpu_features_api",
     "../../../system_wrappers:metrics_api",
     "../utility:block_mean_calculator",
@@ -59,9 +58,7 @@
     sources += [ "aec_core_neon.cc" ]
 
     if (current_cpu != "arm64") {
-      # Enable compilation for the NEON instruction set. This is needed
-      # since //build/config/arm.gni only enables NEON for iOS, not Android.
-      # This provides the same functionality as webrtc/build/arm_neon.gypi.
+      # Enable compilation for the NEON instruction set.
       suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
       cflags += [ "-mfpu=neon" ]
     }
@@ -94,7 +91,6 @@
     deps = [
       ":aec",
       ":aec_core",
-      "../../..:typedefs",
       "../../../rtc_base:checks",
       "../../../rtc_base:rtc_base_approved",
       "../../../test:test_support",
diff --git a/modules/audio_processing/aec/aec_common.h b/modules/audio_processing/aec/aec_common.h
index 80c5c14..ac1f339 100644
--- a/modules/audio_processing/aec/aec_common.h
+++ b/modules/audio_processing/aec/aec_common.h
@@ -11,8 +11,6 @@
 #ifndef MODULES_AUDIO_PROCESSING_AEC_AEC_COMMON_H_
 #define MODULES_AUDIO_PROCESSING_AEC_AEC_COMMON_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 #ifdef _MSC_VER /* visual c++ */
 #define ALIGN16_BEG __declspec(align(16))
 #define ALIGN16_END
diff --git a/modules/audio_processing/aec/aec_core.cc b/modules/audio_processing/aec/aec_core.cc
index 95ed595..5a8cf8f 100644
--- a/modules/audio_processing/aec/aec_core.cc
+++ b/modules/audio_processing/aec/aec_core.cc
@@ -30,9 +30,9 @@
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "modules/audio_processing/utility/delay_estimator_wrapper.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/system/arch.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 #include "system_wrappers/include/metrics.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace {
diff --git a/modules/audio_processing/aec/aec_core.h b/modules/audio_processing/aec/aec_core.h
index 9e25292..35a6c9b 100644
--- a/modules/audio_processing/aec/aec_core.h
+++ b/modules/audio_processing/aec/aec_core.h
@@ -26,7 +26,6 @@
 #include "modules/audio_processing/utility/block_mean_calculator.h"
 #include "modules/audio_processing/utility/ooura_fft.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec/aec_core_optimized_methods.h b/modules/audio_processing/aec/aec_core_optimized_methods.h
index a8a20e9..03c027d 100644
--- a/modules/audio_processing/aec/aec_core_optimized_methods.h
+++ b/modules/audio_processing/aec/aec_core_optimized_methods.h
@@ -14,7 +14,6 @@
 #include <memory>
 
 #include "modules/audio_processing/aec/aec_core.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec/echo_cancellation.cc b/modules/audio_processing/aec/echo_cancellation.cc
index c8382ec..fd1aec4 100644
--- a/modules/audio_processing/aec/echo_cancellation.cc
+++ b/modules/audio_processing/aec/echo_cancellation.cc
@@ -24,7 +24,6 @@
 #include "modules/audio_processing/aec/aec_core.h"
 #include "modules/audio_processing/aec/aec_resampler.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec/echo_cancellation.h b/modules/audio_processing/aec/echo_cancellation.h
index d5c703e..2039347 100644
--- a/modules/audio_processing/aec/echo_cancellation.h
+++ b/modules/audio_processing/aec/echo_cancellation.h
@@ -19,7 +19,6 @@
 #include "common_audio/ring_buffer.h"
 }
 #include "modules/audio_processing/aec/aec_core.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec/system_delay_unittest.cc b/modules/audio_processing/aec/system_delay_unittest.cc
index 01119db..9c57e8b 100644
--- a/modules/audio_processing/aec/system_delay_unittest.cc
+++ b/modules/audio_processing/aec/system_delay_unittest.cc
@@ -12,7 +12,6 @@
 #include "modules/audio_processing/aec/echo_cancellation.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 namespace webrtc {
 namespace {
 
diff --git a/modules/audio_processing/aec3/BUILD.gn b/modules/audio_processing/aec3/BUILD.gn
index f27168d..75ee372 100644
--- a/modules/audio_processing/aec3/BUILD.gn
+++ b/modules/audio_processing/aec3/BUILD.gn
@@ -20,6 +20,8 @@
     "aec3_fft.h",
     "aec_state.cc",
     "aec_state.h",
+    "block_delay_buffer.cc",
+    "block_delay_buffer.h",
     "block_framer.cc",
     "block_framer.h",
     "block_processor.cc",
@@ -28,8 +30,6 @@
     "block_processor_metrics.h",
     "cascaded_biquad_filter.cc",
     "cascaded_biquad_filter.h",
-    "coherence_gain.cc",
-    "coherence_gain.h",
     "comfort_noise_generator.cc",
     "comfort_noise_generator.h",
     "decimator.cc",
@@ -82,6 +82,10 @@
     "render_signal_analyzer.h",
     "residual_echo_estimator.cc",
     "residual_echo_estimator.h",
+    "reverb_decay_estimator.cc",
+    "reverb_decay_estimator.h",
+    "reverb_frequency_response.cc",
+    "reverb_frequency_response.h",
     "reverb_model.cc",
     "reverb_model.h",
     "reverb_model_estimator.cc",
@@ -112,10 +116,14 @@
   ]
 
   defines = []
+  if (rtc_build_with_neon && current_cpu != "arm64") {
+    suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
+    cflags = [ "-mfpu=neon" ]
+  }
+
   deps = [
     "..:apm_logging",
     "..:audio_processing",
-    "../../..:typedefs",
     "../../../api:array_view",
     "../../../api/audio:aec3_config",
     "../../../api/audio:echo_control",
@@ -123,6 +131,7 @@
     "../../../rtc_base:checks",
     "../../../rtc_base:rtc_base_approved",
     "../../../rtc_base:safe_minmax",
+    "../../../rtc_base/system:arch",
     "../../../system_wrappers:cpu_features_api",
     "../../../system_wrappers:field_trial_api",
     "../../../system_wrappers:metrics_api",
@@ -152,12 +161,12 @@
       "..:apm_logging",
       "..:audio_processing",
       "..:audio_processing_unittests",
-      "../../..:typedefs",
       "../../../api:array_view",
       "../../../api/audio:aec3_config",
       "../../../rtc_base:checks",
       "../../../rtc_base:rtc_base_approved",
       "../../../rtc_base:safe_minmax",
+      "../../../rtc_base/system:arch",
       "../../../system_wrappers:cpu_features_api",
       "../../../test:test_support",
       "//third_party/abseil-cpp/absl/types:optional",
@@ -170,6 +179,7 @@
         "adaptive_fir_filter_unittest.cc",
         "aec3_fft_unittest.cc",
         "aec_state_unittest.cc",
+        "block_delay_buffer_unittest.cc",
         "block_framer_unittest.cc",
         "block_processor_metrics_unittest.cc",
         "block_processor_unittest.cc",
diff --git a/modules/audio_processing/aec3/adaptive_fir_filter.cc b/modules/audio_processing/aec3/adaptive_fir_filter.cc
index 377436c..9a1e811 100644
--- a/modules/audio_processing/aec3/adaptive_fir_filter.cc
+++ b/modules/audio_processing/aec3/adaptive_fir_filter.cc
@@ -10,10 +10,12 @@
 
 #include "modules/audio_processing/aec3/adaptive_fir_filter.h"
 
+// Defines WEBRTC_ARCH_X86_FAMILY, used below.
+#include "rtc_base/system/arch.h"
+
 #if defined(WEBRTC_HAS_NEON)
 #include <arm_neon.h>
 #endif
-#include "typedefs.h"  // NOLINT(build/include)
 #if defined(WEBRTC_ARCH_X86_FAMILY)
 #include <emmintrin.h>
 #endif
diff --git a/modules/audio_processing/aec3/adaptive_fir_filter.h b/modules/audio_processing/aec3/adaptive_fir_filter.h
index 9b6ca90..5dfb466 100644
--- a/modules/audio_processing/aec3/adaptive_fir_filter.h
+++ b/modules/audio_processing/aec3/adaptive_fir_filter.h
@@ -22,6 +22,7 @@
 #include "modules/audio_processing/aec3/render_buffer.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/constructormagic.h"
+#include "rtc_base/system/arch.h"
 
 namespace webrtc {
 namespace aec3 {
diff --git a/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc b/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
index 6c441f3..077586e 100644
--- a/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
+++ b/modules/audio_processing/aec3/adaptive_fir_filter_unittest.cc
@@ -10,11 +10,13 @@
 
 #include "modules/audio_processing/aec3/adaptive_fir_filter.h"
 
+// Defines WEBRTC_ARCH_X86_FAMILY, used below.
+#include "rtc_base/system/arch.h"
+
 #include <math.h>
 #include <algorithm>
 #include <numeric>
 #include <string>
-#include "typedefs.h"  // NOLINT(build/include)
 #if defined(WEBRTC_ARCH_X86_FAMILY)
 #include <emmintrin.h>
 #endif
diff --git a/modules/audio_processing/aec3/aec3_common.cc b/modules/audio_processing/aec3/aec3_common.cc
index 3e60b46..c374a35 100644
--- a/modules/audio_processing/aec3/aec3_common.cc
+++ b/modules/audio_processing/aec3/aec3_common.cc
@@ -11,9 +11,9 @@
 #include "modules/audio_processing/aec3/aec3_common.h"
 
 #include "system_wrappers/include/cpu_features_wrapper.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 #include "rtc_base/checks.h"
+#include "rtc_base/system/arch.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/aec3_common.h b/modules/audio_processing/aec3/aec3_common.h
index 6422a52..56c7a90 100644
--- a/modules/audio_processing/aec3/aec3_common.h
+++ b/modules/audio_processing/aec3/aec3_common.h
@@ -12,7 +12,6 @@
 #define MODULES_AUDIO_PROCESSING_AEC3_AEC3_COMMON_H_
 
 #include <stddef.h>
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -37,6 +36,7 @@
 constexpr size_t kFftLengthBy2Plus1 = kFftLengthBy2 + 1;
 constexpr size_t kFftLengthBy2Minus1 = kFftLengthBy2 - 1;
 constexpr size_t kFftLength = 2 * kFftLengthBy2;
+constexpr size_t kFftLengthBy2Log2 = 6;
 
 constexpr int kMaxAdaptiveFilterLength = 50;
 constexpr int kRenderTransferQueueSizeFrames = 100;
@@ -45,7 +45,7 @@
 constexpr size_t kSubFrameLength = 80;
 
 constexpr size_t kBlockSize = kFftLengthBy2;
-constexpr size_t kBlockSizeLog2 = 6;
+constexpr size_t kBlockSizeLog2 = kFftLengthBy2Log2;
 
 constexpr size_t kExtendedBlockSize = 2 * kFftLengthBy2;
 constexpr size_t kMatchedFilterWindowSizeSubBlocks = 32;
@@ -97,6 +97,9 @@
 static_assert(1 << kBlockSizeLog2 == kBlockSize,
               "Proper number of shifts for blocksize");
 
+static_assert(1 << kFftLengthBy2Log2 == kFftLengthBy2,
+              "Proper number of shifts for the fft length");
+
 static_assert(1 == NumBandsForRate(8000), "Number of bands for 8 kHz");
 static_assert(1 == NumBandsForRate(16000), "Number of bands for 16 kHz");
 static_assert(2 == NumBandsForRate(32000), "Number of bands for 32 kHz");
diff --git a/modules/audio_processing/aec3/aec_state.cc b/modules/audio_processing/aec3/aec_state.cc
index d470611..62232ac 100644
--- a/modules/audio_processing/aec3/aec_state.cc
+++ b/modules/audio_processing/aec3/aec_state.cc
@@ -40,11 +40,6 @@
       "WebRTC-Aec3EnforceDelayAfterRealignmentKillSwitch");
 }
 
-bool EnableLinearModeWithDivergedFilter() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3LinearModeWithDivergedFilterKillSwitch");
-}
-
 bool EnableEarlyFilterUsage() {
   return !field_trial::IsEnabled("WebRTC-Aec3EarlyLinearFilterUsageKillSwitch");
 }
@@ -53,25 +48,11 @@
   return !field_trial::IsEnabled("WebRTC-Aec3ShortInitialStateKillSwitch");
 }
 
-bool EnableNoWaitForAlignment() {
-  return !field_trial::IsEnabled("WebRTC-Aec3NoAlignmentWaitKillSwitch");
-}
-
-bool EnableConvergenceTriggeredLinearMode() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3ConvergenceTriggingLinearKillSwitch");
-}
-
 bool EnableUncertaintyUntilSufficientAdapted() {
   return !field_trial::IsEnabled(
       "WebRTC-Aec3ErleUncertaintyUntilSufficientlyAdaptedKillSwitch");
 }
 
-bool TreatTransparentModeAsNonlinear() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3TreatTransparentModeAsNonlinearKillSwitch");
-}
-
 bool LowUncertaintyBeforeConvergence() {
   return !field_trial::IsEnabled(
       "WebRTC-Aec3LowUncertaintyBeforeConvergenceKillSwitch");
@@ -87,16 +68,16 @@
       "WebRTC-Aec3EarlyEntryToConvergedModeKillSwitch");
 }
 
-bool ConservativeFilterDivergence() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3ConservativeFilterDivergenceKillSwitch");
-}
-
 bool UseEarlyLimiterDeactivation() {
   return !field_trial::IsEnabled(
       "WebRTC-Aec3EarlyLimiterDeactivationKillSwitch");
 }
 
+bool ResetErleAfterEchoPathChanges() {
+  return !field_trial::IsEnabled(
+      "WebRTC-Aec3ResetErleAfterEchoPathChangesKillSwitch");
+}
+
 float UncertaintyBeforeConvergence() {
   if (LowUncertaintyBeforeConvergence()) {
     return 1.f;
@@ -128,20 +109,20 @@
           EnableStationaryRenderImprovements() &&
           config_.echo_audibility.use_stationary_properties),
       enforce_delay_after_realignment_(EnableEnforcingDelayAfterRealignment()),
-      allow_linear_mode_with_diverged_filter_(
-          EnableLinearModeWithDivergedFilter()),
-      early_filter_usage_activated_(EnableEarlyFilterUsage()),
-      use_short_initial_state_(EnableShortInitialState()),
-      convergence_trigger_linear_mode_(EnableConvergenceTriggeredLinearMode()),
-      no_alignment_required_for_linear_mode_(EnableNoWaitForAlignment()),
+      early_filter_usage_activated_(EnableEarlyFilterUsage() &&
+                                    !config.filter.conservative_initial_phase),
+      use_short_initial_state_(EnableShortInitialState() &&
+                               !config.filter.conservative_initial_phase),
+      convergence_trigger_linear_mode_(
+          !config.filter.conservative_initial_phase),
+      no_alignment_required_for_linear_mode_(
+          !config.filter.conservative_initial_phase),
       use_uncertainty_until_sufficiently_adapted_(
           EnableUncertaintyUntilSufficientAdapted()),
-      transparent_mode_enforces_nonlinear_mode_(
-          TreatTransparentModeAsNonlinear()),
       uncertainty_before_convergence_(UncertaintyBeforeConvergence()),
       early_entry_to_converged_mode_(EarlyEntryToConvergedMode()),
-      conservative_filter_divergence_(ConservativeFilterDivergence()),
       early_limiter_deactivation_(UseEarlyLimiterDeactivation()),
+      reset_erle_after_echo_path_changes_(ResetErleAfterEchoPathChanges()),
       erle_estimator_(config.erle.min, config.erle.max_l, config.erle.max_h),
       max_render_(config_.filter.main.length_blocks, 0.f),
       gain_rampup_increase_(ComputeGainRampupIncrease(config_)),
@@ -160,7 +141,6 @@
     filter_analyzer_.Reset();
     blocks_since_last_saturation_ = 0;
     usable_linear_estimate_ = false;
-    diverged_linear_filter_ = false;
     capture_signal_saturation_ = false;
     echo_saturation_ = false;
     std::fill(max_render_.begin(), max_render_.end(), 0.f);
@@ -173,6 +153,9 @@
     suppression_gain_limiter_.Reset();
     blocks_since_converged_filter_ = kBlocksSinceConvergencedFilterInit;
     diverged_blocks_ = 0;
+    if (reset_erle_after_echo_path_changes_) {
+      erle_estimator_.Reset();
+    }
   };
 
   // TODO(peah): Refine the reset scheme according to the type of gain and
@@ -252,9 +235,13 @@
   }
 
   // Update the ERL and ERLE measures.
+  if (reset_erle_after_echo_path_changes_ && transition_triggered_) {
+    erle_estimator_.Reset();
+  }
   if (blocks_since_reset_ >= 2 * kNumBlocksPerSecond) {
     const auto& X2 = render_buffer.Spectrum(filter_delay_blocks_);
-    erle_estimator_.Update(X2, Y2, E2_main, converged_filter);
+    erle_estimator_.Update(X2, Y2, E2_main, converged_filter,
+                           config_.erle.onset_detection);
     if (converged_filter) {
       erl_estimator_.Update(X2, Y2);
     }
@@ -283,13 +270,15 @@
   }
 
   // Flag whether the initial state is still active.
+  bool prev_initial_state = initial_state_;
   if (use_short_initial_state_) {
-    initial_state_ =
-        blocks_with_proper_filter_adaptation_ < 2.5f * kNumBlocksPerSecond;
+    initial_state_ = blocks_with_proper_filter_adaptation_ <
+                     config_.filter.initial_state_seconds * kNumBlocksPerSecond;
   } else {
     initial_state_ =
         blocks_with_proper_filter_adaptation_ < 5 * kNumBlocksPerSecond;
   }
+  transition_triggered_ = !initial_state_ && prev_initial_state;
 
   // Update counters for the filter divergence and convergence.
   diverged_blocks_ = diverged_filter ? diverged_blocks_ + 1 : 0;
@@ -372,32 +361,21 @@
   if (!config_.echo_removal_control.linear_and_stable_echo_path) {
     usable_linear_estimate_ =
         usable_linear_estimate_ && recently_converged_filter;
-    if (!allow_linear_mode_with_diverged_filter_) {
-      usable_linear_estimate_ = usable_linear_estimate_ && !diverged_filter;
-    }
   }
-  if (transparent_mode_enforces_nonlinear_mode_) {
-    usable_linear_estimate_ = usable_linear_estimate_ && !TransparentMode();
-  }
+  usable_linear_estimate_ = usable_linear_estimate_ && !TransparentMode();
 
   use_linear_filter_output_ = usable_linear_estimate_ && !TransparentMode();
 
-  if (conservative_filter_divergence_) {
-    diverged_linear_filter_ =
-        subtractor_output_analyzer_.SeverelyDivergedFilter() &&
-        active_render_block;
-  } else {
-    diverged_linear_filter_ = diverged_filter;
-  }
+  const bool stationary_block =
+      use_stationary_properties_ && echo_audibility_.IsBlockStationary();
 
   reverb_model_estimator_.Update(
-      adaptive_filter_impulse_response, adaptive_filter_frequency_response,
+      filter_analyzer_.GetAdjustedFilter(), adaptive_filter_frequency_response,
       erle_estimator_.GetInstLinearQualityEstimate(), filter_delay_blocks_,
-      usable_linear_estimate_, config_.ep_strength.default_len,
-      IsBlockStationary());
+      usable_linear_estimate_, stationary_block);
 
   erle_estimator_.Dump(data_dumper_);
-  reverb_model_estimator_.Dump(data_dumper_);
+  reverb_model_estimator_.Dump(data_dumper_.get());
   data_dumper_->DumpRaw("aec3_erl", Erl());
   data_dumper_->DumpRaw("aec3_erl_time_domain", ErlTimeDomain());
   data_dumper_->DumpRaw("aec3_usable_linear_estimate", UsableLinearEstimate());
@@ -409,7 +387,7 @@
   data_dumper_->DumpRaw("aec3_consistent_filter",
                         filter_analyzer_.Consistent());
   data_dumper_->DumpRaw("aec3_suppression_gain_limit", SuppressionGainLimit());
-  data_dumper_->DumpRaw("aec3_initial_state", InitialState());
+  data_dumper_->DumpRaw("aec3_initial_state", initial_state_);
   data_dumper_->DumpRaw("aec3_capture_saturation", SaturatedCapture());
   data_dumper_->DumpRaw("aec3_echo_saturation", echo_saturation_);
   data_dumper_->DumpRaw("aec3_converged_filter", converged_filter);
@@ -427,8 +405,8 @@
                         recently_converged_filter);
   data_dumper_->DumpRaw("aec3_suppresion_gain_limiter_running",
                         IsSuppressionGainLimitActive());
-  data_dumper_->DumpRaw("aec3_filter_tail_freq_resp_est", GetFreqRespTail());
-
+  data_dumper_->DumpRaw("aec3_filter_tail_freq_resp_est",
+                        GetReverbFrequencyResponse());
 }
 
 bool AecState::DetectActiveRender(rtc::ArrayView<const float> x) const {
diff --git a/modules/audio_processing/aec3/aec_state.h b/modules/audio_processing/aec3/aec_state.h
index 408f9b8..ea30daf 100644
--- a/modules/audio_processing/aec3/aec_state.h
+++ b/modules/audio_processing/aec3/aec_state.h
@@ -67,17 +67,6 @@
   // aec.
   bool UseStationaryProperties() const { return use_stationary_properties_; }
 
-  // Returns true if the current render block is estimated as stationary.
-  bool IsBlockStationary() const {
-    if (UseStationaryProperties()) {
-      return echo_audibility_.IsBlockStationary();
-    } else {
-      // Assume that a non stationary block when the use of
-      // stationary properties are not enabled.
-      return false;
-    }
-  }
-
   // Returns the ERLE.
   const std::array<float, kFftLengthBy2Plus1>& Erle() const {
     return erle_estimator_.Erle();
@@ -85,10 +74,6 @@
 
   // Returns any uncertainty in the ERLE estimate.
   absl::optional<float> ErleUncertainty() const {
-    if (allow_linear_mode_with_diverged_filter_ && diverged_linear_filter_) {
-      return 10.f;
-    }
-
     if (!filter_has_had_time_to_converge_ &&
         use_uncertainty_until_sufficiently_adapted_) {
       return uncertainty_before_convergence_;
@@ -135,6 +120,11 @@
   // Returns the decay factor for the echo reverberation.
   float ReverbDecay() const { return reverb_model_estimator_.ReverbDecay(); }
 
+  // Return the frequency response of the reverberant echo.
+  rtc::ArrayView<const float> GetReverbFrequencyResponse() const {
+    return reverb_model_estimator_.GetReverbFrequencyResponse();
+  }
+
   // Returns the upper limit for the echo suppression gain.
   float SuppressionGainLimit() const {
     return suppression_gain_limiter_.Limit();
@@ -150,8 +140,9 @@
     return filter_has_had_time_to_converge_;
   }
 
-  // Returns whether the filter adaptation is still in the initial state.
-  bool InitialState() const { return initial_state_; }
+  // Returns whether the transition for going out of the initial stated has
+  // been triggered.
+  bool TransitionTriggered() const { return transition_triggered_; }
 
   // Updates the aec state.
   void Update(const absl::optional<DelayEstimate>& external_delay,
@@ -164,11 +155,6 @@
               const SubtractorOutput& subtractor_output,
               rtc::ArrayView<const float> y);
 
-  // Returns the tail freq. response of the linear filter.
-  rtc::ArrayView<const float> GetFreqRespTail() const {
-    return reverb_model_estimator_.GetFreqRespTail();
-  }
-
   // Returns filter length in blocks.
   int FilterLengthBlocks() const {
     return filter_analyzer_.FilterLengthBlocks();
@@ -186,17 +172,15 @@
   const bool allow_transparent_mode_;
   const bool use_stationary_properties_;
   const bool enforce_delay_after_realignment_;
-  const bool allow_linear_mode_with_diverged_filter_;
   const bool early_filter_usage_activated_;
   const bool use_short_initial_state_;
   const bool convergence_trigger_linear_mode_;
   const bool no_alignment_required_for_linear_mode_;
   const bool use_uncertainty_until_sufficiently_adapted_;
-  const bool transparent_mode_enforces_nonlinear_mode_;
   const float uncertainty_before_convergence_;
   const bool early_entry_to_converged_mode_;
-  const bool conservative_filter_divergence_;
   const bool early_limiter_deactivation_;
+  const bool reset_erle_after_echo_path_changes_;
   ErlEstimator erl_estimator_;
   ErleEstimator erle_estimator_;
   size_t capture_block_counter_ = 0;
@@ -204,7 +188,6 @@
   size_t blocks_with_proper_filter_adaptation_ = 0;
   size_t blocks_with_active_render_ = 0;
   bool usable_linear_estimate_ = false;
-  bool diverged_linear_filter_ = false;
   bool capture_signal_saturation_ = false;
   bool echo_saturation_ = false;
   bool transparent_mode_ = false;
@@ -215,6 +198,7 @@
   std::vector<float> max_render_;
   bool filter_has_had_time_to_converge_ = false;
   bool initial_state_ = true;
+  bool transition_triggered_ = false;
   const float gain_rampup_increase_;
   SuppressionGainUpperLimiter suppression_gain_limiter_;
   FilterAnalyzer filter_analyzer_;
diff --git a/modules/audio_processing/aec3/block_delay_buffer.cc b/modules/audio_processing/aec3/block_delay_buffer.cc
new file mode 100644
index 0000000..0a242ee
--- /dev/null
+++ b/modules/audio_processing/aec3/block_delay_buffer.cc
@@ -0,0 +1,47 @@
+/*
+ *  Copyright (c) 2018 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 "modules/audio_processing/aec3/block_delay_buffer.h"
+
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+BlockDelayBuffer::BlockDelayBuffer(size_t num_bands,
+                                   size_t frame_length,
+                                   size_t delay_samples)
+    : frame_length_(frame_length),
+      delay_(delay_samples),
+      buf_(num_bands, std::vector<float>(delay_, 0.f)) {}
+
+BlockDelayBuffer::~BlockDelayBuffer() = default;
+
+void BlockDelayBuffer::DelaySignal(AudioBuffer* frame) {
+  RTC_DCHECK_EQ(1, frame->num_channels());
+  RTC_DCHECK_EQ(buf_.size(), frame->num_bands());
+  if (delay_ == 0) {
+    return;
+  }
+
+  const size_t i_start = last_insert_;
+  size_t i = 0;
+  for (size_t j = 0; j < buf_.size(); ++j) {
+    i = i_start;
+    for (size_t k = 0; k < frame_length_; ++k) {
+      const float tmp = buf_[j][i];
+      buf_[j][i] = frame->split_bands_f(0)[j][k];
+      frame->split_bands_f(0)[j][k] = tmp;
+      i = i < buf_[0].size() - 1 ? i + 1 : 0;
+    }
+  }
+
+  last_insert_ = i;
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_processing/aec3/block_delay_buffer.h b/modules/audio_processing/aec3/block_delay_buffer.h
new file mode 100644
index 0000000..6e5fd5c
--- /dev/null
+++ b/modules/audio_processing/aec3/block_delay_buffer.h
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (c) 2018 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 MODULES_AUDIO_PROCESSING_AEC3_BLOCK_DELAY_BUFFER_H_
+#define MODULES_AUDIO_PROCESSING_AEC3_BLOCK_DELAY_BUFFER_H_
+
+#include <vector>
+
+#include "modules/audio_processing/audio_buffer.h"
+
+namespace webrtc {
+
+// Class for applying a fixed delay to the samples in a signal partitioned using
+// the audiobuffer band-splitting scheme.
+class BlockDelayBuffer {
+ public:
+  BlockDelayBuffer(size_t num_bands, size_t frame_length, size_t delay_samples);
+  ~BlockDelayBuffer();
+
+  // Delays the samples by the specified delay.
+  void DelaySignal(AudioBuffer* frame);
+
+ private:
+  const size_t frame_length_;
+  const size_t delay_;
+  std::vector<std::vector<float>> buf_;
+  size_t last_insert_ = 0;
+};
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_PROCESSING_AEC3_BLOCK_DELAY_BUFFER_H_
diff --git a/modules/audio_processing/aec3/block_delay_buffer_unittest.cc b/modules/audio_processing/aec3/block_delay_buffer_unittest.cc
new file mode 100644
index 0000000..778d43d
--- /dev/null
+++ b/modules/audio_processing/aec3/block_delay_buffer_unittest.cc
@@ -0,0 +1,91 @@
+/*
+ *  Copyright (c) 2017 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 "modules/audio_processing/aec3/block_delay_buffer.h"
+
+#include <string>
+
+#include "modules/audio_processing/aec3/aec3_common.h"
+#include "modules/audio_processing/audio_buffer.h"
+#include "rtc_base/strings/string_builder.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+namespace {
+
+float SampleValue(size_t sample_index) {
+  return sample_index % 32768;
+}
+
+// Populates the frame with linearly increasing sample values for each band.
+void PopulateInputFrame(size_t frame_length,
+                        size_t num_bands,
+                        size_t first_sample_index,
+                        float* const* frame) {
+  for (size_t k = 0; k < num_bands; ++k) {
+    for (size_t i = 0; i < frame_length; ++i) {
+      frame[k][i] = SampleValue(first_sample_index + i);
+    }
+  }
+}
+
+std::string ProduceDebugText(int sample_rate_hz, size_t delay) {
+  char log_stream_buffer[8 * 1024];
+  rtc::SimpleStringBuilder ss(log_stream_buffer);
+  ss << "Sample rate: " << sample_rate_hz;
+  ss << ", Delay: " << delay;
+  return ss.str();
+}
+
+}  // namespace
+
+// Verifies that the correct signal delay is achived.
+TEST(BlockDelayBuffer, CorrectDelayApplied) {
+  for (size_t delay : {0, 1, 27, 160, 4321, 7021}) {
+    for (auto rate : {8000, 16000, 32000, 48000}) {
+      SCOPED_TRACE(ProduceDebugText(rate, delay));
+      size_t num_bands = NumBandsForRate(rate);
+      size_t fullband_frame_length = rate / 100;
+      size_t subband_frame_length = rate == 8000 ? 80 : 160;
+
+      BlockDelayBuffer delay_buffer(num_bands, subband_frame_length, delay);
+
+      static constexpr size_t kNumFramesToProcess = 20;
+      for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
+           ++frame_index) {
+        AudioBuffer audio_buffer(fullband_frame_length, 1,
+                                 fullband_frame_length, 1,
+                                 fullband_frame_length);
+        if (rate > 16000) {
+          audio_buffer.SplitIntoFrequencyBands();
+        }
+        size_t first_sample_index = frame_index * subband_frame_length;
+        PopulateInputFrame(subband_frame_length, num_bands, first_sample_index,
+                           &audio_buffer.split_bands_f(0)[0]);
+        delay_buffer.DelaySignal(&audio_buffer);
+
+        for (size_t k = 0; k < num_bands; ++k) {
+          size_t sample_index = first_sample_index;
+          for (size_t i = 0; i < subband_frame_length; ++i, ++sample_index) {
+            if (sample_index < delay) {
+              EXPECT_EQ(0.f, audio_buffer.split_bands_f(0)[k][i]);
+            } else {
+              EXPECT_EQ(SampleValue(sample_index - delay),
+                        audio_buffer.split_bands_f(0)[k][i]);
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_processing/aec3/coherence_gain.cc b/modules/audio_processing/aec3/coherence_gain.cc
deleted file mode 100644
index ad33382..0000000
--- a/modules/audio_processing/aec3/coherence_gain.cc
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- *  Copyright (c) 2018 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 "modules/audio_processing/aec3/coherence_gain.h"
-
-#include <math.h>
-
-#include <algorithm>
-
-#include "rtc_base/checks.h"
-
-namespace webrtc {
-
-namespace {
-
-// Matlab code to produce table:
-// overDriveCurve = [sqrt(linspace(0,1,65))' + 1];
-// fprintf(1, '\t%.4f, %.4f, %.4f, %.4f, %.4f, %.4f,\n', overDriveCurve);
-const float kOverDriveCurve[kFftLengthBy2Plus1] = {
-    1.0000f, 1.1250f, 1.1768f, 1.2165f, 1.2500f, 1.2795f, 1.3062f, 1.3307f,
-    1.3536f, 1.3750f, 1.3953f, 1.4146f, 1.4330f, 1.4507f, 1.4677f, 1.4841f,
-    1.5000f, 1.5154f, 1.5303f, 1.5449f, 1.5590f, 1.5728f, 1.5863f, 1.5995f,
-    1.6124f, 1.6250f, 1.6374f, 1.6495f, 1.6614f, 1.6731f, 1.6847f, 1.6960f,
-    1.7071f, 1.7181f, 1.7289f, 1.7395f, 1.7500f, 1.7603f, 1.7706f, 1.7806f,
-    1.7906f, 1.8004f, 1.8101f, 1.8197f, 1.8292f, 1.8385f, 1.8478f, 1.8570f,
-    1.8660f, 1.8750f, 1.8839f, 1.8927f, 1.9014f, 1.9100f, 1.9186f, 1.9270f,
-    1.9354f, 1.9437f, 1.9520f, 1.9601f, 1.9682f, 1.9763f, 1.9843f, 1.9922f,
-    2.0000f};
-
-// Matlab code to produce table:
-// weightCurve = [0 ; 0.3 * sqrt(linspace(0,1,64))' + 0.1];
-// fprintf(1, '\t%.4f, %.4f, %.4f, %.4f, %.4f, %.4f,\n', weightCurve);
-const float kWeightCurve[kFftLengthBy2Plus1] = {
-    0.0000f, 0.1000f, 0.1378f, 0.1535f, 0.1655f, 0.1756f, 0.1845f, 0.1926f,
-    0.2000f, 0.2069f, 0.2134f, 0.2195f, 0.2254f, 0.2309f, 0.2363f, 0.2414f,
-    0.2464f, 0.2512f, 0.2558f, 0.2604f, 0.2648f, 0.2690f, 0.2732f, 0.2773f,
-    0.2813f, 0.2852f, 0.2890f, 0.2927f, 0.2964f, 0.3000f, 0.3035f, 0.3070f,
-    0.3104f, 0.3138f, 0.3171f, 0.3204f, 0.3236f, 0.3268f, 0.3299f, 0.3330f,
-    0.3360f, 0.3390f, 0.3420f, 0.3449f, 0.3478f, 0.3507f, 0.3535f, 0.3563f,
-    0.3591f, 0.3619f, 0.3646f, 0.3673f, 0.3699f, 0.3726f, 0.3752f, 0.3777f,
-    0.3803f, 0.3828f, 0.3854f, 0.3878f, 0.3903f, 0.3928f, 0.3952f, 0.3976f,
-    0.4000f};
-
-int CmpFloat(const void* a, const void* b) {
-  const float* da = static_cast<const float*>(a);
-  const float* db = static_cast<const float*>(b);
-  return (*da > *db) - (*da < *db);
-}
-
-}  // namespace
-
-CoherenceGain::CoherenceGain(int sample_rate_hz, size_t num_bands_to_compute)
-    : num_bands_to_compute_(num_bands_to_compute),
-      sample_rate_scaler_(sample_rate_hz >= 16000 ? 2 : 1) {
-  spectra_.Cye.Clear();
-  spectra_.Cxy.Clear();
-  spectra_.Pe.fill(0.f);
-  // Initialize to 1 in order to prevent numerical instability in the first
-  // block.
-  spectra_.Py.fill(1.f);
-  spectra_.Px.fill(1.f);
-}
-
-CoherenceGain::~CoherenceGain() = default;
-
-void CoherenceGain::ComputeGain(const FftData& E,
-                                const FftData& X,
-                                const FftData& Y,
-                                rtc::ArrayView<float> gain) {
-  std::array<float, kFftLengthBy2Plus1> coherence_ye;
-  std::array<float, kFftLengthBy2Plus1> coherence_xy;
-
-  UpdateCoherenceSpectra(E, X, Y);
-  ComputeCoherence(coherence_ye, coherence_xy);
-  FormSuppressionGain(coherence_ye, coherence_xy, gain);
-}
-
-// Updates the following smoothed Power Spectral Densities (PSD):
-//  - sd  : near-end
-//  - se  : residual echo
-//  - sx  : far-end
-//  - sde : cross-PSD of near-end and residual echo
-//  - sxd : cross-PSD of near-end and far-end
-//
-void CoherenceGain::UpdateCoherenceSpectra(const FftData& E,
-                                           const FftData& X,
-                                           const FftData& Y) {
-  const float s = sample_rate_scaler_ == 1 ? 0.9f : 0.92f;
-  const float one_minus_s = 1.f - s;
-  auto& c = spectra_;
-
-  for (size_t i = 0; i < c.Py.size(); i++) {
-    c.Py[i] =
-        s * c.Py[i] + one_minus_s * (Y.re[i] * Y.re[i] + Y.im[i] * Y.im[i]);
-    c.Pe[i] =
-        s * c.Pe[i] + one_minus_s * (E.re[i] * E.re[i] + E.im[i] * E.im[i]);
-    // We threshold here to protect against the ill-effects of a zero farend.
-    // The threshold is not arbitrarily chosen, but balances protection and
-    // adverse interaction with the algorithm's tuning.
-
-    // Threshold to protect against the ill-effects of a zero far-end.
-    c.Px[i] =
-        s * c.Px[i] +
-        one_minus_s * std::max(X.re[i] * X.re[i] + X.im[i] * X.im[i], 15.f);
-
-    c.Cye.re[i] =
-        s * c.Cye.re[i] + one_minus_s * (Y.re[i] * E.re[i] + Y.im[i] * E.im[i]);
-    c.Cye.im[i] =
-        s * c.Cye.im[i] + one_minus_s * (Y.re[i] * E.im[i] - Y.im[i] * E.re[i]);
-
-    c.Cxy.re[i] =
-        s * c.Cxy.re[i] + one_minus_s * (Y.re[i] * X.re[i] + Y.im[i] * X.im[i]);
-    c.Cxy.im[i] =
-        s * c.Cxy.im[i] + one_minus_s * (Y.re[i] * X.im[i] - Y.im[i] * X.re[i]);
-  }
-}
-
-void CoherenceGain::FormSuppressionGain(
-    rtc::ArrayView<const float> coherence_ye,
-    rtc::ArrayView<const float> coherence_xy,
-    rtc::ArrayView<float> gain) {
-  RTC_DCHECK_EQ(kFftLengthBy2Plus1, coherence_ye.size());
-  RTC_DCHECK_EQ(kFftLengthBy2Plus1, coherence_xy.size());
-  RTC_DCHECK_EQ(kFftLengthBy2Plus1, gain.size());
-  constexpr int kPrefBandSize = 24;
-  auto& gs = gain_state_;
-  std::array<float, kPrefBandSize> h_nl_pref;
-  float h_nl_fb = 0;
-  float h_nl_fb_low = 0;
-  const int pref_band_size = kPrefBandSize / sample_rate_scaler_;
-  const int min_pref_band = 4 / sample_rate_scaler_;
-
-  float h_nl_de_avg = 0.f;
-  float h_nl_xd_avg = 0.f;
-  for (int i = min_pref_band; i < pref_band_size + min_pref_band; ++i) {
-    h_nl_xd_avg += coherence_xy[i];
-    h_nl_de_avg += coherence_ye[i];
-  }
-  h_nl_xd_avg /= pref_band_size;
-  h_nl_xd_avg = 1 - h_nl_xd_avg;
-  h_nl_de_avg /= pref_band_size;
-
-  if (h_nl_xd_avg < 0.75f && h_nl_xd_avg < gs.h_nl_xd_avg_min) {
-    gs.h_nl_xd_avg_min = h_nl_xd_avg;
-  }
-
-  if (h_nl_de_avg > 0.98f && h_nl_xd_avg > 0.9f) {
-    gs.near_state = true;
-  } else if (h_nl_de_avg < 0.95f || h_nl_xd_avg < 0.8f) {
-    gs.near_state = false;
-  }
-
-  std::array<float, kFftLengthBy2Plus1> h_nl;
-  if (gs.h_nl_xd_avg_min == 1) {
-    gs.overdrive = 15.f;
-
-    if (gs.near_state) {
-      std::copy(coherence_ye.begin(), coherence_ye.end(), h_nl.begin());
-      h_nl_fb = h_nl_de_avg;
-      h_nl_fb_low = h_nl_de_avg;
-    } else {
-      for (size_t i = 0; i < h_nl.size(); ++i) {
-        h_nl[i] = 1 - coherence_xy[i];
-        h_nl[i] = std::max(h_nl[i], 0.f);
-      }
-      h_nl_fb = h_nl_xd_avg;
-      h_nl_fb_low = h_nl_xd_avg;
-    }
-  } else {
-    if (gs.near_state) {
-      std::copy(coherence_ye.begin(), coherence_ye.end(), h_nl.begin());
-      h_nl_fb = h_nl_de_avg;
-      h_nl_fb_low = h_nl_de_avg;
-    } else {
-      for (size_t i = 0; i < h_nl.size(); ++i) {
-        h_nl[i] = std::min(coherence_ye[i], 1 - coherence_xy[i]);
-        h_nl[i] = std::max(h_nl[i], 0.f);
-      }
-
-      // Select an order statistic from the preferred bands.
-      // TODO(peah): Using quicksort now, but a selection algorithm may be
-      // preferred.
-      std::copy(h_nl.begin() + min_pref_band,
-                h_nl.begin() + min_pref_band + pref_band_size,
-                h_nl_pref.begin());
-      std::qsort(h_nl_pref.data(), pref_band_size, sizeof(float), CmpFloat);
-
-      constexpr float kPrefBandQuant = 0.75f;
-      h_nl_fb = h_nl_pref[static_cast<int>(
-          floor(kPrefBandQuant * (pref_band_size - 1)))];
-      constexpr float kPrefBandQuantLow = 0.5f;
-      h_nl_fb_low = h_nl_pref[static_cast<int>(
-          floor(kPrefBandQuantLow * (pref_band_size - 1)))];
-    }
-  }
-
-  // Track the local filter minimum to determine suppression overdrive.
-  if (h_nl_fb_low < 0.6f && h_nl_fb_low < gs.h_nl_fb_local_min) {
-    gs.h_nl_fb_local_min = h_nl_fb_low;
-    gs.h_nl_fb_min = h_nl_fb_low;
-    gs.h_nl_new_min = 1;
-    gs.h_nl_min_ctr = 0;
-  }
-  gs.h_nl_fb_local_min =
-      std::min(gs.h_nl_fb_local_min + 0.0008f / sample_rate_scaler_, 1.f);
-  gs.h_nl_xd_avg_min =
-      std::min(gs.h_nl_xd_avg_min + 0.0006f / sample_rate_scaler_, 1.f);
-
-  if (gs.h_nl_new_min == 1) {
-    ++gs.h_nl_min_ctr;
-  }
-  if (gs.h_nl_min_ctr == 2) {
-    gs.h_nl_new_min = 0;
-    gs.h_nl_min_ctr = 0;
-    constexpr float epsilon = 1e-10f;
-    gs.overdrive = std::max(
-        -18.4f / static_cast<float>(log(gs.h_nl_fb_min + epsilon) + epsilon),
-        15.f);
-  }
-
-  // Smooth the overdrive.
-  if (gs.overdrive < gs.overdrive_scaling) {
-    gs.overdrive_scaling = 0.99f * gs.overdrive_scaling + 0.01f * gs.overdrive;
-  } else {
-    gs.overdrive_scaling = 0.9f * gs.overdrive_scaling + 0.1f * gs.overdrive;
-  }
-
-  // Apply the overdrive.
-  RTC_DCHECK_LE(num_bands_to_compute_, gain.size());
-  for (size_t i = 0; i < num_bands_to_compute_; ++i) {
-    if (h_nl[i] > h_nl_fb) {
-      h_nl[i] = kWeightCurve[i] * h_nl_fb + (1 - kWeightCurve[i]) * h_nl[i];
-    }
-    gain[i] = powf(h_nl[i], gs.overdrive_scaling * kOverDriveCurve[i]);
-  }
-}
-
-void CoherenceGain::ComputeCoherence(rtc::ArrayView<float> coherence_ye,
-                                     rtc::ArrayView<float> coherence_xy) const {
-  const auto& c = spectra_;
-  constexpr float epsilon = 1e-10f;
-  for (size_t i = 0; i < coherence_ye.size(); ++i) {
-    coherence_ye[i] = (c.Cye.re[i] * c.Cye.re[i] + c.Cye.im[i] * c.Cye.im[i]) /
-                      (c.Py[i] * c.Pe[i] + epsilon);
-    coherence_xy[i] = (c.Cxy.re[i] * c.Cxy.re[i] + c.Cxy.im[i] * c.Cxy.im[i]) /
-                      (c.Px[i] * c.Py[i] + epsilon);
-  }
-}
-
-}  // namespace webrtc
diff --git a/modules/audio_processing/aec3/coherence_gain.h b/modules/audio_processing/aec3/coherence_gain.h
deleted file mode 100644
index b6e22fd..0000000
--- a/modules/audio_processing/aec3/coherence_gain.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *  Copyright (c) 2018 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 MODULES_AUDIO_PROCESSING_AEC3_COHERENCE_GAIN_H_
-#define MODULES_AUDIO_PROCESSING_AEC3_COHERENCE_GAIN_H_
-
-#include <array>
-
-#include "modules/audio_processing/aec3/aec3_common.h"
-#include "modules/audio_processing/aec3/aec3_fft.h"
-#include "rtc_base/constructormagic.h"
-
-namespace webrtc {
-
-// Class for computing an echo suppression gain based on the coherence measure.
-class CoherenceGain {
- public:
-  CoherenceGain(int sample_rate_hz, size_t num_bands_to_compute);
-  ~CoherenceGain();
-
-  // Computes the gain based on the FFTs of the filter error output signal, the
-  // render signal and the capture signal.
-  void ComputeGain(const FftData& E,
-                   const FftData& X,
-                   const FftData& Y,
-                   rtc::ArrayView<float> gain);
-
- private:
-  struct {
-    FftData Cye;
-    FftData Cxy;
-    std::array<float, kFftLengthBy2Plus1> Px;
-    std::array<float, kFftLengthBy2Plus1> Py;
-    std::array<float, kFftLengthBy2Plus1> Pe;
-  } spectra_;
-
-  struct {
-    float h_nl_fb_min = 1;
-    float h_nl_fb_local_min = 1;
-    float h_nl_xd_avg_min = 1.f;
-    int h_nl_new_min = 0;
-    float h_nl_min_ctr = 0;
-    float overdrive = 2;
-    float overdrive_scaling = 2;
-    bool near_state = false;
-  } gain_state_;
-
-  const Aec3Fft fft_;
-  const size_t num_bands_to_compute_;
-  const int sample_rate_scaler_;
-
-  // Updates the spectral estimates used for the coherence computation.
-  void UpdateCoherenceSpectra(const FftData& E,
-                              const FftData& X,
-                              const FftData& Y);
-
-  // Compute the suppression gain based on the coherence.
-  void FormSuppressionGain(rtc::ArrayView<const float> coherence_ye,
-                           rtc::ArrayView<const float> coherence_xy,
-                           rtc::ArrayView<float> h_nl);
-
-  // Compute the coherence.
-  void ComputeCoherence(rtc::ArrayView<float> coherence_ye,
-                        rtc::ArrayView<float> coherence_xy) const;
-
-  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CoherenceGain);
-};
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_PROCESSING_AEC3_COHERENCE_GAIN_H_
diff --git a/modules/audio_processing/aec3/comfort_noise_generator.cc b/modules/audio_processing/aec3/comfort_noise_generator.cc
index dab40a9..55faf4b 100644
--- a/modules/audio_processing/aec3/comfort_noise_generator.cc
+++ b/modules/audio_processing/aec3/comfort_noise_generator.cc
@@ -10,7 +10,9 @@
 
 #include "modules/audio_processing/aec3/comfort_noise_generator.h"
 
-#include "typedefs.h"  // NOLINT(build/include)
+// Defines WEBRTC_ARCH_X86_FAMILY, used below.
+#include "rtc_base/system/arch.h"
+
 #if defined(WEBRTC_ARCH_X86_FAMILY)
 #include <emmintrin.h>
 #endif
diff --git a/modules/audio_processing/aec3/comfort_noise_generator.h b/modules/audio_processing/aec3/comfort_noise_generator.h
index 2d998be..6a47989 100644
--- a/modules/audio_processing/aec3/comfort_noise_generator.h
+++ b/modules/audio_processing/aec3/comfort_noise_generator.h
@@ -18,6 +18,7 @@
 #include "modules/audio_processing/aec3/aec_state.h"
 #include "modules/audio_processing/aec3/fft_data.h"
 #include "rtc_base/constructormagic.h"
+#include "rtc_base/system/arch.h"
 
 namespace webrtc {
 namespace aec3 {
diff --git a/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc b/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
index d7e9407..77a09ed 100644
--- a/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
+++ b/modules/audio_processing/aec3/comfort_noise_generator_unittest.cc
@@ -14,9 +14,9 @@
 #include <numeric>
 
 #include "rtc_base/random.h"
+#include "rtc_base/system/arch.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace aec3 {
diff --git a/modules/audio_processing/aec3/echo_canceller3.cc b/modules/audio_processing/aec3/echo_canceller3.cc
index c02bc14..e5219c7 100644
--- a/modules/audio_processing/aec3/echo_canceller3.cc
+++ b/modules/audio_processing/aec3/echo_canceller3.cc
@@ -342,6 +342,7 @@
                                std::unique_ptr<BlockProcessor> block_processor)
     : data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
+      config_(config),
       sample_rate_hz_(sample_rate_hz),
       num_bands_(NumBandsForRate(sample_rate_hz_)),
       frame_length_(rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)),
@@ -358,7 +359,10 @@
       render_queue_output_frame_(num_bands_,
                                  std::vector<float>(frame_length_, 0.f)),
       block_(num_bands_, std::vector<float>(kBlockSize, 0.f)),
-      sub_frame_view_(num_bands_) {
+      sub_frame_view_(num_bands_),
+      block_delay_buffer_(num_bands_,
+                          frame_length_,
+                          config_.delay.fixed_capture_delay_samples) {
   RTC_DCHECK(ValidFullBandRate(sample_rate_hz_));
 
   std::unique_ptr<CascadedBiQuadFilter> render_highpass_filter;
@@ -421,6 +425,11 @@
   data_dumper_->DumpRaw("aec3_call_order",
                         static_cast<int>(EchoCanceller3ApiCall::kCapture));
 
+  // Optionally delay the capture signal.
+  if (config_.delay.fixed_capture_delay_samples > 0) {
+    block_delay_buffer_.DelaySignal(capture);
+  }
+
   rtc::ArrayView<float> capture_lower_band =
       rtc::ArrayView<float>(&capture->split_bands_f(0)[0][0], frame_length_);
 
diff --git a/modules/audio_processing/aec3/echo_canceller3.h b/modules/audio_processing/aec3/echo_canceller3.h
index b66b8b1..f5520ba 100644
--- a/modules/audio_processing/aec3/echo_canceller3.h
+++ b/modules/audio_processing/aec3/echo_canceller3.h
@@ -12,6 +12,7 @@
 #define MODULES_AUDIO_PROCESSING_AEC3_ECHO_CANCELLER3_H_
 
 #include "api/audio/echo_canceller3_config.h"
+#include "modules/audio_processing/aec3/block_delay_buffer.h"
 #include "modules/audio_processing/aec3/block_framer.h"
 #include "modules/audio_processing/aec3/block_processor.h"
 #include "modules/audio_processing/aec3/cascaded_biquad_filter.h"
@@ -110,6 +111,7 @@
   // State that may be accessed by the capture thread.
   static int instance_count_;
   std::unique_ptr<ApmDataDumper> data_dumper_;
+  const EchoCanceller3Config config_;
   const int sample_rate_hz_;
   const int num_bands_;
   const size_t frame_length_;
@@ -129,6 +131,7 @@
   std::vector<std::vector<float>> block_ RTC_GUARDED_BY(capture_race_checker_);
   std::vector<rtc::ArrayView<float>> sub_frame_view_
       RTC_GUARDED_BY(capture_race_checker_);
+  BlockDelayBuffer block_delay_buffer_ RTC_GUARDED_BY(capture_race_checker_);
 
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3);
 };
diff --git a/modules/audio_processing/aec3/echo_remover.cc b/modules/audio_processing/aec3/echo_remover.cc
index 5394eaf..9b6677e 100644
--- a/modules/audio_processing/aec3/echo_remover.cc
+++ b/modules/audio_processing/aec3/echo_remover.cc
@@ -141,7 +141,6 @@
   bool echo_leakage_detected_ = false;
   AecState aec_state_;
   EchoRemoverMetrics metrics_;
-  bool initial_state_ = true;
   std::array<float, kFftLengthBy2> e_old_;
   std::array<float, kFftLengthBy2> x_old_;
   std::array<float, kFftLengthBy2> y_old_;
@@ -163,7 +162,9 @@
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
       optimization_(DetectOptimization()),
       sample_rate_hz_(sample_rate_hz),
-      use_shadow_filter_output_(UseShadowFilterOutput()),
+      use_shadow_filter_output_(
+          UseShadowFilterOutput() &&
+          config_.filter.enable_shadow_filter_output_usage),
       use_smooth_signal_transitions_(UseSmoothSignalTransitions()),
       subtractor_(config, data_dumper_.get(), optimization_),
       suppression_gain_(config_, optimization_, sample_rate_hz),
@@ -233,7 +234,6 @@
     if (echo_path_variability.delay_change !=
         EchoPathVariability::DelayAdjustment::kNone) {
       suppression_gain_.SetInitialState(true);
-      initial_state_ = true;
     }
   }
   if (gain_change_hangover_ > 0) {
@@ -257,10 +257,9 @@
                                  aec_state_.FilterDelayBlocks());
 
   // Perform linear echo cancellation.
-  if (initial_state_ && !aec_state_.InitialState()) {
+  if (aec_state_.TransitionTriggered()) {
     subtractor_.ExitInitialState();
     suppression_gain_.SetInitialState(false);
-    initial_state_ = false;
   }
 
   // If the delay is known, use the echo subtractor.
@@ -281,17 +280,6 @@
                     subtractor_.FilterImpulseResponse(), *render_buffer, E2, Y2,
                     subtractor_output, y0);
 
-  // Compute spectra.
-  const bool suppression_gain_uses_ffts =
-      config_.suppressor.bands_with_reliable_coherence > 0;
-  FftData X;
-  if (suppression_gain_uses_ffts) {
-    auto& x_aligned = render_buffer->Block(-aec_state_.FilterDelayBlocks())[0];
-    WindowedPaddedFft(fft_, x_aligned, x_old_, &X);
-  } else {
-    X.Clear();
-  }
-
   // Choose the linear output.
   data_dumper_->DumpWav("aec3_output_linear2", kBlockSize, &e[0],
                         LowestBandRate(sample_rate_hz_), 1);
@@ -321,7 +309,9 @@
   cng_.Compute(aec_state_, Y2, &comfort_noise, &high_band_comfort_noise);
 
   // Compute and apply the suppression gain.
-  suppression_gain_.GetGain(E2, R2, cng_.NoiseSpectrum(), E, X, Y,
+  const auto& echo_spectrum =
+      aec_state_.UsableLinearEstimate() ? S2_linear : R2;
+  suppression_gain_.GetGain(E2, echo_spectrum, R2, cng_.NoiseSpectrum(), E, Y,
                             render_signal_analyzer_, aec_state_, x,
                             &high_bands_gain, &G);
 
@@ -366,9 +356,9 @@
   RTC_DCHECK_EQ(subtractor_output.e_shadow.size(), output.size());
   bool use_main_output = true;
   if (use_shadow_filter_output_) {
-    // As the output of the main adaptive filter generally should be better than
-    // the shadow filter output, add a margin and threshold for when choosing
-    // the shadow filter output.
+    // As the output of the main adaptive filter generally should be better
+    // than the shadow filter output, add a margin and threshold for when
+    // choosing the shadow filter output.
     if (subtractor_output.e2_shadow < 0.9f * subtractor_output.e2_main &&
         subtractor_output.y2 > 30.f * 30.f * kBlockSize &&
         (subtractor_output.s2_main > 60.f * 60.f * kBlockSize ||
diff --git a/modules/audio_processing/aec3/erle_estimator.cc b/modules/audio_processing/aec3/erle_estimator.cc
index 52ef8ed..b02245c 100644
--- a/modules/audio_processing/aec3/erle_estimator.cc
+++ b/modules/audio_processing/aec3/erle_estimator.cc
@@ -35,6 +35,13 @@
       max_erle_hf_(max_erle_hf),
       erle_freq_inst_(kPointsToAccumulate),
       erle_time_inst_(kPointsToAccumulate) {
+  Reset();
+}
+
+ErleEstimator::~ErleEstimator() = default;
+
+void ErleEstimator::Reset() {
+  erle_time_inst_.Reset();
   erle_.fill(min_erle_);
   erle_onsets_.fill(min_erle_);
   hold_counters_.fill(0);
@@ -43,8 +50,6 @@
   hold_counter_time_domain_ = 0;
 }
 
-ErleEstimator::~ErleEstimator() = default;
-
 ErleEstimator::ErleTimeInstantaneous::ErleTimeInstantaneous(
     int points_to_accumulate)
     : points_to_accumulate_(points_to_accumulate) {
@@ -167,7 +172,8 @@
 void ErleEstimator::Update(rtc::ArrayView<const float> render_spectrum,
                            rtc::ArrayView<const float> capture_spectrum,
                            rtc::ArrayView<const float> subtractor_spectrum,
-                           bool converged_filter) {
+                           bool converged_filter,
+                           bool onset_detection) {
   RTC_DCHECK_EQ(kFftLengthBy2Plus1, render_spectrum.size());
   RTC_DCHECK_EQ(kFftLengthBy2Plus1, capture_spectrum.size());
   RTC_DCHECK_EQ(kFftLengthBy2Plus1, subtractor_spectrum.size());
@@ -191,19 +197,22 @@
   };
 
   // Update the estimates in a clamped minimum statistics manner.
-  auto erle_update = [&](size_t start, size_t stop, float max_erle) {
+  auto erle_update = [&](size_t start, size_t stop, float max_erle,
+                         bool onset_detection) {
     for (size_t k = start; k < stop; ++k) {
       if (X2[k] > kX2Min) {
         absl::optional<float> new_erle =
             erle_freq_inst_.Update(Y2[k], E2[k], k);
         if (new_erle) {
-          if (coming_onset_[k]) {
-            coming_onset_[k] = false;
-            erle_onsets_[k] =
-                erle_band_update(erle_onsets_[k], new_erle.value(), 0.15f, 0.3f,
-                                 min_erle_, max_erle);
+          if (onset_detection) {
+            if (coming_onset_[k]) {
+              coming_onset_[k] = false;
+              erle_onsets_[k] =
+                  erle_band_update(erle_onsets_[k], new_erle.value(), 0.15f,
+                                   0.3f, min_erle_, max_erle);
+            }
+            hold_counters_[k] = kBlocksForOnsetDetection;
           }
-          hold_counters_[k] = kBlocksForOnsetDetection;
           erle_[k] = erle_band_update(erle_[k], new_erle.value(), 0.05f, 0.1f,
                                       min_erle_, max_erle);
         }
@@ -216,20 +225,22 @@
     // a minimum of the erle that can be estimated as that flag would
     // be false if the filter is performing poorly.
     constexpr size_t kFftLengthBy4 = kFftLengthBy2 / 2;
-    erle_update(1, kFftLengthBy4, max_erle_lf_);
-    erle_update(kFftLengthBy4, kFftLengthBy2, max_erle_hf_);
+    erle_update(1, kFftLengthBy4, max_erle_lf_, onset_detection);
+    erle_update(kFftLengthBy4, kFftLengthBy2, max_erle_hf_, onset_detection);
   }
 
-  for (size_t k = 1; k < kFftLengthBy2; ++k) {
-    hold_counters_[k]--;
-    if (hold_counters_[k] <= (kBlocksForOnsetDetection - kErleHold)) {
-      if (erle_[k] > erle_onsets_[k]) {
-        erle_[k] = std::max(erle_onsets_[k], 0.97f * erle_[k]);
-        RTC_DCHECK_LE(min_erle_, erle_[k]);
-      }
-      if (hold_counters_[k] <= 0) {
-        coming_onset_[k] = true;
-        hold_counters_[k] = 0;
+  if (onset_detection) {
+    for (size_t k = 1; k < kFftLengthBy2; ++k) {
+      hold_counters_[k]--;
+      if (hold_counters_[k] <= (kBlocksForOnsetDetection - kErleHold)) {
+        if (erle_[k] > erle_onsets_[k]) {
+          erle_[k] = std::max(erle_onsets_[k], 0.97f * erle_[k]);
+          RTC_DCHECK_LE(min_erle_, erle_[k]);
+        }
+        if (hold_counters_[k] <= 0) {
+          coming_onset_[k] = true;
+          hold_counters_[k] = 0;
+        }
       }
     }
   }
diff --git a/modules/audio_processing/aec3/erle_estimator.h b/modules/audio_processing/aec3/erle_estimator.h
index 19bc7b4..8160dbe 100644
--- a/modules/audio_processing/aec3/erle_estimator.h
+++ b/modules/audio_processing/aec3/erle_estimator.h
@@ -27,11 +27,15 @@
   ErleEstimator(float min_erle, float max_erle_lf, float max_erle_hf);
   ~ErleEstimator();
 
+  // Reset the ERLE estimator.
+  void Reset();
+
   // Updates the ERLE estimate.
   void Update(rtc::ArrayView<const float> render_spectrum,
               rtc::ArrayView<const float> capture_spectrum,
               rtc::ArrayView<const float> subtractor_spectrum,
-              bool converged_filter);
+              bool converged_filter,
+              bool onset_detection);
 
   // Returns the most recent ERLE estimate.
   const std::array<float, kFftLengthBy2Plus1>& Erle() const { return erle_; }
diff --git a/modules/audio_processing/aec3/erle_estimator_unittest.cc b/modules/audio_processing/aec3/erle_estimator_unittest.cc
index 86ac5df..1687568 100644
--- a/modules/audio_processing/aec3/erle_estimator_unittest.cc
+++ b/modules/audio_processing/aec3/erle_estimator_unittest.cc
@@ -10,8 +10,8 @@
 
 #include <cmath>
 
-#include "modules/audio_processing/aec3/erle_estimator.h"
 #include "api/array_view.h"
+#include "modules/audio_processing/aec3/erle_estimator.h"
 #include "test/gtest.h"
 
 namespace webrtc {
@@ -74,7 +74,7 @@
   FormFarendFrame(&X2, &E2, &Y2, kTrueErle);
 
   for (size_t k = 0; k < 200; ++k) {
-    estimator.Update(X2, Y2, E2, true);
+    estimator.Update(X2, Y2, E2, true, true);
   }
   VerifyErle(estimator.Erle(), std::pow(2.f, estimator.ErleTimeDomainLog2()),
              kMaxErleLf, kMaxErleHf);
@@ -83,7 +83,7 @@
   // Verifies that the ERLE is not immediately decreased during nearend
   // activity.
   for (size_t k = 0; k < 50; ++k) {
-    estimator.Update(X2, Y2, E2, true);
+    estimator.Update(X2, Y2, E2, true, true);
   }
   VerifyErle(estimator.Erle(), std::pow(2.f, estimator.ErleTimeDomainLog2()),
              kMaxErleLf, kMaxErleHf);
@@ -99,21 +99,21 @@
   for (size_t burst = 0; burst < 20; ++burst) {
     FormFarendFrame(&X2, &E2, &Y2, kTrueErleOnsets);
     for (size_t k = 0; k < 10; ++k) {
-      estimator.Update(X2, Y2, E2, true);
+      estimator.Update(X2, Y2, E2, true, true);
     }
     FormFarendFrame(&X2, &E2, &Y2, kTrueErle);
     for (size_t k = 0; k < 200; ++k) {
-      estimator.Update(X2, Y2, E2, true);
+      estimator.Update(X2, Y2, E2, true, true);
     }
     FormNearendFrame(&X2, &E2, &Y2);
     for (size_t k = 0; k < 300; ++k) {
-      estimator.Update(X2, Y2, E2, true);
+      estimator.Update(X2, Y2, E2, true, true);
     }
   }
   VerifyErleBands(estimator.ErleOnsets(), kMinErle, kMinErle);
   FormNearendFrame(&X2, &E2, &Y2);
   for (size_t k = 0; k < 1000; k++) {
-    estimator.Update(X2, Y2, E2, true);
+    estimator.Update(X2, Y2, E2, true, true);
   }
   // Verifies that during ne activity, Erle converges to the Erle for onsets.
   VerifyErle(estimator.Erle(), std::pow(2.f, estimator.ErleTimeDomainLog2()),
@@ -131,7 +131,7 @@
   X2.fill(1000.f * 1000.f);
   Y2.fill(10 * E2[0]);
   for (size_t k = 0; k < 200; ++k) {
-    estimator.Update(X2, Y2, E2, true);
+    estimator.Update(X2, Y2, E2, true, true);
   }
   VerifyErle(estimator.Erle(), std::pow(2.f, estimator.ErleTimeDomainLog2()),
              kMinErle, kMinErle);
diff --git a/modules/audio_processing/aec3/fft_data.h b/modules/audio_processing/aec3/fft_data.h
index 59511b5..5e5adb6 100644
--- a/modules/audio_processing/aec3/fft_data.h
+++ b/modules/audio_processing/aec3/fft_data.h
@@ -11,7 +11,9 @@
 #ifndef MODULES_AUDIO_PROCESSING_AEC3_FFT_DATA_H_
 #define MODULES_AUDIO_PROCESSING_AEC3_FFT_DATA_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+// Defines WEBRTC_ARCH_X86_FAMILY, used below.
+#include "rtc_base/system/arch.h"
+
 #if defined(WEBRTC_ARCH_X86_FAMILY)
 #include <emmintrin.h>
 #endif
diff --git a/modules/audio_processing/aec3/fft_data_unittest.cc b/modules/audio_processing/aec3/fft_data_unittest.cc
index 8fc5ca7..0812fd6 100644
--- a/modules/audio_processing/aec3/fft_data_unittest.cc
+++ b/modules/audio_processing/aec3/fft_data_unittest.cc
@@ -10,9 +10,9 @@
 
 #include "modules/audio_processing/aec3/fft_data.h"
 
+#include "rtc_base/system/arch.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec3/filter_analyzer.cc b/modules/audio_processing/aec3/filter_analyzer.cc
index ab2c4f2..790cb1e 100644
--- a/modules/audio_processing/aec3/filter_analyzer.cc
+++ b/modules/audio_processing/aec3/filter_analyzer.cc
@@ -95,10 +95,9 @@
     const RenderBuffer& render_buffer) {
   // Preprocess the filter to avoid issues with low-frequency components in the
   // filter.
-  if (use_preprocessed_filter_) {
-    PreProcessFilter(filter_time_domain);
-    data_dumper_->DumpRaw("aec3_linear_filter_processed_td", h_highpass_);
-  }
+  PreProcessFilter(filter_time_domain);
+  data_dumper_->DumpRaw("aec3_linear_filter_processed_td", h_highpass_);
+
   const auto& filter_to_analyze =
       use_preprocessed_filter_ ? h_highpass_ : filter_time_domain;
   RTC_DCHECK_EQ(filter_to_analyze.size(), filter_time_domain.size());
diff --git a/modules/audio_processing/aec3/filter_analyzer.h b/modules/audio_processing/aec3/filter_analyzer.h
index 627341d..47e9533 100644
--- a/modules/audio_processing/aec3/filter_analyzer.h
+++ b/modules/audio_processing/aec3/filter_analyzer.h
@@ -54,16 +54,14 @@
   // Returns the number of blocks for the current used filter.
   float FilterLengthBlocks() const { return filter_length_blocks_; }
 
+  // Returns the preprocessed filter.
+  rtc::ArrayView<const float> GetAdjustedFilter() const { return h_highpass_; }
+
  private:
   void UpdateFilterGain(rtc::ArrayView<const float> filter_time_domain,
                         size_t max_index);
   void PreProcessFilter(rtc::ArrayView<const float> filter_time_domain);
 
-  // Updates the estimation of the frequency response at the filter tails.
-  void UpdateFreqRespTail(
-      const std::vector<std::array<float, kFftLengthBy2Plus1>>&
-          filter_freq_response);
-
   static int instance_count_;
   std::unique_ptr<ApmDataDumper> data_dumper_;
   const bool use_preprocessed_filter_;
diff --git a/modules/audio_processing/aec3/main_filter_update_gain.cc b/modules/audio_processing/aec3/main_filter_update_gain.cc
index 6d31ed0..4f48cd4 100644
--- a/modules/audio_processing/aec3/main_filter_update_gain.cc
+++ b/modules/audio_processing/aec3/main_filter_update_gain.cc
@@ -22,7 +22,6 @@
 namespace {
 
 constexpr float kHErrorInitial = 10000.f;
-constexpr float kHErrorGainChange = 10000.f;
 constexpr int kPoorExcitationCounterInitial = 1000;
 
 }  // namespace
@@ -48,7 +47,7 @@
 void MainFilterUpdateGain::HandleEchoPathChange(
     const EchoPathVariability& echo_path_variability) {
   if (echo_path_variability.gain_change) {
-    H_error_.fill(kHErrorGainChange);
+    // TODO(bugs.webrtc.org/9526) Handle gain changes.
   }
 
   if (echo_path_variability.delay_change !=
diff --git a/modules/audio_processing/aec3/matched_filter.cc b/modules/audio_processing/aec3/matched_filter.cc
index 466acd4..7486ddf 100644
--- a/modules/audio_processing/aec3/matched_filter.cc
+++ b/modules/audio_processing/aec3/matched_filter.cc
@@ -9,10 +9,12 @@
  */
 #include "modules/audio_processing/aec3/matched_filter.h"
 
+// Defines WEBRTC_ARCH_X86_FAMILY, used below.
+#include "rtc_base/system/arch.h"
+
 #if defined(WEBRTC_HAS_NEON)
 #include <arm_neon.h>
 #endif
-#include "typedefs.h"  // NOLINT(build/include)
 #if defined(WEBRTC_ARCH_X86_FAMILY)
 #include <emmintrin.h>
 #endif
diff --git a/modules/audio_processing/aec3/matched_filter.h b/modules/audio_processing/aec3/matched_filter.h
index 8add6fe..1c06b5e 100644
--- a/modules/audio_processing/aec3/matched_filter.h
+++ b/modules/audio_processing/aec3/matched_filter.h
@@ -20,6 +20,7 @@
 #include "modules/audio_processing/aec3/aec3_common.h"
 #include "modules/audio_processing/aec3/downsampled_render_buffer.h"
 #include "rtc_base/constructormagic.h"
+#include "rtc_base/system/arch.h"
 
 namespace webrtc {
 namespace aec3 {
diff --git a/modules/audio_processing/aec3/matched_filter_unittest.cc b/modules/audio_processing/aec3/matched_filter_unittest.cc
index fd878ff..c7dc211 100644
--- a/modules/audio_processing/aec3/matched_filter_unittest.cc
+++ b/modules/audio_processing/aec3/matched_filter_unittest.cc
@@ -10,7 +10,9 @@
 
 #include "modules/audio_processing/aec3/matched_filter.h"
 
-#include "typedefs.h"  // NOLINT(build/include)
+// Defines WEBRTC_ARCH_X86_FAMILY, used below.
+#include "rtc_base/system/arch.h"
+
 #if defined(WEBRTC_ARCH_X86_FAMILY)
 #include <emmintrin.h>
 #endif
diff --git a/modules/audio_processing/aec3/render_buffer.cc b/modules/audio_processing/aec3/render_buffer.cc
index 6e224be..235e3e3 100644
--- a/modules/audio_processing/aec3/render_buffer.cc
+++ b/modules/audio_processing/aec3/render_buffer.cc
@@ -47,4 +47,28 @@
   }
 }
 
+void RenderBuffer::SpectralSums(
+    size_t num_spectra_shorter,
+    size_t num_spectra_longer,
+    std::array<float, kFftLengthBy2Plus1>* X2_shorter,
+    std::array<float, kFftLengthBy2Plus1>* X2_longer) const {
+  RTC_DCHECK_LE(num_spectra_shorter, num_spectra_longer);
+  X2_shorter->fill(0.f);
+  int position = spectrum_buffer_->read;
+  size_t j = 0;
+  for (; j < num_spectra_shorter; ++j) {
+    std::transform(X2_shorter->begin(), X2_shorter->end(),
+                   spectrum_buffer_->buffer[position].begin(),
+                   X2_shorter->begin(), std::plus<float>());
+    position = spectrum_buffer_->IncIndex(position);
+  }
+  std::copy(X2_shorter->begin(), X2_shorter->end(), X2_longer->begin());
+  for (; j < num_spectra_longer; ++j) {
+    std::transform(X2_longer->begin(), X2_longer->end(),
+                   spectrum_buffer_->buffer[position].begin(),
+                   X2_longer->begin(), std::plus<float>());
+    position = spectrum_buffer_->IncIndex(position);
+  }
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec3/render_buffer.h b/modules/audio_processing/aec3/render_buffer.h
index 34e7edf..dd67268 100644
--- a/modules/audio_processing/aec3/render_buffer.h
+++ b/modules/audio_processing/aec3/render_buffer.h
@@ -61,6 +61,12 @@
   void SpectralSum(size_t num_spectra,
                    std::array<float, kFftLengthBy2Plus1>* X2) const;
 
+  // Returns the sums of the spectrums for two numbers of FFTs.
+  void SpectralSums(size_t num_spectra_shorter,
+                    size_t num_spectra_longer,
+                    std::array<float, kFftLengthBy2Plus1>* X2_shorter,
+                    std::array<float, kFftLengthBy2Plus1>* X2_longer) const;
+
   // Gets the recent activity seen in the render signal.
   bool GetRenderActivity() const { return render_activity_; }
 
diff --git a/modules/audio_processing/aec3/residual_echo_estimator.cc b/modules/audio_processing/aec3/residual_echo_estimator.cc
index 43002e3..2e3ad9f 100644
--- a/modules/audio_processing/aec3/residual_echo_estimator.cc
+++ b/modules/audio_processing/aec3/residual_echo_estimator.cc
@@ -113,7 +113,7 @@
     if (echo_reverb_) {
       echo_reverb_->AddReverb(
           render_buffer.Spectrum(aec_state.FilterLengthBlocks() + 1),
-          aec_state.GetFreqRespTail(), aec_state.ReverbDecay(), *R2);
+          aec_state.GetReverbFrequencyResponse(), aec_state.ReverbDecay(), *R2);
 
     } else {
       RTC_DCHECK(echo_reverb_fallback);
diff --git a/modules/audio_processing/aec3/reverb_decay_estimator.cc b/modules/audio_processing/aec3/reverb_decay_estimator.cc
new file mode 100644
index 0000000..f80afa2
--- /dev/null
+++ b/modules/audio_processing/aec3/reverb_decay_estimator.cc
@@ -0,0 +1,413 @@
+/*
+ *  Copyright (c) 2018 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 "modules/audio_processing/aec3/reverb_decay_estimator.h"
+
+#include <algorithm>
+#include <cmath>
+#include <numeric>
+
+#include "api/array_view.h"
+#include "modules/audio_processing/logging/apm_data_dumper.h"
+#include "rtc_base/checks.h"
+#include "system_wrappers/include/field_trial.h"
+
+namespace webrtc {
+
+namespace {
+
+bool EnforceAdaptiveEchoReverbEstimation() {
+  return field_trial::IsEnabled(
+      "WebRTC-Aec3EnableAdaptiveEchoReverbEstimation");
+}
+
+constexpr int kEarlyReverbMinSizeBlocks = 3;
+constexpr int kBlocksPerSection = 6;
+// Linear regression approach assumes symmetric index around 0.
+constexpr float kEarlyReverbFirstPointAtLinearRegressors =
+    -0.5f * kBlocksPerSection * kFftLengthBy2 + 0.5f;
+
+// Averages the values in a block of size kFftLengthBy2;
+float BlockAverage(rtc::ArrayView<const float> v, size_t block_index) {
+  constexpr float kOneByFftLengthBy2 = 1.f / kFftLengthBy2;
+  const int i = block_index * kFftLengthBy2;
+  RTC_DCHECK_GE(v.size(), i + kFftLengthBy2);
+  const float sum =
+      std::accumulate(v.begin() + i, v.begin() + i + kFftLengthBy2, 0.f);
+  return sum * kOneByFftLengthBy2;
+}
+
+// Analyzes the gain in a block.
+void AnalyzeBlockGain(const std::array<float, kFftLengthBy2>& h2,
+                      float floor_gain,
+                      float* previous_gain,
+                      bool* block_adapting,
+                      bool* decaying_gain) {
+  float gain = std::max(BlockAverage(h2, 0), 1e-32f);
+  *block_adapting =
+      *previous_gain > 1.1f * gain || *previous_gain < 0.9f * gain;
+  *decaying_gain = gain > floor_gain;
+  *previous_gain = gain;
+}
+
+// Arithmetic sum of $2 \sum_{i=0.5}^{(N-1)/2}i^2$ calculated directly.
+constexpr float SymmetricArithmetricSum(int N) {
+  return N * (N * N - 1.0f) * (1.f / 12.f);
+}
+
+// Returns the peak energy of an impulse response.
+float BlockEnergyPeak(rtc::ArrayView<const float> h, int peak_block) {
+  RTC_DCHECK_LE((peak_block + 1) * kFftLengthBy2, h.size());
+  RTC_DCHECK_GE(peak_block, 0);
+  float peak_value =
+      *std::max_element(h.begin() + peak_block * kFftLengthBy2,
+                        h.begin() + (peak_block + 1) * kFftLengthBy2,
+                        [](float a, float b) { return a * a < b * b; });
+  return peak_value * peak_value;
+}
+
+// Returns the average energy of an impulse response block.
+float BlockEnergyAverage(rtc::ArrayView<const float> h, int block_index) {
+  RTC_DCHECK_LE((block_index + 1) * kFftLengthBy2, h.size());
+  RTC_DCHECK_GE(block_index, 0);
+  constexpr float kOneByFftLengthBy2 = 1.f / kFftLengthBy2;
+  const auto sum_of_squares = [](float a, float b) { return a + b * b; };
+  return std::accumulate(h.begin() + block_index * kFftLengthBy2,
+                         h.begin() + (block_index + 1) * kFftLengthBy2, 0.f,
+                         sum_of_squares) *
+         kOneByFftLengthBy2;
+}
+
+}  // namespace
+
+ReverbDecayEstimator::ReverbDecayEstimator(const EchoCanceller3Config& config)
+    : filter_length_blocks_(config.filter.main.length_blocks),
+      filter_length_coefficients_(GetTimeDomainLength(filter_length_blocks_)),
+      use_adaptive_echo_decay_(config.ep_strength.default_len < 0.f ||
+                               EnforceAdaptiveEchoReverbEstimation()),
+      early_reverb_estimator_(config.filter.main.length_blocks -
+                              kEarlyReverbMinSizeBlocks),
+      late_reverb_start_(kEarlyReverbMinSizeBlocks),
+      late_reverb_end_(kEarlyReverbMinSizeBlocks),
+      decay_(std::fabs(config.ep_strength.default_len)) {
+  previous_gains_.fill(0.f);
+  RTC_DCHECK_GT(config.filter.main.length_blocks,
+                static_cast<size_t>(kEarlyReverbMinSizeBlocks));
+}
+
+ReverbDecayEstimator::~ReverbDecayEstimator() = default;
+
+void ReverbDecayEstimator::Update(rtc::ArrayView<const float> filter,
+                                  const absl::optional<float>& filter_quality,
+                                  int filter_delay_blocks,
+                                  bool usable_linear_filter,
+                                  bool stationary_signal) {
+  const int filter_size = static_cast<int>(filter.size());
+
+  if (stationary_signal) {
+    return;
+  }
+
+  bool estimation_feasible =
+      filter_delay_blocks <=
+      filter_length_blocks_ - kEarlyReverbMinSizeBlocks - 1;
+  estimation_feasible =
+      estimation_feasible && filter_size == filter_length_coefficients_;
+  estimation_feasible = estimation_feasible && filter_delay_blocks > 0;
+  estimation_feasible = estimation_feasible && usable_linear_filter;
+
+  if (!estimation_feasible) {
+    ResetDecayEstimation();
+    return;
+  }
+
+  if (!use_adaptive_echo_decay_) {
+    return;
+  }
+
+  const float new_smoothing = filter_quality ? *filter_quality * 0.2f : 0.f;
+  smoothing_constant_ = std::max(new_smoothing, smoothing_constant_);
+  if (smoothing_constant_ == 0.f) {
+    return;
+  }
+
+  if (block_to_analyze_ < filter_length_blocks_) {
+    // Analyze the filter and accumulate data for reverb estimation.
+    AnalyzeFilter(filter);
+    ++block_to_analyze_;
+  } else {
+    // When the filter is fully analyzed, estimate the reverb decay and reset
+    // the block_to_analyze_ counter.
+    EstimateDecay(filter, filter_delay_blocks);
+  }
+}
+
+void ReverbDecayEstimator::ResetDecayEstimation() {
+  early_reverb_estimator_.Reset();
+  late_reverb_decay_estimator_.Reset(0);
+  block_to_analyze_ = 0;
+  estimation_region_candidate_size_ = 0;
+  estimation_region_identified_ = false;
+  smoothing_constant_ = 0.f;
+  late_reverb_start_ = 0;
+  late_reverb_end_ = 0;
+}
+
+void ReverbDecayEstimator::EstimateDecay(rtc::ArrayView<const float> filter,
+                                         int peak_block) {
+  auto& h = filter;
+  RTC_DCHECK_EQ(0, h.size() % kFftLengthBy2);
+
+  // Reset the block analysis counter.
+  block_to_analyze_ =
+      std::min(peak_block + kEarlyReverbMinSizeBlocks, filter_length_blocks_);
+
+  // To estimate the reverb decay, the energy of the first filter section must
+  // be substantially larger than the last. Also, the first filter section
+  // energy must not deviate too much from the max peak.
+  const float first_reverb_gain = BlockEnergyAverage(h, block_to_analyze_);
+  const size_t h_size_blocks = h.size() >> kFftLengthBy2Log2;
+  tail_gain_ = BlockEnergyAverage(h, h_size_blocks - 1);
+  float peak_energy = BlockEnergyPeak(h, peak_block);
+  const bool sufficient_reverb_decay = first_reverb_gain > 4.f * tail_gain_;
+  const bool valid_filter =
+      first_reverb_gain > 2.f * tail_gain_ && peak_energy < 100.f;
+
+  // Estimate the size of the regions with early and late reflections.
+  const int size_early_reverb = early_reverb_estimator_.Estimate();
+  const int size_late_reverb =
+      std::max(estimation_region_candidate_size_ - size_early_reverb, 0);
+
+  // Only update the reverb decay estimate if the size of the identified late
+  // reverb is sufficiently large.
+  if (size_late_reverb >= 5) {
+    if (valid_filter && late_reverb_decay_estimator_.EstimateAvailable()) {
+      float decay = std::pow(
+          2.0f, late_reverb_decay_estimator_.Estimate() * kFftLengthBy2);
+      constexpr float kMaxDecay = 0.95f;  // ~1 sec min RT60.
+      constexpr float kMinDecay = 0.02f;  // ~15 ms max RT60.
+      decay = std::max(.97f * decay_, decay);
+      decay = std::min(decay, kMaxDecay);
+      decay = std::max(decay, kMinDecay);
+      decay_ += smoothing_constant_ * (decay - decay_);
+    }
+
+    // Update length of decay. Must have enough data (number of sections) in
+    // order to estimate decay rate.
+    late_reverb_decay_estimator_.Reset(size_late_reverb * kFftLengthBy2);
+    late_reverb_start_ =
+        peak_block + kEarlyReverbMinSizeBlocks + size_early_reverb;
+    late_reverb_end_ =
+        block_to_analyze_ + estimation_region_candidate_size_ - 1;
+  } else {
+    late_reverb_decay_estimator_.Reset(0);
+    late_reverb_start_ = 0;
+    late_reverb_end_ = 0;
+  }
+
+  // Reset variables for the identification of the region for reverb decay
+  // estimation.
+  estimation_region_identified_ = !(valid_filter && sufficient_reverb_decay);
+  estimation_region_candidate_size_ = 0;
+
+  // Stop estimation of the decay until another good filter is received.
+  smoothing_constant_ = 0.f;
+
+  // Reset early reflections detector.
+  early_reverb_estimator_.Reset();
+}
+
+void ReverbDecayEstimator::AnalyzeFilter(rtc::ArrayView<const float> filter) {
+  auto h = rtc::ArrayView<const float>(
+      filter.begin() + block_to_analyze_ * kFftLengthBy2, kFftLengthBy2);
+
+  // Compute squared filter coeffiecients for the block to analyze_;
+  std::array<float, kFftLengthBy2> h2;
+  std::transform(h.begin(), h.end(), h2.begin(), [](float a) { return a * a; });
+
+  // Map out the region for estimating the reverb decay.
+  bool adapting;
+  bool above_noise_floor;
+  AnalyzeBlockGain(h2, tail_gain_, &previous_gains_[block_to_analyze_],
+                   &adapting, &above_noise_floor);
+
+  // Count consecutive number of "good" filter sections, where "good" means:
+  // 1) energy is above noise floor.
+  // 2) energy of current section has not changed too much from last check.
+  estimation_region_identified_ =
+      estimation_region_identified_ || adapting || !above_noise_floor;
+  if (!estimation_region_identified_) {
+    ++estimation_region_candidate_size_;
+  }
+
+  // Accumulate data for reverb decay estimation and for the estimation of early
+  // reflections.
+  if (block_to_analyze_ <= late_reverb_end_) {
+    if (block_to_analyze_ >= late_reverb_start_) {
+      for (float h2_k : h2) {
+        float h2_log2 = FastApproxLog2f(h2_k + 1e-10);
+        late_reverb_decay_estimator_.Accumulate(h2_log2);
+        early_reverb_estimator_.Accumulate(h2_log2, smoothing_constant_);
+      }
+    } else {
+      for (float h2_k : h2) {
+        float h2_log2 = FastApproxLog2f(h2_k + 1e-10);
+        early_reverb_estimator_.Accumulate(h2_log2, smoothing_constant_);
+      }
+    }
+  }
+}
+
+void ReverbDecayEstimator::Dump(ApmDataDumper* data_dumper) const {
+  data_dumper->DumpRaw("aec3_reverb_decay", decay_);
+  data_dumper->DumpRaw("aec3_reverb_tail_energy", tail_gain_);
+  data_dumper->DumpRaw("aec3_reverb_alpha", smoothing_constant_);
+  data_dumper->DumpRaw("aec3_num_reverb_decay_blocks",
+                       late_reverb_end_ - late_reverb_start_);
+  data_dumper->DumpRaw("aec3_late_reverb_start", late_reverb_start_);
+  data_dumper->DumpRaw("aec3_late_reverb_end", late_reverb_end_);
+  early_reverb_estimator_.Dump(data_dumper);
+}
+
+void ReverbDecayEstimator::LateReverbLinearRegressor::Reset(
+    int num_data_points) {
+  RTC_DCHECK_LE(0, num_data_points);
+  RTC_DCHECK_EQ(0, num_data_points % 2);
+  const int N = num_data_points;
+  nz_ = 0.f;
+  // Arithmetic sum of $2 \sum_{i=0.5}^{(N-1)/2}i^2$ calculated directly.
+  nn_ = SymmetricArithmetricSum(N);
+  // The linear regression approach assumes symmetric index around 0.
+  count_ = N > 0 ? count_ = -N * 0.5f + 0.5f : 0.f;
+  N_ = N;
+  n_ = 0;
+}
+
+void ReverbDecayEstimator::LateReverbLinearRegressor::Accumulate(float z) {
+  nz_ += count_ * z;
+  ++count_;
+  ++n_;
+}
+
+float ReverbDecayEstimator::LateReverbLinearRegressor::Estimate() {
+  RTC_DCHECK(EstimateAvailable());
+  if (nn_ == 0.f) {
+    RTC_NOTREACHED();
+    return 0.f;
+  }
+  return nz_ / nn_;
+}
+
+ReverbDecayEstimator::EarlyReverbLengthEstimator::EarlyReverbLengthEstimator(
+    int max_blocks)
+    : numerators_smooth_(max_blocks - kBlocksPerSection, 0.f),
+      numerators_(numerators_smooth_.size(), 0.f),
+      coefficients_counter_(0) {
+  RTC_DCHECK_LE(0, max_blocks);
+}
+
+ReverbDecayEstimator::EarlyReverbLengthEstimator::
+    ~EarlyReverbLengthEstimator() = default;
+
+void ReverbDecayEstimator::EarlyReverbLengthEstimator::Reset() {
+  coefficients_counter_ = 0;
+  std::fill(numerators_.begin(), numerators_.end(), 0.f);
+  block_counter_ = 0;
+}
+
+void ReverbDecayEstimator::EarlyReverbLengthEstimator::Accumulate(
+    float value,
+    float smoothing) {
+  // Each section is composed by kBlocksPerSection blocks and each section
+  // overlaps with the next one in (kBlocksPerSection - 1) blocks. For example,
+  // the first section covers the blocks [0:5], the second covers the blocks
+  // [1:6] and so on. As a result, for each value, kBlocksPerSection sections
+  // need to be updated.
+  int first_section_index = std::max(block_counter_ - kBlocksPerSection + 1, 0);
+  int last_section_index =
+      std::min(block_counter_, static_cast<int>(numerators_.size() - 1));
+  float x_value = static_cast<float>(coefficients_counter_) +
+                  kEarlyReverbFirstPointAtLinearRegressors;
+  const float value_to_inc = kFftLengthBy2 * value;
+  float value_to_add =
+      x_value * value + (block_counter_ - last_section_index) * value_to_inc;
+  for (int section = last_section_index; section >= first_section_index;
+       --section, value_to_add += value_to_inc) {
+    numerators_[section] += value_to_add;
+  }
+
+  // Check if this update was the last coefficient of the current block. In that
+  // case, check if we are at the end of one of the sections and update the
+  // numerator of the linear regressor that is computed in such section.
+  if (++coefficients_counter_ == kFftLengthBy2) {
+    if (block_counter_ >= (kBlocksPerSection - 1)) {
+      size_t section = block_counter_ - (kBlocksPerSection - 1);
+      RTC_DCHECK_GT(numerators_.size(), section);
+      RTC_DCHECK_GT(numerators_smooth_.size(), section);
+      numerators_smooth_[section] +=
+          smoothing * (numerators_[section] - numerators_smooth_[section]);
+      n_sections_ = section + 1;
+    }
+    ++block_counter_;
+    coefficients_counter_ = 0;
+  }
+}
+
+// Estimates the size in blocks of the early reverb. The estimation is done by
+// comparing the tilt that is estimated in each section. As an optimization
+// detail and due to the fact that all the linear regressors that are computed
+// shared the same denominator, the comparison of the tilts is done by a
+// comparison of the numerator of the linear regressors.
+int ReverbDecayEstimator::EarlyReverbLengthEstimator::Estimate() {
+  constexpr float N = kBlocksPerSection * kFftLengthBy2;
+  constexpr float nn = SymmetricArithmetricSum(N);
+  // numerator_11 refers to the quantity that the linear regressor needs in the
+  // numerator for getting a decay equal to 1.1 (which is not a decay).
+  // log2(1.1) * nn / kFftLengthBy2.
+  constexpr float numerator_11 = 0.13750352374993502f * nn / kFftLengthBy2;
+  // log2(0.8) *  nn / kFftLengthBy2.
+  constexpr float numerator_08 = -0.32192809488736229f * nn / kFftLengthBy2;
+  constexpr int kNumSectionsToAnalyze = 9;
+
+  if (n_sections_ < kNumSectionsToAnalyze) {
+    return 0;
+  }
+
+  // Estimation of the blocks that correspond to early reverberations. The
+  // estimation is done by analyzing the impulse response. The portions of the
+  // impulse response whose energy is not decreasing over its coefficients are
+  // considered to be part of the early reverberations. Furthermore, the blocks
+  // where the energy is decreasing faster than what it does at the end of the
+  // impulse response are also considered to be part of the early
+  // reverberations. The estimation is limited to the first
+  // kNumSectionsToAnalyze sections.
+
+  RTC_DCHECK_LE(n_sections_, numerators_smooth_.size());
+  const float min_numerator_tail =
+      *std::min_element(numerators_smooth_.begin() + kNumSectionsToAnalyze,
+                        numerators_smooth_.begin() + n_sections_);
+  int early_reverb_size_minus_1 = 0;
+  for (int k = 0; k < kNumSectionsToAnalyze; ++k) {
+    if ((numerators_smooth_[k] > numerator_11) ||
+        (numerators_smooth_[k] < numerator_08 &&
+         numerators_smooth_[k] < 0.9f * min_numerator_tail)) {
+      early_reverb_size_minus_1 = k;
+    }
+  }
+
+  return early_reverb_size_minus_1 == 0 ? 0 : early_reverb_size_minus_1 + 1;
+}
+
+void ReverbDecayEstimator::EarlyReverbLengthEstimator::Dump(
+    ApmDataDumper* data_dumper) const {
+  data_dumper->DumpRaw("aec3_er_acum_numerator", numerators_smooth_);
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_processing/aec3/reverb_decay_estimator.h b/modules/audio_processing/aec3/reverb_decay_estimator.h
new file mode 100644
index 0000000..67a84ab
--- /dev/null
+++ b/modules/audio_processing/aec3/reverb_decay_estimator.h
@@ -0,0 +1,112 @@
+/*
+ *  Copyright (c) 2018 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 MODULES_AUDIO_PROCESSING_AEC3_REVERB_DECAY_ESTIMATOR_H_
+#define MODULES_AUDIO_PROCESSING_AEC3_REVERB_DECAY_ESTIMATOR_H_
+
+#include <array>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/audio/echo_canceller3_config.h"
+#include "modules/audio_processing/aec3/aec3_common.h"
+
+namespace webrtc {
+
+class ApmDataDumper;
+
+// Class for estimating the decay of the late reverb.
+class ReverbDecayEstimator {
+ public:
+  explicit ReverbDecayEstimator(const EchoCanceller3Config& config);
+  ~ReverbDecayEstimator();
+  // Updates the decay estimate.
+  void Update(rtc::ArrayView<const float> filter,
+              const absl::optional<float>& filter_quality,
+              int filter_delay_blocks,
+              bool usable_linear_filter,
+              bool stationary_signal);
+  // Returns the decay for the exponential model.
+  float Decay() const { return decay_; }
+  // Dumps debug data.
+  void Dump(ApmDataDumper* data_dumper) const;
+
+ private:
+  void EstimateDecay(rtc::ArrayView<const float> filter, int peak_block);
+  void AnalyzeFilter(rtc::ArrayView<const float> filter);
+
+  void ResetDecayEstimation();
+
+  // Class for estimating the decay of the late reverb from the linear filter.
+  class LateReverbLinearRegressor {
+   public:
+    // Resets the estimator to receive a specified number of data points.
+    void Reset(int num_data_points);
+    // Accumulates estimation data.
+    void Accumulate(float z);
+    // Estimates the decay.
+    float Estimate();
+    // Returns whether an estimate is available.
+    bool EstimateAvailable() const { return n_ == N_ && N_ != 0; }
+
+   public:
+    float nz_ = 0.f;
+    float nn_ = 0.f;
+    float count_ = 0.f;
+    int N_ = 0;
+    int n_ = 0;
+  };
+
+  // Class for identifying the length of the early reverb from the linear
+  // filter. For identifying the early reverberations, the impulse response is
+  // divided in sections and the tilt of each section is computed by a linear
+  // regressor.
+  class EarlyReverbLengthEstimator {
+   public:
+    explicit EarlyReverbLengthEstimator(int max_blocks);
+    ~EarlyReverbLengthEstimator();
+
+    // Resets the estimator.
+    void Reset();
+    // Accumulates estimation data.
+    void Accumulate(float value, float smoothing);
+    // Estimates the size in blocks of the early reverb.
+    int Estimate();
+    // Dumps debug data.
+    void Dump(ApmDataDumper* data_dumper) const;
+
+   private:
+    std::vector<float> numerators_smooth_;
+    std::vector<float> numerators_;
+    int coefficients_counter_;
+    int block_counter_ = 0;
+    int n_sections_ = 0;
+  };
+
+  const int filter_length_blocks_;
+  const int filter_length_coefficients_;
+  const bool use_adaptive_echo_decay_;
+  LateReverbLinearRegressor late_reverb_decay_estimator_;
+  EarlyReverbLengthEstimator early_reverb_estimator_;
+  int late_reverb_start_;
+  int late_reverb_end_;
+  int block_to_analyze_ = 0;
+  int estimation_region_candidate_size_ = 0;
+  bool estimation_region_identified_ = false;
+  std::array<float, kMaxAdaptiveFilterLength> previous_gains_;
+  float decay_;
+  float tail_gain_ = 0.f;
+  float smoothing_constant_ = 0.f;
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_PROCESSING_AEC3_REVERB_DECAY_ESTIMATOR_H_
diff --git a/modules/audio_processing/aec3/reverb_frequency_response.cc b/modules/audio_processing/aec3/reverb_frequency_response.cc
new file mode 100644
index 0000000..0d82515
--- /dev/null
+++ b/modules/audio_processing/aec3/reverb_frequency_response.cc
@@ -0,0 +1,111 @@
+/*
+ *  Copyright (c) 2018 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 "modules/audio_processing/aec3/reverb_frequency_response.h"
+
+#include <algorithm>
+#include <array>
+#include <cmath>
+#include <memory>
+#include <numeric>
+
+#include "api/array_view.h"
+#include "api/audio/echo_canceller3_config.h"
+#include "modules/audio_processing/aec3/aec3_common.h"
+#include "rtc_base/checks.h"
+#include "system_wrappers/include/field_trial.h"
+
+namespace webrtc {
+
+namespace {
+
+bool EnableSmoothUpdatesTailFreqResp() {
+  return !field_trial::IsEnabled(
+      "WebRTC-Aec3SmoothUpdatesTailFreqRespKillSwitch");
+}
+
+// Computes the ratio of the energies between the direct path and the tail. The
+// energy is computed in the power spectrum domain discarding the DC
+// contributions.
+float AverageDecayWithinFilter(
+    rtc::ArrayView<const float> freq_resp_direct_path,
+    rtc::ArrayView<const float> freq_resp_tail) {
+  // Skipping the DC for the ratio computation
+  constexpr size_t kSkipBins = 1;
+  RTC_CHECK_EQ(freq_resp_direct_path.size(), freq_resp_tail.size());
+
+  float direct_path_energy =
+      std::accumulate(freq_resp_direct_path.begin() + kSkipBins,
+                      freq_resp_direct_path.end(), 0.f);
+
+  if (direct_path_energy == 0.f) {
+    return 0.f;
+  }
+
+  float tail_energy = std::accumulate(freq_resp_tail.begin() + kSkipBins,
+                                      freq_resp_tail.end(), 0.f);
+  return tail_energy / direct_path_energy;
+}
+
+}  // namespace
+
+ReverbFrequencyResponse::ReverbFrequencyResponse()
+    : enable_smooth_tail_response_updates_(EnableSmoothUpdatesTailFreqResp()) {
+  tail_response_.fill(0.f);
+}
+ReverbFrequencyResponse::~ReverbFrequencyResponse() = default;
+
+void ReverbFrequencyResponse::Update(
+    const std::vector<std::array<float, kFftLengthBy2Plus1>>&
+        frequency_response,
+    int filter_delay_blocks,
+    const absl::optional<float>& linear_filter_quality,
+    bool stationary_block) {
+  if (!enable_smooth_tail_response_updates_) {
+    Update(frequency_response, filter_delay_blocks, 0.5f);
+    return;
+  }
+
+  if (stationary_block || !linear_filter_quality) {
+    return;
+  }
+
+  Update(frequency_response, filter_delay_blocks, *linear_filter_quality);
+}
+
+void ReverbFrequencyResponse::Update(
+    const std::vector<std::array<float, kFftLengthBy2Plus1>>&
+        frequency_response,
+    int filter_delay_blocks,
+    float linear_filter_quality) {
+  rtc::ArrayView<const float> freq_resp_tail(
+      frequency_response[frequency_response.size() - 1]);
+
+  rtc::ArrayView<const float> freq_resp_direct_path(
+      frequency_response[filter_delay_blocks]);
+
+  float average_decay =
+      AverageDecayWithinFilter(freq_resp_direct_path, freq_resp_tail);
+
+  const float smoothing = 0.2f * linear_filter_quality;
+  average_decay_ += smoothing * (average_decay - average_decay_);
+
+  for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) {
+    tail_response_[k] = freq_resp_direct_path[k] * average_decay_;
+  }
+
+  for (size_t k = 1; k < kFftLengthBy2; ++k) {
+    const float avg_neighbour =
+        0.5f * (tail_response_[k - 1] + tail_response_[k + 1]);
+    tail_response_[k] = std::max(tail_response_[k], avg_neighbour);
+  }
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_processing/aec3/reverb_frequency_response.h b/modules/audio_processing/aec3/reverb_frequency_response.h
new file mode 100644
index 0000000..23485e0
--- /dev/null
+++ b/modules/audio_processing/aec3/reverb_frequency_response.h
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (c) 2018 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 MODULES_AUDIO_PROCESSING_AEC3_REVERB_FREQUENCY_RESPONSE_H_
+#define MODULES_AUDIO_PROCESSING_AEC3_REVERB_FREQUENCY_RESPONSE_H_
+
+#include <memory>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "modules/audio_processing/aec3/aec3_common.h"
+#include "modules/audio_processing/logging/apm_data_dumper.h"
+
+namespace webrtc {
+
+// Class for updating the frequency response for the reverb.
+class ReverbFrequencyResponse {
+ public:
+  ReverbFrequencyResponse();
+  ~ReverbFrequencyResponse();
+
+  // Updates the frequency response estimate of the reverb.
+  void Update(const std::vector<std::array<float, kFftLengthBy2Plus1>>&
+                  frequency_response,
+              int filter_delay_blocks,
+              const absl::optional<float>& linear_filter_quality,
+              bool stationary_block);
+
+  // Returns the estimated frequency response for the reverb.
+  rtc::ArrayView<const float> FrequencyResponse() const {
+    return tail_response_;
+  }
+
+ private:
+  void Update(const std::vector<std::array<float, kFftLengthBy2Plus1>>&
+                  frequency_response,
+              int filter_delay_blocks,
+              float linear_filter_quality);
+
+  const bool enable_smooth_tail_response_updates_;
+  float average_decay_ = 0.f;
+  std::array<float, kFftLengthBy2Plus1> tail_response_;
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_PROCESSING_AEC3_REVERB_FREQUENCY_RESPONSE_H_
diff --git a/modules/audio_processing/aec3/reverb_model_estimator.cc b/modules/audio_processing/aec3/reverb_model_estimator.cc
index 84e8e48..ce3e2be 100644
--- a/modules/audio_processing/aec3/reverb_model_estimator.cc
+++ b/modules/audio_processing/aec3/reverb_model_estimator.cc
@@ -10,313 +10,28 @@
 
 #include "modules/audio_processing/aec3/reverb_model_estimator.h"
 
-#include <algorithm>
-#include <array>
-#include <cmath>
-#include <memory>
-#include <numeric>
-
-#include "api/array_view.h"
-#include "api/audio/echo_canceller3_config.h"
-#include "modules/audio_processing/aec3/aec3_common.h"
-#include "rtc_base/checks.h"
-#include "system_wrappers/include/field_trial.h"
-
 namespace webrtc {
 
-namespace {
-
-bool EnableSmoothUpdatesTailFreqResp() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3SmoothUpdatesTailFreqRespKillSwitch");
-}
-
-// Computes the ratio of the energies between the direct path and the tail. The
-// energy is computed in the power spectrum domain discarding the DC
-// contributions.
-float ComputeRatioEnergies(
-    const rtc::ArrayView<const float>& freq_resp_direct_path,
-    const rtc::ArrayView<const float>& freq_resp_tail) {
-  // Skipping the DC for the ratio computation
-  constexpr size_t n_skip_bins = 1;
-  RTC_CHECK_EQ(freq_resp_direct_path.size(), freq_resp_tail.size());
-
-  float direct_path_energy =
-      std::accumulate(freq_resp_direct_path.begin() + n_skip_bins,
-                      freq_resp_direct_path.end(), 0.f);
-
-  float tail_energy = std::accumulate(freq_resp_tail.begin() + n_skip_bins,
-                                      freq_resp_tail.end(), 0.f);
-
-  if (direct_path_energy > 0) {
-    return tail_energy / direct_path_energy;
-  } else {
-    return 0.f;
-  }
-}
-
-}  // namespace
-
 ReverbModelEstimator::ReverbModelEstimator(const EchoCanceller3Config& config)
-    : filter_main_length_blocks_(config.filter.main.length_blocks),
-      reverb_decay_(std::fabs(config.ep_strength.default_len)),
-      enable_smooth_freq_resp_tail_updates_(EnableSmoothUpdatesTailFreqResp()) {
-  block_energies_.fill(0.f);
-  freq_resp_tail_.fill(0.f);
-}
+    : reverb_decay_estimator_(config) {}
 
 ReverbModelEstimator::~ReverbModelEstimator() = default;
 
-bool ReverbModelEstimator::IsAGoodFilterForDecayEstimation(
-    int filter_delay_blocks,
-    bool usable_linear_estimate,
-    size_t length_filter) {
-  if ((filter_delay_blocks && usable_linear_estimate) &&
-      (filter_delay_blocks <=
-       static_cast<int>(filter_main_length_blocks_) - 4) &&
-      (length_filter >=
-       static_cast<size_t>(GetTimeDomainLength(filter_main_length_blocks_)))) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
 void ReverbModelEstimator::Update(
-    const std::vector<float>& impulse_response,
+    rtc::ArrayView<const float> impulse_response,
     const std::vector<std::array<float, kFftLengthBy2Plus1>>&
-        filter_freq_response,
-    const absl::optional<float>& quality_linear,
+        frequency_response,
+    const absl::optional<float>& linear_filter_quality,
     int filter_delay_blocks,
     bool usable_linear_estimate,
-    float default_decay,
     bool stationary_block) {
-  if (enable_smooth_freq_resp_tail_updates_) {
-    if (!stationary_block) {
-      float alpha = 0;
-      if (quality_linear) {
-        alpha = 0.2f * quality_linear.value();
-        UpdateFreqRespTail(filter_freq_response, filter_delay_blocks, alpha);
-      }
-      if (IsAGoodFilterForDecayEstimation(filter_delay_blocks,
-                                          usable_linear_estimate,
-                                          impulse_response.size())) {
-        alpha_ = std::max(alpha, alpha_);
-        if ((alpha_ > 0.f) && (default_decay < 0.f)) {
-          // Echo tail decay estimation if default_decay is negative.
-          UpdateReverbDecay(impulse_response);
-        }
-      } else {
-        ResetDecayEstimation();
-      }
-    }
-  } else {
-    UpdateFreqRespTail(filter_freq_response, filter_delay_blocks, 0.1f);
-  }
+  // Estimate the frequency response for the reverb.
+  reverb_frequency_response_.Update(frequency_response, filter_delay_blocks,
+                                    linear_filter_quality, stationary_block);
+
+  // Estimate the reverb decay,
+  reverb_decay_estimator_.Update(impulse_response, linear_filter_quality,
+                                 filter_delay_blocks, usable_linear_estimate,
+                                 stationary_block);
 }
-
-void ReverbModelEstimator::ResetDecayEstimation() {
-  accumulated_nz_ = 0.f;
-  accumulated_nn_ = 0.f;
-  accumulated_count_ = 0.f;
-  current_reverb_decay_section_ = 0;
-  num_reverb_decay_sections_ = 0;
-  num_reverb_decay_sections_next_ = 0;
-  found_end_of_reverb_decay_ = false;
-  alpha_ = 0.f;
-}
-
-void ReverbModelEstimator::UpdateReverbDecay(
-    const std::vector<float>& impulse_response) {
-  constexpr float kOneByFftLengthBy2 = 1.f / kFftLengthBy2;
-
-  // Form the data to match against by squaring the impulse response
-  // coefficients.
-  std::array<float, GetTimeDomainLength(kMaxAdaptiveFilterLength)>
-      matching_data_data;
-  RTC_DCHECK_LE(GetTimeDomainLength(filter_main_length_blocks_),
-                matching_data_data.size());
-  rtc::ArrayView<float> matching_data(
-      matching_data_data.data(),
-      GetTimeDomainLength(filter_main_length_blocks_));
-  std::transform(
-      impulse_response.begin(), impulse_response.end(), matching_data.begin(),
-      [](float a) { return a * a; });  // TODO(devicentepena) check if focusing
-                                       // on one block would be enough.
-
-  if (current_reverb_decay_section_ < filter_main_length_blocks_) {
-    // Update accumulated variables for the current filter section.
-
-    const size_t start_index = current_reverb_decay_section_ * kFftLengthBy2;
-
-    RTC_DCHECK_GT(matching_data.size(), start_index);
-    RTC_DCHECK_GE(matching_data.size(), start_index + kFftLengthBy2);
-    float section_energy =
-        std::accumulate(matching_data.begin() + start_index,
-                        matching_data.begin() + start_index + kFftLengthBy2,
-                        0.f) *
-        kOneByFftLengthBy2;
-
-    section_energy = std::max(
-        section_energy, 1e-32f);  // Regularization to avoid division by 0.
-
-    RTC_DCHECK_LT(current_reverb_decay_section_, block_energies_.size());
-    const float energy_ratio =
-        block_energies_[current_reverb_decay_section_] / section_energy;
-
-    found_end_of_reverb_decay_ = found_end_of_reverb_decay_ ||
-                                 (energy_ratio > 1.1f || energy_ratio < 0.9f);
-
-    // Count consecutive number of "good" filter sections, where "good" means:
-    // 1) energy is above noise floor.
-    // 2) energy of current section has not changed too much from last check.
-    if (!found_end_of_reverb_decay_ && section_energy > tail_energy_) {
-      ++num_reverb_decay_sections_next_;
-    } else {
-      found_end_of_reverb_decay_ = true;
-    }
-
-    block_energies_[current_reverb_decay_section_] = section_energy;
-
-    if (num_reverb_decay_sections_ > 0) {
-      // Linear regression of log squared magnitude of impulse response.
-      for (size_t i = 0; i < kFftLengthBy2; i++) {
-        RTC_DCHECK_GT(matching_data.size(), start_index + i);
-        float z = FastApproxLog2f(matching_data[start_index + i] + 1e-10);
-        accumulated_nz_ += accumulated_count_ * z;
-        ++accumulated_count_;
-      }
-    }
-
-    num_reverb_decay_sections_ =
-        num_reverb_decay_sections_ > 0 ? num_reverb_decay_sections_ - 1 : 0;
-    ++current_reverb_decay_section_;
-
-  } else {
-    constexpr float kMaxDecay = 0.95f;  // ~1 sec min RT60.
-    constexpr float kMinDecay = 0.02f;  // ~15 ms max RT60.
-
-    // Accumulated variables throughout whole filter.
-
-    // Solve for decay rate.
-
-    float decay = reverb_decay_;
-
-    if (accumulated_nn_ != 0.f) {
-      const float exp_candidate = -accumulated_nz_ / accumulated_nn_;
-      decay = std::pow(2.0f, -exp_candidate * kFftLengthBy2);
-      decay = std::min(decay, kMaxDecay);
-      decay = std::max(decay, kMinDecay);
-    }
-
-    // Filter tail energy (assumed to be noise).
-    constexpr size_t kTailLength = kFftLengthBy2;
-
-    constexpr float k1ByTailLength = 1.f / kTailLength;
-    const size_t tail_index =
-        GetTimeDomainLength(filter_main_length_blocks_) - kTailLength;
-
-    RTC_DCHECK_GT(matching_data.size(), tail_index);
-
-    tail_energy_ = std::accumulate(matching_data.begin() + tail_index,
-                                   matching_data.end(), 0.f) *
-                   k1ByTailLength;
-
-    // Update length of decay.
-    num_reverb_decay_sections_ = num_reverb_decay_sections_next_;
-    num_reverb_decay_sections_next_ = 0;
-    // Must have enough data (number of sections) in order
-    // to estimate decay rate.
-    if (num_reverb_decay_sections_ < 5) {
-      num_reverb_decay_sections_ = 0;
-    }
-
-    const float N = num_reverb_decay_sections_ * kFftLengthBy2;
-    accumulated_nz_ = 0.f;
-    const float k1By12 = 1.f / 12.f;
-    // Arithmetic sum $2 \sum_{i=0.5}^{(N-1)/2}i^2$ calculated directly.
-    accumulated_nn_ = N * (N * N - 1.0f) * k1By12;
-    accumulated_count_ = -N * 0.5f;
-    // Linear regression approach assumes symmetric index around 0.
-    accumulated_count_ += 0.5f;
-
-    // Identify the peak index of the impulse response.
-    const size_t peak_index = std::distance(
-        matching_data.begin(),
-        std::max_element(matching_data.begin(), matching_data.end()));
-
-    current_reverb_decay_section_ = peak_index * kOneByFftLengthBy2 + 3;
-    // Make sure we're not out of bounds.
-    if (current_reverb_decay_section_ + 1 >= filter_main_length_blocks_) {
-      current_reverb_decay_section_ = filter_main_length_blocks_;
-    }
-    size_t start_index = current_reverb_decay_section_ * kFftLengthBy2;
-    float first_section_energy =
-        std::accumulate(matching_data.begin() + start_index,
-                        matching_data.begin() + start_index + kFftLengthBy2,
-                        0.f) *
-        kOneByFftLengthBy2;
-
-    // To estimate the reverb decay, the energy of the first filter section
-    // must be substantially larger than the last.
-    // Also, the first filter section energy must not deviate too much
-    // from the max peak.
-    bool main_filter_has_reverb = first_section_energy > 4.f * tail_energy_;
-    bool main_filter_is_sane = first_section_energy > 2.f * tail_energy_ &&
-                               matching_data[peak_index] < 100.f;
-
-    // Not detecting any decay, but tail is over noise - assume max decay.
-    if (num_reverb_decay_sections_ == 0 && main_filter_is_sane &&
-        main_filter_has_reverb) {
-      decay = kMaxDecay;
-    }
-
-    if (main_filter_is_sane && num_reverb_decay_sections_ > 0) {
-      decay = std::max(.97f * reverb_decay_, decay);
-      reverb_decay_ -= alpha_ * (reverb_decay_ - decay);
-    }
-
-    found_end_of_reverb_decay_ =
-        !(main_filter_is_sane && main_filter_has_reverb);
-    alpha_ = 0.f;  // Stop estimation of the decay until another good filter is
-                   // received
-  }
-}
-
-// Updates the estimation of the frequency response at the filter tail.
-void ReverbModelEstimator::UpdateFreqRespTail(
-    const std::vector<std::array<float, kFftLengthBy2Plus1>>&
-        filter_freq_response,
-    int filter_delay_blocks,
-    float alpha) {
-  size_t num_blocks = filter_freq_response.size();
-  rtc::ArrayView<const float> freq_resp_tail(
-      filter_freq_response[num_blocks - 1]);
-  rtc::ArrayView<const float> freq_resp_direct_path(
-      filter_freq_response[filter_delay_blocks]);
-  float ratio_energies =
-      ComputeRatioEnergies(freq_resp_direct_path, freq_resp_tail);
-  ratio_tail_to_direct_path_ +=
-      alpha * (ratio_energies - ratio_tail_to_direct_path_);
-
-  for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) {
-    freq_resp_tail_[k] = freq_resp_direct_path[k] * ratio_tail_to_direct_path_;
-  }
-
-  for (size_t k = 1; k < kFftLengthBy2; ++k) {
-    float avg_neighbour =
-        0.5f * (freq_resp_tail_[k - 1] + freq_resp_tail_[k + 1]);
-    freq_resp_tail_[k] = std::max(freq_resp_tail_[k], avg_neighbour);
-  }
-}
-
-void ReverbModelEstimator::Dump(
-    const std::unique_ptr<ApmDataDumper>& data_dumper) {
-  data_dumper->DumpRaw("aec3_reverb_decay", reverb_decay_);
-  data_dumper->DumpRaw("aec3_reverb_tail_energy", tail_energy_);
-  data_dumper->DumpRaw("aec3_reverb_alpha", alpha_);
-  data_dumper->DumpRaw("aec3_num_reverb_decay_sections",
-                       static_cast<int>(num_reverb_decay_sections_));
-}
-
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec3/reverb_model_estimator.h b/modules/audio_processing/aec3/reverb_model_estimator.h
index d2015aa..b6a3591 100644
--- a/modules/audio_processing/aec3/reverb_model_estimator.h
+++ b/modules/audio_processing/aec3/reverb_model_estimator.h
@@ -11,72 +11,49 @@
 #ifndef MODULES_AUDIO_PROCESSING_AEC3_REVERB_MODEL_ESTIMATOR_H_
 #define MODULES_AUDIO_PROCESSING_AEC3_REVERB_MODEL_ESTIMATOR_H_
 
-#include <memory>
 #include <vector>
 
 #include "absl/types/optional.h"
 #include "api/array_view.h"
 #include "api/audio/echo_canceller3_config.h"
-#include "modules/audio_processing/aec3/aec3_common.h"
-#include "modules/audio_processing/logging/apm_data_dumper.h"
+#include "modules/audio_processing/aec3/reverb_decay_estimator.h"
+#include "modules/audio_processing/aec3/reverb_frequency_response.h"
 
 namespace webrtc {
 
-// The ReverbModelEstimator class describes an estimator of the parameters
-// that are used for the reverberant model.
+class ApmDataDumper;
+
+// Class for estimating the model parameters for the reverberant echo.
 class ReverbModelEstimator {
  public:
   explicit ReverbModelEstimator(const EchoCanceller3Config& config);
   ~ReverbModelEstimator();
-  // Updates the model.
-  void Update(const std::vector<float>& impulse_response,
+
+  // Updates the estimates based on new data.
+  void Update(rtc::ArrayView<const float> impulse_response,
               const std::vector<std::array<float, kFftLengthBy2Plus1>>&
-                  filter_freq_response,
-              const absl::optional<float>& quality_linear,
+                  frequency_response,
+              const absl::optional<float>& linear_filter_quality,
               int filter_delay_blocks,
               bool usable_linear_estimate,
-              float default_decay,
               bool stationary_block);
-  // Returns the decay for the exponential model.
-  float ReverbDecay() const { return reverb_decay_; }
 
-  void Dump(const std::unique_ptr<ApmDataDumper>& data_dumper);
+  // Returns the exponential decay of the reverberant echo.
+  float ReverbDecay() const { return reverb_decay_estimator_.Decay(); }
 
-  // Return the estimated freq. response of the tail of the filter.
-  rtc::ArrayView<const float> GetFreqRespTail() const {
-    return freq_resp_tail_;
+  // Return the frequency response of the reverberant echo.
+  rtc::ArrayView<const float> GetReverbFrequencyResponse() const {
+    return reverb_frequency_response_.FrequencyResponse();
+  }
+
+  // Dumps debug data.
+  void Dump(ApmDataDumper* data_dumper) const {
+    reverb_decay_estimator_.Dump(data_dumper);
   }
 
  private:
-  bool IsAGoodFilterForDecayEstimation(int filter_delay_blocks,
-                                       bool usable_linear_estimate,
-                                       size_t length_filter);
-  void UpdateReverbDecay(const std::vector<float>& impulse_response);
-
-  void UpdateFreqRespTail(
-      const std::vector<std::array<float, kFftLengthBy2Plus1>>&
-          filter_freq_response,
-      int filter_delay_blocks,
-      float alpha);
-
-  void ResetDecayEstimation();
-
-  const size_t filter_main_length_blocks_;
-
-  float accumulated_nz_ = 0.f;
-  float accumulated_nn_ = 0.f;
-  float accumulated_count_ = 0.f;
-  size_t current_reverb_decay_section_ = 0;
-  size_t num_reverb_decay_sections_ = 0;
-  size_t num_reverb_decay_sections_next_ = 0;
-  bool found_end_of_reverb_decay_ = false;
-  std::array<float, kMaxAdaptiveFilterLength> block_energies_;
-  float reverb_decay_;
-  float tail_energy_ = 0.f;
-  float alpha_ = 0.f;
-  std::array<float, kFftLengthBy2Plus1> freq_resp_tail_;
-  float ratio_tail_to_direct_path_ = 0.f;
-  bool enable_smooth_freq_resp_tail_updates_;
+  ReverbDecayEstimator reverb_decay_estimator_;
+  ReverbFrequencyResponse reverb_frequency_response_;
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec3/reverb_model_estimator_unittest.cc b/modules/audio_processing/aec3/reverb_model_estimator_unittest.cc
index 9667f4f..aa5e96f 100644
--- a/modules/audio_processing/aec3/reverb_model_estimator_unittest.cc
+++ b/modules/audio_processing/aec3/reverb_model_estimator_unittest.cc
@@ -29,16 +29,16 @@
 class ReverbModelEstimatorTest {
  public:
   explicit ReverbModelEstimatorTest(float default_decay)
-      : default_decay_(default_decay),
-        estimated_decay_(default_decay),
-        h_(aec3_config_.filter.main.length_blocks * kBlockSize, 0.f),
-        H2_(aec3_config_.filter.main.length_blocks) {
+      : default_decay_(default_decay), estimated_decay_(default_decay) {
     aec3_config_.ep_strength.default_len = default_decay_;
+    aec3_config_.filter.main.length_blocks = 40;
+    h_.resize(aec3_config_.filter.main.length_blocks * kBlockSize);
+    H2_.resize(aec3_config_.filter.main.length_blocks);
     CreateImpulseResponseWithDecay();
   }
   void RunEstimator();
   float GetDecay() { return estimated_decay_; }
-  float GetTrueDecay() { return true_power_decay_; }
+  float GetTrueDecay() { return kTruePowerDecay; }
   float GetPowerTailDb() { return 10.f * log10(estimated_power_tail_); }
   float GetTruePowerTailDb() { return 10.f * log10(true_power_tail_); }
 
@@ -46,10 +46,10 @@
   void CreateImpulseResponseWithDecay();
 
   absl::optional<float> quality_linear_ = 1.0f;
-  static constexpr int filter_delay_blocks_ = 2;
-  static constexpr bool usable_linear_estimate_ = true;
-  static constexpr bool stationary_block_ = false;
-  static constexpr float true_power_decay_ = 0.5f;
+  static constexpr int kFilterDelayBlocks = 2;
+  static constexpr bool kUsableLinearEstimate = true;
+  static constexpr bool kStationaryBlock = false;
+  static constexpr float kTruePowerDecay = 0.5f;
   EchoCanceller3Config aec3_config_;
   float default_decay_;
   float estimated_decay_;
@@ -63,43 +63,35 @@
   const Aec3Fft fft;
   RTC_DCHECK_EQ(h_.size(), aec3_config_.filter.main.length_blocks * kBlockSize);
   RTC_DCHECK_EQ(H2_.size(), aec3_config_.filter.main.length_blocks);
-  RTC_DCHECK_EQ(filter_delay_blocks_, 2);
-  const float peak = 1.0f;
-  float decay_power_sample = std::sqrt(true_power_decay_);
-  for (size_t k = 1; k < kBlockSizeLog2; k++) {
-    decay_power_sample = std::sqrt(decay_power_sample);
-  }
-  h_[filter_delay_blocks_ * kBlockSize] = peak;
-  for (size_t k = filter_delay_blocks_ * kBlockSize + 1; k < h_.size(); ++k) {
-    h_[k] = h_[k - 1] * std::sqrt(decay_power_sample);
+  RTC_DCHECK_EQ(kFilterDelayBlocks, 2);
+
+  float decay_sample = std::sqrt(powf(kTruePowerDecay, 1.f / kBlockSize));
+  const size_t filter_delay_coefficients = kFilterDelayBlocks * kBlockSize;
+  std::fill(h_.begin(), h_.end(), 0.f);
+  h_[filter_delay_coefficients] = 1.f;
+  for (size_t k = filter_delay_coefficients + 1; k < h_.size(); ++k) {
+    h_[k] = h_[k - 1] * decay_sample;
   }
 
-  for (size_t block = 0; block < H2_.size(); ++block) {
-    std::array<float, kFftLength> h_block;
-    h_block.fill(0.f);
-    FftData H_block;
-    rtc::ArrayView<float> H2_block(H2_[block]);
-    std::copy(h_.begin() + block * kBlockSize,
-              h_.begin() + block * (kBlockSize + 1), h_block.begin());
-
-    fft.Fft(&h_block, &H_block);
-    for (size_t k = 0; k < H2_block.size(); ++k) {
-      H2_block[k] =
-          H_block.re[k] * H_block.re[k] + H_block.im[k] * H_block.im[k];
-    }
+  std::array<float, kFftLength> fft_data;
+  FftData H_j;
+  for (size_t j = 0, k = 0; j < H2_.size(); ++j, k += kBlockSize) {
+    fft_data.fill(0.f);
+    std::copy(h_.begin() + k, h_.begin() + k + kBlockSize, fft_data.begin());
+    fft.Fft(&fft_data, &H_j);
+    H_j.Spectrum(Aec3Optimization::kNone, H2_[j]);
   }
   rtc::ArrayView<float> H2_tail(H2_[H2_.size() - 1]);
   true_power_tail_ = std::accumulate(H2_tail.begin(), H2_tail.end(), 0.f);
 }
 void ReverbModelEstimatorTest::RunEstimator() {
   ReverbModelEstimator estimator(aec3_config_);
-  for (size_t k = 0; k < 1000; ++k) {
-    estimator.Update(h_, H2_, quality_linear_, filter_delay_blocks_,
-                     usable_linear_estimate_, default_decay_,
-                     stationary_block_);
+  for (size_t k = 0; k < 3000; ++k) {
+    estimator.Update(h_, H2_, quality_linear_, kFilterDelayBlocks,
+                     kUsableLinearEstimate, kStationaryBlock);
   }
   estimated_decay_ = estimator.ReverbDecay();
-  rtc::ArrayView<const float> freq_resp_tail = estimator.GetFreqRespTail();
+  auto freq_resp_tail = estimator.GetReverbFrequencyResponse();
   estimated_power_tail_ =
       std::accumulate(freq_resp_tail.begin(), freq_resp_tail.end(), 0.f);
 }
diff --git a/modules/audio_processing/aec3/subtractor.cc b/modules/audio_processing/aec3/subtractor.cc
index 614034b..609e8ac 100644
--- a/modules/audio_processing/aec3/subtractor.cc
+++ b/modules/audio_processing/aec3/subtractor.cc
@@ -128,12 +128,6 @@
       G_shadow_(config_.filter.shadow_initial,
                 config.filter.config_change_duration_blocks) {
   RTC_DCHECK(data_dumper_);
-  // Currently, the rest of AEC3 requires the main and shadow filter lengths to
-  // be identical.
-  RTC_DCHECK_EQ(config_.filter.main.length_blocks,
-                config_.filter.shadow.length_blocks);
-  RTC_DCHECK_EQ(config_.filter.main_initial.length_blocks,
-                config_.filter.shadow_initial.length_blocks);
 }
 
 Subtractor::~Subtractor() = default;
@@ -159,8 +153,6 @@
   }
 
   if (echo_path_variability.gain_change && enable_agc_gain_change_response_) {
-    RTC_LOG(LS_WARNING) << "Resetting main filter adaptation speed due to "
-                           "microphone gain change";
     G_main_.HandleEchoPathChange(echo_path_variability);
   }
 }
@@ -222,11 +214,28 @@
   E_shadow.Spectrum(optimization_, output->E2_shadow);
   E_main.Spectrum(optimization_, output->E2_main);
 
+  // Compute the render powers.
+  std::array<float, kFftLengthBy2Plus1> X2_main;
+  std::array<float, kFftLengthBy2Plus1> X2_shadow_data;
+  std::array<float, kFftLengthBy2Plus1>& X2_shadow =
+      main_filter_.SizePartitions() == shadow_filter_.SizePartitions()
+          ? X2_main
+          : X2_shadow_data;
+  if (main_filter_.SizePartitions() == shadow_filter_.SizePartitions()) {
+    render_buffer.SpectralSum(main_filter_.SizePartitions(), &X2_main);
+  } else if (main_filter_.SizePartitions() > shadow_filter_.SizePartitions()) {
+    render_buffer.SpectralSums(shadow_filter_.SizePartitions(),
+                               main_filter_.SizePartitions(), &X2_shadow,
+                               &X2_main);
+  } else {
+    render_buffer.SpectralSums(main_filter_.SizePartitions(),
+                               shadow_filter_.SizePartitions(), &X2_main,
+                               &X2_shadow);
+  }
+
   // Update the main filter.
-  std::array<float, kFftLengthBy2Plus1> X2;
-  render_buffer.SpectralSum(main_filter_.SizePartitions(), &X2);
   if (!main_filter_adjusted) {
-    G_main_.Compute(X2, render_signal_analyzer, *output, main_filter_,
+    G_main_.Compute(X2_main, render_signal_analyzer, *output, main_filter_,
                     aec_state.SaturatedCapture() || main_saturation, &G);
   } else {
     G.re.fill(0.f);
@@ -244,19 +253,15 @@
        (poor_shadow_filter_counter_ < 10 &&
         !enable_early_shadow_filter_jumpstart_)) ||
       !enable_shadow_filter_jumpstart_) {
-    if (shadow_filter_.SizePartitions() != main_filter_.SizePartitions()) {
-      render_buffer.SpectralSum(shadow_filter_.SizePartitions(), &X2);
-    }
-    G_shadow_.Compute(X2, render_signal_analyzer, E_shadow,
+    G_shadow_.Compute(X2_shadow, render_signal_analyzer, E_shadow,
                       shadow_filter_.SizePartitions(),
                       aec_state.SaturatedCapture() || shadow_saturation, &G);
     shadow_filter_.Adapt(render_buffer, G);
   } else {
     poor_shadow_filter_counter_ = 0;
-
     if (enable_shadow_filter_boosted_jumpstart_) {
       shadow_filter_.SetFilter(main_filter_.GetFilter());
-      G_shadow_.Compute(X2, render_signal_analyzer, E_main,
+      G_shadow_.Compute(X2_shadow, render_signal_analyzer, E_main,
                         shadow_filter_.SizePartitions(),
                         aec_state.SaturatedCapture() || main_saturation, &G);
       shadow_filter_.Adapt(render_buffer, G);
@@ -277,6 +282,11 @@
     std::for_each(e_main.begin(), e_main.end(),
                   [](float& a) { a = rtc::SafeClamp(a, -32768.f, 32767.f); });
   }
+
+  data_dumper_->DumpWav("aec3_main_filter_output", kBlockSize, &e_main[0],
+                        16000, 1);
+  data_dumper_->DumpWav("aec3_shadow_filter_output", kBlockSize, &e_shadow[0],
+                        16000, 1);
 }
 
 void Subtractor::FilterMisadjustmentEstimator::Update(
diff --git a/modules/audio_processing/aec3/subtractor_output_analyzer.cc b/modules/audio_processing/aec3/subtractor_output_analyzer.cc
index 93675f5..3cacb45 100644
--- a/modules/audio_processing/aec3/subtractor_output_analyzer.cc
+++ b/modules/audio_processing/aec3/subtractor_output_analyzer.cc
@@ -36,19 +36,16 @@
   constexpr float kConvergenceThreshold = 50 * 50 * kBlockSize;
   main_filter_converged_ = e2_main < 0.5f * y2 && y2 > kConvergenceThreshold;
   shadow_filter_converged_ =
-      e2_shadow < 0.05 * y2 && y2 > kConvergenceThreshold;
+      e2_shadow < 0.05f * y2 && y2 > kConvergenceThreshold;
   float min_e2 =
       strict_divergence_check_ ? std::min(e2_main, e2_shadow) : e2_main;
   filter_diverged_ = min_e2 > 1.5f * y2 && y2 > 30.f * 30.f * kBlockSize;
-  filter_severely_diverged_ =
-      min_e2 > 1.5f * y2 && y2 > 200.f * 200.f * kBlockSize;
 }
 
 void SubtractorOutputAnalyzer::HandleEchoPathChange() {
   shadow_filter_converged_ = false;
   main_filter_converged_ = false;
   filter_diverged_ = false;
-  filter_severely_diverged_ = false;
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec3/subtractor_output_analyzer.h b/modules/audio_processing/aec3/subtractor_output_analyzer.h
index b9a2445..b59a68e 100644
--- a/modules/audio_processing/aec3/subtractor_output_analyzer.h
+++ b/modules/audio_processing/aec3/subtractor_output_analyzer.h
@@ -30,7 +30,6 @@
   }
 
   bool DivergedFilter() const { return filter_diverged_; }
-  bool SeverelyDivergedFilter() const { return filter_severely_diverged_; }
 
   // Handle echo path change.
   void HandleEchoPathChange();
@@ -40,7 +39,6 @@
   bool shadow_filter_converged_ = false;
   bool main_filter_converged_ = false;
   bool filter_diverged_ = false;
-  bool filter_severely_diverged_ = false;
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec3/subtractor_unittest.cc b/modules/audio_processing/aec3/subtractor_unittest.cc
index 35abf1c..7791805 100644
--- a/modules/audio_processing/aec3/subtractor_unittest.cc
+++ b/modules/audio_processing/aec3/subtractor_unittest.cc
@@ -25,13 +25,15 @@
 
 float RunSubtractorTest(int num_blocks_to_process,
                         int delay_samples,
-                        int filter_length_blocks,
+                        int main_filter_length_blocks,
+                        int shadow_filter_length_blocks,
                         bool uncorrelated_inputs,
                         const std::vector<int>& blocks_with_echo_path_changes) {
   ApmDataDumper data_dumper(42);
   EchoCanceller3Config config;
-  config.filter.main.length_blocks = config.filter.shadow.length_blocks =
-      filter_length_blocks;
+  config.filter.main.length_blocks = main_filter_length_blocks;
+  config.filter.shadow.length_blocks = shadow_filter_length_blocks;
+
   Subtractor subtractor(config, &data_dumper, DetectOptimization());
   absl::optional<DelayEstimate> delay_estimate;
   std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
@@ -160,9 +162,9 @@
     for (size_t delay_samples : {0, 64, 150, 200, 301}) {
       SCOPED_TRACE(ProduceDebugText(delay_samples, filter_length_blocks));
 
-      float echo_to_nearend_power =
-          RunSubtractorTest(400, delay_samples, filter_length_blocks, false,
-                            blocks_with_echo_path_changes);
+      float echo_to_nearend_power = RunSubtractorTest(
+          400, delay_samples, filter_length_blocks, filter_length_blocks, false,
+          blocks_with_echo_path_changes);
 
       // Use different criteria to take overmodelling into account.
       if (filter_length_blocks == 12) {
@@ -174,6 +176,24 @@
   }
 }
 
+// Verifies that the subtractor is able to handle the case when the main filter
+// is longer than the shadow filter.
+TEST(Subtractor, MainFilterLongerThanShadowFilter) {
+  std::vector<int> blocks_with_echo_path_changes;
+  float echo_to_nearend_power =
+      RunSubtractorTest(400, 64, 20, 15, false, blocks_with_echo_path_changes);
+  EXPECT_GT(0.5f, echo_to_nearend_power);
+}
+
+// Verifies that the subtractor is able to handle the case when the shadow
+// filter is longer than the main filter.
+TEST(Subtractor, ShadowFilterLongerThanMainFilter) {
+  std::vector<int> blocks_with_echo_path_changes;
+  float echo_to_nearend_power =
+      RunSubtractorTest(400, 64, 15, 20, false, blocks_with_echo_path_changes);
+  EXPECT_GT(0.5f, echo_to_nearend_power);
+}
+
 // Verifies that the subtractor does not converge on uncorrelated signals.
 TEST(Subtractor, NonConvergenceOnUncorrelatedSignals) {
   std::vector<int> blocks_with_echo_path_changes;
@@ -181,9 +201,9 @@
     for (size_t delay_samples : {0, 64, 150, 200, 301}) {
       SCOPED_TRACE(ProduceDebugText(delay_samples, filter_length_blocks));
 
-      float echo_to_nearend_power =
-          RunSubtractorTest(300, delay_samples, filter_length_blocks, true,
-                            blocks_with_echo_path_changes);
+      float echo_to_nearend_power = RunSubtractorTest(
+          300, delay_samples, filter_length_blocks, filter_length_blocks, true,
+          blocks_with_echo_path_changes);
       EXPECT_NEAR(1.f, echo_to_nearend_power, 0.1);
     }
   }
@@ -198,9 +218,9 @@
     for (size_t delay_samples : {0, 64, 150, 200, 301}) {
       SCOPED_TRACE(ProduceDebugText(delay_samples, filter_length_blocks));
 
-      float echo_to_nearend_power =
-          RunSubtractorTest(100, delay_samples, filter_length_blocks, false,
-                            blocks_with_echo_path_changes);
+      float echo_to_nearend_power = RunSubtractorTest(
+          100, delay_samples, filter_length_blocks, filter_length_blocks, false,
+          blocks_with_echo_path_changes);
       EXPECT_NEAR(1.f, echo_to_nearend_power, 0.0000001f);
     }
   }
diff --git a/modules/audio_processing/aec3/suppression_gain.cc b/modules/audio_processing/aec3/suppression_gain.cc
index 846836d..c389a6a 100644
--- a/modules/audio_processing/aec3/suppression_gain.cc
+++ b/modules/audio_processing/aec3/suppression_gain.cc
@@ -1,4 +1,3 @@
-
 /*
  *  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
  *
@@ -11,10 +10,6 @@
 
 #include "modules/audio_processing/aec3/suppression_gain.h"
 
-#include "typedefs.h"  // NOLINT(build/include)
-#if defined(WEBRTC_ARCH_X86_FAMILY)
-#include <emmintrin.h>
-#endif
 #include <math.h>
 #include <algorithm>
 #include <functional>
@@ -30,11 +25,6 @@
 namespace webrtc {
 namespace {
 
-bool EnableTransparencyImprovements() {
-  return !field_trial::IsEnabled(
-      "WebRTC-Aec3TransparencyImprovementsKillSwitch");
-}
-
 bool EnableNewSuppression() {
   return !field_trial::IsEnabled("WebRTC-Aec3NewSuppressionKillSwitch");
 }
@@ -57,60 +47,6 @@
   (*gain)[kFftLengthBy2] = (*gain)[kFftLengthBy2Minus1];
 }
 
-// Computes the gain to apply for the bands beyond the first band.
-float UpperBandsGain(
-    const absl::optional<int>& narrow_peak_band,
-    bool saturated_echo,
-    const std::vector<std::vector<float>>& render,
-    const std::array<float, kFftLengthBy2Plus1>& low_band_gain) {
-  RTC_DCHECK_LT(0, render.size());
-  if (render.size() == 1) {
-    return 1.f;
-  }
-
-  if (narrow_peak_band &&
-      (*narrow_peak_band > static_cast<int>(kFftLengthBy2Plus1 - 10))) {
-    return 0.001f;
-  }
-
-  constexpr size_t kLowBandGainLimit = kFftLengthBy2 / 2;
-  const float gain_below_8_khz = *std::min_element(
-      low_band_gain.begin() + kLowBandGainLimit, low_band_gain.end());
-
-  // Always attenuate the upper bands when there is saturated echo.
-  if (saturated_echo) {
-    return std::min(0.001f, gain_below_8_khz);
-  }
-
-  // Compute the upper and lower band energies.
-  const auto sum_of_squares = [](float a, float b) { return a + b * b; };
-  const float low_band_energy =
-      std::accumulate(render[0].begin(), render[0].end(), 0.f, sum_of_squares);
-  float high_band_energy = 0.f;
-  for (size_t k = 1; k < render.size(); ++k) {
-    const float energy = std::accumulate(render[k].begin(), render[k].end(),
-                                         0.f, sum_of_squares);
-    high_band_energy = std::max(high_band_energy, energy);
-  }
-
-  // If there is more power in the lower frequencies than the upper frequencies,
-  // or if the power in upper frequencies is low, do not bound the gain in the
-  // upper bands.
-  float anti_howling_gain;
-  constexpr float kThreshold = kBlockSize * 10.f * 10.f / 4.f;
-  if (high_band_energy < std::max(low_band_energy, kThreshold)) {
-    anti_howling_gain = 1.f;
-  } else {
-    // In all other cases, bound the gain for upper frequencies.
-    RTC_DCHECK_LE(low_band_energy, high_band_energy);
-    RTC_DCHECK_NE(0.f, high_band_energy);
-    anti_howling_gain = 0.01f * sqrtf(low_band_energy / high_band_energy);
-  }
-
-  // Choose the gain as the minimum of the lower and upper gains.
-  return std::min(gain_below_8_khz, anti_howling_gain);
-}
-
 // Scales the echo according to assessed audibility at the other end.
 void WeightEchoForAudibility(const EchoCanceller3Config& config,
                              rtc::ArrayView<const float> echo,
@@ -159,7 +95,6 @@
     bool low_noise_render,
     bool saturated_echo,
     bool linear_echo_estimate,
-    bool enable_transparency_improvements,
     const std::array<float, kFftLengthBy2Plus1>& nearend,
     const std::array<float, kFftLengthBy2Plus1>& weighted_echo,
     const std::array<float, kFftLengthBy2Plus1>& masker,
@@ -181,10 +116,7 @@
   RTC_DCHECK_GT(1.f, nearend_masking_margin);
 
   const float masker_margin =
-      linear_echo_estimate
-          ? (enable_transparency_improvements ? config.gain_mask.m0
-                                              : config.gain_mask.m1)
-          : config.gain_mask.m8;
+      linear_echo_estimate ? config.gain_mask.m0 : config.gain_mask.m8;
 
   for (size_t k = 0; k < gain->size(); ++k) {
     // TODO(devicentepena): Experiment by removing the reverberation estimation
@@ -211,54 +143,6 @@
 // TODO(peah): Make adaptive to take the actual filter error into account.
 constexpr size_t kUpperAccurateBandPlus1 = 29;
 
-// Computes the signal output power that masks the echo signal.
-void MaskingPower(const EchoCanceller3Config& config,
-                  bool enable_transparency_improvements,
-                  const std::array<float, kFftLengthBy2Plus1>& nearend,
-                  const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
-                  const std::array<float, kFftLengthBy2Plus1>& last_masker,
-                  const std::array<float, kFftLengthBy2Plus1>& gain,
-                  std::array<float, kFftLengthBy2Plus1>* masker) {
-  if (enable_transparency_improvements) {
-    std::copy(comfort_noise.begin(), comfort_noise.end(), masker->begin());
-    return;
-  }
-
-  // Apply masking over time.
-  float masking_factor = config.gain_mask.temporal_masking_lf;
-  auto limit = config.gain_mask.temporal_masking_lf_bands;
-  std::transform(
-      comfort_noise.begin(), comfort_noise.begin() + limit, last_masker.begin(),
-      masker->begin(),
-      [masking_factor](float a, float b) { return a + masking_factor * b; });
-  masking_factor = config.gain_mask.temporal_masking_hf;
-  std::transform(
-      comfort_noise.begin() + limit, comfort_noise.end(),
-      last_masker.begin() + limit, masker->begin() + limit,
-      [masking_factor](float a, float b) { return a + masking_factor * b; });
-
-  // Apply masking only between lower frequency bands.
-  std::array<float, kFftLengthBy2Plus1> side_band_masker;
-  float max_nearend_after_gain = 0.f;
-  for (size_t k = 0; k < gain.size(); ++k) {
-    const float nearend_after_gain = nearend[k] * gain[k];
-    max_nearend_after_gain =
-        std::max(max_nearend_after_gain, nearend_after_gain);
-    side_band_masker[k] = nearend_after_gain + comfort_noise[k];
-  }
-
-  RTC_DCHECK_LT(kUpperAccurateBandPlus1, gain.size());
-  for (size_t k = 1; k < kUpperAccurateBandPlus1; ++k) {
-    (*masker)[k] += config.gain_mask.m5 *
-                    (side_band_masker[k - 1] + side_band_masker[k + 1]);
-  }
-
-  // Add full-band masking as a minimum value for the masker.
-  const float min_masker = max_nearend_after_gain * config.gain_mask.m6;
-  std::for_each(masker->begin(), masker->end(),
-                [min_masker](float& a) { a = std::max(a, min_masker); });
-}
-
 // Limits the gain in the frequencies for which the adaptive filter has not
 // converged. Currently, these frequencies are not hardcoded to the frequencies
 // which are typically not excited by speech.
@@ -280,6 +164,75 @@
 
 int SuppressionGain::instance_count_ = 0;
 
+float SuppressionGain::UpperBandsGain(
+    const std::array<float, kFftLengthBy2Plus1>& echo_spectrum,
+    const std::array<float, kFftLengthBy2Plus1>& comfort_noise_spectrum,
+    const absl::optional<int>& narrow_peak_band,
+    bool saturated_echo,
+    const std::vector<std::vector<float>>& render,
+    const std::array<float, kFftLengthBy2Plus1>& low_band_gain) const {
+  RTC_DCHECK_LT(0, render.size());
+  if (render.size() == 1) {
+    return 1.f;
+  }
+
+  if (narrow_peak_band &&
+      (*narrow_peak_band > static_cast<int>(kFftLengthBy2Plus1 - 10))) {
+    return 0.001f;
+  }
+
+  constexpr size_t kLowBandGainLimit = kFftLengthBy2 / 2;
+  const float gain_below_8_khz = *std::min_element(
+      low_band_gain.begin() + kLowBandGainLimit, low_band_gain.end());
+
+  // Always attenuate the upper bands when there is saturated echo.
+  if (saturated_echo) {
+    return std::min(0.001f, gain_below_8_khz);
+  }
+
+  // Compute the upper and lower band energies.
+  const auto sum_of_squares = [](float a, float b) { return a + b * b; };
+  const float low_band_energy =
+      std::accumulate(render[0].begin(), render[0].end(), 0.f, sum_of_squares);
+  float high_band_energy = 0.f;
+  for (size_t k = 1; k < render.size(); ++k) {
+    const float energy = std::accumulate(render[k].begin(), render[k].end(),
+                                         0.f, sum_of_squares);
+    high_band_energy = std::max(high_band_energy, energy);
+  }
+
+  // If there is more power in the lower frequencies than the upper frequencies,
+  // or if the power in upper frequencies is low, do not bound the gain in the
+  // upper bands.
+  float anti_howling_gain;
+  constexpr float kThreshold = kBlockSize * 10.f * 10.f / 4.f;
+  if (high_band_energy < std::max(low_band_energy, kThreshold)) {
+    anti_howling_gain = 1.f;
+  } else {
+    // In all other cases, bound the gain for upper frequencies.
+    RTC_DCHECK_LE(low_band_energy, high_band_energy);
+    RTC_DCHECK_NE(0.f, high_band_energy);
+    anti_howling_gain = 0.01f * sqrtf(low_band_energy / high_band_energy);
+  }
+
+  // Bound the upper gain during significant echo activity.
+  auto low_frequency_energy = [](rtc::ArrayView<const float> spectrum) {
+    RTC_DCHECK_LE(16, spectrum.size());
+    return std::accumulate(spectrum.begin() + 1, spectrum.begin() + 16, 0.f);
+  };
+  const float echo_sum = low_frequency_energy(echo_spectrum);
+  const float noise_sum = low_frequency_energy(comfort_noise_spectrum);
+  const auto& cfg = config_.suppressor.high_bands_suppression;
+  float gain_bound = 1.f;
+  if (echo_sum > cfg.enr_threshold * noise_sum &&
+      !dominant_nearend_detector_.IsNearendState()) {
+    gain_bound = cfg.max_gain_during_echo;
+  }
+
+  // Choose the gain as the minimum of the lower and upper gains.
+  return std::min(std::min(gain_below_8_khz, anti_howling_gain), gain_bound);
+}
+
 // Computes the gain to reduce the echo to a non audible level.
 void SuppressionGain::GainToNoAudibleEcho(
     const std::array<float, kFftLengthBy2Plus1>& nearend,
@@ -288,13 +241,16 @@
     const std::array<float, kFftLengthBy2Plus1>& min_gain,
     const std::array<float, kFftLengthBy2Plus1>& max_gain,
     std::array<float, kFftLengthBy2Plus1>* gain) const {
+  const auto& p = dominant_nearend_detector_.IsNearendState() ? nearend_params_
+                                                              : normal_params_;
   for (size_t k = 0; k < gain->size(); ++k) {
     float enr = echo[k] / (nearend[k] + 1.f);  // Echo-to-nearend ratio.
     float emr = echo[k] / (masker[k] + 1.f);   // Echo-to-masker (noise) ratio.
     float g = 1.0f;
-    if (enr > enr_transparent_[k] && emr > emr_transparent_[k]) {
-      g = (enr_suppress_[k] - enr) / (enr_suppress_[k] - enr_transparent_[k]);
-      g = std::max(g, emr_transparent_[k] / emr);
+    if (enr > p.enr_transparent_[k] && emr > p.emr_transparent_[k]) {
+      g = (p.enr_suppress_[k] - enr) /
+          (p.enr_suppress_[k] - p.enr_transparent_[k]);
+      g = std::max(g, p.emr_transparent_[k] / emr);
     }
     (*gain)[k] = std::max(std::min(g, max_gain[k]), min_gain[k]);
   }
@@ -310,6 +266,9 @@
     std::array<float, kFftLengthBy2Plus1>* gain) {
   const bool saturated_echo = aec_state.SaturatedEcho();
   const bool linear_echo_estimate = aec_state.UsableLinearEstimate();
+  const auto& params = dominant_nearend_detector_.IsNearendState()
+                           ? nearend_params_
+                           : normal_params_;
 
   // Weight echo power in terms of audibility. // Precompute 1/weighted echo
   // (note that when the echo is zero, the precomputed value is never used).
@@ -329,16 +288,13 @@
       min_gain[k] = denom > 0.f ? min_echo_power / denom : 1.f;
       min_gain[k] = std::min(min_gain[k], 1.f);
     }
-    if (enable_transparency_improvements_) {
-      for (size_t k = 0; k < 6; ++k) {
-        // Make sure the gains of the low frequencies do not decrease too
-        // quickly after strong nearend.
-        if (last_nearend_[k] > last_echo_[k]) {
-          min_gain[k] =
-              std::max(min_gain[k],
-                       last_gain_[k] * config_.gain_updates.max_dec_factor_lf);
-          min_gain[k] = std::min(min_gain[k], 1.f);
-        }
+    for (size_t k = 0; k < 6; ++k) {
+      // Make sure the gains of the low frequencies do not decrease too
+      // quickly after strong nearend.
+      if (last_nearend_[k] > last_echo_[k]) {
+        min_gain[k] =
+            std::max(min_gain[k], last_gain_[k] * params.max_dec_factor_lf);
+        min_gain[k] = std::min(min_gain[k], 1.f);
       }
     }
   } else {
@@ -348,20 +304,10 @@
   // Compute the maximum gain by limiting the gain increase from the previous
   // gain.
   std::array<float, kFftLengthBy2Plus1> max_gain;
-  if (enable_transparency_improvements_) {
-    for (size_t k = 0; k < gain->size(); ++k) {
-      max_gain[k] =
-          std::min(std::max(last_gain_[k] * config_.gain_updates.max_inc_factor,
-                            config_.gain_updates.floor_first_increase),
-                   1.f);
-    }
-  } else {
-    for (size_t k = 0; k < gain->size(); ++k) {
-      max_gain[k] =
-          std::min(std::max(last_gain_[k] * gain_increase_[k],
-                            config_.gain_updates.floor_first_increase),
-                   1.f);
-    }
+  for (size_t k = 0; k < gain->size(); ++k) {
+    max_gain[k] = std::min(std::max(last_gain_[k] * params.max_inc_factor,
+                                    config_.suppressor.floor_first_increase),
+                           1.f);
   }
 
   // Iteratively compute the gain required to attenuate the echo to a non
@@ -374,12 +320,11 @@
   } else {
     gain->fill(0.f);
     for (int k = 0; k < 2; ++k) {
-      MaskingPower(config_, enable_transparency_improvements_, nearend,
-                   comfort_noise, last_masker_, *gain, &masker);
-      GainToNoAudibleEchoFallback(
-          config_, low_noise_render, saturated_echo, linear_echo_estimate,
-          enable_transparency_improvements_, nearend, weighted_echo, masker,
-          min_gain, max_gain, one_by_weighted_echo, gain);
+      std::copy(comfort_noise.begin(), comfort_noise.end(), masker.begin());
+      GainToNoAudibleEchoFallback(config_, low_noise_render, saturated_echo,
+                                  linear_echo_estimate, nearend, weighted_echo,
+                                  masker, min_gain, max_gain,
+                                  one_by_weighted_echo, gain);
       AdjustForExternalFilters(gain);
     }
   }
@@ -387,23 +332,16 @@
   // Adjust the gain for frequencies which have not yet converged.
   AdjustNonConvergedFrequencies(gain);
 
-  // Update the allowed maximum gain increase.
-  UpdateGainIncrease(low_noise_render, linear_echo_estimate, saturated_echo,
-                     weighted_echo, *gain);
-
   // Store data required for the gain computation of the next block.
   std::copy(nearend.begin(), nearend.end(), last_nearend_.begin());
   std::copy(weighted_echo.begin(), weighted_echo.end(), last_echo_.begin());
   std::copy(gain->begin(), gain->end(), last_gain_.begin());
-  MaskingPower(config_, enable_transparency_improvements_, nearend,
-               comfort_noise, last_masker_, *gain, &last_masker_);
   aec3::VectorMath(optimization_).Sqrt(*gain);
 
   // Debug outputs for the purpose of development and analysis.
   data_dumper_->DumpRaw("aec3_suppressor_min_gain", min_gain);
   data_dumper_->DumpRaw("aec3_suppressor_max_gain", max_gain);
   data_dumper_->DumpRaw("aec3_suppressor_masker", masker);
-  data_dumper_->DumpRaw("aec3_suppressor_last_masker", last_masker_);
 }
 
 SuppressionGain::SuppressionGain(const EchoCanceller3Config& config,
@@ -415,41 +353,18 @@
       config_(config),
       state_change_duration_blocks_(
           static_cast<int>(config_.filter.config_change_duration_blocks)),
-      coherence_gain_(sample_rate_hz,
-                      config_.suppressor.bands_with_reliable_coherence),
-      enable_transparency_improvements_(EnableTransparencyImprovements()),
       enable_new_suppression_(EnableNewSuppression()),
       moving_average_(kFftLengthBy2Plus1,
-                      config.suppressor.nearend_average_blocks) {
+                      config.suppressor.nearend_average_blocks),
+      nearend_params_(config_.suppressor.nearend_tuning),
+      normal_params_(config_.suppressor.normal_tuning),
+      dominant_nearend_detector_(
+          config_.suppressor.dominant_nearend_detection) {
   RTC_DCHECK_LT(0, state_change_duration_blocks_);
   one_by_state_change_duration_blocks_ = 1.f / state_change_duration_blocks_;
   last_gain_.fill(1.f);
-  last_masker_.fill(0.f);
-  gain_increase_.fill(1.f);
   last_nearend_.fill(0.f);
   last_echo_.fill(0.f);
-
-  // Compute per-band masking thresholds.
-  constexpr size_t kLastLfBand = 5;
-  constexpr size_t kFirstHfBand = 8;
-  RTC_DCHECK_LT(kLastLfBand, kFirstHfBand);
-  auto& lf = config.suppressor.mask_lf;
-  auto& hf = config.suppressor.mask_hf;
-  RTC_DCHECK_LT(lf.enr_transparent, lf.enr_suppress);
-  RTC_DCHECK_LT(hf.enr_transparent, hf.enr_suppress);
-  for (size_t k = 0; k < kFftLengthBy2Plus1; k++) {
-    float a;
-    if (k <= kLastLfBand) {
-      a = 0.f;
-    } else if (k < kFirstHfBand) {
-      a = (k - kLastLfBand) / static_cast<float>(kFirstHfBand - kLastLfBand);
-    } else {
-      a = 1.f;
-    }
-    enr_transparent_[k] = (1 - a) * lf.enr_transparent + a * hf.enr_transparent;
-    enr_suppress_[k] = (1 - a) * lf.enr_suppress + a * hf.enr_suppress;
-    emr_transparent_[k] = (1 - a) * lf.emr_transparent + a * hf.emr_transparent;
-  }
 }
 
 SuppressionGain::~SuppressionGain() = default;
@@ -457,9 +372,9 @@
 void SuppressionGain::GetGain(
     const std::array<float, kFftLengthBy2Plus1>& nearend_spectrum,
     const std::array<float, kFftLengthBy2Plus1>& echo_spectrum,
+    const std::array<float, kFftLengthBy2Plus1>& residual_echo_spectrum,
     const std::array<float, kFftLengthBy2Plus1>& comfort_noise_spectrum,
     const FftData& linear_aec_fft,
-    const FftData& render_fft,
     const FftData& capture_fft,
     const RenderSignalAnalyzer& render_signal_analyzer,
     const AecState& aec_state,
@@ -468,28 +383,27 @@
     std::array<float, kFftLengthBy2Plus1>* low_band_gain) {
   RTC_DCHECK(high_bands_gain);
   RTC_DCHECK(low_band_gain);
+  const auto& cfg = config_.suppressor;
+
+  if (cfg.enforce_transparent) {
+    low_band_gain->fill(1.f);
+    *high_bands_gain = cfg.enforce_empty_higher_bands ? 0.f : 1.f;
+    return;
+  }
 
   std::array<float, kFftLengthBy2Plus1> nearend_average;
   moving_average_.Average(nearend_spectrum, nearend_average);
 
+  // Update the state selection.
+  dominant_nearend_detector_.Update(nearend_spectrum, residual_echo_spectrum,
+                                    comfort_noise_spectrum);
+
   // Compute gain for the lower band.
   bool low_noise_render = low_render_detector_.Detect(render);
   const absl::optional<int> narrow_peak_band =
       render_signal_analyzer.NarrowPeakBand();
-  LowerBandGain(low_noise_render, aec_state, nearend_average, echo_spectrum,
-                comfort_noise_spectrum, low_band_gain);
-
-  // Adjust the gain for bands where the coherence indicates not echo.
-  if (config_.suppressor.bands_with_reliable_coherence > 0 &&
-      !enable_transparency_improvements_) {
-    std::array<float, kFftLengthBy2Plus1> G_coherence;
-    coherence_gain_.ComputeGain(linear_aec_fft, render_fft, capture_fft,
-                                G_coherence);
-    for (size_t k = 0; k < config_.suppressor.bands_with_reliable_coherence;
-         ++k) {
-      (*low_band_gain)[k] = std::max((*low_band_gain)[k], G_coherence[k]);
-    }
-  }
+  LowerBandGain(low_noise_render, aec_state, nearend_average,
+                residual_echo_spectrum, comfort_noise_spectrum, low_band_gain);
 
   // Limit the gain of the lower bands during start up and after resets.
   const float gain_upper_bound = aec_state.SuppressionGainLimit();
@@ -500,8 +414,12 @@
   }
 
   // Compute the gain for the upper bands.
-  *high_bands_gain = UpperBandsGain(narrow_peak_band, aec_state.SaturatedEcho(),
-                                    render, *low_band_gain);
+  *high_bands_gain =
+      UpperBandsGain(echo_spectrum, comfort_noise_spectrum, narrow_peak_band,
+                     aec_state.SaturatedEcho(), render, *low_band_gain);
+  if (cfg.enforce_empty_higher_bands) {
+    *high_bands_gain = 0.f;
+  }
 }
 
 void SuppressionGain::SetInitialState(bool state) {
@@ -513,102 +431,6 @@
   }
 }
 
-void SuppressionGain::UpdateGainIncrease(
-    bool low_noise_render,
-    bool linear_echo_estimate,
-    bool saturated_echo,
-    const std::array<float, kFftLengthBy2Plus1>& echo,
-    const std::array<float, kFftLengthBy2Plus1>& new_gain) {
-  float max_inc;
-  float max_dec;
-  float rate_inc;
-  float rate_dec;
-  float min_inc;
-  float min_dec;
-
-  RTC_DCHECK_GE(state_change_duration_blocks_, initial_state_change_counter_);
-  if (initial_state_change_counter_ > 0) {
-    if (--initial_state_change_counter_ == 0) {
-      initial_state_ = false;
-    }
-  }
-  RTC_DCHECK_LE(0, initial_state_change_counter_);
-
-  // EchoCanceller3Config::GainUpdates
-  auto& p = config_.gain_updates;
-  if (!linear_echo_estimate) {
-    max_inc = p.nonlinear.max_inc;
-    max_dec = p.nonlinear.max_dec;
-    rate_inc = p.nonlinear.rate_inc;
-    rate_dec = p.nonlinear.rate_dec;
-    min_inc = p.nonlinear.min_inc;
-    min_dec = p.nonlinear.min_dec;
-  } else if (initial_state_ && !saturated_echo) {
-    if (initial_state_change_counter_ > 0) {
-      float change_factor =
-          initial_state_change_counter_ * one_by_state_change_duration_blocks_;
-
-      auto average = [](float from, float to, float from_weight) {
-        return from * from_weight + to * (1.f - from_weight);
-      };
-
-      max_inc = average(p.initial.max_inc, p.normal.max_inc, change_factor);
-      max_dec = average(p.initial.max_dec, p.normal.max_dec, change_factor);
-      rate_inc = average(p.initial.rate_inc, p.normal.rate_inc, change_factor);
-      rate_dec = average(p.initial.rate_dec, p.normal.rate_dec, change_factor);
-      min_inc = average(p.initial.min_inc, p.normal.min_inc, change_factor);
-      min_dec = average(p.initial.min_dec, p.normal.min_dec, change_factor);
-    } else {
-      max_inc = p.initial.max_inc;
-      max_dec = p.initial.max_dec;
-      rate_inc = p.initial.rate_inc;
-      rate_dec = p.initial.rate_dec;
-      min_inc = p.initial.min_inc;
-      min_dec = p.initial.min_dec;
-    }
-  } else if (low_noise_render) {
-    max_inc = p.low_noise.max_inc;
-    max_dec = p.low_noise.max_dec;
-    rate_inc = p.low_noise.rate_inc;
-    rate_dec = p.low_noise.rate_dec;
-    min_inc = p.low_noise.min_inc;
-    min_dec = p.low_noise.min_dec;
-  } else if (!saturated_echo) {
-    max_inc = p.normal.max_inc;
-    max_dec = p.normal.max_dec;
-    rate_inc = p.normal.rate_inc;
-    rate_dec = p.normal.rate_dec;
-    min_inc = p.normal.min_inc;
-    min_dec = p.normal.min_dec;
-  } else {
-    max_inc = p.saturation.max_inc;
-    max_dec = p.saturation.max_dec;
-    rate_inc = p.saturation.rate_inc;
-    rate_dec = p.saturation.rate_dec;
-    min_inc = p.saturation.min_inc;
-    min_dec = p.saturation.min_dec;
-  }
-
-  for (size_t k = 0; k < new_gain.size(); ++k) {
-    auto increase_update = [](float new_gain, float last_gain,
-                              float current_inc, float max_inc, float min_inc,
-                              float change_rate) {
-      return new_gain > last_gain ? std::min(max_inc, current_inc * change_rate)
-                                  : min_inc;
-    };
-
-    if (echo[k] > last_echo_[k]) {
-      gain_increase_[k] =
-          increase_update(new_gain[k], last_gain_[k], gain_increase_[k],
-                          max_inc, min_inc, rate_inc);
-    } else {
-      gain_increase_[k] =
-          increase_update(new_gain[k], last_gain_[k], gain_increase_[k],
-                          max_dec, min_dec, rate_dec);
-    }
-  }
-}
-
 // Detects when the render signal can be considered to have low power and
 // consist of stationary noise.
 bool SuppressionGain::LowNoiseRenderDetector::Detect(
@@ -628,4 +450,69 @@
   return low_noise_render;
 }
 
+SuppressionGain::DominantNearendDetector::DominantNearendDetector(
+    const EchoCanceller3Config::Suppressor::DominantNearendDetection config)
+    : enr_threshold_(config.enr_threshold),
+      snr_threshold_(config.snr_threshold),
+      hold_duration_(config.hold_duration),
+      trigger_threshold_(config.trigger_threshold) {}
+
+void SuppressionGain::DominantNearendDetector::Update(
+    rtc::ArrayView<const float> nearend_spectrum,
+    rtc::ArrayView<const float> residual_echo_spectrum,
+    rtc::ArrayView<const float> comfort_noise_spectrum) {
+  auto low_frequency_energy = [](rtc::ArrayView<const float> spectrum) {
+    RTC_DCHECK_LE(16, spectrum.size());
+    return std::accumulate(spectrum.begin() + 1, spectrum.begin() + 16, 0.f);
+  };
+  const float ne_sum = low_frequency_energy(nearend_spectrum);
+  const float echo_sum = low_frequency_energy(residual_echo_spectrum);
+  const float noise_sum = low_frequency_energy(comfort_noise_spectrum);
+
+  // Detect strong active nearend if the nearend is sufficiently stronger than
+  // the echo and the nearend noise.
+  if (ne_sum > enr_threshold_ * echo_sum &&
+      ne_sum > snr_threshold_ * noise_sum) {
+    if (++trigger_counter_ >= trigger_threshold_) {
+      // After a period of strong active nearend activity, flag nearend mode.
+      hold_counter_ = hold_duration_;
+      trigger_counter_ = trigger_threshold_;
+    }
+  } else {
+    // Forget previously detected strong active nearend activity.
+    trigger_counter_ = std::max(0, trigger_counter_ - 1);
+  }
+
+  // Remain in any nearend mode for a certain duration.
+  hold_counter_ = std::max(0, hold_counter_ - 1);
+  nearend_state_ = hold_counter_ > 0;
+}
+
+SuppressionGain::GainParameters::GainParameters(
+    const EchoCanceller3Config::Suppressor::Tuning& tuning)
+    : max_inc_factor(tuning.max_inc_factor),
+      max_dec_factor_lf(tuning.max_dec_factor_lf) {
+  // Compute per-band masking thresholds.
+  constexpr size_t kLastLfBand = 5;
+  constexpr size_t kFirstHfBand = 8;
+  RTC_DCHECK_LT(kLastLfBand, kFirstHfBand);
+  auto& lf = tuning.mask_lf;
+  auto& hf = tuning.mask_hf;
+  RTC_DCHECK_LT(lf.enr_transparent, lf.enr_suppress);
+  RTC_DCHECK_LT(hf.enr_transparent, hf.enr_suppress);
+  for (size_t k = 0; k < kFftLengthBy2Plus1; k++) {
+    float a;
+    if (k <= kLastLfBand) {
+      a = 0.f;
+    } else if (k < kFirstHfBand) {
+      a = (k - kLastLfBand) / static_cast<float>(kFirstHfBand - kLastLfBand);
+    } else {
+      a = 1.f;
+    }
+    enr_transparent_[k] = (1 - a) * lf.enr_transparent + a * hf.enr_transparent;
+    enr_suppress_[k] = (1 - a) * lf.enr_suppress + a * hf.enr_suppress;
+    emr_transparent_[k] = (1 - a) * lf.emr_transparent + a * hf.emr_transparent;
+  }
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_processing/aec3/suppression_gain.h b/modules/audio_processing/aec3/suppression_gain.h
index 4c0c85d..b851930 100644
--- a/modules/audio_processing/aec3/suppression_gain.h
+++ b/modules/audio_processing/aec3/suppression_gain.h
@@ -17,7 +17,6 @@
 #include "api/audio/echo_canceller3_config.h"
 #include "modules/audio_processing/aec3/aec3_common.h"
 #include "modules/audio_processing/aec3/aec_state.h"
-#include "modules/audio_processing/aec3/coherence_gain.h"
 #include "modules/audio_processing/aec3/moving_average.h"
 #include "modules/audio_processing/aec3/render_signal_analyzer.h"
 #include "rtc_base/constructormagic.h"
@@ -33,9 +32,9 @@
   void GetGain(
       const std::array<float, kFftLengthBy2Plus1>& nearend_spectrum,
       const std::array<float, kFftLengthBy2Plus1>& echo_spectrum,
+      const std::array<float, kFftLengthBy2Plus1>& residual_echo_spectrum,
       const std::array<float, kFftLengthBy2Plus1>& comfort_noise_spectrum,
       const FftData& linear_aec_fft,
-      const FftData& render_fft,
       const FftData& capture_fft,
       const RenderSignalAnalyzer& render_signal_analyzer,
       const AecState& aec_state,
@@ -47,6 +46,15 @@
   void SetInitialState(bool state);
 
  private:
+  // Computes the gain to apply for the bands beyond the first band.
+  float UpperBandsGain(
+      const std::array<float, kFftLengthBy2Plus1>& echo_spectrum,
+      const std::array<float, kFftLengthBy2Plus1>& comfort_noise_spectrum,
+      const absl::optional<int>& narrow_peak_band,
+      bool saturated_echo,
+      const std::vector<std::vector<float>>& render,
+      const std::array<float, kFftLengthBy2Plus1>& low_band_gain) const;
+
   void GainToNoAudibleEcho(
       const std::array<float, kFftLengthBy2Plus1>& nearend,
       const std::array<float, kFftLengthBy2Plus1>& echo,
@@ -62,14 +70,6 @@
                      const std::array<float, kFftLengthBy2Plus1>& comfort_noise,
                      std::array<float, kFftLengthBy2Plus1>* gain);
 
-  // Limits the gain increase.
-  void UpdateGainIncrease(
-      bool low_noise_render,
-      bool linear_echo_estimate,
-      bool saturated_echo,
-      const std::array<float, kFftLengthBy2Plus1>& echo,
-      const std::array<float, kFftLengthBy2Plus1>& new_gain);
-
   class LowNoiseRenderDetector {
    public:
     bool Detect(const std::vector<std::vector<float>>& render);
@@ -78,6 +78,42 @@
     float average_power_ = 32768.f * 32768.f;
   };
 
+  // Class for selecting whether the suppressor is in the nearend or echo state.
+  class DominantNearendDetector {
+   public:
+    explicit DominantNearendDetector(
+        const EchoCanceller3Config::Suppressor::DominantNearendDetection
+            config);
+
+    // Returns whether the current state is the nearend state.
+    bool IsNearendState() const { return nearend_state_; }
+
+    // Updates the state selection based on latest spectral estimates.
+    void Update(rtc::ArrayView<const float> nearend_spectrum,
+                rtc::ArrayView<const float> residual_echo_spectrum,
+                rtc::ArrayView<const float> comfort_noise_spectrum);
+
+   private:
+    const float enr_threshold_;
+    const float snr_threshold_;
+    const int hold_duration_;
+    const int trigger_threshold_;
+
+    bool nearend_state_ = false;
+    int trigger_counter_ = 0;
+    int hold_counter_ = 0;
+  };
+
+  struct GainParameters {
+    explicit GainParameters(
+        const EchoCanceller3Config::Suppressor::Tuning& tuning);
+    const float max_inc_factor;
+    const float max_dec_factor_lf;
+    std::array<float, kFftLengthBy2Plus1> enr_transparent_;
+    std::array<float, kFftLengthBy2Plus1> enr_suppress_;
+    std::array<float, kFftLengthBy2Plus1> emr_transparent_;
+  };
+
   static int instance_count_;
   std::unique_ptr<ApmDataDumper> data_dumper_;
   const Aec3Optimization optimization_;
@@ -85,20 +121,16 @@
   const int state_change_duration_blocks_;
   float one_by_state_change_duration_blocks_;
   std::array<float, kFftLengthBy2Plus1> last_gain_;
-  std::array<float, kFftLengthBy2Plus1> last_masker_;
-  std::array<float, kFftLengthBy2Plus1> gain_increase_;
   std::array<float, kFftLengthBy2Plus1> last_nearend_;
   std::array<float, kFftLengthBy2Plus1> last_echo_;
-  std::array<float, kFftLengthBy2Plus1> enr_transparent_;
-  std::array<float, kFftLengthBy2Plus1> enr_suppress_;
-  std::array<float, kFftLengthBy2Plus1> emr_transparent_;
   LowNoiseRenderDetector low_render_detector_;
   bool initial_state_ = true;
   int initial_state_change_counter_ = 0;
-  CoherenceGain coherence_gain_;
-  const bool enable_transparency_improvements_;
   const bool enable_new_suppression_;
   aec3::MovingAverage moving_average_;
+  const GainParameters nearend_params_;
+  const GainParameters normal_params_;
+  DominantNearendDetector dominant_nearend_detector_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(SuppressionGain);
 };
diff --git a/modules/audio_processing/aec3/suppression_gain_unittest.cc b/modules/audio_processing/aec3/suppression_gain_unittest.cc
index 2eeb68b..ef31371 100644
--- a/modules/audio_processing/aec3/suppression_gain_unittest.cc
+++ b/modules/audio_processing/aec3/suppression_gain_unittest.cc
@@ -18,7 +18,6 @@
 #include "rtc_base/checks.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace aec3 {
@@ -29,17 +28,16 @@
 TEST(SuppressionGain, NullOutputGains) {
   std::array<float, kFftLengthBy2Plus1> E2;
   std::array<float, kFftLengthBy2Plus1> R2;
+  std::array<float, kFftLengthBy2Plus1> S2;
   std::array<float, kFftLengthBy2Plus1> N2;
   FftData E;
-  FftData X;
   FftData Y;
   E2.fill(0.f);
   R2.fill(0.f);
+  S2.fill(0.1f);
   N2.fill(0.f);
   E.re.fill(0.f);
   E.im.fill(0.f);
-  X.re.fill(0.f);
-  X.im.fill(0.f);
   Y.re.fill(0.f);
   Y.im.fill(0.f);
 
@@ -47,7 +45,7 @@
   AecState aec_state(EchoCanceller3Config{});
   EXPECT_DEATH(
       SuppressionGain(EchoCanceller3Config{}, DetectOptimization(), 16000)
-          .GetGain(E2, R2, N2, E, X, Y,
+          .GetGain(E2, S2, R2, N2, E, Y,
                    RenderSignalAnalyzer((EchoCanceller3Config{})), aec_state,
                    std::vector<std::vector<float>>(
                        3, std::vector<float>(kBlockSize, 0.f)),
@@ -64,6 +62,7 @@
   RenderSignalAnalyzer analyzer(EchoCanceller3Config{});
   float high_bands_gain;
   std::array<float, kFftLengthBy2Plus1> E2;
+  std::array<float, kFftLengthBy2Plus1> S2;
   std::array<float, kFftLengthBy2Plus1> Y2;
   std::array<float, kFftLengthBy2Plus1> R2;
   std::array<float, kFftLengthBy2Plus1> N2;
@@ -71,7 +70,6 @@
   SubtractorOutput output;
   std::array<float, kBlockSize> y;
   FftData E;
-  FftData X;
   FftData Y;
   std::vector<std::vector<float>> x(1, std::vector<float>(kBlockSize, 0.f));
   EchoCanceller3Config config;
@@ -86,13 +84,12 @@
   E2.fill(10.f);
   Y2.fill(10.f);
   R2.fill(0.1f);
+  S2.fill(0.1f);
   N2.fill(100.f);
   output.Reset();
   y.fill(0.f);
   E.re.fill(sqrtf(E2[0]));
   E.im.fill(0.f);
-  X.re.fill(sqrtf(R2[0]));
-  X.im.fill(0.f);
   Y.re.fill(sqrtf(Y2[0]));
   Y.im.fill(0.f);
 
@@ -109,7 +106,7 @@
                      subtractor.FilterImpulseResponse(),
                      *render_delay_buffer->GetRenderBuffer(), E2, Y2, output,
                      y);
-    suppression_gain.GetGain(E2, R2, N2, E, X, Y, analyzer, aec_state, x,
+    suppression_gain.GetGain(E2, S2, R2, N2, E, Y, analyzer, aec_state, x,
                              &high_bands_gain, &g);
   }
   std::for_each(g.begin(), g.end(),
@@ -119,9 +116,9 @@
   E2.fill(100.f);
   Y2.fill(100.f);
   R2.fill(0.1f);
+  S2.fill(0.1f);
   N2.fill(0.f);
   E.re.fill(sqrtf(E2[0]));
-  X.re.fill(sqrtf(R2[0]));
   Y.re.fill(sqrtf(Y2[0]));
 
   for (int k = 0; k < 100; ++k) {
@@ -129,7 +126,7 @@
                      subtractor.FilterImpulseResponse(),
                      *render_delay_buffer->GetRenderBuffer(), E2, Y2, output,
                      y);
-    suppression_gain.GetGain(E2, R2, N2, E, X, Y, analyzer, aec_state, x,
+    suppression_gain.GetGain(E2, S2, R2, N2, E, Y, analyzer, aec_state, x,
                              &high_bands_gain, &g);
   }
   std::for_each(g.begin(), g.end(),
@@ -139,10 +136,9 @@
   E2.fill(1000000000.f);
   R2.fill(10000000000000.f);
   E.re.fill(sqrtf(E2[0]));
-  X.re.fill(sqrtf(R2[0]));
 
   for (int k = 0; k < 10; ++k) {
-    suppression_gain.GetGain(E2, R2, N2, E, X, Y, analyzer, aec_state, x,
+    suppression_gain.GetGain(E2, S2, R2, N2, E, Y, analyzer, aec_state, x,
                              &high_bands_gain, &g);
   }
   std::for_each(g.begin(), g.end(),
diff --git a/modules/audio_processing/aec3/vector_math.h b/modules/audio_processing/aec3/vector_math.h
index 0672b51..255331b 100644
--- a/modules/audio_processing/aec3/vector_math.h
+++ b/modules/audio_processing/aec3/vector_math.h
@@ -11,7 +11,9 @@
 #ifndef MODULES_AUDIO_PROCESSING_AEC3_VECTOR_MATH_H_
 #define MODULES_AUDIO_PROCESSING_AEC3_VECTOR_MATH_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+// Defines WEBRTC_ARCH_X86_FAMILY, used below.
+#include "rtc_base/system/arch.h"
+
 #if defined(WEBRTC_HAS_NEON)
 #include <arm_neon.h>
 #endif
diff --git a/modules/audio_processing/aec3/vector_math_unittest.cc b/modules/audio_processing/aec3/vector_math_unittest.cc
index 6bf60ec..fdab2e5 100644
--- a/modules/audio_processing/aec3/vector_math_unittest.cc
+++ b/modules/audio_processing/aec3/vector_math_unittest.cc
@@ -12,9 +12,9 @@
 
 #include <math.h>
 
+#include "rtc_base/system/arch.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/aec_dump/aec_dump_impl.cc b/modules/audio_processing/aec_dump/aec_dump_impl.cc
index 1b8df40..9e07367 100644
--- a/modules/audio_processing/aec_dump/aec_dump_impl.cc
+++ b/modules/audio_processing/aec_dump/aec_dump_impl.cc
@@ -45,8 +45,6 @@
 
   pb_cfg->set_transient_suppression_enabled(
       config.transient_suppression_enabled);
-  pb_cfg->set_intelligibility_enhancer_enabled(
-      config.intelligibility_enhancer_enabled);
 
   pb_cfg->set_pre_amplifier_enabled(config.pre_amplifier_enabled);
   pb_cfg->set_pre_amplifier_fixed_gain_factor(
@@ -74,7 +72,8 @@
   thread_sync_event.Wait(rtc::Event::kForever);
 }
 
-void AecDumpImpl::WriteInitMessage(const ProcessingConfig& api_format) {
+void AecDumpImpl::WriteInitMessage(const ProcessingConfig& api_format,
+                                   int64_t time_now_ms) {
   auto task = CreateWriteToFileTask();
   auto* event = task->GetEvent();
   event->set_type(audioproc::Event::INIT);
@@ -95,6 +94,7 @@
       static_cast<int32_t>(api_format.reverse_input_stream().num_channels()));
   msg->set_num_reverse_output_channels(
       api_format.reverse_output_stream().num_channels());
+  msg->set_timestamp_ms(time_now_ms);
 
   worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
 }
diff --git a/modules/audio_processing/aec_dump/aec_dump_impl.h b/modules/audio_processing/aec_dump/aec_dump_impl.h
index 1ad4fc8..a5416a0 100644
--- a/modules/audio_processing/aec_dump/aec_dump_impl.h
+++ b/modules/audio_processing/aec_dump/aec_dump_impl.h
@@ -52,8 +52,8 @@
 
   ~AecDumpImpl() override;
 
-  void WriteInitMessage(const ProcessingConfig& api_format) override;
-
+  void WriteInitMessage(const ProcessingConfig& api_format,
+                        int64_t time_now_ms) override;
   void AddCaptureStreamInput(const AudioFrameView<const float>& src) override;
   void AddCaptureStreamOutput(const AudioFrameView<const float>& src) override;
   void AddCaptureStreamInput(const AudioFrame& frame) override;
diff --git a/modules/audio_processing/aec_dump/aec_dump_integration_test.cc b/modules/audio_processing/aec_dump/aec_dump_integration_test.cc
index 53e731a..b6d8756 100644
--- a/modules/audio_processing/aec_dump/aec_dump_integration_test.cc
+++ b/modules/audio_processing/aec_dump/aec_dump_integration_test.cc
@@ -33,7 +33,7 @@
   auto mock_aec_dump =
       absl::make_unique<testing::StrictMock<webrtc::test::MockAecDump>>();
   EXPECT_CALL(*mock_aec_dump.get(), WriteConfig(_)).Times(AtLeast(1));
-  EXPECT_CALL(*mock_aec_dump.get(), WriteInitMessage(_)).Times(AtLeast(1));
+  EXPECT_CALL(*mock_aec_dump.get(), WriteInitMessage(_, _)).Times(AtLeast(1));
   return std::unique_ptr<webrtc::test::MockAecDump>(std::move(mock_aec_dump));
 }
 
diff --git a/modules/audio_processing/aec_dump/aec_dump_unittest.cc b/modules/audio_processing/aec_dump/aec_dump_unittest.cc
index dea149d..75ed529 100644
--- a/modules/audio_processing/aec_dump/aec_dump_unittest.cc
+++ b/modules/audio_processing/aec_dump/aec_dump_unittest.cc
@@ -40,7 +40,8 @@
     aec_dump->WriteConfig(apm_config);
 
     webrtc::ProcessingConfig api_format;
-    aec_dump->WriteInitMessage(api_format);
+    constexpr int64_t kTimeNowMs = 123456789ll;
+    aec_dump->WriteInitMessage(api_format, kTimeNowMs);
   }
   // Remove file after the AecDump d-tor has finished.
   ASSERT_EQ(0, remove(filename.c_str()));
diff --git a/modules/audio_processing/aec_dump/mock_aec_dump.h b/modules/audio_processing/aec_dump/mock_aec_dump.h
index 95f912f..c01de51 100644
--- a/modules/audio_processing/aec_dump/mock_aec_dump.h
+++ b/modules/audio_processing/aec_dump/mock_aec_dump.h
@@ -25,7 +25,8 @@
   MockAecDump();
   virtual ~MockAecDump();
 
-  MOCK_METHOD1(WriteInitMessage, void(const ProcessingConfig& api_format));
+  MOCK_METHOD2(WriteInitMessage,
+               void(const ProcessingConfig& api_format, int64_t time_now_ms));
 
   MOCK_METHOD1(AddCaptureStreamInput,
                void(const AudioFrameView<const float>& src));
diff --git a/modules/audio_processing/aecm/BUILD.gn b/modules/audio_processing/aecm/BUILD.gn
index 54d839e..8250173 100644
--- a/modules/audio_processing/aecm/BUILD.gn
+++ b/modules/audio_processing/aecm/BUILD.gn
@@ -17,7 +17,6 @@
     "echo_control_mobile.h",
   ]
   deps = [
-    "../../..:typedefs",
     "../../../common_audio:common_audio_c",
     "../../../rtc_base:checks",
     "../../../rtc_base:rtc_base_approved",
@@ -31,9 +30,7 @@
     sources += [ "aecm_core_neon.cc" ]
 
     if (current_cpu != "arm64") {
-      # Enable compilation for the NEON instruction set. This is needed
-      # since //build/config/arm.gni only enables NEON for iOS, not Android.
-      # This provides the same functionality as webrtc/build/arm_neon.gypi.
+      # Enable compilation for the NEON instruction set.
       suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
       cflags += [ "-mfpu=neon" ]
     }
diff --git a/modules/audio_processing/aecm/aecm_core.cc b/modules/audio_processing/aecm/aecm_core.cc
index 21a2ba1..0e56b50 100644
--- a/modules/audio_processing/aecm/aecm_core.cc
+++ b/modules/audio_processing/aecm/aecm_core.cc
@@ -25,7 +25,6 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_conversions.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 #ifdef AEC_DEBUG
 FILE* dfile;
diff --git a/modules/audio_processing/aecm/aecm_core.h b/modules/audio_processing/aecm/aecm_core.h
index 3da3bca..1681d2a 100644
--- a/modules/audio_processing/aecm/aecm_core.h
+++ b/modules/audio_processing/aecm/aecm_core.h
@@ -18,7 +18,6 @@
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 }
 #include "modules/audio_processing/aecm/aecm_defines.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 #ifdef _MSC_VER  // visual c++
 #define ALIGN8_BEG __declspec(align(8))
diff --git a/modules/audio_processing/aecm/aecm_core_c.cc b/modules/audio_processing/aecm/aecm_core_c.cc
index b640f1a..905274f 100644
--- a/modules/audio_processing/aecm/aecm_core_c.cc
+++ b/modules/audio_processing/aecm/aecm_core_c.cc
@@ -26,7 +26,6 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/sanitizer.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 // Square root of Hanning window in Q14.
 static const ALIGN8_BEG int16_t WebRtcAecm_kSqrtHanning[] ALIGN8_END = {
diff --git a/modules/audio_processing/aecm/echo_control_mobile.h b/modules/audio_processing/aecm/echo_control_mobile.h
index 576cf19..cea13b8 100644
--- a/modules/audio_processing/aecm/echo_control_mobile.h
+++ b/modules/audio_processing/aecm/echo_control_mobile.h
@@ -11,9 +11,8 @@
 #ifndef MODULES_AUDIO_PROCESSING_AECM_ECHO_CONTROL_MOBILE_H_
 #define MODULES_AUDIO_PROCESSING_AECM_ECHO_CONTROL_MOBILE_H_
 
-#include <stdlib.h>
-
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stddef.h>
+#include <stdint.h>
 
 enum { AecmFalse = 0, AecmTrue };
 
diff --git a/modules/audio_processing/agc/BUILD.gn b/modules/audio_processing/agc/BUILD.gn
index fe2f107..65653a0 100644
--- a/modules/audio_processing/agc/BUILD.gn
+++ b/modules/audio_processing/agc/BUILD.gn
@@ -19,9 +19,9 @@
     ":level_estimation",
     "..:apm_logging",
     "..:gain_control_interface",
-    "../../..:typedefs",
     "../../..:webrtc_common",
     "../../../rtc_base:checks",
+    "../../../rtc_base:gtest_prod",
     "../../../rtc_base:logging",
     "../../../rtc_base:macromagic",
     "../../../rtc_base:safe_minmax",
@@ -41,7 +41,6 @@
     "utility.h",
   ]
   deps = [
-    "../../..:typedefs",
     "../../..:webrtc_common",
     "../../../rtc_base:checks",
     "../../../rtc_base:macromagic",
@@ -66,11 +65,10 @@
   ]
 
   deps = [
-    "../../..:typedefs",
     "../../..:webrtc_common",
     "../../../common_audio",
     "../../../common_audio:common_audio_c",
-    "../../../common_audio:fft4g",
+    "../../../common_audio/third_party/fft4g",
     "../../../rtc_base:checks",
     "../../../rtc_base:rtc_base_approved",
     "../../../system_wrappers:cpu_features_api",
@@ -78,9 +76,7 @@
 
   if (rtc_build_with_neon) {
     if (current_cpu != "arm64") {
-      # Enable compilation for the NEON instruction set. This is needed
-      # since //build/config/arm.gni only enables NEON for iOS, not Android.
-      # This provides the same functionality as webrtc/build/arm_neon.gypi.
+      # Enable compilation for the NEON instruction set.
       suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
       cflags = [ "-mfpu=neon" ]
     }
diff --git a/modules/audio_processing/agc/agc.h b/modules/audio_processing/agc/agc.h
index 98bbf1f..5d34c21 100644
--- a/modules/audio_processing/agc/agc.h
+++ b/modules/audio_processing/agc/agc.h
@@ -14,7 +14,6 @@
 #include <memory>
 
 #include "modules/audio_processing/vad/voice_activity_detector.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/agc/agc_manager_direct.cc b/modules/audio_processing/agc/agc_manager_direct.cc
index 132cf82..dc6d451 100644
--- a/modules/audio_processing/agc/agc_manager_direct.cc
+++ b/modules/audio_processing/agc/agc_manager_direct.cc
@@ -84,6 +84,31 @@
   return new_level;
 }
 
+int InitializeGainControl(GainControl* gain_control,
+                          bool disable_digital_adaptive) {
+  if (gain_control->set_mode(GainControl::kFixedDigital) != 0) {
+    RTC_LOG(LS_ERROR) << "set_mode(GainControl::kFixedDigital) failed.";
+    return -1;
+  }
+  const int target_level_dbfs = disable_digital_adaptive ? 0 : 2;
+  if (gain_control->set_target_level_dbfs(target_level_dbfs) != 0) {
+    RTC_LOG(LS_ERROR) << "set_target_level_dbfs() failed.";
+    return -1;
+  }
+  const int compression_gain_db =
+      disable_digital_adaptive ? 0 : kDefaultCompressionGain;
+  if (gain_control->set_compression_gain_db(compression_gain_db) != 0) {
+    RTC_LOG(LS_ERROR) << "set_compression_gain_db() failed.";
+    return -1;
+  }
+  const bool enable_limiter = !disable_digital_adaptive;
+  if (gain_control->enable_limiter(enable_limiter) != 0) {
+    RTC_LOG(LS_ERROR) << "enable_limiter() failed.";
+    return -1;
+  }
+  return 0;
+}
+
 }  // namespace
 
 // Facility for dumping debug audio files. All methods are no-ops in the
@@ -114,14 +139,16 @@
                                    int startup_min_level,
                                    int clipped_level_min,
                                    bool use_agc2_level_estimation,
-                                   bool use_agc2_digital_adaptive)
-    : AgcManagerDirect(new Agc(),
+                                   bool disable_digital_adaptive)
+    : AgcManagerDirect(use_agc2_level_estimation ? nullptr : new Agc(),
                        gctrl,
                        volume_callbacks,
                        startup_min_level,
                        clipped_level_min,
                        use_agc2_level_estimation,
-                       use_agc2_digital_adaptive) {}
+                       disable_digital_adaptive) {
+  RTC_DCHECK(agc_);
+}
 
 AgcManagerDirect::AgcManagerDirect(Agc* agc,
                                    GainControl* gctrl,
@@ -134,7 +161,9 @@
                        startup_min_level,
                        clipped_level_min,
                        false,
-                       false) {}
+                       false) {
+  RTC_DCHECK(agc_);
+}
 
 AgcManagerDirect::AgcManagerDirect(Agc* agc,
                                    GainControl* gctrl,
@@ -142,7 +171,7 @@
                                    int startup_min_level,
                                    int clipped_level_min,
                                    bool use_agc2_level_estimation,
-                                   bool use_agc2_digital_adaptive)
+                                   bool disable_digital_adaptive)
     : data_dumper_(new ApmDataDumper(instance_counter_)),
       agc_(agc),
       gctrl_(gctrl),
@@ -158,7 +187,7 @@
       check_volume_on_next_process_(true),  // Check at startup.
       startup_(true),
       use_agc2_level_estimation_(use_agc2_level_estimation),
-      use_agc2_digital_adaptive_(use_agc2_digital_adaptive),
+      disable_digital_adaptive_(disable_digital_adaptive),
       startup_min_level_(ClampLevel(startup_min_level)),
       clipped_level_min_(clipped_level_min),
       file_preproc_(new DebugFile("agc_preproc.pcm")),
@@ -170,9 +199,6 @@
   } else {
     RTC_DCHECK(agc);
   }
-  if (use_agc2_digital_adaptive_) {
-    RTC_NOTREACHED() << "Agc2 digital adaptive not implemented.";
-  }
 }
 
 AgcManagerDirect::~AgcManagerDirect() {}
@@ -180,8 +206,8 @@
 int AgcManagerDirect::Initialize() {
   max_level_ = kMaxMicLevel;
   max_compression_gain_ = kMaxCompressionGain;
-  target_compression_ = kDefaultCompressionGain;
-  compression_ = target_compression_;
+  target_compression_ = disable_digital_adaptive_ ? 0 : kDefaultCompressionGain;
+  compression_ = disable_digital_adaptive_ ? 0 : target_compression_;
   compression_accumulator_ = compression_;
   capture_muted_ = false;
   check_volume_on_next_process_ = true;
@@ -190,24 +216,7 @@
 
   data_dumper_->InitiateNewSetOfRecordings();
 
-  if (gctrl_->set_mode(GainControl::kFixedDigital) != 0) {
-    RTC_LOG(LS_ERROR) << "set_mode(GainControl::kFixedDigital) failed.";
-    return -1;
-  }
-  if (gctrl_->set_target_level_dbfs(2) != 0) {
-    RTC_LOG(LS_ERROR) << "set_target_level_dbfs(2) failed.";
-    return -1;
-  }
-  if (gctrl_->set_compression_gain_db(kDefaultCompressionGain) != 0) {
-    RTC_LOG(LS_ERROR)
-        << "set_compression_gain_db(kDefaultCompressionGain) failed.";
-    return -1;
-  }
-  if (gctrl_->enable_limiter(true) != 0) {
-    RTC_LOG(LS_ERROR) << "enable_limiter(true) failed.";
-    return -1;
-  }
-  return 0;
+  return InitializeGainControl(gctrl_, disable_digital_adaptive_);
 }
 
 void AgcManagerDirect::AnalyzePreProcess(int16_t* audio,
@@ -272,7 +281,9 @@
   agc_->Process(audio, length, sample_rate_hz);
 
   UpdateGain();
-  UpdateCompressor();
+  if (!disable_digital_adaptive_) {
+    UpdateCompressor();
+  }
 
   file_postproc_->Write(audio, length);
 
@@ -437,10 +448,19 @@
     // level_ was updated by SetLevel; log the new value.
     RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.AgcSetLevel", level_, 1,
                                 kMaxMicLevel, 50);
+    // Reset the AGC since the level has changed.
+    agc_->Reset();
   }
 }
 
 void AgcManagerDirect::UpdateCompressor() {
+  calls_since_last_gain_log_++;
+  if (calls_since_last_gain_log_ == 100) {
+    calls_since_last_gain_log_ = 0;
+    RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.Agc.DigitalGainApplied",
+                                compression_, 0, kMaxCompressionGain,
+                                kMaxCompressionGain + 1);
+  }
   if (compression_ == target_compression_) {
     return;
   }
@@ -465,6 +485,9 @@
 
   // Set the new compression gain.
   if (new_compression != compression_) {
+    RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.Agc.DigitalGainUpdated",
+                                new_compression, 0, kMaxCompressionGain,
+                                kMaxCompressionGain + 1);
     compression_ = new_compression;
     compression_accumulator_ = new_compression;
     if (gctrl_->set_compression_gain_db(compression_) != 0) {
diff --git a/modules/audio_processing/agc/agc_manager_direct.h b/modules/audio_processing/agc/agc_manager_direct.h
index de3d1cb..cbfd6a1 100644
--- a/modules/audio_processing/agc/agc_manager_direct.h
+++ b/modules/audio_processing/agc/agc_manager_direct.h
@@ -16,6 +16,7 @@
 #include "modules/audio_processing/agc/agc.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/constructormagic.h"
+#include "rtc_base/gtest_prod_util.h"
 
 namespace webrtc {
 
@@ -50,7 +51,7 @@
                    int startup_min_level,
                    int clipped_level_min,
                    bool use_agc2_level_estimation,
-                   bool use_agc2_digital_adaptive);
+                   bool disable_digital_adaptive);
 
   ~AgcManagerDirect();
 
@@ -71,6 +72,9 @@
  private:
   friend class AgcManagerDirectTest;
 
+  FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest,
+                           DisableDigitalDisablesDigital);
+
   // Dependency injection for testing. Don't delete |agc| as the memory is owned
   // by the manager.
   AgcManagerDirect(Agc* agc,
@@ -86,7 +90,7 @@
                    int startup_min_level,
                    int clipped_level_min,
                    bool use_agc2_level_estimation,
-                   bool use_agc2_digital_adaptive);
+                   bool disable_digital_adaptive);
 
   // Sets a new microphone level, after first checking that it hasn't been
   // updated by the user, in which case no action is taken.
@@ -119,9 +123,10 @@
   bool check_volume_on_next_process_;
   bool startup_;
   const bool use_agc2_level_estimation_;
-  const bool use_agc2_digital_adaptive_;
+  const bool disable_digital_adaptive_;
   int startup_min_level_;
   const int clipped_level_min_;
+  int calls_since_last_gain_log_ = 0;
 
   std::unique_ptr<DebugFile> file_preproc_;
   std::unique_ptr<DebugFile> file_postproc_;
diff --git a/modules/audio_processing/agc/agc_manager_direct_unittest.cc b/modules/audio_processing/agc/agc_manager_direct_unittest.cc
index 1a03402..73ea55d 100644
--- a/modules/audio_processing/agc/agc_manager_direct_unittest.cc
+++ b/modules/audio_processing/agc/agc_manager_direct_unittest.cc
@@ -17,6 +17,7 @@
 #include "test/gtest.h"
 
 using ::testing::_;
+using ::testing::AtLeast;
 using ::testing::DoAll;
 using ::testing::Return;
 using ::testing::SetArgPointee;
@@ -53,7 +54,7 @@
   }
 
   void FirstProcess() {
-    EXPECT_CALL(*agc_, Reset());
+    EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
     EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false));
     CallProcess(1);
   }
@@ -366,11 +367,14 @@
   // to SetMicVolume.
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
+
+  // When the analog volume changes, the gain controller is reset.
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
+
   // GetMicVolume returns a value outside of the quantization slack, indicating
   // a manual volume change.
+  ASSERT_NE(volume_.GetMicVolume(), 154);
   volume_.SetMicVolume(154);
-  // SetMicVolume should not be called.
-  EXPECT_CALL(*agc_, Reset()).Times(1);
   CallProcess(1);
   EXPECT_EQ(154, volume_.GetMicVolume());
 
@@ -378,7 +382,7 @@
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
   volume_.SetMicVolume(100);
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallProcess(1);
   EXPECT_EQ(100, volume_.GetMicVolume());
 
@@ -407,7 +411,7 @@
   EXPECT_CALL(*agc_, GetRmsErrorDb(_))
       .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
   volume_.SetMicVolume(50);
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallProcess(1);
   EXPECT_EQ(50, volume_.GetMicVolume());
 
@@ -426,7 +430,7 @@
       .WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
   // Don't set to zero, which will cause AGC to take no action.
   volume_.SetMicVolume(1);
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallProcess(1);
   EXPECT_EQ(1, volume_.GetMicVolume());
 
@@ -467,7 +471,7 @@
   SetVolumeAndProcess(255);
 
   EXPECT_CALL(*agc_, AnalyzePreproc(_, _)).WillOnce(Return(0.101));
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1);
   EXPECT_EQ(240, volume_.GetMicVolume());
 }
@@ -477,7 +481,7 @@
 
   EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
       .WillOnce(Return(kAboveClippedThreshold));
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1);
   EXPECT_EQ(240, volume_.GetMicVolume());
 
@@ -489,7 +493,7 @@
 
   EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
       .WillOnce(Return(kAboveClippedThreshold));
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1);
   EXPECT_EQ(225, volume_.GetMicVolume());
 }
@@ -499,7 +503,7 @@
 
   EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
       .WillOnce(Return(kAboveClippedThreshold));
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1);
   EXPECT_EQ(kClippedMin, volume_.GetMicVolume());
 
@@ -515,7 +519,7 @@
 
   EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
       .WillOnce(Return(kAboveClippedThreshold));
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1);
   EXPECT_EQ(240, volume_.GetMicVolume());
 
@@ -530,7 +534,7 @@
 
   EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
       .WillOnce(Return(kAboveClippedThreshold));
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1);
   EXPECT_EQ(185, volume_.GetMicVolume());
 
@@ -547,7 +551,7 @@
 
   EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
       .WillOnce(Return(kAboveClippedThreshold));
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1);
   EXPECT_EQ(195, volume_.GetMicVolume());
 
@@ -576,14 +580,14 @@
   CallPreProc(300);
   EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
       .WillOnce(Return(kAboveClippedThreshold));
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1);
   EXPECT_EQ(180, volume_.GetMicVolume());
 
   CallPreProc(300);
   EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
       .WillOnce(Return(kAboveClippedThreshold));
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1);
   EXPECT_EQ(kClippedMin, volume_.GetMicVolume());
 
@@ -628,7 +632,7 @@
 
   EXPECT_CALL(*agc_, AnalyzePreproc(_, _))
       .WillOnce(Return(kAboveClippedThreshold));
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallPreProc(1);
   EXPECT_EQ(210, volume_.GetMicVolume());
 
@@ -637,7 +641,7 @@
       .WillOnce(DoAll(SetArgPointee<0>(14), Return(true)));
   // User changed the volume.
   volume_.SetMicVolume(250);
-  EXPECT_CALL(*agc_, Reset()).Times(1);
+  EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
   CallProcess(1);
   EXPECT_EQ(250, volume_.GetMicVolume());
 
@@ -679,4 +683,22 @@
   EXPECT_EQ(0, volume_.GetMicVolume());
 }
 
+TEST(AgcManagerDirectStandaloneTest, DisableDigitalDisablesDigital) {
+  auto agc = std::unique_ptr<Agc>(new testing::NiceMock<MockAgc>());
+  test::MockGainControl gctrl;
+  TestVolumeCallbacks volume;
+
+  AgcManagerDirect manager(agc.release(), &gctrl, &volume, kInitialVolume,
+                           kClippedMin,
+                           /* use agc2 level estimation */ false,
+                           /* disable digital adaptive */ true);
+
+  EXPECT_CALL(gctrl, set_mode(GainControl::kFixedDigital));
+  EXPECT_CALL(gctrl, set_target_level_dbfs(0));
+  EXPECT_CALL(gctrl, set_compression_gain_db(0));
+  EXPECT_CALL(gctrl, enable_limiter(false));
+
+  manager.Initialize();
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc/legacy/analog_agc.h b/modules/audio_processing/agc/legacy/analog_agc.h
index 1fed377..619d95a 100644
--- a/modules/audio_processing/agc/legacy/analog_agc.h
+++ b/modules/audio_processing/agc/legacy/analog_agc.h
@@ -18,7 +18,6 @@
 
 #include "modules/audio_processing/agc/legacy/digital_agc.h"
 #include "modules/audio_processing/agc/legacy/gain_control.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 /* Analog Automatic Gain Control variables:
  * Constant declarations (inner limits inside which no changes are done)
diff --git a/modules/audio_processing/agc/legacy/digital_agc.c b/modules/audio_processing/agc/legacy/digital_agc.c
index 7801196..d1c30bd 100644
--- a/modules/audio_processing/agc/legacy/digital_agc.c
+++ b/modules/audio_processing/agc/legacy/digital_agc.c
@@ -583,6 +583,7 @@
   int16_t buf2[4];
   int16_t HPstate;
   int16_t zeros, dB;
+  int64_t tmp64;
 
   // process in 10 sub frames of 1 ms (to save on memory)
   nrg = 0;
@@ -688,17 +689,17 @@
   tmp32 = WebRtcSpl_DivW32W16(tmp32, state->stdLongTerm);
   tmpU16 = (13 << 12);
   tmp32b = WEBRTC_SPL_MUL_16_U16(state->logRatio, tmpU16);
-  tmp32 += tmp32b >> 10;
-
-  state->logRatio = (int16_t)(tmp32 >> 6);
+  tmp64 = tmp32;
+  tmp64 += tmp32b >> 10;
+  tmp64 >>= 6;
 
   // limit
-  if (state->logRatio > 2048) {
-    state->logRatio = 2048;
+  if (tmp64 > 2048) {
+    tmp64 = 2048;
+  } else if (tmp64 < -2048) {
+    tmp64 = -2048;
   }
-  if (state->logRatio < -2048) {
-    state->logRatio = -2048;
-  }
+  state->logRatio = (int16_t)tmp64;
 
   return state->logRatio;  // Q10
 }
diff --git a/modules/audio_processing/agc/legacy/digital_agc.h b/modules/audio_processing/agc/legacy/digital_agc.h
index af6cf48..f086294 100644
--- a/modules/audio_processing/agc/legacy/digital_agc.h
+++ b/modules/audio_processing/agc/legacy/digital_agc.h
@@ -15,7 +15,6 @@
 #include <stdio.h>
 #endif
 #include "common_audio/signal_processing/include/signal_processing_library.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 // the 32 most significant bits of A(19) * B(26) >> 13
 #define AGC_MUL32(A, B) (((B) >> 13) * (A) + (((0x00001FFF & (B)) * (A)) >> 13))
diff --git a/modules/audio_processing/agc/legacy/gain_control.h b/modules/audio_processing/agc/legacy/gain_control.h
index 05b7ff6..a0ac96d 100644
--- a/modules/audio_processing/agc/legacy/gain_control.h
+++ b/modules/audio_processing/agc/legacy/gain_control.h
@@ -11,8 +11,6 @@
 #ifndef MODULES_AUDIO_PROCESSING_AGC_LEGACY_GAIN_CONTROL_H_
 #define MODULES_AUDIO_PROCESSING_AGC_LEGACY_GAIN_CONTROL_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 // Errors
 #define AGC_UNSPECIFIED_ERROR 18000
 #define AGC_UNSUPPORTED_FUNCTION_ERROR 18001
diff --git a/modules/audio_processing/agc/loudness_histogram.h b/modules/audio_processing/agc/loudness_histogram.h
index ab45276..d8ad751 100644
--- a/modules/audio_processing/agc/loudness_histogram.h
+++ b/modules/audio_processing/agc/loudness_histogram.h
@@ -15,8 +15,6 @@
 
 #include <memory>
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 namespace webrtc {
 
 // This class implements the histogram of loudness with circular buffers so that
diff --git a/modules/audio_processing/agc/mock_agc.h b/modules/audio_processing/agc/mock_agc.h
index ff1e9fd..4297e2a 100644
--- a/modules/audio_processing/agc/mock_agc.h
+++ b/modules/audio_processing/agc/mock_agc.h
@@ -19,6 +19,7 @@
 
 class MockAgc : public Agc {
  public:
+  virtual ~MockAgc() {}
   MOCK_METHOD2(AnalyzePreproc, float(const int16_t* audio, size_t length));
   MOCK_METHOD3(Process,
                void(const int16_t* audio, size_t length, int sample_rate_hz));
diff --git a/modules/audio_processing/agc2/BUILD.gn b/modules/audio_processing/agc2/BUILD.gn
index dcdc7fa..45ef968 100644
--- a/modules/audio_processing/agc2/BUILD.gn
+++ b/modules/audio_processing/agc2/BUILD.gn
@@ -29,7 +29,6 @@
     ":rnn_vad_with_level",
     "..:apm_logging",
     "..:audio_frame_view",
-    "../../..:typedefs",
     "../../../api:array_view",
     "../../../common_audio",
     "../../../rtc_base:checks",
@@ -66,6 +65,7 @@
     "../../../rtc_base:checks",
     "../../../rtc_base:rtc_base_approved",
     "../../../rtc_base:safe_minmax",
+    "../../../system_wrappers:metrics_api",
   ]
 }
 
@@ -165,7 +165,7 @@
     "../../../api:array_view",
     "../../../common_audio",
     "../../../rtc_base:checks",
-    "rnn_vad:lib",
+    "rnn_vad",
   ]
 }
 
@@ -232,6 +232,7 @@
     "../../../rtc_base:checks",
     "../../../rtc_base:rtc_base_approved",
     "../../../rtc_base:rtc_base_tests_utils",
+    "../../../system_wrappers:metrics_default",
     "//third_party/abseil-cpp/absl/memory",
   ]
 }
diff --git a/modules/audio_processing/agc2/adaptive_agc.cc b/modules/audio_processing/agc2/adaptive_agc.cc
index 7b24244..805be0c 100644
--- a/modules/audio_processing/agc2/adaptive_agc.cc
+++ b/modules/audio_processing/agc2/adaptive_agc.cc
@@ -30,14 +30,6 @@
 AdaptiveAgc::~AdaptiveAgc() = default;
 
 void AdaptiveAgc::Process(AudioFrameView<float> float_frame) {
-  // TODO(webrtc:7494): Remove this loop. Remove the vectors from
-  // VadWithData after we move to a VAD that outputs an estimate every
-  // kFrameDurationMs ms.
-  //
-  // Some VADs are 'bursty'. They return several estimates for some
-  // frames, and no estimates for other frames. We want to feed all to
-  // the level estimator, but only care about the last level it
-  // produces.
   const VadWithLevel::LevelAndProbability vad_result =
       vad_.AnalyzeFrame(float_frame);
   apm_data_dumper_->DumpRaw("agc2_vad_probability",
@@ -58,4 +50,8 @@
                         float_frame);
 }
 
+void AdaptiveAgc::Reset() {
+  speech_level_estimator_.Reset();
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/adaptive_agc.h b/modules/audio_processing/agc2/adaptive_agc.h
index dabe783..8f5efec 100644
--- a/modules/audio_processing/agc2/adaptive_agc.h
+++ b/modules/audio_processing/agc2/adaptive_agc.h
@@ -25,9 +25,11 @@
 class AdaptiveAgc {
  public:
   explicit AdaptiveAgc(ApmDataDumper* apm_data_dumper);
-  void Process(AudioFrameView<float> float_frame);
   ~AdaptiveAgc();
 
+  void Process(AudioFrameView<float> float_frame);
+  void Reset();
+
  private:
   AdaptiveModeLevelEstimator speech_level_estimator_;
   VadWithLevel vad_;
diff --git a/modules/audio_processing/agc2/adaptive_digital_gain_applier.cc b/modules/audio_processing/agc2/adaptive_digital_gain_applier.cc
index ca6ec5d..f5342df 100644
--- a/modules/audio_processing/agc2/adaptive_digital_gain_applier.cc
+++ b/modules/audio_processing/agc2/adaptive_digital_gain_applier.cc
@@ -16,6 +16,7 @@
 #include "modules/audio_processing/agc2/agc2_common.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/numerics/safe_minmax.h"
+#include "system_wrappers/include/metrics.h"
 
 namespace webrtc {
 namespace {
@@ -76,6 +77,15 @@
     float input_noise_level_dbfs,
     const VadWithLevel::LevelAndProbability vad_result,
     AudioFrameView<float> float_frame) {
+  calls_since_last_gain_log_++;
+  if (calls_since_last_gain_log_ == 100) {
+    calls_since_last_gain_log_ = 0;
+    RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.Agc2.DigitalGainApplied",
+                                last_gain_db_, 0, kMaxGainDb, kMaxGainDb + 1);
+    RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.Agc2.EstimatedNoiseLevel",
+                                input_noise_level_dbfs, 0, 100, 101);
+  }
+
   input_level_dbfs = std::min(input_level_dbfs, 0.f);
 
   RTC_DCHECK_GE(input_level_dbfs, -150.f);
diff --git a/modules/audio_processing/agc2/adaptive_digital_gain_applier.h b/modules/audio_processing/agc2/adaptive_digital_gain_applier.h
index 31f87f1..a3a1ff5 100644
--- a/modules/audio_processing/agc2/adaptive_digital_gain_applier.h
+++ b/modules/audio_processing/agc2/adaptive_digital_gain_applier.h
@@ -32,6 +32,7 @@
  private:
   float last_gain_db_ = kInitialAdaptiveDigitalGainDb;
   GainApplier gain_applier_;
+  int calls_since_last_gain_log_ = 0;
 
   // For some combinations of noise and speech probability, increasing
   // the level is not allowed. Since we may get VAD results in bursts,
diff --git a/modules/audio_processing/agc2/fixed_digital_level_estimator.cc b/modules/audio_processing/agc2/fixed_digital_level_estimator.cc
index 9a1fd28..39cc764 100644
--- a/modules/audio_processing/agc2/fixed_digital_level_estimator.cc
+++ b/modules/audio_processing/agc2/fixed_digital_level_estimator.cc
@@ -17,11 +17,17 @@
 #include "rtc_base/checks.h"
 
 namespace webrtc {
+namespace {
+
+constexpr float kInitialFilterStateLevel = 0.f;
+
+}  // namespace
 
 FixedDigitalLevelEstimator::FixedDigitalLevelEstimator(
     size_t sample_rate_hz,
     ApmDataDumper* apm_data_dumper)
-    : apm_data_dumper_(apm_data_dumper) {
+    : apm_data_dumper_(apm_data_dumper),
+      filter_state_level_(kInitialFilterStateLevel) {
   SetSampleRate(sample_rate_hz);
   CheckParameterCombination();
   RTC_DCHECK(apm_data_dumper_);
@@ -97,4 +103,9 @@
       rtc::CheckedDivExact(samples_in_frame_, kSubFramesInFrame);
   CheckParameterCombination();
 }
+
+void FixedDigitalLevelEstimator::Reset() {
+  filter_state_level_ = kInitialFilterStateLevel;
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/fixed_digital_level_estimator.h b/modules/audio_processing/agc2/fixed_digital_level_estimator.h
index b0e7a6d..4907ec7 100644
--- a/modules/audio_processing/agc2/fixed_digital_level_estimator.h
+++ b/modules/audio_processing/agc2/fixed_digital_level_estimator.h
@@ -45,11 +45,14 @@
   // value passed to the constructor. The class is not thread safe.
   void SetSampleRate(size_t sample_rate_hz);
 
+  // Resets the level estimator internal state.
+  void Reset();
+
  private:
   void CheckParameterCombination();
 
   ApmDataDumper* const apm_data_dumper_ = nullptr;
-  float filter_state_level_ = 0.f;
+  float filter_state_level_;
   size_t samples_in_frame_;
   size_t samples_in_sub_frame_;
 
diff --git a/modules/audio_processing/agc2/fixed_gain_controller.cc b/modules/audio_processing/agc2/fixed_gain_controller.cc
index e59ae34..d49d181 100644
--- a/modules/audio_processing/agc2/fixed_gain_controller.cc
+++ b/modules/audio_processing/agc2/fixed_gain_controller.cc
@@ -34,8 +34,17 @@
 }  // namespace
 
 FixedGainController::FixedGainController(ApmDataDumper* apm_data_dumper)
+    : FixedGainController(apm_data_dumper, "Agc2") {}
+
+FixedGainController::FixedGainController(ApmDataDumper* apm_data_dumper,
+                                         std::string histogram_name_prefix)
     : apm_data_dumper_(apm_data_dumper),
-      gain_curve_applier_(48000, apm_data_dumper_) {}
+      gain_curve_applier_(48000, apm_data_dumper_, histogram_name_prefix) {
+  // Do update histograms.xml when adding name prefixes.
+  RTC_DCHECK(histogram_name_prefix == "" || histogram_name_prefix == "Test" ||
+             histogram_name_prefix == "AudioMixer" ||
+             histogram_name_prefix == "Agc2");
+}
 
 void FixedGainController::SetGain(float gain_to_apply_db) {
   // Changes in gain_to_apply_ cause discontinuities. We assume
@@ -45,9 +54,15 @@
   // The gain
   RTC_DCHECK_LE(-50.f, gain_to_apply_db);
   RTC_DCHECK_LE(gain_to_apply_db, 50.f);
+  const float previous_applied_gained = gain_to_apply_;
   gain_to_apply_ = DbToRatio(gain_to_apply_db);
   RTC_DCHECK_LT(0.f, gain_to_apply_);
   RTC_DLOG(LS_INFO) << "Gain to apply: " << gain_to_apply_db << " db.";
+  // Reset the gain curve applier to quickly react on abrupt level changes
+  // caused by large changes of the applied gain.
+  if (previous_applied_gained != gain_to_apply_) {
+    gain_curve_applier_.Reset();
+  }
 }
 
 void FixedGainController::SetSampleRate(size_t sample_rate_hz) {
diff --git a/modules/audio_processing/agc2/fixed_gain_controller.h b/modules/audio_processing/agc2/fixed_gain_controller.h
index 2b92cfc..a41a13f 100644
--- a/modules/audio_processing/agc2/fixed_gain_controller.h
+++ b/modules/audio_processing/agc2/fixed_gain_controller.h
@@ -20,6 +20,8 @@
 class FixedGainController {
  public:
   explicit FixedGainController(ApmDataDumper* apm_data_dumper);
+  FixedGainController(ApmDataDumper* apm_data_dumper,
+                      std::string histogram_name_prefix);
 
   void Process(AudioFrameView<float> signal);
 
diff --git a/modules/audio_processing/agc2/fixed_gain_controller_unittest.cc b/modules/audio_processing/agc2/fixed_gain_controller_unittest.cc
index 72bb409..bd7c356 100644
--- a/modules/audio_processing/agc2/fixed_gain_controller_unittest.cc
+++ b/modules/audio_processing/agc2/fixed_gain_controller_unittest.cc
@@ -16,6 +16,7 @@
 #include "modules/audio_processing/agc2/vector_float_frame.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/gunit.h"
+#include "system_wrappers/include/metrics_default.h"
 
 namespace webrtc {
 namespace {
@@ -45,24 +46,38 @@
       vectors_with_float_frame_last.float_frame_view().channel(0);
   return channel[channel.size() - 1];
 }
-ApmDataDumper test_data_dumper(0);
+
+std::unique_ptr<ApmDataDumper> GetApmDataDumper() {
+  return absl::make_unique<ApmDataDumper>(0);
+}
 
 std::unique_ptr<FixedGainController> CreateFixedGainController(
     float gain_to_apply,
-    size_t rate) {
+    size_t rate,
+    std::string histogram_name_prefix,
+    ApmDataDumper* test_data_dumper) {
   std::unique_ptr<FixedGainController> fgc =
-      absl::make_unique<FixedGainController>(&test_data_dumper);
+      absl::make_unique<FixedGainController>(test_data_dumper,
+                                             histogram_name_prefix);
   fgc->SetGain(gain_to_apply);
   fgc->SetSampleRate(rate);
   return fgc;
 }
 
+std::unique_ptr<FixedGainController> CreateFixedGainController(
+    float gain_to_apply,
+    size_t rate,
+    ApmDataDumper* test_data_dumper) {
+  return CreateFixedGainController(gain_to_apply, rate, "", test_data_dumper);
+}
+
 }  // namespace
 
 TEST(AutomaticGainController2FixedDigital, CreateUse) {
   const int kSampleRate = 44000;
-  std::unique_ptr<FixedGainController> fixed_gc =
-      CreateFixedGainController(kGainToApplyDb, kSampleRate);
+  auto test_data_dumper = GetApmDataDumper();
+  std::unique_ptr<FixedGainController> fixed_gc = CreateFixedGainController(
+      kGainToApplyDb, kSampleRate, test_data_dumper.get());
   VectorFloatFrame vectors_with_float_frame(
       1, rtc::CheckedDivExact(kSampleRate, 100), kInputLevelLinear);
   auto float_frame = vectors_with_float_frame.float_frame_view();
@@ -76,13 +91,15 @@
   const size_t kNumFrames = 5;
   const size_t kSampleRate = 42000;
 
+  auto test_data_dumper = GetApmDataDumper();
+
   const auto gains_no_saturation =
       test::LinSpace(0.1, test::kLimiterMaxInputLevelDbFs - 0.01, 10);
   for (const auto gain_db : gains_no_saturation) {
     // Since |test::kLimiterMaxInputLevelDbFs| > |gain_db|, the
     // limiter will not saturate the signal.
     std::unique_ptr<FixedGainController> fixed_gc_no_saturation =
-        CreateFixedGainController(gain_db, kSampleRate);
+        CreateFixedGainController(gain_db, kSampleRate, test_data_dumper.get());
 
     // Saturation not expected.
     SCOPED_TRACE(std::to_string(gain_db));
@@ -98,7 +115,7 @@
     // Since |test::kLimiterMaxInputLevelDbFs| < |gain|, the limiter
     // will saturate the signal.
     std::unique_ptr<FixedGainController> fixed_gc_saturation =
-        CreateFixedGainController(gain_db, kSampleRate);
+        CreateFixedGainController(gain_db, kSampleRate, test_data_dumper.get());
 
     // Saturation expected.
     SCOPED_TRACE(std::to_string(gain_db));
@@ -115,13 +132,15 @@
   const size_t kNumFrames = 5;
   const size_t kSampleRate = 8000;
 
+  auto test_data_dumper = GetApmDataDumper();
+
   const auto gains_no_saturation =
       test::LinSpace(0.1, test::kLimiterMaxInputLevelDbFs - 0.01, 10);
   for (const auto gain_db : gains_no_saturation) {
     // Since |gain| > |test::kLimiterMaxInputLevelDbFs|, the limiter will
     // not saturate the signal.
     std::unique_ptr<FixedGainController> fixed_gc_no_saturation =
-        CreateFixedGainController(gain_db, kSampleRate);
+        CreateFixedGainController(gain_db, kSampleRate, test_data_dumper.get());
 
     // Saturation not expected.
     SCOPED_TRACE(std::to_string(gain_db));
@@ -137,7 +156,7 @@
     // Singe |gain| < |test::kLimiterMaxInputLevelDbFs|, the limiter will
     // saturate the signal.
     std::unique_ptr<FixedGainController> fixed_gc_saturation =
-        CreateFixedGainController(gain_db, kSampleRate);
+        CreateFixedGainController(gain_db, kSampleRate, test_data_dumper.get());
 
     // Saturation expected.
     SCOPED_TRACE(std::to_string(gain_db));
@@ -155,8 +174,10 @@
   constexpr float kGainDbNoChange = 0.f;
   constexpr float kGainDbFactor10 = 20.f;
 
+  auto test_data_dumper = GetApmDataDumper();
   std::unique_ptr<FixedGainController> fixed_gc_no_saturation =
-      CreateFixedGainController(kGainDbNoChange, kSampleRate);
+      CreateFixedGainController(kGainDbNoChange, kSampleRate,
+                                test_data_dumper.get());
 
   // Signal level is unchanged with 0 db gain.
   EXPECT_FLOAT_EQ(
@@ -173,4 +194,65 @@
       kInputLevel * 10);
 }
 
+TEST(AutomaticGainController2FixedDigital,
+     SetGainShouldBeFastAndTimeInvariant) {
+  // Number of frames required for the fixed gain controller to adapt on the
+  // input signal when the gain changes.
+  constexpr size_t kNumFrames = 5;
+
+  constexpr float kInputLevel = 1000.f;
+  constexpr size_t kSampleRate = 8000;
+  constexpr float kGainDbLow = 0.f;
+  constexpr float kGainDbHigh = 40.f;
+  static_assert(kGainDbLow < kGainDbHigh, "");
+
+  auto test_data_dumper = GetApmDataDumper();
+  std::unique_ptr<FixedGainController> fixed_gc = CreateFixedGainController(
+      kGainDbLow, kSampleRate, test_data_dumper.get());
+
+  fixed_gc->SetGain(kGainDbLow);
+  const float output_level_pre = RunFixedGainControllerWithConstantInput(
+      fixed_gc.get(), kInputLevel, kNumFrames, kSampleRate);
+
+  fixed_gc->SetGain(kGainDbHigh);
+  RunFixedGainControllerWithConstantInput(fixed_gc.get(), kInputLevel,
+                                          kNumFrames, kSampleRate);
+
+  fixed_gc->SetGain(kGainDbLow);
+  const float output_level_post = RunFixedGainControllerWithConstantInput(
+      fixed_gc.get(), kInputLevel, kNumFrames, kSampleRate);
+
+  EXPECT_EQ(output_level_pre, output_level_post);
+}
+
+TEST(AutomaticGainController2FixedDigital, RegionHistogramIsUpdated) {
+  constexpr size_t kSampleRate = 8000;
+  constexpr float kGainDb = 0.f;
+  constexpr float kInputLevel = 1000.f;
+  constexpr size_t kNumFrames = 5;
+
+  metrics::Reset();
+
+  auto test_data_dumper = GetApmDataDumper();
+  std::unique_ptr<FixedGainController> fixed_gc_no_saturation =
+      CreateFixedGainController(kGainDb, kSampleRate, "Test",
+                                test_data_dumper.get());
+
+  static_cast<void>(RunFixedGainControllerWithConstantInput(
+      fixed_gc_no_saturation.get(), kInputLevel, kNumFrames, kSampleRate));
+
+  // Destroying FixedGainController should cause the last limiter region to be
+  // logged.
+  fixed_gc_no_saturation.reset();
+
+  EXPECT_EQ(1, metrics::NumSamples(
+                   "WebRTC.Audio.Test.FixedDigitalGainCurveRegion.Identity"));
+  EXPECT_EQ(0, metrics::NumSamples(
+                   "WebRTC.Audio.Test.FixedDigitalGainCurveRegion.Knee"));
+  EXPECT_EQ(0, metrics::NumSamples(
+                   "WebRTC.Audio.Test.FixedDigitalGainCurveRegion.Limiter"));
+  EXPECT_EQ(0, metrics::NumSamples(
+                   "WebRTC.Audio.Test.FixedDigitalGainCurveRegion.Saturation"));
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/gain_curve_applier.cc b/modules/audio_processing/agc2/gain_curve_applier.cc
index 122839a..b52e0d7 100644
--- a/modules/audio_processing/agc2/gain_curve_applier.cc
+++ b/modules/audio_processing/agc2/gain_curve_applier.cc
@@ -84,8 +84,9 @@
 }  // namespace
 
 GainCurveApplier::GainCurveApplier(size_t sample_rate_hz,
-                                   ApmDataDumper* apm_data_dumper)
-    : interp_gain_curve_(apm_data_dumper),
+                                   ApmDataDumper* apm_data_dumper,
+                                   std::string histogram_name)
+    : interp_gain_curve_(apm_data_dumper, histogram_name),
       level_estimator_(sample_rate_hz, apm_data_dumper),
       apm_data_dumper_(apm_data_dumper) {}
 
@@ -129,4 +130,8 @@
                 kMaximalNumberOfSamplesPerChannel * 1000 / kFrameDurationMs);
 }
 
+void GainCurveApplier::Reset() {
+  level_estimator_.Reset();
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/gain_curve_applier.h b/modules/audio_processing/agc2/gain_curve_applier.h
index 86ca251..a7ffa36 100644
--- a/modules/audio_processing/agc2/gain_curve_applier.h
+++ b/modules/audio_processing/agc2/gain_curve_applier.h
@@ -23,7 +23,9 @@
 
 class GainCurveApplier {
  public:
-  GainCurveApplier(size_t sample_rate_hz, ApmDataDumper* apm_data_dumper);
+  GainCurveApplier(size_t sample_rate_hz,
+                   ApmDataDumper* apm_data_dumper,
+                   std::string histogram_name_prefix);
 
   ~GainCurveApplier();
 
@@ -37,6 +39,9 @@
   //   per_sample_scaling_factors_ array.
   void SetSampleRate(size_t sample_rate_hz);
 
+  // Resets the internal state.
+  void Reset();
+
  private:
   const InterpolatedGainCurve interp_gain_curve_;
   FixedDigitalLevelEstimator level_estimator_;
diff --git a/modules/audio_processing/agc2/gain_curve_applier_unittest.cc b/modules/audio_processing/agc2/gain_curve_applier_unittest.cc
index d9179a4..0f75f62 100644
--- a/modules/audio_processing/agc2/gain_curve_applier_unittest.cc
+++ b/modules/audio_processing/agc2/gain_curve_applier_unittest.cc
@@ -23,7 +23,7 @@
   const int sample_rate_hz = 48000;
   ApmDataDumper apm_data_dumper(0);
 
-  GainCurveApplier gain_curve_applier(sample_rate_hz, &apm_data_dumper);
+  GainCurveApplier gain_curve_applier(sample_rate_hz, &apm_data_dumper, "");
 
   VectorFloatFrame vectors_with_float_frame(1, sample_rate_hz / 100,
                                             kMaxAbsFloatS16Value);
@@ -37,7 +37,7 @@
       2.f;
   ApmDataDumper apm_data_dumper(0);
 
-  GainCurveApplier gain_curve_applier(sample_rate_hz, &apm_data_dumper);
+  GainCurveApplier gain_curve_applier(sample_rate_hz, &apm_data_dumper, "");
 
   // Give the level estimator time to adapt.
   for (int i = 0; i < 5; ++i) {
diff --git a/modules/audio_processing/agc2/interpolated_gain_curve.cc b/modules/audio_processing/agc2/interpolated_gain_curve.cc
index 7f1f16c..73e6a8e 100644
--- a/modules/audio_processing/agc2/interpolated_gain_curve.cc
+++ b/modules/audio_processing/agc2/interpolated_gain_curve.cc
@@ -14,41 +14,8 @@
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "system_wrappers/include/metrics.h"
 
 namespace webrtc {
-namespace {
-void LogRegionStats(const InterpolatedGainCurve::Stats& stats) {
-  using Region = InterpolatedGainCurve::GainCurveRegion;
-  const int duration_s =
-      stats.region_duration_frames / (1000 / kFrameDurationMs);
-
-  switch (stats.region) {
-    case Region::kIdentity: {
-      RTC_HISTOGRAM_COUNTS_10000(
-          "WebRTC.Audio.Agc2.FixedDigitalGainCurveRegion.Identity", duration_s);
-      break;
-    }
-    case Region::kKnee: {
-      RTC_HISTOGRAM_COUNTS_10000(
-          "WebRTC.Audio.Agc2.FixedDigitalGainCurveRegion.Knee", duration_s);
-      break;
-    }
-    case Region::kLimiter: {
-      RTC_HISTOGRAM_COUNTS_10000(
-          "WebRTC.Audio.Agc2.FixedDigitalGainCurveRegion.Limiter", duration_s);
-      break;
-    }
-    case Region::kSaturation: {
-      RTC_HISTOGRAM_COUNTS_10000(
-          "WebRTC.Audio.Agc2.FixedDigitalGainCurveRegion.Saturation",
-          duration_s);
-      break;
-    }
-    default: { RTC_NOTREACHED(); }
-  }
-}
-}  // namespace
 
 constexpr std::array<float, kInterpolatedGainCurveTotalPoints>
     InterpolatedGainCurve::approximation_params_x_;
@@ -59,8 +26,17 @@
 constexpr std::array<float, kInterpolatedGainCurveTotalPoints>
     InterpolatedGainCurve::approximation_params_q_;
 
-InterpolatedGainCurve::InterpolatedGainCurve(ApmDataDumper* apm_data_dumper)
-    : apm_data_dumper_(apm_data_dumper) {}
+InterpolatedGainCurve::InterpolatedGainCurve(ApmDataDumper* apm_data_dumper,
+                                             std::string histogram_name_prefix)
+    : region_logger_("WebRTC.Audio." + histogram_name_prefix +
+                         ".FixedDigitalGainCurveRegion.Identity",
+                     "WebRTC.Audio." + histogram_name_prefix +
+                         ".FixedDigitalGainCurveRegion.Knee",
+                     "WebRTC.Audio." + histogram_name_prefix +
+                         ".FixedDigitalGainCurveRegion.Limiter",
+                     "WebRTC.Audio." + histogram_name_prefix +
+                         ".FixedDigitalGainCurveRegion.Saturation"),
+      apm_data_dumper_(apm_data_dumper) {}
 
 InterpolatedGainCurve::~InterpolatedGainCurve() {
   if (stats_.available) {
@@ -73,7 +49,69 @@
                               stats_.look_ups_limiter_region);
     apm_data_dumper_->DumpRaw("agc2_interp_gain_curve_lookups_saturation",
                               stats_.look_ups_saturation_region);
-    LogRegionStats(stats_);
+    region_logger_.LogRegionStats(stats_);
+  }
+}
+
+InterpolatedGainCurve::RegionLogger::RegionLogger(
+    std::string identity_histogram_name,
+    std::string knee_histogram_name,
+    std::string limiter_histogram_name,
+    std::string saturation_histogram_name)
+    : identity_histogram(
+          metrics::HistogramFactoryGetCounts(identity_histogram_name,
+                                             1,
+                                             10000,
+                                             50)),
+      knee_histogram(metrics::HistogramFactoryGetCounts(knee_histogram_name,
+                                                        1,
+                                                        10000,
+                                                        50)),
+      limiter_histogram(
+          metrics::HistogramFactoryGetCounts(limiter_histogram_name,
+                                             1,
+                                             10000,
+                                             50)),
+      saturation_histogram(
+          metrics::HistogramFactoryGetCounts(saturation_histogram_name,
+                                             1,
+                                             10000,
+                                             50)) {}
+
+InterpolatedGainCurve::RegionLogger::~RegionLogger() = default;
+
+void InterpolatedGainCurve::RegionLogger::LogRegionStats(
+    const InterpolatedGainCurve::Stats& stats) const {
+  using Region = InterpolatedGainCurve::GainCurveRegion;
+  const int duration_s =
+      stats.region_duration_frames / (1000 / kFrameDurationMs);
+
+  switch (stats.region) {
+    case Region::kIdentity: {
+      if (identity_histogram) {
+        metrics::HistogramAdd(identity_histogram, duration_s);
+      }
+      break;
+    }
+    case Region::kKnee: {
+      if (knee_histogram) {
+        metrics::HistogramAdd(knee_histogram, duration_s);
+      }
+      break;
+    }
+    case Region::kLimiter: {
+      if (limiter_histogram) {
+        metrics::HistogramAdd(limiter_histogram, duration_s);
+      }
+      break;
+    }
+    case Region::kSaturation: {
+      if (saturation_histogram) {
+        metrics::HistogramAdd(saturation_histogram, duration_s);
+      }
+      break;
+    }
+    default: { RTC_NOTREACHED(); }
   }
 }
 
@@ -100,7 +138,7 @@
   if (region == stats_.region) {
     ++stats_.region_duration_frames;
   } else {
-    LogRegionStats(stats_);
+    region_logger_.LogRegionStats(stats_);
 
     stats_.region_duration_frames = 0;
     stats_.region = region;
diff --git a/modules/audio_processing/agc2/interpolated_gain_curve.h b/modules/audio_processing/agc2/interpolated_gain_curve.h
index fc5842b..68d4532 100644
--- a/modules/audio_processing/agc2/interpolated_gain_curve.h
+++ b/modules/audio_processing/agc2/interpolated_gain_curve.h
@@ -12,11 +12,13 @@
 #define MODULES_AUDIO_PROCESSING_AGC2_INTERPOLATED_GAIN_CURVE_H_
 
 #include <array>
+#include <string>
 
 #include "modules/audio_processing/agc2/agc2_common.h"
 
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/gtest_prod_util.h"
+#include "system_wrappers/include/metrics.h"
 
 namespace webrtc {
 
@@ -59,8 +61,8 @@
     int64_t region_duration_frames = 0;
   };
 
-  // InterpolatedGainCurve(InterpolatedGainCurve&&);
-  explicit InterpolatedGainCurve(ApmDataDumper* apm_data_dumper);
+  InterpolatedGainCurve(ApmDataDumper* apm_data_dumper,
+                        std::string histogram_name_prefix);
   ~InterpolatedGainCurve();
 
   Stats get_stats() const { return stats_; }
@@ -76,6 +78,23 @@
   // ComputeInterpolatedGainCurve.
   FRIEND_TEST_ALL_PREFIXES(AutomaticGainController2InterpolatedGainCurve,
                            CheckApproximationParams);
+
+  struct RegionLogger {
+    metrics::Histogram* identity_histogram;
+    metrics::Histogram* knee_histogram;
+    metrics::Histogram* limiter_histogram;
+    metrics::Histogram* saturation_histogram;
+
+    RegionLogger(std::string identity_histogram_name,
+                 std::string knee_histogram_name,
+                 std::string limiter_histogram_name,
+                 std::string saturation_histogram_name);
+
+    ~RegionLogger();
+
+    void LogRegionStats(const InterpolatedGainCurve::Stats& stats) const;
+  } region_logger_;
+
   void UpdateStats(float input_level) const;
 
   ApmDataDumper* const apm_data_dumper_;
diff --git a/modules/audio_processing/agc2/interpolated_gain_curve_unittest.cc b/modules/audio_processing/agc2/interpolated_gain_curve_unittest.cc
index d75ddbd..dd69631 100644
--- a/modules/audio_processing/agc2/interpolated_gain_curve_unittest.cc
+++ b/modules/audio_processing/agc2/interpolated_gain_curve_unittest.cc
@@ -32,7 +32,7 @@
 }  // namespace
 
 TEST(AutomaticGainController2InterpolatedGainCurve, CreateUse) {
-  InterpolatedGainCurve igc(&apm_data_dumper);
+  InterpolatedGainCurve igc(&apm_data_dumper, "");
 
   const auto levels = test::LinSpace(
       kLevelEpsilon, DbfsToFloatS16(limiter.max_input_level_db() + 1), 500);
@@ -42,7 +42,7 @@
 }
 
 TEST(AutomaticGainController2InterpolatedGainCurve, CheckValidOutput) {
-  InterpolatedGainCurve igc(&apm_data_dumper);
+  InterpolatedGainCurve igc(&apm_data_dumper, "");
 
   const auto levels = test::LinSpace(
       kLevelEpsilon, limiter.max_input_level_linear() * 2.0, 500);
@@ -55,7 +55,7 @@
 }
 
 TEST(AutomaticGainController2InterpolatedGainCurve, CheckMonotonicity) {
-  InterpolatedGainCurve igc(&apm_data_dumper);
+  InterpolatedGainCurve igc(&apm_data_dumper, "");
 
   const auto levels = test::LinSpace(
       kLevelEpsilon, limiter.max_input_level_linear() + kLevelEpsilon + 0.5,
@@ -69,7 +69,7 @@
 }
 
 TEST(AutomaticGainController2InterpolatedGainCurve, CheckApproximation) {
-  InterpolatedGainCurve igc(&apm_data_dumper);
+  InterpolatedGainCurve igc(&apm_data_dumper, "");
 
   const auto levels = test::LinSpace(
       kLevelEpsilon, limiter.max_input_level_linear() - kLevelEpsilon, 500);
@@ -82,7 +82,7 @@
 }
 
 TEST(AutomaticGainController2InterpolatedGainCurve, CheckRegionBoundaries) {
-  InterpolatedGainCurve igc(&apm_data_dumper);
+  InterpolatedGainCurve igc(&apm_data_dumper, "");
 
   const std::vector<double> levels{
       {kLevelEpsilon, limiter.knee_start_linear() + kLevelEpsilon,
@@ -101,7 +101,7 @@
 
 TEST(AutomaticGainController2InterpolatedGainCurve, CheckIdentityRegion) {
   constexpr size_t kNumSteps = 10;
-  InterpolatedGainCurve igc(&apm_data_dumper);
+  InterpolatedGainCurve igc(&apm_data_dumper, "");
 
   const auto levels =
       test::LinSpace(kLevelEpsilon, limiter.knee_start_linear(), kNumSteps);
@@ -120,7 +120,7 @@
 TEST(AutomaticGainController2InterpolatedGainCurve,
      CheckNoOverApproximationKnee) {
   constexpr size_t kNumSteps = 10;
-  InterpolatedGainCurve igc(&apm_data_dumper);
+  InterpolatedGainCurve igc(&apm_data_dumper, "");
 
   const auto levels =
       test::LinSpace(limiter.knee_start_linear() + kLevelEpsilon,
@@ -142,7 +142,7 @@
 TEST(AutomaticGainController2InterpolatedGainCurve,
      CheckNoOverApproximationBeyondKnee) {
   constexpr size_t kNumSteps = 10;
-  InterpolatedGainCurve igc(&apm_data_dumper);
+  InterpolatedGainCurve igc(&apm_data_dumper, "");
 
   const auto levels = test::LinSpace(
       limiter.limiter_start_linear() + kLevelEpsilon,
@@ -164,7 +164,7 @@
 TEST(AutomaticGainController2InterpolatedGainCurve,
      CheckNoOverApproximationWithSaturation) {
   constexpr size_t kNumSteps = 3;
-  InterpolatedGainCurve igc(&apm_data_dumper);
+  InterpolatedGainCurve igc(&apm_data_dumper, "");
 
   const auto levels = test::LinSpace(
       limiter.max_input_level_linear() + kLevelEpsilon,
@@ -185,7 +185,7 @@
   test::InterpolatedParameters parameters =
       test::ComputeInterpolatedGainCurveApproximationParams();
 
-  InterpolatedGainCurve igc(&apm_data_dumper);
+  InterpolatedGainCurve igc(&apm_data_dumper, "");
 
   for (size_t i = 0; i < kInterpolatedGainCurveTotalPoints; ++i) {
     // The tolerance levels are chosen to account for deviations due
diff --git a/modules/audio_processing/agc2/rnn_vad/BUILD.gn b/modules/audio_processing/agc2/rnn_vad/BUILD.gn
index 41521df..d1edece 100644
--- a/modules/audio_processing/agc2/rnn_vad/BUILD.gn
+++ b/modules/audio_processing/agc2/rnn_vad/BUILD.gn
@@ -8,13 +8,7 @@
 
 import("../../../../webrtc.gni")
 
-group("rnn_vad") {
-  deps = [
-    ":lib",
-  ]
-}
-
-rtc_source_set("lib") {
+rtc_source_set("rnn_vad") {
   sources = [
     "common.h",
     "features_extraction.cc",
@@ -50,7 +44,7 @@
 }
 
 if (rtc_include_tests) {
-  rtc_source_set("lib_test") {
+  rtc_source_set("test_utils") {
     testonly = true
     sources = [
       "test_utils.cc",
@@ -104,8 +98,8 @@
       "symmetric_matrix_buffer_unittest.cc",
     ]
     deps = [
-      ":lib",
-      ":lib_test",
+      ":rnn_vad",
+      ":test_utils",
       "../..:audioproc_test_utils",
       "../../../../api:array_view",
       "../../../../common_audio/",
@@ -126,7 +120,7 @@
       "rnn_vad_tool.cc",
     ]
     deps = [
-      ":lib",
+      ":rnn_vad",
       "../../../../api:array_view",
       "../../../../common_audio:common_audio",
       "../../../../rtc_base:rtc_base_approved",
diff --git a/modules/audio_processing/audio_buffer.h b/modules/audio_processing/audio_buffer.h
index 3d7c4a8..ade3eec 100644
--- a/modules/audio_processing/audio_buffer.h
+++ b/modules/audio_processing/audio_buffer.h
@@ -18,7 +18,6 @@
 #include "common_audio/channel_buffer.h"
 #include "modules/audio_processing/include/audio_processing.h"
 #include "modules/audio_processing/splitting_filter.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 7e5955a..8848b73 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -24,7 +24,9 @@
 #include "modules/audio_processing/audio_buffer.h"
 #include "modules/audio_processing/common.h"
 #include "modules/audio_processing/echo_cancellation_impl.h"
+#include "modules/audio_processing/echo_cancellation_proxy.h"
 #include "modules/audio_processing/echo_control_mobile_impl.h"
+#include "modules/audio_processing/echo_control_mobile_proxy.h"
 #include "modules/audio_processing/gain_control_for_experimental_agc.h"
 #include "modules/audio_processing/gain_control_impl.h"
 #include "modules/audio_processing/gain_controller2.h"
@@ -33,10 +35,9 @@
 #include "rtc_base/logging.h"
 #include "rtc_base/platform_file.h"
 #include "rtc_base/refcountedobject.h"
+#include "rtc_base/system/arch.h"
+#include "rtc_base/timeutils.h"
 #include "rtc_base/trace_event.h"
-#if WEBRTC_INTELLIGIBILITY_ENHANCER
-#include "modules/audio_processing/intelligibility/intelligibility_enhancer.h"
-#endif
 #include "modules/audio_processing/level_estimator_impl.h"
 #include "modules/audio_processing/low_cut_filter.h"
 #include "modules/audio_processing/noise_suppression_impl.h"
@@ -46,14 +47,6 @@
 #include "rtc_base/atomicops.h"
 #include "system_wrappers/include/metrics.h"
 
-// Check to verify that the define for the intelligibility enhancer is properly
-// set.
-#if !defined(WEBRTC_INTELLIGIBILITY_ENHANCER) || \
-    (WEBRTC_INTELLIGIBILITY_ENHANCER != 0 &&     \
-     WEBRTC_INTELLIGIBILITY_ENHANCER != 1)
-#error "Set WEBRTC_INTELLIGIBILITY_ENHANCER to either 0 or 1"
-#endif
-
 #define RETURN_ON_ERR(expr) \
   do {                      \
     int err = (expr);       \
@@ -154,9 +147,11 @@
 
 AudioProcessingImpl::ApmSubmoduleStates::ApmSubmoduleStates(
     bool capture_post_processor_enabled,
-    bool render_pre_processor_enabled)
+    bool render_pre_processor_enabled,
+    bool capture_analyzer_enabled)
     : capture_post_processor_enabled_(capture_post_processor_enabled),
-      render_pre_processor_enabled_(render_pre_processor_enabled) {}
+      render_pre_processor_enabled_(render_pre_processor_enabled),
+      capture_analyzer_enabled_(capture_analyzer_enabled) {}
 
 bool AudioProcessingImpl::ApmSubmoduleStates::Update(
     bool low_cut_filter_enabled,
@@ -164,7 +159,6 @@
     bool mobile_echo_controller_enabled,
     bool residual_echo_detector_enabled,
     bool noise_suppressor_enabled,
-    bool intelligibility_enhancer_enabled,
     bool adaptive_gain_controller_enabled,
     bool gain_controller2_enabled,
     bool pre_amplifier_enabled,
@@ -181,8 +175,6 @@
       (residual_echo_detector_enabled != residual_echo_detector_enabled_);
   changed |= (noise_suppressor_enabled != noise_suppressor_enabled_);
   changed |=
-      (intelligibility_enhancer_enabled != intelligibility_enhancer_enabled_);
-  changed |=
       (adaptive_gain_controller_enabled != adaptive_gain_controller_enabled_);
   changed |=
       (gain_controller2_enabled != gain_controller2_enabled_);
@@ -198,7 +190,6 @@
     mobile_echo_controller_enabled_ = mobile_echo_controller_enabled;
     residual_echo_detector_enabled_ = residual_echo_detector_enabled;
     noise_suppressor_enabled_ = noise_suppressor_enabled;
-    intelligibility_enhancer_enabled_ = intelligibility_enhancer_enabled;
     adaptive_gain_controller_enabled_ = adaptive_gain_controller_enabled;
     gain_controller2_enabled_ = gain_controller2_enabled;
     pre_amplifier_enabled_ = pre_amplifier_enabled;
@@ -215,12 +206,7 @@
 
 bool AudioProcessingImpl::ApmSubmoduleStates::CaptureMultiBandSubModulesActive()
     const {
-#if WEBRTC_INTELLIGIBILITY_ENHANCER
-  return CaptureMultiBandProcessingActive() ||
-         intelligibility_enhancer_enabled_ || voice_activity_detector_enabled_;
-#else
   return CaptureMultiBandProcessingActive() || voice_activity_detector_enabled_;
-#endif
 }
 
 bool AudioProcessingImpl::ApmSubmoduleStates::CaptureMultiBandProcessingActive()
@@ -236,6 +222,10 @@
          pre_amplifier_enabled_;
 }
 
+bool AudioProcessingImpl::ApmSubmoduleStates::CaptureAnalyzerActive() const {
+  return capture_analyzer_enabled_;
+}
+
 bool AudioProcessingImpl::ApmSubmoduleStates::RenderMultiBandSubModulesActive()
     const {
   return RenderMultiBandProcessingActive() || echo_canceller_enabled_ ||
@@ -250,11 +240,7 @@
 
 bool AudioProcessingImpl::ApmSubmoduleStates::RenderMultiBandProcessingActive()
     const {
-#if WEBRTC_INTELLIGIBILITY_ENHANCER
-  return intelligibility_enhancer_enabled_;
-#else
   return false;
-#endif
 }
 
 struct AudioProcessingImpl::ApmPublicSubmodules {
@@ -262,6 +248,8 @@
   // Accessed externally of APM without any lock acquired.
   std::unique_ptr<EchoCancellationImpl> echo_cancellation;
   std::unique_ptr<EchoControlMobileImpl> echo_control_mobile;
+  std::unique_ptr<EchoCancellationProxy> echo_cancellation_proxy;
+  std::unique_ptr<EchoControlMobileProxy> echo_control_mobile_proxy;
   std::unique_ptr<GainControlImpl> gain_control;
   std::unique_ptr<LevelEstimatorImpl> level_estimator;
   std::unique_ptr<NoiseSuppressionImpl> noise_suppression;
@@ -271,18 +259,17 @@
 
   // Accessed internally from both render and capture.
   std::unique_ptr<TransientSuppressor> transient_suppressor;
-#if WEBRTC_INTELLIGIBILITY_ENHANCER
-  std::unique_ptr<IntelligibilityEnhancer> intelligibility_enhancer;
-#endif
 };
 
 struct AudioProcessingImpl::ApmPrivateSubmodules {
   ApmPrivateSubmodules(std::unique_ptr<CustomProcessing> capture_post_processor,
                        std::unique_ptr<CustomProcessing> render_pre_processor,
-                       rtc::scoped_refptr<EchoDetector> echo_detector)
+                       rtc::scoped_refptr<EchoDetector> echo_detector,
+                       std::unique_ptr<CustomAudioAnalyzer> capture_analyzer)
       : echo_detector(std::move(echo_detector)),
         capture_post_processor(std::move(capture_post_processor)),
-        render_pre_processor(std::move(render_pre_processor)) {}
+        render_pre_processor(std::move(render_pre_processor)),
+        capture_analyzer(std::move(capture_analyzer)) {}
   // Accessed internally from capture or during initialization
   std::unique_ptr<AgcManagerDirect> agc_manager;
   std::unique_ptr<GainController2> gain_controller2;
@@ -292,6 +279,7 @@
   std::unique_ptr<CustomProcessing> capture_post_processor;
   std::unique_ptr<CustomProcessing> render_pre_processor;
   std::unique_ptr<GainApplier> pre_amplifier;
+  std::unique_ptr<CustomAudioAnalyzer> capture_analyzer;
 };
 
 AudioProcessingBuilder::AudioProcessingBuilder() = default;
@@ -309,6 +297,12 @@
   return *this;
 }
 
+AudioProcessingBuilder& AudioProcessingBuilder::SetCaptureAnalyzer(
+    std::unique_ptr<CustomAudioAnalyzer> capture_analyzer) {
+  capture_analyzer_ = std::move(capture_analyzer);
+  return *this;
+}
+
 AudioProcessingBuilder& AudioProcessingBuilder::SetEchoControlFactory(
     std::unique_ptr<EchoControlFactory> echo_control_factory) {
   echo_control_factory_ = std::move(echo_control_factory);
@@ -330,7 +324,7 @@
   AudioProcessingImpl* apm = new rtc::RefCountedObject<AudioProcessingImpl>(
       config, std::move(capture_post_processing_),
       std::move(render_pre_processing_), std::move(echo_control_factory_),
-      std::move(echo_detector_));
+      std::move(echo_detector_), std::move(capture_analyzer_));
   if (apm->Initialize() != AudioProcessing::kNoError) {
     delete apm;
     apm = nullptr;
@@ -339,7 +333,8 @@
 }
 
 AudioProcessingImpl::AudioProcessingImpl(const webrtc::Config& config)
-    : AudioProcessingImpl(config, nullptr, nullptr, nullptr, nullptr) {}
+    : AudioProcessingImpl(config, nullptr, nullptr, nullptr, nullptr, nullptr) {
+}
 
 int AudioProcessingImpl::instance_count_ = 0;
 
@@ -348,7 +343,8 @@
     std::unique_ptr<CustomProcessing> capture_post_processor,
     std::unique_ptr<CustomProcessing> render_pre_processor,
     std::unique_ptr<EchoControlFactory> echo_control_factory,
-    rtc::scoped_refptr<EchoDetector> echo_detector)
+    rtc::scoped_refptr<EchoDetector> echo_detector,
+    std::unique_ptr<CustomAudioAnalyzer> capture_analyzer)
     : data_dumper_(
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
       capture_runtime_settings_(kRuntimeSettingQueueSize),
@@ -357,12 +353,15 @@
       render_runtime_settings_enqueuer_(&render_runtime_settings_),
       high_pass_filter_impl_(new HighPassFilterImpl(this)),
       echo_control_factory_(std::move(echo_control_factory)),
-      submodule_states_(!!capture_post_processor, !!render_pre_processor),
+      submodule_states_(!!capture_post_processor,
+                        !!render_pre_processor,
+                        !!capture_analyzer),
       public_submodules_(new ApmPublicSubmodules()),
       private_submodules_(
           new ApmPrivateSubmodules(std::move(capture_post_processor),
                                    std::move(render_pre_processor),
-                                   std::move(echo_detector))),
+                                   std::move(echo_detector),
+                                   std::move(capture_analyzer))),
       constants_(config.Get<ExperimentalAgc>().startup_min_volume,
                  config.Get<ExperimentalAgc>().clipped_level_min,
 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
@@ -372,14 +371,14 @@
 #else
                  config.Get<ExperimentalAgc>().enabled,
                  config.Get<ExperimentalAgc>().enabled_agc2_level_estimator,
-                 config.Get<ExperimentalAgc>().enabled_agc2_digital_adaptive),
+                 config.Get<ExperimentalAgc>().digital_adaptive_disabled),
 #endif
 #if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
       capture_(false),
 #else
       capture_(config.Get<ExperimentalNs>().enabled),
 #endif
-      capture_nonlocked_(config.Get<Intelligibility>().enabled) {
+      capture_nonlocked_() {
   {
     rtc::CritScope cs_render(&crit_render_);
     rtc::CritScope cs_capture(&crit_capture_);
@@ -392,6 +391,11 @@
         new EchoCancellationImpl(&crit_render_, &crit_capture_));
     public_submodules_->echo_control_mobile.reset(
         new EchoControlMobileImpl(&crit_render_, &crit_capture_));
+    public_submodules_->echo_cancellation_proxy.reset(new EchoCancellationProxy(
+        this, public_submodules_->echo_cancellation.get()));
+    public_submodules_->echo_control_mobile_proxy.reset(
+        new EchoControlMobileProxy(
+            this, public_submodules_->echo_control_mobile.get()));
     public_submodules_->gain_control.reset(
         new GainControlImpl(&crit_render_, &crit_capture_));
     public_submodules_->level_estimator.reset(
@@ -414,7 +418,9 @@
     // implemented.
     private_submodules_->gain_controller2.reset(new GainController2());
 
-    RTC_LOG(LS_INFO) << "Capture post processor activated: "
+    RTC_LOG(LS_INFO) << "Capture analyzer activated: "
+                     << !!private_submodules_->capture_analyzer
+                     << "\nCapture post processor activated: "
                      << !!private_submodules_->capture_post_processor
                      << "\nRender pre processor activated: "
                      << !!private_submodules_->render_pre_processor;
@@ -556,9 +562,6 @@
     public_submodules_->gain_control_for_experimental_agc->Initialize();
   }
   InitializeTransient();
-#if WEBRTC_INTELLIGIBILITY_ENHANCER
-  InitializeIntelligibility();
-#endif
   InitializeLowCutFilter();
   public_submodules_->noise_suppression->Initialize(num_proc_channels(),
                                                     proc_sample_rate_hz());
@@ -567,11 +570,12 @@
   InitializeResidualEchoDetector();
   InitializeEchoController();
   InitializeGainController2();
+  InitializeAnalyzer();
   InitializePostProcessor();
   InitializePreProcessor();
 
   if (aec_dump_) {
-    aec_dump_->WriteInitMessage(formats_.api_format);
+    aec_dump_->WriteInitMessage(formats_.api_format, rtc::TimeUTCMillis());
   }
   return kNoError;
 }
@@ -666,6 +670,13 @@
   rtc::CritScope cs_render(&crit_render_);
   rtc::CritScope cs_capture(&crit_capture_);
 
+  static_cast<EchoCancellation*>(public_submodules_->echo_cancellation.get())
+      ->Enable(config_.echo_canceller.enabled &&
+               !config_.echo_canceller.mobile_mode);
+  static_cast<EchoControlMobile*>(public_submodules_->echo_control_mobile.get())
+      ->Enable(config_.echo_canceller.enabled &&
+               config_.echo_canceller.mobile_mode);
+
   InitializeLowCutFilter();
 
   RTC_LOG(LS_INFO) << "Highpass filter activated: "
@@ -701,15 +712,6 @@
         config.Get<ExperimentalNs>().enabled;
     InitializeTransient();
   }
-
-#if WEBRTC_INTELLIGIBILITY_ENHANCER
-  if (capture_nonlocked_.intelligibility_enabled !=
-     config.Get<Intelligibility>().enabled) {
-    capture_nonlocked_.intelligibility_enabled =
-        config.Get<Intelligibility>().enabled;
-    InitializeIntelligibility();
-  }
-#endif
 }
 
 int AudioProcessingImpl::proc_sample_rate_hz() const {
@@ -1098,10 +1100,10 @@
   TRACE_EVENT0("webrtc", "AudioProcessing::ProcessStream_AudioFrame");
   {
     // Acquire the capture lock in order to safely call the function
-    // that retrieves the render side data. This function accesses apm
+    // that retrieves the render side data. This function accesses APM
     // getters that need the capture lock held when being called.
     // The lock needs to be released as
-    // public_submodules_->echo_control_mobile->is_enabled() aquires this lock
+    // public_submodules_->echo_control_mobile->is_enabled() acquires this lock
     // as well.
     rtc::CritScope cs_capture(&crit_capture_);
     EmptyQueuedRenderAudio();
@@ -1265,18 +1267,6 @@
     capture_buffer->CopyLowPassToReference();
   }
   public_submodules_->noise_suppression->ProcessCaptureAudio(capture_buffer);
-#if WEBRTC_INTELLIGIBILITY_ENHANCER
-  if (capture_nonlocked_.intelligibility_enabled) {
-    RTC_DCHECK(public_submodules_->noise_suppression->is_enabled());
-    const int gain_db =
-        public_submodules_->gain_control->is_enabled()
-            ? public_submodules_->gain_control->compression_gain_db()
-            : 0;
-    const float gain = DbToRatio(gain_db);
-    public_submodules_->intelligibility_enhancer->SetCaptureNoiseEstimate(
-        public_submodules_->noise_suppression->NoiseEstimate(), gain);
-  }
-#endif
 
   // Ensure that the stream delay was set before the call to the
   // AECM ProcessCaptureAudio function.
@@ -1332,7 +1322,14 @@
         capture_.key_pressed);
   }
 
+  // Experimental APM sub-module that analyzes |capture_buffer|.
+  if (private_submodules_->capture_analyzer) {
+    private_submodules_->capture_analyzer->Analyze(capture_buffer);
+  }
+
   if (config_.gain_controller2.enabled) {
+    private_submodules_->gain_controller2->NotifyAnalogLevel(
+        gain_control()->stream_analog_level());
     private_submodules_->gain_controller2->Process(capture_buffer);
   }
 
@@ -1478,32 +1475,25 @@
 int AudioProcessingImpl::ProcessRenderStreamLocked() {
   AudioBuffer* render_buffer = render_.render_audio.get();  // For brevity.
 
-  QueueNonbandedRenderAudio(render_buffer);
-
   HandleRenderRuntimeSettings();
 
   if (private_submodules_->render_pre_processor) {
     private_submodules_->render_pre_processor->Process(render_buffer);
   }
 
+  QueueNonbandedRenderAudio(render_buffer);
+
   if (submodule_states_.RenderMultiBandSubModulesActive() &&
       SampleRateSupportsMultiBand(
           formats_.render_processing_format.sample_rate_hz())) {
     render_buffer->SplitIntoFrequencyBands();
   }
 
-#if WEBRTC_INTELLIGIBILITY_ENHANCER
-  if (capture_nonlocked_.intelligibility_enabled) {
-    public_submodules_->intelligibility_enhancer->ProcessRenderAudio(
-        render_buffer);
-  }
-#endif
-
   if (submodule_states_.RenderMultiBandSubModulesActive()) {
     QueueBandedRenderAudio(render_buffer);
   }
 
-  // TODO(peah): Perform the queueing ínside QueueRenderAudiuo().
+  // TODO(peah): Perform the queuing inside QueueRenderAudiuo().
   if (private_submodules_->echo_controller) {
     private_submodules_->echo_controller->AnalyzeRender(render_buffer);
   }
@@ -1572,7 +1562,7 @@
   // 'aec_dump' parameter, which is after locks are released.
   aec_dump_.swap(aec_dump);
   WriteAecDumpConfigMessage(true);
-  aec_dump_->WriteInitMessage(formats_.api_format);
+  aec_dump_->WriteInitMessage(formats_.api_format, rtc::TimeUTCMillis());
 }
 
 void AudioProcessingImpl::DetachAecDump() {
@@ -1710,11 +1700,11 @@
 }
 
 EchoCancellation* AudioProcessingImpl::echo_cancellation() const {
-  return public_submodules_->echo_cancellation.get();
+  return public_submodules_->echo_cancellation_proxy.get();
 }
 
 EchoControlMobile* AudioProcessingImpl::echo_control_mobile() const {
-  return public_submodules_->echo_control_mobile.get();
+  return public_submodules_->echo_control_mobile_proxy.get();
 }
 
 GainControl* AudioProcessingImpl::gain_control() const {
@@ -1761,7 +1751,6 @@
       public_submodules_->echo_control_mobile->is_enabled(),
       config_.residual_echo_detector.enabled,
       public_submodules_->noise_suppression->is_enabled(),
-      capture_nonlocked_.intelligibility_enabled,
       public_submodules_->gain_control->is_enabled(),
       config_.gain_controller2.enabled, config_.pre_amplifier.enabled,
       capture_nonlocked_.echo_controller_enabled,
@@ -1782,18 +1771,6 @@
   }
 }
 
-void AudioProcessingImpl::InitializeIntelligibility() {
-#if WEBRTC_INTELLIGIBILITY_ENHANCER
-  if (capture_nonlocked_.intelligibility_enabled) {
-    public_submodules_->intelligibility_enhancer.reset(
-        new IntelligibilityEnhancer(capture_nonlocked_.split_rate,
-                                    render_.render_audio->num_channels(),
-                                    render_.render_audio->num_bands(),
-                                    NoiseSuppressionImpl::num_noise_bins()));
-  }
-#endif
-}
-
 void AudioProcessingImpl::InitializeLowCutFilter() {
   if (config_.high_pass_filter.enabled) {
     private_submodules_->low_cut_filter.reset(
@@ -1834,6 +1811,13 @@
       formats_.render_processing_format.sample_rate_hz(), 1);
 }
 
+void AudioProcessingImpl::InitializeAnalyzer() {
+  if (private_submodules_->capture_analyzer) {
+    private_submodules_->capture_analyzer->Initialize(proc_sample_rate_hz(),
+                                                      num_proc_channels());
+  }
+}
+
 void AudioProcessingImpl::InitializePostProcessor() {
   if (private_submodules_->capture_post_processor) {
     private_submodules_->capture_post_processor->Initialize(
@@ -1974,8 +1958,6 @@
 
   apm_config.transient_suppression_enabled =
       capture_.transient_suppressor_enabled;
-  apm_config.intelligibility_enhancer_enabled =
-      capture_nonlocked_.intelligibility_enabled;
   apm_config.experiments_description = experiments_description;
   apm_config.pre_amplifier_enabled = config_.pre_amplifier.enabled;
   apm_config.pre_amplifier_fixed_gain_factor =
diff --git a/modules/audio_processing/audio_processing_impl.h b/modules/audio_processing/audio_processing_impl.h
index 44d0d08..a95e150 100644
--- a/modules/audio_processing/audio_processing_impl.h
+++ b/modules/audio_processing/audio_processing_impl.h
@@ -42,7 +42,8 @@
                       std::unique_ptr<CustomProcessing> capture_post_processor,
                       std::unique_ptr<CustomProcessing> render_pre_processor,
                       std::unique_ptr<EchoControlFactory> echo_control_factory,
-                      rtc::scoped_refptr<EchoDetector> echo_detector);
+                      rtc::scoped_refptr<EchoDetector> echo_detector,
+                      std::unique_ptr<CustomAudioAnalyzer> capture_analyzer);
   ~AudioProcessingImpl() override;
   int Initialize() override;
   int Initialize(int capture_input_sample_rate_hz,
@@ -174,14 +175,14 @@
   class ApmSubmoduleStates {
    public:
     ApmSubmoduleStates(bool capture_post_processor_enabled,
-                       bool render_pre_processor_enabled);
+                       bool render_pre_processor_enabled,
+                       bool capture_analyzer_enabled);
     // Updates the submodule state and returns true if it has changed.
     bool Update(bool low_cut_filter_enabled,
                 bool echo_canceller_enabled,
                 bool mobile_echo_controller_enabled,
                 bool residual_echo_detector_enabled,
                 bool noise_suppressor_enabled,
-                bool intelligibility_enhancer_enabled,
                 bool adaptive_gain_controller_enabled,
                 bool gain_controller2_enabled,
                 bool pre_amplifier_enabled,
@@ -192,6 +193,7 @@
     bool CaptureMultiBandSubModulesActive() const;
     bool CaptureMultiBandProcessingActive() const;
     bool CaptureFullBandProcessingActive() const;
+    bool CaptureAnalyzerActive() const;
     bool RenderMultiBandSubModulesActive() const;
     bool RenderFullBandProcessingActive() const;
     bool RenderMultiBandProcessingActive() const;
@@ -199,12 +201,12 @@
    private:
     const bool capture_post_processor_enabled_ = false;
     const bool render_pre_processor_enabled_ = false;
+    const bool capture_analyzer_enabled_ = false;
     bool low_cut_filter_enabled_ = false;
     bool echo_canceller_enabled_ = false;
     bool mobile_echo_controller_enabled_ = false;
     bool residual_echo_detector_enabled_ = false;
     bool noise_suppressor_enabled_ = false;
-    bool intelligibility_enhancer_enabled_ = false;
     bool adaptive_gain_controller_enabled_ = false;
     bool gain_controller2_enabled_ = false;
     bool pre_amplifier_enabled_ = false;
@@ -241,8 +243,6 @@
   // acquired.
   void InitializeTransient()
       RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_);
-  void InitializeIntelligibility()
-      RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_);
   int InitializeLocked(const ProcessingConfig& config)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_);
   void InitializeResidualEchoDetector()
@@ -252,6 +252,7 @@
   void InitializeGainController2() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
   void InitializePreAmplifier() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
   void InitializePostProcessor() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
+  void InitializeAnalyzer() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
   void InitializePreProcessor() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_render_);
 
   // Empties and handles the respective RuntimeSetting queues.
@@ -394,18 +395,16 @@
   } capture_ RTC_GUARDED_BY(crit_capture_);
 
   struct ApmCaptureNonLockedState {
-    ApmCaptureNonLockedState(bool intelligibility_enabled)
+    ApmCaptureNonLockedState()
         : capture_processing_format(kSampleRate16kHz),
           split_rate(kSampleRate16kHz),
-          stream_delay_ms(0),
-          intelligibility_enabled(intelligibility_enabled) {}
+          stream_delay_ms(0) {}
     // Only the rate and samples fields of capture_processing_format_ are used
     // because the forward processing number of channels is mutable and is
     // tracked by the capture_audio_.
     StreamConfig capture_processing_format;
     int split_rate;
     int stream_delay_ms;
-    bool intelligibility_enabled;
     bool echo_controller_enabled = false;
   } capture_nonlocked_;
 
diff --git a/modules/audio_processing/audio_processing_impl_unittest.cc b/modules/audio_processing/audio_processing_impl_unittest.cc
index 3ac5e71..8926f02 100644
--- a/modules/audio_processing/audio_processing_impl_unittest.cc
+++ b/modules/audio_processing/audio_processing_impl_unittest.cc
@@ -10,7 +10,10 @@
 
 #include "modules/audio_processing/audio_processing_impl.h"
 
+#include "modules/audio_processing/include/audio_processing.h"
 #include "modules/audio_processing/test/test_utils.h"
+#include "rtc_base/refcountedobject.h"
+#include "rtc_base/scoped_ref_ptr.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 
@@ -33,24 +36,83 @@
   MOCK_CONST_METHOD0(Release, rtc::RefCountReleaseStatus());
 };
 
-void GenerateFixedFrame(int16_t audio_level,
-                        size_t input_rate,
-                        size_t num_channels,
-                        AudioFrame* fixed_frame) {
+void InitializeAudioFrame(size_t input_rate,
+                          size_t num_channels,
+                          AudioFrame* frame) {
   const size_t samples_per_input_channel = rtc::CheckedDivExact(
       input_rate, static_cast<size_t>(rtc::CheckedDivExact(
                       1000, AudioProcessing::kChunkSizeMs)));
-  fixed_frame->samples_per_channel_ = samples_per_input_channel;
-  fixed_frame->sample_rate_hz_ = input_rate;
-  fixed_frame->num_channels_ = num_channels;
-
   RTC_DCHECK_LE(samples_per_input_channel * num_channels,
                 AudioFrame::kMaxDataSizeSamples);
-  for (size_t i = 0; i < samples_per_input_channel * num_channels; ++i) {
-    fixed_frame->mutable_data()[i] = audio_level;
+  frame->samples_per_channel_ = samples_per_input_channel;
+  frame->sample_rate_hz_ = input_rate;
+  frame->num_channels_ = num_channels;
+}
+
+void FillFixedFrame(int16_t audio_level, AudioFrame* frame) {
+  const size_t num_samples = frame->samples_per_channel_ * frame->num_channels_;
+  for (size_t i = 0; i < num_samples; ++i) {
+    frame->mutable_data()[i] = audio_level;
   }
 }
 
+// Mocks EchoDetector and records the first samples of the last analyzed render
+// stream frame. Used to check what data is read by an EchoDetector
+// implementation injected into an APM.
+class TestEchoDetector : public EchoDetector {
+ public:
+  TestEchoDetector()
+      : analyze_render_audio_called_(false),
+        last_render_audio_first_sample_(0.f) {}
+  ~TestEchoDetector() override = default;
+  void AnalyzeRenderAudio(rtc::ArrayView<const float> render_audio) override {
+    last_render_audio_first_sample_ = render_audio[0];
+    analyze_render_audio_called_ = true;
+  }
+  void AnalyzeCaptureAudio(rtc::ArrayView<const float> capture_audio) override {
+  }
+  void Initialize(int capture_sample_rate_hz,
+                  int num_capture_channels,
+                  int render_sample_rate_hz,
+                  int num_render_channels) override {}
+  EchoDetector::Metrics GetMetrics() const override { return {}; }
+  // Returns true if AnalyzeRenderAudio() has been called at least once.
+  bool analyze_render_audio_called() const {
+    return analyze_render_audio_called_;
+  }
+  // Returns the first sample of the last analyzed render frame.
+  float last_render_audio_first_sample() const {
+    return last_render_audio_first_sample_;
+  }
+
+ private:
+  bool analyze_render_audio_called_;
+  float last_render_audio_first_sample_;
+};
+
+// Mocks CustomProcessing and applies ProcessSample() to all the samples.
+// Meant to be injected into an APM to modify samples in a known and detectable
+// way.
+class TestRenderPreProcessor : public CustomProcessing {
+ public:
+  TestRenderPreProcessor() = default;
+  ~TestRenderPreProcessor() = default;
+  void Initialize(int sample_rate_hz, int num_channels) override {}
+  void Process(AudioBuffer* audio) override {
+    for (size_t k = 0; k < audio->num_channels(); ++k) {
+      rtc::ArrayView<float> channel_view(audio->channels_f()[k],
+                                         audio->num_frames());
+      std::transform(channel_view.begin(), channel_view.end(),
+                     channel_view.begin(), ProcessSample);
+    }
+  };
+  std::string ToString() const override { return "TestRenderPreProcessor"; }
+  void SetRuntimeSetting(AudioProcessing::RuntimeSetting setting) override {}
+  // Modifies a sample. This member is used in Process() to modify a frame and
+  // it is publicly visible to enable tests.
+  static constexpr float ProcessSample(float x) { return 2.f * x; }
+};
+
 }  // namespace
 
 TEST(AudioProcessingImplTest, AudioParameterChangeTriggersInit) {
@@ -98,26 +160,74 @@
   apm->ApplyConfig(apm_config);
 
   AudioFrame frame;
-  constexpr int16_t audio_level = 10000;
-  constexpr size_t input_rate = 48000;
-  constexpr size_t num_channels = 2;
+  constexpr int16_t kAudioLevel = 10000;
+  constexpr size_t kSampleRateHz = 48000;
+  constexpr size_t kNumChannels = 2;
+  InitializeAudioFrame(kSampleRateHz, kNumChannels, &frame);
 
-  GenerateFixedFrame(audio_level, input_rate, num_channels, &frame);
+  FillFixedFrame(kAudioLevel, &frame);
   apm->ProcessStream(&frame);
-  EXPECT_EQ(frame.data()[100], audio_level)
+  EXPECT_EQ(frame.data()[100], kAudioLevel)
       << "With factor 1, frame shouldn't be modified.";
 
-  constexpr float gain_factor = 2.f;
+  constexpr float kGainFactor = 2.f;
   apm->SetRuntimeSetting(
-      AudioProcessing::RuntimeSetting::CreateCapturePreGain(gain_factor));
+      AudioProcessing::RuntimeSetting::CreateCapturePreGain(kGainFactor));
 
   // Process for two frames to have time to ramp up gain.
   for (int i = 0; i < 2; ++i) {
-    GenerateFixedFrame(audio_level, input_rate, num_channels, &frame);
+    FillFixedFrame(kAudioLevel, &frame);
     apm->ProcessStream(&frame);
   }
-  EXPECT_EQ(frame.data()[100], gain_factor * audio_level)
+  EXPECT_EQ(frame.data()[100], kGainFactor * kAudioLevel)
       << "Frame should be amplified.";
 }
 
+TEST(AudioProcessingImplTest, RenderPreProcessorBeforeEchoDetector) {
+  // Make sure that signal changes caused by a render pre-processing sub-module
+  // take place before any echo detector analysis.
+  rtc::scoped_refptr<TestEchoDetector> test_echo_detector(
+      new rtc::RefCountedObject<TestEchoDetector>());
+  std::unique_ptr<CustomProcessing> test_render_pre_processor(
+      new TestRenderPreProcessor());
+  // Create APM injecting the test echo detector and render pre-processor.
+  std::unique_ptr<AudioProcessing> apm(
+      AudioProcessingBuilder()
+          .SetEchoDetector(test_echo_detector)
+          .SetRenderPreProcessing(std::move(test_render_pre_processor))
+          .Create());
+  webrtc::AudioProcessing::Config apm_config;
+  apm_config.pre_amplifier.enabled = true;
+  apm_config.residual_echo_detector.enabled = true;
+  apm->ApplyConfig(apm_config);
+
+  constexpr int16_t kAudioLevel = 1000;
+  constexpr int kSampleRateHz = 16000;
+  constexpr size_t kNumChannels = 1;
+  AudioFrame frame;
+  InitializeAudioFrame(kSampleRateHz, kNumChannels, &frame);
+
+  constexpr float kAudioLevelFloat = static_cast<float>(kAudioLevel);
+  constexpr float kExpectedPreprocessedAudioLevel =
+      TestRenderPreProcessor::ProcessSample(kAudioLevelFloat);
+  ASSERT_NE(kAudioLevelFloat, kExpectedPreprocessedAudioLevel);
+
+  // Analyze a render stream frame.
+  FillFixedFrame(kAudioLevel, &frame);
+  ASSERT_EQ(AudioProcessing::Error::kNoError,
+            apm->ProcessReverseStream(&frame));
+  // Trigger a call to in EchoDetector::AnalyzeRenderAudio() via
+  // ProcessStream().
+  FillFixedFrame(kAudioLevel, &frame);
+  ASSERT_EQ(AudioProcessing::Error::kNoError, apm->ProcessStream(&frame));
+  // Regardless of how the call to in EchoDetector::AnalyzeRenderAudio() is
+  // triggered, the line below checks that the call has occurred. If not, the
+  // APM implementation may have changed and this test might need to be adapted.
+  ASSERT_TRUE(test_echo_detector->analyze_render_audio_called());
+  // Check that the data read in EchoDetector::AnalyzeRenderAudio() is that
+  // produced by the render pre-processor.
+  EXPECT_EQ(kExpectedPreprocessedAudioLevel,
+            test_echo_detector->last_render_audio_first_sample());
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_processing/audio_processing_performance_unittest.cc b/modules/audio_processing/audio_processing_performance_unittest.cc
index 56615cb..df8d5fe 100644
--- a/modules/audio_processing/audio_processing_performance_unittest.cc
+++ b/modules/audio_processing/audio_processing_performance_unittest.cc
@@ -26,14 +26,6 @@
 #include "test/gtest.h"
 #include "test/testsupport/perf_test.h"
 
-// Check to verify that the define for the intelligibility enhancer is properly
-// set.
-#if !defined(WEBRTC_INTELLIGIBILITY_ENHANCER) || \
-    (WEBRTC_INTELLIGIBILITY_ENHANCER != 0 &&     \
-     WEBRTC_INTELLIGIBILITY_ENHANCER != 1)
-#error "Set WEBRTC_INTELLIGIBILITY_ENHANCER to either 0 or 1"
-#endif
-
 namespace webrtc {
 
 namespace {
@@ -49,7 +41,6 @@
 enum class SettingsType {
   kDefaultApmDesktop,
   kDefaultApmMobile,
-  kDefaultApmDesktopAndIntelligibilityEnhancer,
   kAllSubmodulesTurnedOff,
   kDefaultApmDesktopWithoutDelayAgnostic,
   kDefaultApmDesktopWithoutExtendedFilter
@@ -99,20 +90,6 @@
         simulation_configs.push_back(SimulationConfig(sample_rate, settings));
       }
     }
-
-#if WEBRTC_INTELLIGIBILITY_ENHANCER == 1
-    const SettingsType intelligibility_enhancer_settings[] = {
-        SettingsType::kDefaultApmDesktopAndIntelligibilityEnhancer};
-
-    const int intelligibility_enhancer_sample_rates[] = {8000, 16000, 32000,
-                                                         48000};
-
-    for (auto sample_rate : intelligibility_enhancer_sample_rates) {
-      for (auto settings : intelligibility_enhancer_settings) {
-        simulation_configs.push_back(SimulationConfig(sample_rate, settings));
-      }
-    }
-#endif
 #endif
 
     const SettingsType mobile_settings[] = {SettingsType::kDefaultApmMobile};
@@ -137,9 +114,6 @@
       case SettingsType::kDefaultApmDesktop:
         description = "DefaultApmDesktop";
         break;
-      case SettingsType::kDefaultApmDesktopAndIntelligibilityEnhancer:
-        description = "DefaultApmDesktopAndIntelligibilityEnhancer";
-        break;
       case SettingsType::kAllSubmodulesTurnedOff:
         description = "AllSubmodulesOff";
         break;
@@ -538,16 +512,6 @@
         apm_->SetExtraOptions(config);
         break;
       }
-      case SettingsType::kDefaultApmDesktopAndIntelligibilityEnhancer: {
-        Config config;
-        config.Set<Intelligibility>(new Intelligibility(true));
-        add_default_desktop_config(&config);
-        apm_.reset(AudioProcessingBuilder().Create(config));
-        ASSERT_TRUE(!!apm_);
-        set_default_desktop_apm_runtime_settings(apm_.get());
-        apm_->SetExtraOptions(config);
-        break;
-      }
       case SettingsType::kAllSubmodulesTurnedOff: {
         apm_.reset(AudioProcessingBuilder().Create());
         ASSERT_TRUE(!!apm_);
diff --git a/modules/audio_processing/audio_processing_unittest.cc b/modules/audio_processing/audio_processing_unittest.cc
index 4b244fc..b04f89a 100644
--- a/modules/audio_processing/audio_processing_unittest.cc
+++ b/modules/audio_processing/audio_processing_unittest.cc
@@ -28,6 +28,7 @@
 #include "modules/audio_processing/test/test_utils.h"
 #include "rtc_base/arraysize.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/fakeclock.h"
 #include "rtc_base/gtest_prod_util.h"
 #include "rtc_base/ignore_wundef.h"
 #include "rtc_base/numerics/safe_conversions.h"
@@ -35,6 +36,7 @@
 #include "rtc_base/protobuf_utils.h"
 #include "rtc_base/refcountedobject.h"
 #include "rtc_base/swap_queue.h"
+#include "rtc_base/system/arch.h"
 #include "rtc_base/task_queue.h"
 #include "rtc_base/thread.h"
 #include "system_wrappers/include/event_wrapper.h"
@@ -176,23 +178,26 @@
 }
 
 void EnableAllAPComponents(AudioProcessing* ap) {
+  AudioProcessing::Config apm_config = ap->GetConfig();
+  apm_config.echo_canceller.enabled = true;
 #if defined(WEBRTC_AUDIOPROC_FIXED_PROFILE)
-  EXPECT_NOERR(ap->echo_control_mobile()->Enable(true));
+  apm_config.echo_canceller.mobile_mode = true;
 
   EXPECT_NOERR(ap->gain_control()->set_mode(GainControl::kAdaptiveDigital));
   EXPECT_NOERR(ap->gain_control()->Enable(true));
 #elif defined(WEBRTC_AUDIOPROC_FLOAT_PROFILE)
+  apm_config.echo_canceller.mobile_mode = false;
   EXPECT_NOERR(ap->echo_cancellation()->enable_drift_compensation(true));
   EXPECT_NOERR(ap->echo_cancellation()->enable_metrics(true));
   EXPECT_NOERR(ap->echo_cancellation()->enable_delay_logging(true));
-  EXPECT_NOERR(ap->echo_cancellation()->Enable(true));
+  EXPECT_NOERR(ap->echo_cancellation()->set_suppression_level(
+      EchoCancellation::SuppressionLevel::kModerateSuppression));
 
   EXPECT_NOERR(ap->gain_control()->set_mode(GainControl::kAdaptiveAnalog));
   EXPECT_NOERR(ap->gain_control()->set_analog_level_limits(0, 255));
   EXPECT_NOERR(ap->gain_control()->Enable(true));
 #endif
 
-  AudioProcessing::Config apm_config;
   apm_config.high_pass_filter.enabled = true;
   ap->ApplyConfig(apm_config);
 
@@ -1729,6 +1734,7 @@
 }
 
 void ApmTest::VerifyDebugDumpTest(Format format) {
+  rtc::ScopedFakeClock fake_clock;
   const std::string in_filename = test::ResourcePath("ref03", "aecdump");
   std::string format_string;
   switch (format) {
@@ -2182,9 +2188,9 @@
       // or generate a separate android reference.
 #if defined(WEBRTC_ANDROID)
       const int kHasVoiceCountOffset = 3;
-      const int kHasVoiceCountNear = 4;
+      const int kHasVoiceCountNear = 8;
       const int kMaxOutputAverageOffset = 9;
-      const int kMaxOutputAverageNear = 9;
+      const int kMaxOutputAverageNear = 26;
 #else
       const int kHasVoiceCountOffset = 0;
       const int kHasVoiceCountNear = kIntNear;
@@ -2796,6 +2802,25 @@
   apm->ProcessReverseStream(&audio);
 }
 
+TEST(ApmConfiguration, EnableCaptureAnalyzer) {
+  // Verify that apm uses a capture analyzer if one is provided.
+  auto mock_capture_analyzer_ptr =
+      new testing::NiceMock<test::MockCustomAudioAnalyzer>();
+  auto mock_capture_analyzer =
+      std::unique_ptr<CustomAudioAnalyzer>(mock_capture_analyzer_ptr);
+  rtc::scoped_refptr<AudioProcessing> apm =
+      AudioProcessingBuilder()
+          .SetCaptureAnalyzer(std::move(mock_capture_analyzer))
+          .Create();
+
+  AudioFrame audio;
+  audio.num_channels_ = 1;
+  SetFrameSampleRate(&audio, AudioProcessing::NativeRate::kSampleRate16kHz);
+
+  EXPECT_CALL(*mock_capture_analyzer_ptr, Analyze(testing::_)).Times(1);
+  apm->ProcessStream(&audio);
+}
+
 TEST(ApmConfiguration, PreProcessingReceivesRuntimeSettings) {
   auto mock_pre_processor_ptr =
       new testing::NiceMock<test::MockCustomProcessing>();
diff --git a/modules/audio_processing/debug.proto b/modules/audio_processing/debug.proto
index f7f8d10..b19f7fe 100644
--- a/modules/audio_processing/debug.proto
+++ b/modules/audio_processing/debug.proto
@@ -14,6 +14,7 @@
   optional int32 output_sample_rate = 7;
   optional int32 reverse_output_sample_rate = 8;
   optional int32 num_reverse_output_channels = 9;
+  optional int64 timestamp_ms = 10;
 }
 
 // May contain interleaved or deinterleaved data, but don't store both formats.
@@ -46,7 +47,6 @@
 // Contains the configurations of various APM component. A Config message is
 // added when any of the fields are changed.
 message Config {
-  // Next field number 19.
   // Acoustic echo canceler.
   optional bool aec_enabled = 1;
   optional bool aec_delay_agnostic_enabled = 2;
@@ -72,11 +72,12 @@
   // Semicolon-separated string containing experimental feature
   // descriptions.
   optional string experiments_description = 17;
-  // Intelligibility Enhancer.
-  optional bool intelligibility_enhancer_enabled = 18;
+  reserved 18;  // Intelligibility enhancer enabled (deprecated).
   // Pre amplifier.
   optional bool pre_amplifier_enabled = 19;
   optional float pre_amplifier_fixed_gain_factor = 20;
+
+  // Next field number 21.
 }
 
 message Event {
diff --git a/modules/audio_processing/echo_cancellation_impl.cc b/modules/audio_processing/echo_cancellation_impl.cc
index 15cd0db..9feaea7 100644
--- a/modules/audio_processing/echo_cancellation_impl.cc
+++ b/modules/audio_processing/echo_cancellation_impl.cc
@@ -109,7 +109,7 @@
       crit_capture_(crit_capture),
       drift_compensation_enabled_(false),
       metrics_enabled_(false),
-      suppression_level_(kModerateSuppression),
+      suppression_level_(kHighSuppression),
       stream_drift_samples_(0),
       was_stream_drift_set_(false),
       stream_has_echo_(false),
diff --git a/modules/audio_processing/echo_cancellation_proxy.cc b/modules/audio_processing/echo_cancellation_proxy.cc
new file mode 100644
index 0000000..e8b1fbd
--- /dev/null
+++ b/modules/audio_processing/echo_cancellation_proxy.cc
@@ -0,0 +1,100 @@
+/*
+ *  Copyright (c) 2018 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 "modules/audio_processing/echo_cancellation_proxy.h"
+
+namespace webrtc {
+
+EchoCancellationProxy::EchoCancellationProxy(
+    AudioProcessing* audio_processing,
+    EchoCancellation* echo_cancellation)
+    : audio_processing_(audio_processing),
+      echo_cancellation_(echo_cancellation) {}
+
+EchoCancellationProxy::~EchoCancellationProxy() = default;
+
+int EchoCancellationProxy::Enable(bool enable) {
+  // Change the config in APM to mirror the applied settings.
+  // TODO(bugs.webrtc.org/9535): Remove the call to EchoCancellation::Enable
+  // when APM starts taking the config into account.
+  AudioProcessing::Config apm_config = audio_processing_->GetConfig();
+  bool aec2_enabled = apm_config.echo_canceller.enabled &&
+                      !apm_config.echo_canceller.mobile_mode;
+  if ((aec2_enabled && !enable) || (!aec2_enabled && enable)) {
+    apm_config.echo_canceller.enabled = enable;
+    apm_config.echo_canceller.mobile_mode = false;
+    audio_processing_->ApplyConfig(apm_config);
+  }
+  echo_cancellation_->Enable(enable);
+  return AudioProcessing::kNoError;
+}
+
+bool EchoCancellationProxy::is_enabled() const {
+  return echo_cancellation_->is_enabled();
+}
+
+int EchoCancellationProxy::enable_drift_compensation(bool enable) {
+  return echo_cancellation_->enable_drift_compensation(enable);
+}
+
+bool EchoCancellationProxy::is_drift_compensation_enabled() const {
+  return echo_cancellation_->is_drift_compensation_enabled();
+}
+
+void EchoCancellationProxy::set_stream_drift_samples(int drift) {
+  echo_cancellation_->set_stream_drift_samples(drift);
+}
+
+int EchoCancellationProxy::stream_drift_samples() const {
+  return echo_cancellation_->stream_drift_samples();
+}
+
+int EchoCancellationProxy::set_suppression_level(
+    EchoCancellation::SuppressionLevel level) {
+  return echo_cancellation_->set_suppression_level(level);
+}
+
+EchoCancellation::SuppressionLevel EchoCancellationProxy::suppression_level()
+    const {
+  return echo_cancellation_->suppression_level();
+}
+
+bool EchoCancellationProxy::stream_has_echo() const {
+  return echo_cancellation_->stream_has_echo();
+}
+int EchoCancellationProxy::enable_metrics(bool enable) {
+  return echo_cancellation_->enable_metrics(enable);
+}
+bool EchoCancellationProxy::are_metrics_enabled() const {
+  return echo_cancellation_->are_metrics_enabled();
+}
+int EchoCancellationProxy::GetMetrics(Metrics* metrics) {
+  return echo_cancellation_->GetMetrics(metrics);
+}
+int EchoCancellationProxy::enable_delay_logging(bool enable) {
+  return echo_cancellation_->enable_delay_logging(enable);
+}
+bool EchoCancellationProxy::is_delay_logging_enabled() const {
+  return echo_cancellation_->is_delay_logging_enabled();
+}
+int EchoCancellationProxy::GetDelayMetrics(int* median, int* std) {
+  return echo_cancellation_->GetDelayMetrics(median, std);
+}
+int EchoCancellationProxy::GetDelayMetrics(int* median,
+                                           int* std,
+                                           float* fraction_poor_delays) {
+  return echo_cancellation_->GetDelayMetrics(median, std, fraction_poor_delays);
+}
+
+struct AecCore* EchoCancellationProxy::aec_core() const {
+  return echo_cancellation_->aec_core();
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_processing/echo_cancellation_proxy.h b/modules/audio_processing/echo_cancellation_proxy.h
new file mode 100644
index 0000000..f2d3017
--- /dev/null
+++ b/modules/audio_processing/echo_cancellation_proxy.h
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (c) 2018 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 MODULES_AUDIO_PROCESSING_ECHO_CANCELLATION_PROXY_H_
+#define MODULES_AUDIO_PROCESSING_ECHO_CANCELLATION_PROXY_H_
+
+#include "modules/audio_processing/include/audio_processing.h"
+#include "rtc_base/constructormagic.h"
+#include "rtc_base/scoped_ref_ptr.h"
+
+namespace webrtc {
+
+// Class for temporarily redirecting AEC2 configuration to a new API.
+class EchoCancellationProxy : public EchoCancellation {
+ public:
+  EchoCancellationProxy(AudioProcessing* audio_processing,
+                        EchoCancellation* echo_cancellation);
+  ~EchoCancellationProxy() override;
+
+  int Enable(bool enable) override;
+  bool is_enabled() const override;
+  int enable_drift_compensation(bool enable) override;
+  bool is_drift_compensation_enabled() const override;
+  void set_stream_drift_samples(int drift) override;
+  int stream_drift_samples() const override;
+  int set_suppression_level(SuppressionLevel level) override;
+  SuppressionLevel suppression_level() const override;
+  bool stream_has_echo() const override;
+  int enable_metrics(bool enable) override;
+  bool are_metrics_enabled() const override;
+  int GetMetrics(Metrics* metrics) override;
+  int enable_delay_logging(bool enable) override;
+  bool is_delay_logging_enabled() const override;
+  int GetDelayMetrics(int* median, int* std) override;
+  int GetDelayMetrics(int* median,
+                      int* std,
+                      float* fraction_poor_delays) override;
+  struct AecCore* aec_core() const override;
+
+ private:
+  AudioProcessing* audio_processing_;
+  EchoCancellation* echo_cancellation_;
+
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCancellationProxy);
+};
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_PROCESSING_ECHO_CANCELLATION_PROXY_H_
diff --git a/modules/audio_processing/echo_control_mobile_impl.cc b/modules/audio_processing/echo_control_mobile_impl.cc
index 841364f..272da7a 100644
--- a/modules/audio_processing/echo_control_mobile_impl.cc
+++ b/modules/audio_processing/echo_control_mobile_impl.cc
@@ -113,7 +113,7 @@
     : crit_render_(crit_render),
       crit_capture_(crit_capture),
       routing_mode_(kSpeakerphone),
-      comfort_noise_enabled_(true),
+      comfort_noise_enabled_(false),
       external_echo_path_(NULL) {
   RTC_DCHECK(crit_render);
   RTC_DCHECK(crit_capture);
diff --git a/modules/audio_processing/echo_control_mobile_proxy.cc b/modules/audio_processing/echo_control_mobile_proxy.cc
new file mode 100644
index 0000000..fd29834
--- /dev/null
+++ b/modules/audio_processing/echo_control_mobile_proxy.cc
@@ -0,0 +1,69 @@
+/*
+ *  Copyright (c) 2018 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 "modules/audio_processing/echo_control_mobile_proxy.h"
+
+namespace webrtc {
+
+EchoControlMobileProxy::EchoControlMobileProxy(
+    AudioProcessing* audio_processing,
+    EchoControlMobile* echo_control_mobile)
+    : audio_processing_(audio_processing),
+      echo_control_mobile_(echo_control_mobile) {}
+
+EchoControlMobileProxy::~EchoControlMobileProxy() = default;
+
+int EchoControlMobileProxy::Enable(bool enable) {
+  // Change the config in APM to mirror the applied settings.
+  // TODO(bugs.webrtc.org/9535): Remove the call to EchoControlMobile::Enable
+  // when APM starts taking the config into account.
+  AudioProcessing::Config apm_config = audio_processing_->GetConfig();
+  bool aecm_enabled = apm_config.echo_canceller.enabled &&
+                      apm_config.echo_canceller.mobile_mode;
+  if ((aecm_enabled && !enable) || (!aecm_enabled && enable)) {
+    apm_config.echo_canceller.enabled = enable;
+    apm_config.echo_canceller.mobile_mode = true;
+    audio_processing_->ApplyConfig(apm_config);
+  }
+  echo_control_mobile_->Enable(enable);
+  return AudioProcessing::kNoError;
+}
+
+bool EchoControlMobileProxy::is_enabled() const {
+  return echo_control_mobile_->is_enabled();
+}
+
+int EchoControlMobileProxy::set_routing_mode(RoutingMode mode) {
+  return echo_control_mobile_->set_routing_mode(mode);
+}
+
+EchoControlMobile::RoutingMode EchoControlMobileProxy::routing_mode() const {
+  return echo_control_mobile_->routing_mode();
+}
+
+int EchoControlMobileProxy::enable_comfort_noise(bool enable) {
+  return echo_control_mobile_->enable_comfort_noise(enable);
+}
+
+bool EchoControlMobileProxy::is_comfort_noise_enabled() const {
+  return echo_control_mobile_->is_comfort_noise_enabled();
+}
+
+int EchoControlMobileProxy::SetEchoPath(const void* echo_path,
+                                        size_t size_bytes) {
+  return echo_control_mobile_->SetEchoPath(echo_path, size_bytes);
+}
+
+int EchoControlMobileProxy::GetEchoPath(void* echo_path,
+                                        size_t size_bytes) const {
+  return echo_control_mobile_->GetEchoPath(echo_path, size_bytes);
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_processing/echo_control_mobile_proxy.h b/modules/audio_processing/echo_control_mobile_proxy.h
new file mode 100644
index 0000000..eb5908a
--- /dev/null
+++ b/modules/audio_processing/echo_control_mobile_proxy.h
@@ -0,0 +1,44 @@
+/*
+ *  Copyright (c) 2018 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 MODULES_AUDIO_PROCESSING_ECHO_CONTROL_MOBILE_PROXY_H_
+#define MODULES_AUDIO_PROCESSING_ECHO_CONTROL_MOBILE_PROXY_H_
+
+#include "modules/audio_processing/include/audio_processing.h"
+#include "rtc_base/constructormagic.h"
+#include "rtc_base/scoped_ref_ptr.h"
+
+namespace webrtc {
+
+// Class for temporarily redirecting AECM configuration to a new API.
+class EchoControlMobileProxy : public EchoControlMobile {
+ public:
+  EchoControlMobileProxy(AudioProcessing* audio_processing,
+                         EchoControlMobile* echo_control_mobile);
+  ~EchoControlMobileProxy() override;
+
+  bool is_enabled() const override;
+  RoutingMode routing_mode() const override;
+  bool is_comfort_noise_enabled() const override;
+  int Enable(bool enable) override;
+  int set_routing_mode(RoutingMode mode) override;
+  int enable_comfort_noise(bool enable) override;
+  int SetEchoPath(const void* echo_path, size_t size_bytes) override;
+  int GetEchoPath(void* echo_path, size_t size_bytes) const override;
+
+ private:
+  AudioProcessing* audio_processing_;
+  EchoControlMobile* echo_control_mobile_;
+
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoControlMobileProxy);
+};
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_PROCESSING_ECHO_CONTROL_MOBILE_PROXY_H_
diff --git a/modules/audio_processing/gain_control_for_experimental_agc.cc b/modules/audio_processing/gain_control_for_experimental_agc.cc
index d5d978c..4ab856c 100644
--- a/modules/audio_processing/gain_control_for_experimental_agc.cc
+++ b/modules/audio_processing/gain_control_for_experimental_agc.cc
@@ -12,6 +12,7 @@
 
 #include "modules/audio_processing/include/audio_processing.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
+#include "rtc_base/atomicops.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/criticalsection.h"
 
@@ -22,12 +23,11 @@
 GainControlForExperimentalAgc::GainControlForExperimentalAgc(
     GainControl* gain_control,
     rtc::CriticalSection* crit_capture)
-    : data_dumper_(new ApmDataDumper(instance_counter_)),
+    : data_dumper_(
+          new ApmDataDumper(rtc::AtomicOps::Increment(&instance_counter_))),
       real_gain_control_(gain_control),
       volume_(0),
-      crit_capture_(crit_capture) {
-  instance_counter_++;
-}
+      crit_capture_(crit_capture) {}
 
 GainControlForExperimentalAgc::~GainControlForExperimentalAgc() = default;
 
@@ -43,14 +43,18 @@
   rtc::CritScope cs_capture(crit_capture_);
   data_dumper_->DumpRaw("experimental_gain_control_set_stream_analog_level", 1,
                         &level);
+  do_log_level_ = true;
   volume_ = level;
   return AudioProcessing::kNoError;
 }
 
 int GainControlForExperimentalAgc::stream_analog_level() {
   rtc::CritScope cs_capture(crit_capture_);
-  data_dumper_->DumpRaw("experimental_gain_control_stream_analog_level", 1,
-                        &volume_);
+  if (do_log_level_) {
+    data_dumper_->DumpRaw("experimental_gain_control_stream_analog_level", 1,
+                          &volume_);
+    do_log_level_ = false;
+  }
   return volume_;
 }
 
diff --git a/modules/audio_processing/gain_control_for_experimental_agc.h b/modules/audio_processing/gain_control_for_experimental_agc.h
index 0894a0e..b20fbc9 100644
--- a/modules/audio_processing/gain_control_for_experimental_agc.h
+++ b/modules/audio_processing/gain_control_for_experimental_agc.h
@@ -68,6 +68,7 @@
   GainControl* real_gain_control_;
   int volume_;
   rtc::CriticalSection* crit_capture_;
+  bool do_log_level_ = true;
   static int instance_counter_;
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(GainControlForExperimentalAgc);
 };
diff --git a/modules/audio_processing/gain_controller2.cc b/modules/audio_processing/gain_controller2.cc
index 6c0149a..fd4b411 100644
--- a/modules/audio_processing/gain_controller2.cc
+++ b/modules/audio_processing/gain_controller2.cc
@@ -41,15 +41,25 @@
 void GainController2::Process(AudioBuffer* audio) {
   AudioFrameView<float> float_frame(audio->channels_f(), audio->num_channels(),
                                     audio->num_frames());
-  adaptive_agc_.Process(float_frame);
+  if (adaptive_digital_mode_) {
+    adaptive_agc_.Process(float_frame);
+  }
   fixed_gain_controller_.Process(float_frame);
 }
 
+void GainController2::NotifyAnalogLevel(int level) {
+  if (analog_level_ != level && adaptive_digital_mode_) {
+    adaptive_agc_.Reset();
+  }
+  analog_level_ = level;
+}
+
 void GainController2::ApplyConfig(
     const AudioProcessing::Config::GainController2& config) {
   RTC_DCHECK(Validate(config));
   config_ = config;
   fixed_gain_controller_.SetGain(config_.fixed_gain_db);
+  adaptive_digital_mode_ = config_.adaptive_digital_mode;
 }
 
 bool GainController2::Validate(
diff --git a/modules/audio_processing/gain_controller2.h b/modules/audio_processing/gain_controller2.h
index e2ca05e..b4727d0 100644
--- a/modules/audio_processing/gain_controller2.h
+++ b/modules/audio_processing/gain_controller2.h
@@ -33,6 +33,7 @@
 
   void Initialize(int sample_rate_hz);
   void Process(AudioBuffer* audio);
+  void NotifyAnalogLevel(int level);
 
   void ApplyConfig(const AudioProcessing::Config::GainController2& config);
   static bool Validate(const AudioProcessing::Config::GainController2& config);
@@ -45,6 +46,8 @@
   FixedGainController fixed_gain_controller_;
   AudioProcessing::Config::GainController2 config_;
   AdaptiveAgc adaptive_agc_;
+  int analog_level_ = -1;
+  bool adaptive_digital_mode_ = true;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(GainController2);
 };
diff --git a/modules/audio_processing/include/aec_dump.cc b/modules/audio_processing/include/aec_dump.cc
index c243b52..67809d0 100644
--- a/modules/audio_processing/include/aec_dump.cc
+++ b/modules/audio_processing/include/aec_dump.cc
@@ -32,8 +32,6 @@
          hpf_enabled == other.hpf_enabled && ns_enabled == other.ns_enabled &&
          ns_level == other.ns_level &&
          transient_suppression_enabled == other.transient_suppression_enabled &&
-         intelligibility_enhancer_enabled ==
-             other.intelligibility_enhancer_enabled &&
          noise_robust_agc_enabled == other.noise_robust_agc_enabled &&
          pre_amplifier_enabled == other.pre_amplifier_enabled &&
          pre_amplifier_fixed_gain_factor ==
diff --git a/modules/audio_processing/include/aec_dump.h b/modules/audio_processing/include/aec_dump.h
index 25c08b8..e32fa67 100644
--- a/modules/audio_processing/include/aec_dump.h
+++ b/modules/audio_processing/include/aec_dump.h
@@ -49,7 +49,6 @@
   bool ns_enabled = false;
   int ns_level = 0;
   bool transient_suppression_enabled = false;
-  bool intelligibility_enhancer_enabled = false;
   bool noise_robust_agc_enabled = false;
   bool pre_amplifier_enabled = false;
   float pre_amplifier_fixed_gain_factor = 1.f;
@@ -76,7 +75,11 @@
   virtual ~AecDump() = default;
 
   // Logs Event::Type INIT message.
-  virtual void WriteInitMessage(const ProcessingConfig& api_format) = 0;
+  virtual void WriteInitMessage(const ProcessingConfig& api_format,
+                                int64_t time_now_ms) = 0;
+  RTC_DEPRECATED void WriteInitMessage(const ProcessingConfig& api_format) {
+    WriteInitMessage(api_format, 0);
+  }
 
   // Logs Event::Type STREAM message. To log an input/output pair,
   // call the AddCapture* and AddAudioProcessingState methods followed
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index 9d27f16..f05d7b6 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -34,7 +34,6 @@
 #include "rtc_base/platform_file.h"
 #include "rtc_base/refcount.h"
 #include "rtc_base/scoped_ref_ptr.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -54,12 +53,10 @@
 class HighPassFilter;
 class LevelEstimator;
 class NoiseSuppression;
+class CustomAudioAnalyzer;
 class CustomProcessing;
 class VoiceDetection;
 
-// webrtc:8665, addedd temporarily to avoid breaking dependencies.
-typedef CustomProcessing PostProcessing;
-
 // Use to enable the extended filter mode in the AEC, along with robustness
 // measures around the reported system delays. It comes with a significant
 // increase in AEC complexity, but is much more robust to unreliable reported
@@ -125,10 +122,10 @@
   explicit ExperimentalAgc(bool enabled) : enabled(enabled) {}
   ExperimentalAgc(bool enabled,
                   bool enabled_agc2_level_estimator,
-                  bool enabled_agc2_digital_adaptive)
+                  bool digital_adaptive_disabled)
       : enabled(enabled),
         enabled_agc2_level_estimator(enabled_agc2_level_estimator),
-        enabled_agc2_digital_adaptive(enabled_agc2_digital_adaptive) {}
+        digital_adaptive_disabled(digital_adaptive_disabled) {}
 
   ExperimentalAgc(bool enabled, int startup_min_volume)
       : enabled(enabled), startup_min_volume(startup_min_volume) {}
@@ -142,7 +139,7 @@
   // Lowest microphone level that will be applied in response to clipping.
   int clipped_level_min = kClippedLevelMin;
   bool enabled_agc2_level_estimator = false;
-  bool enabled_agc2_digital_adaptive = false;
+  bool digital_adaptive_disabled = false;
 };
 
 // Use to enable experimental noise suppression. It can be set in the
@@ -154,17 +151,6 @@
   bool enabled;
 };
 
-// Use to enable intelligibility enhancer in audio processing.
-//
-// Note: If enabled and the reverse stream has more than one output channel,
-// the reverse stream will become an upmixed mono signal.
-struct Intelligibility {
-  Intelligibility() : enabled(false) {}
-  explicit Intelligibility(bool enabled) : enabled(enabled) {}
-  static const ConfigOptionID identifier = ConfigOptionID::kIntelligibility;
-  bool enabled;
-};
-
 // The Audio Processing Module (APM) provides a collection of voice processing
 // components designed for real-time communications software.
 //
@@ -253,6 +239,15 @@
   // by changing the default values in the AudioProcessing::Config struct.
   // The config is applied by passing the struct to the ApplyConfig method.
   struct Config {
+    // TODO(bugs.webrtc.org/9535): Currently unused. Use this to determine AEC.
+    struct EchoCanceller {
+      bool enabled = false;
+      bool mobile_mode = false;
+      // Recommended not to use. Will be removed in the future.
+      // APM components are not fine-tuned for legacy suppression levels.
+      bool legacy_moderate_suppression_level = false;
+    } echo_canceller;
+
     struct ResidualEchoDetector {
       bool enabled = true;
     } residual_echo_detector;
@@ -268,12 +263,15 @@
       float fixed_gain_factor = 1.f;
     } pre_amplifier;
 
-    // Enables the next generation AGC functionality. This feature
-    // replaces the standard methods of gain control in the previous
-    // AGC. This functionality is currently only partially
-    // implemented.
+    // Enables the next generation AGC functionality. This feature replaces the
+    // standard methods of gain control in the previous AGC. Enabling this
+    // submodule enables an adaptive digital AGC followed by a limiter. By
+    // setting |fixed_gain_db|, the limiter can be turned into a compressor that
+    // first applies a fixed gain. The adaptive digital AGC can be turned off by
+    // setting |adaptive_digital_mode=false|.
     struct GainController2 {
       bool enabled = false;
+      bool adaptive_digital_mode = true;
       float fixed_gain_db = 0.f;
     } gain_controller2;
 
@@ -667,6 +665,9 @@
   // The AudioProcessingBuilder takes ownership of the echo_detector.
   AudioProcessingBuilder& SetEchoDetector(
       rtc::scoped_refptr<EchoDetector> echo_detector);
+  // The AudioProcessingBuilder takes ownership of the capture_analyzer.
+  AudioProcessingBuilder& SetCaptureAnalyzer(
+      std::unique_ptr<CustomAudioAnalyzer> capture_analyzer);
   // This creates an APM instance using the previously set components. Calling
   // the Create function resets the AudioProcessingBuilder to its initial state.
   AudioProcessing* Create();
@@ -677,6 +678,7 @@
   std::unique_ptr<CustomProcessing> capture_post_processing_;
   std::unique_ptr<CustomProcessing> render_pre_processing_;
   rtc::scoped_refptr<EchoDetector> echo_detector_;
+  std::unique_ptr<CustomAudioAnalyzer> capture_analyzer_;
   RTC_DISALLOW_COPY_AND_ASSIGN(AudioProcessingBuilder);
 };
 
@@ -1010,6 +1012,19 @@
   virtual ~NoiseSuppression() {}
 };
 
+// Experimental interface for a custom analysis submodule.
+class CustomAudioAnalyzer {
+ public:
+  // (Re-) Initializes the submodule.
+  virtual void Initialize(int sample_rate_hz, int num_channels) = 0;
+  // Analyzes the given capture or render signal.
+  virtual void Analyze(const AudioBuffer* audio) = 0;
+  // Returns a string representation of the module state.
+  virtual std::string ToString() const = 0;
+
+  virtual ~CustomAudioAnalyzer() {}
+};
+
 // Interface for a custom processing submodule.
 class CustomProcessing {
  public:
diff --git a/modules/audio_processing/include/config.h b/modules/audio_processing/include/config.h
index 9232b2e..398aab6 100644
--- a/modules/audio_processing/include/config.h
+++ b/modules/audio_processing/include/config.h
@@ -30,9 +30,9 @@
   kDelayAgnostic,
   kExperimentalAgc,
   kExperimentalNs,
-  kBeamforming,  // Deprecated
-  kIntelligibility,
-  kEchoCanceller3,  // Deprecated
+  kBeamforming,      // Deprecated
+  kIntelligibility,  // Deprecated
+  kEchoCanceller3,   // Deprecated
   kAecRefinedAdaptiveFilter,
   kLevelControl  // Deprecated
 };
diff --git a/modules/audio_processing/include/mock_audio_processing.h b/modules/audio_processing/include/mock_audio_processing.h
index 9ceee10..2864e48 100644
--- a/modules/audio_processing/include/mock_audio_processing.h
+++ b/modules/audio_processing/include/mock_audio_processing.h
@@ -115,6 +115,14 @@
   MOCK_CONST_METHOD0(ToString, std::string());
 };
 
+class MockCustomAudioAnalyzer : public CustomAudioAnalyzer {
+ public:
+  virtual ~MockCustomAudioAnalyzer() {}
+  MOCK_METHOD2(Initialize, void(int sample_rate_hz, int num_channels));
+  MOCK_METHOD1(Analyze, void(const AudioBuffer* audio));
+  MOCK_CONST_METHOD0(ToString, std::string());
+};
+
 class MockEchoControl : public EchoControl {
  public:
   virtual ~MockEchoControl() {}
diff --git a/modules/audio_processing/intelligibility/intelligibility_enhancer.cc b/modules/audio_processing/intelligibility/intelligibility_enhancer.cc
deleted file mode 100644
index 0f7b118..0000000
--- a/modules/audio_processing/intelligibility/intelligibility_enhancer.cc
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- *  Copyright (c) 2014 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 "modules/audio_processing/intelligibility/intelligibility_enhancer.h"
-
-#include <math.h>
-#include <stdlib.h>
-#include <algorithm>
-#include <limits>
-#include <numeric>
-
-#include "common_audio/include/audio_util.h"
-#include "common_audio/window_generator.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/numerics/safe_minmax.h"
-
-namespace webrtc {
-
-namespace {
-
-const size_t kErbResolution = 2;
-const int kWindowSizeMs = 16;
-const int kChunkSizeMs = 10;  // Size provided by APM.
-const float kClipFreqKhz = 0.2f;
-const float kKbdAlpha = 1.5f;
-const float kLambdaBot = -1.f;    // Extreme values in bisection
-const float kLambdaTop = -1e-5f;  // search for lamda.
-const float kVoiceProbabilityThreshold = 0.5f;
-// Number of chunks after voice activity which is still considered speech.
-const size_t kSpeechOffsetDelay = 10;
-const float kDecayRate = 0.995f;  // Power estimation decay rate.
-const float kMaxRelativeGainChange = 0.005f;
-const float kRho = 0.0004f;  // Default production and interpretation SNR.
-const float kPowerNormalizationFactor = 1.f / (1 << 30);
-const float kMaxActiveSNR = 128.f;   // 21dB
-const float kMinInactiveSNR = 32.f;  // 15dB
-const size_t kGainUpdatePeriod = 10u;
-
-// Returns dot product of vectors |a| and |b| with size |length|.
-float DotProduct(const float* a, const float* b, size_t length) {
-  float ret = 0.f;
-  for (size_t i = 0; i < length; ++i) {
-    ret += a[i] * b[i];
-  }
-  return ret;
-}
-
-// Computes the power across ERB bands from the power spectral density |pow|.
-// Stores it in |result|.
-void MapToErbBands(const float* pow,
-                   const std::vector<std::vector<float>>& filter_bank,
-                   float* result) {
-  for (size_t i = 0; i < filter_bank.size(); ++i) {
-    RTC_DCHECK_GT(filter_bank[i].size(), 0);
-    result[i] = kPowerNormalizationFactor *
-                DotProduct(filter_bank[i].data(), pow, filter_bank[i].size());
-  }
-}
-
-}  // namespace
-
-IntelligibilityEnhancer::IntelligibilityEnhancer(int sample_rate_hz,
-                                                 size_t num_render_channels,
-                                                 size_t num_bands,
-                                                 size_t num_noise_bins)
-    : freqs_(RealFourier::ComplexLength(
-          RealFourier::FftOrder(sample_rate_hz * kWindowSizeMs / 1000))),
-      num_noise_bins_(num_noise_bins),
-      chunk_length_(static_cast<size_t>(sample_rate_hz * kChunkSizeMs / 1000)),
-      bank_size_(GetBankSize(sample_rate_hz, kErbResolution)),
-      sample_rate_hz_(sample_rate_hz),
-      num_render_channels_(num_render_channels),
-      clear_power_estimator_(freqs_, kDecayRate),
-      noise_power_estimator_(num_noise_bins, kDecayRate),
-      filtered_clear_pow_(bank_size_, 0.f),
-      filtered_noise_pow_(num_noise_bins, 0.f),
-      center_freqs_(bank_size_),
-      capture_filter_bank_(CreateErbBank(num_noise_bins)),
-      render_filter_bank_(CreateErbBank(freqs_)),
-      gains_eq_(bank_size_),
-      gain_applier_(freqs_, kMaxRelativeGainChange),
-      audio_s16_(chunk_length_),
-      chunks_since_voice_(kSpeechOffsetDelay),
-      is_speech_(false),
-      snr_(kMaxActiveSNR),
-      is_active_(false),
-      num_chunks_(0u),
-      num_active_chunks_(0u),
-      noise_estimation_buffer_(num_noise_bins),
-      noise_estimation_queue_(kMaxNumNoiseEstimatesToBuffer,
-                              std::vector<float>(num_noise_bins),
-                              RenderQueueItemVerifier<float>(num_noise_bins)) {
-  RTC_DCHECK_LE(kRho, 1.f);
-
-  const size_t erb_index = static_cast<size_t>(
-      ceilf(11.17f * logf((kClipFreqKhz + 0.312f) / (kClipFreqKhz + 14.6575f)) +
-            43.f));
-  start_freq_ = std::max(static_cast<size_t>(1), erb_index * kErbResolution);
-
-  size_t window_size = static_cast<size_t>(1) << RealFourier::FftOrder(freqs_);
-  std::vector<float> kbd_window(window_size);
-  WindowGenerator::KaiserBesselDerived(kKbdAlpha, window_size,
-                                       kbd_window.data());
-  render_mangler_.reset(new LappedTransform(
-      num_render_channels_, num_render_channels_, chunk_length_,
-      kbd_window.data(), window_size, window_size / 2, this));
-
-  const size_t initial_delay = render_mangler_->initial_delay();
-  for (size_t i = 0u; i < num_bands - 1; ++i) {
-    high_bands_buffers_.push_back(std::unique_ptr<intelligibility::DelayBuffer>(
-        new intelligibility::DelayBuffer(initial_delay, num_render_channels_)));
-  }
-}
-
-IntelligibilityEnhancer::~IntelligibilityEnhancer() {
-  // Don't rely on this log, since the destructor isn't called when the
-  // app/tab is killed.
-  if (num_chunks_ > 0) {
-    RTC_LOG(LS_INFO) << "Intelligibility Enhancer was active for "
-                     << 100.f * static_cast<float>(num_active_chunks_) /
-                            num_chunks_
-                     << "% of the call.";
-  } else {
-    RTC_LOG(LS_INFO) << "Intelligibility Enhancer processed no chunk.";
-  }
-}
-
-void IntelligibilityEnhancer::SetCaptureNoiseEstimate(std::vector<float> noise,
-                                                      float gain) {
-  RTC_DCHECK_EQ(noise.size(), num_noise_bins_);
-  for (auto& bin : noise) {
-    bin *= gain;
-  }
-  // Disregarding return value since buffer overflow is acceptable, because it
-  // is not critical to get each noise estimate.
-  if (noise_estimation_queue_.Insert(&noise)) {
-  };
-}
-
-void IntelligibilityEnhancer::ProcessRenderAudio(AudioBuffer* audio) {
-  RTC_DCHECK_EQ(num_render_channels_, audio->num_channels());
-  while (noise_estimation_queue_.Remove(&noise_estimation_buffer_)) {
-    noise_power_estimator_.Step(noise_estimation_buffer_.data());
-  }
-  float* const* low_band = audio->split_channels_f(kBand0To8kHz);
-  is_speech_ = IsSpeech(low_band[0]);
-  render_mangler_->ProcessChunk(low_band, low_band);
-  DelayHighBands(audio);
-}
-
-void IntelligibilityEnhancer::ProcessAudioBlock(
-    const std::complex<float>* const* in_block,
-    size_t in_channels,
-    size_t frames,
-    size_t /* out_channels */,
-    std::complex<float>* const* out_block) {
-  RTC_DCHECK_EQ(freqs_, frames);
-  if (is_speech_) {
-    clear_power_estimator_.Step(in_block[0]);
-  }
-  SnrBasedEffectActivation();
-  ++num_chunks_;
-  if (is_active_) {
-    ++num_active_chunks_;
-    if (num_chunks_ % kGainUpdatePeriod == 0) {
-      MapToErbBands(clear_power_estimator_.power().data(), render_filter_bank_,
-                    filtered_clear_pow_.data());
-      MapToErbBands(noise_power_estimator_.power().data(), capture_filter_bank_,
-                    filtered_noise_pow_.data());
-      SolveForGainsGivenLambda(kLambdaTop, start_freq_, gains_eq_.data());
-      const float power_target =
-          std::accumulate(filtered_clear_pow_.data(),
-                          filtered_clear_pow_.data() + bank_size_, 0.f);
-      const float power_top =
-          DotProduct(gains_eq_.data(), filtered_clear_pow_.data(), bank_size_);
-      SolveForGainsGivenLambda(kLambdaBot, start_freq_, gains_eq_.data());
-      const float power_bot =
-          DotProduct(gains_eq_.data(), filtered_clear_pow_.data(), bank_size_);
-      if (power_target >= power_bot && power_target <= power_top) {
-        SolveForLambda(power_target);
-        UpdateErbGains();
-      }  // Else experiencing power underflow, so do nothing.
-    }
-  }
-  for (size_t i = 0; i < in_channels; ++i) {
-    gain_applier_.Apply(in_block[i], out_block[i]);
-  }
-}
-
-void IntelligibilityEnhancer::SnrBasedEffectActivation() {
-  const float* clear_psd = clear_power_estimator_.power().data();
-  const float* noise_psd = noise_power_estimator_.power().data();
-  const float clear_power = std::accumulate(clear_psd, clear_psd + freqs_, 0.f);
-  const float noise_power = std::accumulate(noise_psd, noise_psd + freqs_, 0.f);
-  snr_ = kDecayRate * snr_ +
-         (1.f - kDecayRate) * clear_power /
-             (noise_power + std::numeric_limits<float>::epsilon());
-  if (is_active_) {
-    if (snr_ > kMaxActiveSNR) {
-      RTC_LOG(LS_INFO) << "Intelligibility Enhancer was deactivated at chunk "
-                       << num_chunks_;
-      is_active_ = false;
-      // Set the target gains to unity.
-      float* gains = gain_applier_.target();
-      for (size_t i = 0; i < freqs_; ++i) {
-        gains[i] = 1.f;
-      }
-    }
-  } else {
-    if (snr_ < kMinInactiveSNR) {
-      RTC_LOG(LS_INFO) << "Intelligibility Enhancer was activated at chunk "
-                       << num_chunks_;
-      is_active_ = true;
-    }
-  }
-}
-
-void IntelligibilityEnhancer::SolveForLambda(float power_target) {
-  const float kConvergeThresh = 0.001f;  // TODO(ekmeyerson): Find best values
-  const int kMaxIters = 100;             // for these, based on experiments.
-
-  const float reciprocal_power_target =
-      1.f / (power_target + std::numeric_limits<float>::epsilon());
-  float lambda_bot = kLambdaBot;
-  float lambda_top = kLambdaTop;
-  float power_ratio = 2.f;  // Ratio of achieved power to target power.
-  int iters = 0;
-  while (std::fabs(power_ratio - 1.f) > kConvergeThresh && iters <= kMaxIters) {
-    const float lambda = (lambda_bot + lambda_top) / 2.f;
-    SolveForGainsGivenLambda(lambda, start_freq_, gains_eq_.data());
-    const float power =
-        DotProduct(gains_eq_.data(), filtered_clear_pow_.data(), bank_size_);
-    if (power < power_target) {
-      lambda_bot = lambda;
-    } else {
-      lambda_top = lambda;
-    }
-    power_ratio = std::fabs(power * reciprocal_power_target);
-    ++iters;
-  }
-}
-
-void IntelligibilityEnhancer::UpdateErbGains() {
-  // (ERB gain) = filterbank' * (freq gain)
-  float* gains = gain_applier_.target();
-  for (size_t i = 0; i < freqs_; ++i) {
-    gains[i] = 0.f;
-    for (size_t j = 0; j < bank_size_; ++j) {
-      gains[i] += render_filter_bank_[j][i] * gains_eq_[j];
-    }
-  }
-}
-
-size_t IntelligibilityEnhancer::GetBankSize(int sample_rate,
-                                            size_t erb_resolution) {
-  float freq_limit = sample_rate / 2000.f;
-  size_t erb_scale = static_cast<size_t>(ceilf(
-      11.17f * logf((freq_limit + 0.312f) / (freq_limit + 14.6575f)) + 43.f));
-  return erb_scale * erb_resolution;
-}
-
-std::vector<std::vector<float>> IntelligibilityEnhancer::CreateErbBank(
-    size_t num_freqs) {
-  std::vector<std::vector<float>> filter_bank(bank_size_);
-  size_t lf = 1, rf = 4;
-
-  for (size_t i = 0; i < bank_size_; ++i) {
-    float abs_temp = fabsf((i + 1.f) / static_cast<float>(kErbResolution));
-    center_freqs_[i] = 676170.4f / (47.06538f - expf(0.08950404f * abs_temp));
-    center_freqs_[i] -= 14678.49f;
-  }
-  float last_center_freq = center_freqs_[bank_size_ - 1];
-  for (size_t i = 0; i < bank_size_; ++i) {
-    center_freqs_[i] *= 0.5f * sample_rate_hz_ / last_center_freq;
-  }
-
-  for (size_t i = 0; i < bank_size_; ++i) {
-    filter_bank[i].resize(num_freqs);
-  }
-
-  for (size_t i = 1; i <= bank_size_; ++i) {
-    size_t lll = static_cast<size_t>(
-        round(center_freqs_[rtc::SafeMax<size_t>(1, i - lf) - 1] * num_freqs /
-              (0.5f * sample_rate_hz_)));
-    size_t ll = static_cast<size_t>(
-        round(center_freqs_[rtc::SafeMax<size_t>(1, i) - 1] * num_freqs /
-              (0.5f * sample_rate_hz_)));
-    lll = rtc::SafeClamp<size_t>(lll, 1, num_freqs) - 1;
-    ll = rtc::SafeClamp<size_t>(ll, 1, num_freqs) - 1;
-
-    size_t rrr = static_cast<size_t>(
-        round(center_freqs_[rtc::SafeMin<size_t>(bank_size_, i + rf) - 1] *
-              num_freqs / (0.5f * sample_rate_hz_)));
-    size_t rr = static_cast<size_t>(
-        round(center_freqs_[rtc::SafeMin<size_t>(bank_size_, i + 1) - 1] *
-              num_freqs / (0.5f * sample_rate_hz_)));
-    rrr = rtc::SafeClamp<size_t>(rrr, 1, num_freqs) - 1;
-    rr = rtc::SafeClamp<size_t>(rr, 1, num_freqs) - 1;
-
-    float step = ll == lll ? 0.f : 1.f / (ll - lll);
-    float element = 0.f;
-    for (size_t j = lll; j <= ll; ++j) {
-      filter_bank[i - 1][j] = element;
-      element += step;
-    }
-    step = rr == rrr ? 0.f : 1.f / (rrr - rr);
-    element = 1.f;
-    for (size_t j = rr; j <= rrr; ++j) {
-      filter_bank[i - 1][j] = element;
-      element -= step;
-    }
-    for (size_t j = ll; j <= rr; ++j) {
-      filter_bank[i - 1][j] = 1.f;
-    }
-  }
-
-  for (size_t i = 0; i < num_freqs; ++i) {
-    float sum = 0.f;
-    for (size_t j = 0; j < bank_size_; ++j) {
-      sum += filter_bank[j][i];
-    }
-    for (size_t j = 0; j < bank_size_; ++j) {
-      filter_bank[j][i] /= sum;
-    }
-  }
-  return filter_bank;
-}
-
-void IntelligibilityEnhancer::SolveForGainsGivenLambda(float lambda,
-                                                       size_t start_freq,
-                                                       float* sols) {
-  const float kMinPower = 1e-5f;
-
-  const float* pow_x0 = filtered_clear_pow_.data();
-  const float* pow_n0 = filtered_noise_pow_.data();
-
-  for (size_t n = 0; n < start_freq; ++n) {
-    sols[n] = 1.f;
-  }
-
-  // Analytic solution for optimal gains. See paper for derivation.
-  for (size_t n = start_freq; n < bank_size_; ++n) {
-    if (pow_x0[n] < kMinPower || pow_n0[n] < kMinPower) {
-      sols[n] = 1.f;
-    } else {
-      const float gamma0 = 0.5f * kRho * pow_x0[n] * pow_n0[n] +
-                           lambda * pow_x0[n] * pow_n0[n] * pow_n0[n];
-      const float beta0 =
-          lambda * pow_x0[n] * (2.f - kRho) * pow_x0[n] * pow_n0[n];
-      const float alpha0 =
-          lambda * pow_x0[n] * (1.f - kRho) * pow_x0[n] * pow_x0[n];
-      RTC_DCHECK_LT(alpha0, 0.f);
-      // The quadratic equation should always have real roots, but to guard
-      // against numerical errors we limit it to a minimum of zero.
-      sols[n] = std::max(
-          0.f, (-beta0 - std::sqrt(std::max(
-                             0.f, beta0 * beta0 - 4.f * alpha0 * gamma0))) /
-                   (2.f * alpha0));
-    }
-  }
-}
-
-bool IntelligibilityEnhancer::IsSpeech(const float* audio) {
-  FloatToS16(audio, chunk_length_, audio_s16_.data());
-  vad_.ProcessChunk(audio_s16_.data(), chunk_length_, sample_rate_hz_);
-  if (vad_.last_voice_probability() > kVoiceProbabilityThreshold) {
-    chunks_since_voice_ = 0;
-  } else if (chunks_since_voice_ < kSpeechOffsetDelay) {
-    ++chunks_since_voice_;
-  }
-  return chunks_since_voice_ < kSpeechOffsetDelay;
-}
-
-void IntelligibilityEnhancer::DelayHighBands(AudioBuffer* audio) {
-  RTC_DCHECK_EQ(audio->num_bands(), high_bands_buffers_.size() + 1);
-  for (size_t i = 0u; i < high_bands_buffers_.size(); ++i) {
-    Band band = static_cast<Band>(i + 1);
-    high_bands_buffers_[i]->Delay(audio->split_channels_f(band), chunk_length_);
-  }
-}
-
-}  // namespace webrtc
diff --git a/modules/audio_processing/intelligibility/intelligibility_enhancer.h b/modules/audio_processing/intelligibility/intelligibility_enhancer.h
deleted file mode 100644
index 3513092..0000000
--- a/modules/audio_processing/intelligibility/intelligibility_enhancer.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- *  Copyright (c) 2014 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 MODULES_AUDIO_PROCESSING_INTELLIGIBILITY_INTELLIGIBILITY_ENHANCER_H_
-#define MODULES_AUDIO_PROCESSING_INTELLIGIBILITY_INTELLIGIBILITY_ENHANCER_H_
-
-#include <complex>
-#include <memory>
-#include <vector>
-
-#include "common_audio/channel_buffer.h"
-#include "common_audio/lapped_transform.h"
-#include "modules/audio_processing/audio_buffer.h"
-#include "modules/audio_processing/intelligibility/intelligibility_utils.h"
-#include "modules/audio_processing/render_queue_item_verifier.h"
-#include "modules/audio_processing/vad/voice_activity_detector.h"
-#include "rtc_base/swap_queue.h"
-
-namespace webrtc {
-
-// Speech intelligibility enhancement module. Reads render and capture
-// audio streams and modifies the render stream with a set of gains per
-// frequency bin to enhance speech against the noise background.
-// Details of the model and algorithm can be found in the original paper:
-// http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=6882788
-class IntelligibilityEnhancer : public LappedTransform::Callback {
- public:
-  IntelligibilityEnhancer(int sample_rate_hz,
-                          size_t num_render_channels,
-                          size_t num_bands,
-                          size_t num_noise_bins);
-
-  ~IntelligibilityEnhancer() override;
-
-  // Sets the capture noise magnitude spectrum estimate.
-  void SetCaptureNoiseEstimate(std::vector<float> noise, float gain);
-
-  // Reads chunk of speech in time domain and updates with modified signal.
-  void ProcessRenderAudio(AudioBuffer* audio);
-  bool active() const;
-
- protected:
-  // All in frequency domain, receives input |in_block|, applies
-  // intelligibility enhancement, and writes result to |out_block|.
-  void ProcessAudioBlock(const std::complex<float>* const* in_block,
-                         size_t in_channels,
-                         size_t frames,
-                         size_t out_channels,
-                         std::complex<float>* const* out_block) override;
-
- private:
-  FRIEND_TEST_ALL_PREFIXES(IntelligibilityEnhancerTest, TestRenderUpdate);
-  FRIEND_TEST_ALL_PREFIXES(IntelligibilityEnhancerTest, TestErbCreation);
-  FRIEND_TEST_ALL_PREFIXES(IntelligibilityEnhancerTest, TestSolveForGains);
-  FRIEND_TEST_ALL_PREFIXES(IntelligibilityEnhancerTest,
-                           TestNoiseGainHasExpectedResult);
-  FRIEND_TEST_ALL_PREFIXES(IntelligibilityEnhancerTest,
-                           TestAllBandsHaveSameDelay);
-
-  // Updates the SNR estimation and enables or disables this component using a
-  // hysteresis.
-  void SnrBasedEffectActivation();
-
-  // Bisection search for optimal |lambda|.
-  void SolveForLambda(float power_target);
-
-  // Transforms freq gains to ERB gains.
-  void UpdateErbGains();
-
-  // Returns number of ERB filters.
-  static size_t GetBankSize(int sample_rate, size_t erb_resolution);
-
-  // Initializes ERB filterbank.
-  std::vector<std::vector<float>> CreateErbBank(size_t num_freqs);
-
-  // Analytically solves quadratic for optimal gains given |lambda|.
-  // Negative gains are set to 0. Stores the results in |sols|.
-  void SolveForGainsGivenLambda(float lambda, size_t start_freq, float* sols);
-
-  // Returns true if the audio is speech.
-  bool IsSpeech(const float* audio);
-
-  // Delays the high bands to compensate for the processing delay in the low
-  // band.
-  void DelayHighBands(AudioBuffer* audio);
-
-  static const size_t kMaxNumNoiseEstimatesToBuffer = 5;
-
-  const size_t freqs_;  // Num frequencies in frequency domain.
-  const size_t num_noise_bins_;
-  const size_t chunk_length_;  // Chunk size in samples.
-  const size_t bank_size_;     // Num ERB filters.
-  const int sample_rate_hz_;
-  const size_t num_render_channels_;
-
-  intelligibility::PowerEstimator<std::complex<float>> clear_power_estimator_;
-  intelligibility::PowerEstimator<float> noise_power_estimator_;
-  std::vector<float> filtered_clear_pow_;
-  std::vector<float> filtered_noise_pow_;
-  std::vector<float> center_freqs_;
-  std::vector<std::vector<float>> capture_filter_bank_;
-  std::vector<std::vector<float>> render_filter_bank_;
-  size_t start_freq_;
-
-  std::vector<float> gains_eq_;  // Pre-filter modified gains.
-  intelligibility::GainApplier gain_applier_;
-
-  std::unique_ptr<LappedTransform> render_mangler_;
-
-  VoiceActivityDetector vad_;
-  std::vector<int16_t> audio_s16_;
-  size_t chunks_since_voice_;
-  bool is_speech_;
-  float snr_;
-  bool is_active_;
-
-  unsigned long int num_chunks_;
-  unsigned long int num_active_chunks_;
-
-  std::vector<float> noise_estimation_buffer_;
-  SwapQueue<std::vector<float>, RenderQueueItemVerifier<float>>
-      noise_estimation_queue_;
-
-  std::vector<std::unique_ptr<intelligibility::DelayBuffer>>
-      high_bands_buffers_;
-};
-
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_PROCESSING_INTELLIGIBILITY_INTELLIGIBILITY_ENHANCER_H_
diff --git a/modules/audio_processing/intelligibility/intelligibility_enhancer_unittest.cc b/modules/audio_processing/intelligibility/intelligibility_enhancer_unittest.cc
deleted file mode 100644
index 98a8dae..0000000
--- a/modules/audio_processing/intelligibility/intelligibility_enhancer_unittest.cc
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- *  Copyright (c) 2015 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 <math.h>
-#include <stdlib.h>
-
-#include <algorithm>
-#include <memory>
-#include <vector>
-
-#include "api/array_view.h"
-#include "common_audio/signal_processing/include/signal_processing_library.h"
-#include "modules/audio_processing/audio_buffer.h"
-#include "modules/audio_processing/intelligibility/intelligibility_enhancer.h"
-#include "modules/audio_processing/noise_suppression_impl.h"
-#include "modules/audio_processing/test/audio_buffer_tools.h"
-#include "modules/audio_processing/test/bitexactness_tools.h"
-#include "rtc_base/arraysize.h"
-#include "test/gtest.h"
-
-namespace webrtc {
-
-namespace {
-
-// Target output for ERB create test. Generated with matlab.
-const float kTestCenterFreqs[] = {
-    14.5213f, 29.735f,  45.6781f, 62.3884f, 79.9058f, 98.2691f, 117.521f,
-    137.708f, 158.879f, 181.084f, 204.378f, 228.816f, 254.459f, 281.371f,
-    309.618f, 339.273f, 370.411f, 403.115f, 437.469f, 473.564f, 511.497f,
-    551.371f, 593.293f, 637.386f, 683.77f,  732.581f, 783.96f,  838.06f,
-    895.046f, 955.09f,  1018.38f, 1085.13f, 1155.54f, 1229.85f, 1308.32f,
-    1391.22f, 1478.83f, 1571.5f,  1669.55f, 1773.37f, 1883.37f, 2000.f};
-const float kTestFilterBank[][33] = {
-    {0.2f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,  0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,  0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.2f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,  0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,  0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.2f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,  0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,  0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.2f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,  0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,  0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.2f, 0.25f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,  0.f,   0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,  0.f,   0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.25f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f,   0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f,   0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.25f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f,   0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f,   0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.25f, 0.25f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f,   0.f,   0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f,   0.f,   0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.f, 0.25f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f,   0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f,   0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.f, 0.25f, 0.142857f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f,   0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f,   0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.f, 0.25f, 0.285714f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f,   0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f,   0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.f, 0.f, 0.285714f, 0.142857f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.f, 0.f, 0.285714f, 0.285714f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.f, 0.f, 0.f, 0.285714f, 0.142857f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.f, 0.f, 0.f, 0.285714f, 0.285714f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f, 0.142857f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f, 0.285714f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f, 0.142857f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f, 0.f, 0.f},
-    {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f, 0.285714f, 0.157895f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f, 0.f},
-    {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f, 0.210526f, 0.117647f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f},
-    {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f, 0.315789f, 0.176471f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f},
-    {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.315789f, 0.352941f, 0.142857f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f},
-    {0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.352941f, 0.285714f,
-     0.157895f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,
-     0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f},
-    {0.f,       0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.285714f,
-     0.210526f, 0.111111f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,       0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f, 0.f,       0.f,       0.f,       0.f,       0.f, 0.f, 0.f, 0.f,
-     0.f, 0.285714f, 0.315789f, 0.222222f, 0.111111f, 0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f,       0.f,       0.f,       0.f,       0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f,       0.f,       0.f,       0.f,       0.f},
-    {0.f, 0.f, 0.f,       0.f,       0.f,       0.f,       0.f, 0.f, 0.f,
-     0.f, 0.f, 0.315789f, 0.333333f, 0.222222f, 0.111111f, 0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f,       0.f,       0.f,       0.f,       0.f, 0.f, 0.f,
-     0.f, 0.f, 0.f,       0.f,       0.f,       0.f},
-    {0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f,       0.f, 0.f,
-     0.f, 0.f, 0.f, 0.333333f, 0.333333f, 0.222222f, 0.111111f, 0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f,       0.f, 0.f,
-     0.f, 0.f, 0.f, 0.f,       0.f,       0.f},
-    {0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f,       0.f,
-     0.f, 0.f, 0.f, 0.f, 0.333333f, 0.333333f, 0.222222f, 0.111111f, 0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f,       0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f,       0.f},
-    {0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.333333f, 0.333333f, 0.222222f, 0.111111f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,
-     0.f,       0.f, 0.f, 0.f, 0.f, 0.f, 0.333333f, 0.333333f, 0.222222f,
-     0.108108f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,
-     0.f,       0.f, 0.f, 0.f, 0.f, 0.f},
-    {0.f,       0.f,       0.f,        0.f, 0.f, 0.f, 0.f, 0.f,       0.f,
-     0.f,       0.f,       0.f,        0.f, 0.f, 0.f, 0.f, 0.333333f, 0.333333f,
-     0.243243f, 0.153846f, 0.0833333f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,
-     0.f,       0.f,       0.f,        0.f, 0.f, 0.f},
-    {0.f,       0.f,       0.f,       0.f,        0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,       0.f,       0.f,       0.f,        0.f, 0.f, 0.f, 0.f, 0.333333f,
-     0.324324f, 0.230769f, 0.166667f, 0.0909091f, 0.f, 0.f, 0.f, 0.f, 0.f,
-     0.f,       0.f,       0.f,       0.f,        0.f, 0.f},
-    {0.f,       0.f,       0.f,   0.f,       0.f,        0.f, 0.f, 0.f, 0.f,
-     0.f,       0.f,       0.f,   0.f,       0.f,        0.f, 0.f, 0.f, 0.f,
-     0.324324f, 0.307692f, 0.25f, 0.181818f, 0.0833333f, 0.f, 0.f, 0.f, 0.f,
-     0.f,       0.f,       0.f,   0.f,       0.f,        0.f},
-    {0.f,       0.f,   0.f,       0.f,        0.f, 0.f,       0.f,
-     0.f,       0.f,   0.f,       0.f,        0.f, 0.f,       0.f,
-     0.f,       0.f,   0.f,       0.f,        0.f, 0.307692f, 0.333333f,
-     0.363636f, 0.25f, 0.151515f, 0.0793651f, 0.f, 0.f,       0.f,
-     0.f,       0.f,   0.f,       0.f,        0.f},
-    {0.f,       0.f,       0.f,        0.f,       0.f,       0.f,
-     0.f,       0.f,       0.f,        0.f,       0.f,       0.f,
-     0.f,       0.f,       0.f,        0.f,       0.f,       0.f,
-     0.f,       0.f,       0.166667f,  0.363636f, 0.333333f, 0.242424f,
-     0.190476f, 0.133333f, 0.0689655f, 0.f,       0.f,       0.f,
-     0.f,       0.f,       0.f},
-    {0.f,        0.f, 0.f, 0.f, 0.f,       0.f,      0.f,       0.f,  0.f,
-     0.f,        0.f, 0.f, 0.f, 0.f,       0.f,      0.f,       0.f,  0.f,
-     0.f,        0.f, 0.f, 0.f, 0.333333f, 0.30303f, 0.253968f, 0.2f, 0.137931f,
-     0.0714286f, 0.f, 0.f, 0.f, 0.f,       0.f},
-    {0.f,    0.f,        0.f,      0.f,      0.f,       0.f,       0.f,
-     0.f,    0.f,        0.f,      0.f,      0.f,       0.f,       0.f,
-     0.f,    0.f,        0.f,      0.f,      0.f,       0.f,       0.f,
-     0.f,    0.f,        0.30303f, 0.31746f, 0.333333f, 0.275862f, 0.214286f,
-     0.125f, 0.0655738f, 0.f,      0.f,      0.f},
-    {0.f,   0.f,       0.f,       0.f,        0.f,       0.f,       0.f,
-     0.f,   0.f,       0.f,       0.f,        0.f,       0.f,       0.f,
-     0.f,   0.f,       0.f,       0.f,        0.f,       0.f,       0.f,
-     0.f,   0.f,       0.f,       0.15873f,   0.333333f, 0.344828f, 0.357143f,
-     0.25f, 0.196721f, 0.137931f, 0.0816327f, 0.f},
-    {0.f,     0.f,       0.f,       0.f,       0.f, 0.f,       0.f,
-     0.f,     0.f,       0.f,       0.f,       0.f, 0.f,       0.f,
-     0.f,     0.f,       0.f,       0.f,       0.f, 0.f,       0.f,
-     0.f,     0.f,       0.f,       0.f,       0.f, 0.172414f, 0.357143f,
-     0.3125f, 0.245902f, 0.172414f, 0.102041f, 0.f},
-    {0.f, 0.f,     0.f,       0.f,       0.f,       0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f,     0.f,       0.f,       0.f,       0.f, 0.f, 0.f, 0.f,
-     0.f, 0.f,     0.f,       0.f,       0.f,       0.f, 0.f, 0.f, 0.f,
-     0.f, 0.3125f, 0.327869f, 0.344828f, 0.204082f, 0.f},
-    {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,       0.f,       0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.163934f, 0.344828f, 0.408163f, 0.5f},
-    {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,       0.f,
-     0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.204082f, 0.5f}};
-static_assert(arraysize(kTestCenterFreqs) == arraysize(kTestFilterBank),
-              "Test filterbank badly initialized.");
-
-// Target output for gain solving test. Generated with matlab.
-const size_t kTestStartFreq = 12;  // Lowest integral frequency for ERBs.
-const float kTestZeroVar = 1.f;
-const float kTestNonZeroVarLambdaTop[] = {
-    1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 0.f, 0.f,
-    0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f,
-    0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f};
-static_assert(arraysize(kTestCenterFreqs) ==
-                  arraysize(kTestNonZeroVarLambdaTop),
-              "Power test data badly initialized.");
-const float kMaxTestError = 0.005f;
-
-// Enhancer initialization parameters.
-const int kSamples = 10000;
-const int kSampleRate = 4000;
-const int kNumChannels = 1;
-const int kFragmentSize = kSampleRate / 100;
-const size_t kNumNoiseBins = 129;
-const size_t kNumBands = 1;
-
-// Number of frames to process in the bitexactness tests.
-const size_t kNumFramesToProcess = 1000;
-
-int IntelligibilityEnhancerSampleRate(int sample_rate_hz) {
-  return (sample_rate_hz > AudioProcessing::kSampleRate16kHz
-              ? AudioProcessing::kSampleRate16kHz
-              : sample_rate_hz);
-}
-
-// Process one frame of data and produce the output.
-void ProcessOneFrame(int sample_rate_hz,
-                     AudioBuffer* render_audio_buffer,
-                     AudioBuffer* capture_audio_buffer,
-                     NoiseSuppressionImpl* noise_suppressor,
-                     IntelligibilityEnhancer* intelligibility_enhancer) {
-  if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) {
-    render_audio_buffer->SplitIntoFrequencyBands();
-    capture_audio_buffer->SplitIntoFrequencyBands();
-  }
-
-  intelligibility_enhancer->ProcessRenderAudio(render_audio_buffer);
-
-  noise_suppressor->AnalyzeCaptureAudio(capture_audio_buffer);
-  noise_suppressor->ProcessCaptureAudio(capture_audio_buffer);
-
-  intelligibility_enhancer->SetCaptureNoiseEstimate(
-      noise_suppressor->NoiseEstimate(), 0);
-
-  if (sample_rate_hz > AudioProcessing::kSampleRate16kHz) {
-    render_audio_buffer->MergeFrequencyBands();
-  }
-}
-
-// Processes a specified amount of frames, verifies the results and reports
-// any errors.
-void RunBitexactnessTest(int sample_rate_hz,
-                         size_t num_channels,
-                         rtc::ArrayView<const float> output_reference) {
-  const StreamConfig render_config(sample_rate_hz, num_channels, false);
-  AudioBuffer render_buffer(
-      render_config.num_frames(), render_config.num_channels(),
-      render_config.num_frames(), render_config.num_channels(),
-      render_config.num_frames());
-  test::InputAudioFile render_file(
-      test::GetApmRenderTestVectorFileName(sample_rate_hz));
-  std::vector<float> render_input(render_buffer.num_frames() *
-                                  render_buffer.num_channels());
-
-  const StreamConfig capture_config(sample_rate_hz, num_channels, false);
-  AudioBuffer capture_buffer(
-      capture_config.num_frames(), capture_config.num_channels(),
-      capture_config.num_frames(), capture_config.num_channels(),
-      capture_config.num_frames());
-  test::InputAudioFile capture_file(
-      test::GetApmCaptureTestVectorFileName(sample_rate_hz));
-  std::vector<float> capture_input(render_buffer.num_frames() *
-                                   capture_buffer.num_channels());
-
-  rtc::CriticalSection crit_capture;
-  NoiseSuppressionImpl noise_suppressor(&crit_capture);
-  noise_suppressor.Initialize(capture_config.num_channels(), sample_rate_hz);
-  noise_suppressor.Enable(true);
-
-  IntelligibilityEnhancer intelligibility_enhancer(
-      IntelligibilityEnhancerSampleRate(sample_rate_hz),
-      render_config.num_channels(), kNumBands,
-      NoiseSuppressionImpl::num_noise_bins());
-
-  for (size_t frame_no = 0u; frame_no < kNumFramesToProcess; ++frame_no) {
-    ReadFloatSamplesFromStereoFile(render_buffer.num_frames(),
-                                   render_buffer.num_channels(), &render_file,
-                                   render_input);
-    ReadFloatSamplesFromStereoFile(capture_buffer.num_frames(),
-                                   capture_buffer.num_channels(), &capture_file,
-                                   capture_input);
-
-    test::CopyVectorToAudioBuffer(render_config, render_input, &render_buffer);
-    test::CopyVectorToAudioBuffer(capture_config, capture_input,
-                                  &capture_buffer);
-
-    ProcessOneFrame(sample_rate_hz, &render_buffer, &capture_buffer,
-                    &noise_suppressor, &intelligibility_enhancer);
-  }
-
-  // Extract and verify the test results.
-  std::vector<float> render_output;
-  test::ExtractVectorFromAudioBuffer(render_config, &render_buffer,
-                                     &render_output);
-
-  const float kElementErrorBound = 1.f / static_cast<float>(1 << 15);
-
-  // Compare the output with the reference. Only the first values of the output
-  // from last frame processed are compared in order not having to specify all
-  // preceeding frames as testvectors. As the algorithm being tested has a
-  // memory, testing only the last frame implicitly also tests the preceeding
-  // frames.
-  EXPECT_TRUE(test::VerifyDeinterleavedArray(
-      render_buffer.num_frames(), render_config.num_channels(),
-      output_reference, render_output, kElementErrorBound));
-}
-
-float float_rand() {
-  return std::rand() * 2.f / RAND_MAX - 1;
-}
-
-}  // namespace
-
-class IntelligibilityEnhancerTest : public ::testing::Test {
- protected:
-  IntelligibilityEnhancerTest()
-      : clear_buffer_(kFragmentSize,
-                      kNumChannels,
-                      kFragmentSize,
-                      kNumChannels,
-                      kFragmentSize),
-        stream_config_(kSampleRate, kNumChannels),
-        clear_data_(kSamples),
-        noise_data_(kNumNoiseBins),
-        orig_data_(kSamples) {
-    std::srand(1);
-    enh_.reset(new IntelligibilityEnhancer(kSampleRate, kNumChannels, kNumBands,
-                                           kNumNoiseBins));
-  }
-
-  bool CheckUpdate() {
-    enh_.reset(new IntelligibilityEnhancer(kSampleRate, kNumChannels, kNumBands,
-                                           kNumNoiseBins));
-    float* clear_cursor = clear_data_.data();
-    for (int i = 0; i < kSamples; i += kFragmentSize) {
-      enh_->SetCaptureNoiseEstimate(noise_data_, 1);
-      clear_buffer_.CopyFrom(&clear_cursor, stream_config_);
-      enh_->ProcessRenderAudio(&clear_buffer_);
-      clear_buffer_.CopyTo(stream_config_, &clear_cursor);
-      clear_cursor += kFragmentSize;
-    }
-    for (int i = initial_delay_; i < kSamples; i++) {
-      if (std::fabs(clear_data_[i] - orig_data_[i - initial_delay_]) >
-          kMaxTestError) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  std::unique_ptr<IntelligibilityEnhancer> enh_;
-  // Render clean speech buffer.
-  AudioBuffer clear_buffer_;
-  StreamConfig stream_config_;
-  std::vector<float> clear_data_;
-  std::vector<float> noise_data_;
-  std::vector<float> orig_data_;
-  size_t initial_delay_;
-};
-
-// For each class of generated data, tests that render stream is updated when
-// it should be.
-TEST_F(IntelligibilityEnhancerTest, TestRenderUpdate) {
-  initial_delay_ = enh_->render_mangler_->initial_delay();
-  std::fill(noise_data_.begin(), noise_data_.end(), 0.f);
-  std::fill(orig_data_.begin(), orig_data_.end(), 0.f);
-  std::fill(clear_data_.begin(), clear_data_.end(), 0.f);
-  EXPECT_FALSE(CheckUpdate());
-  std::generate(clear_data_.begin(), clear_data_.end(), float_rand);
-  orig_data_ = clear_data_;
-  EXPECT_FALSE(CheckUpdate());
-  std::generate(clear_data_.begin(), clear_data_.end(), float_rand);
-  orig_data_ = clear_data_;
-  std::generate(noise_data_.begin(), noise_data_.end(), float_rand);
-  FloatToFloatS16(noise_data_.data(), noise_data_.size(), noise_data_.data());
-  EXPECT_TRUE(CheckUpdate());
-}
-
-// Tests ERB bank creation, comparing against matlab output.
-TEST_F(IntelligibilityEnhancerTest, TestErbCreation) {
-  ASSERT_EQ(arraysize(kTestCenterFreqs), enh_->bank_size_);
-  for (size_t i = 0; i < enh_->bank_size_; ++i) {
-    EXPECT_NEAR(kTestCenterFreqs[i], enh_->center_freqs_[i], kMaxTestError);
-    ASSERT_EQ(arraysize(kTestFilterBank[0]), enh_->freqs_);
-    for (size_t j = 0; j < enh_->freqs_; ++j) {
-      EXPECT_NEAR(kTestFilterBank[i][j], enh_->render_filter_bank_[i][j],
-                  kMaxTestError);
-    }
-  }
-}
-
-// Tests analytic solution for optimal gains, comparing
-// against matlab output.
-TEST_F(IntelligibilityEnhancerTest, TestSolveForGains) {
-  ASSERT_EQ(kTestStartFreq, enh_->start_freq_);
-  std::vector<float> sols(enh_->bank_size_);
-  float lambda = -0.001f;
-  for (size_t i = 0; i < enh_->bank_size_; i++) {
-    enh_->filtered_clear_pow_[i] = 0.f;
-    enh_->filtered_noise_pow_[i] = 0.f;
-  }
-  enh_->SolveForGainsGivenLambda(lambda, enh_->start_freq_, sols.data());
-  for (size_t i = 0; i < enh_->bank_size_; i++) {
-    EXPECT_NEAR(kTestZeroVar, sols[i], kMaxTestError);
-  }
-  for (size_t i = 0; i < enh_->bank_size_; i++) {
-    enh_->filtered_clear_pow_[i] = static_cast<float>(i + 1);
-    enh_->filtered_noise_pow_[i] = static_cast<float>(enh_->bank_size_ - i);
-  }
-  enh_->SolveForGainsGivenLambda(lambda, enh_->start_freq_, sols.data());
-  for (size_t i = 0; i < enh_->bank_size_; i++) {
-    EXPECT_NEAR(kTestNonZeroVarLambdaTop[i], sols[i], kMaxTestError);
-  }
-  lambda = -1.f;
-  enh_->SolveForGainsGivenLambda(lambda, enh_->start_freq_, sols.data());
-  for (size_t i = 0; i < enh_->bank_size_; i++) {
-    EXPECT_NEAR(kTestNonZeroVarLambdaTop[i], sols[i], kMaxTestError);
-  }
-}
-
-TEST_F(IntelligibilityEnhancerTest, TestNoiseGainHasExpectedResult) {
-  const float kGain = 2.f;
-  const float kTolerance = 0.007f;
-  std::vector<float> noise(kNumNoiseBins);
-  std::vector<float> noise_psd(kNumNoiseBins);
-  std::generate(noise.begin(), noise.end(), float_rand);
-  for (size_t i = 0; i < kNumNoiseBins; ++i) {
-    noise_psd[i] = kGain * kGain * noise[i] * noise[i];
-  }
-  float* clear_cursor = clear_data_.data();
-  for (size_t i = 0; i < kNumFramesToProcess; ++i) {
-    enh_->SetCaptureNoiseEstimate(noise, kGain);
-    clear_buffer_.CopyFrom(&clear_cursor, stream_config_);
-    enh_->ProcessRenderAudio(&clear_buffer_);
-  }
-  const std::vector<float>& estimated_psd =
-      enh_->noise_power_estimator_.power();
-  for (size_t i = 0; i < kNumNoiseBins; ++i) {
-    EXPECT_LT(std::abs(estimated_psd[i] - noise_psd[i]) / noise_psd[i],
-              kTolerance);
-  }
-}
-
-TEST_F(IntelligibilityEnhancerTest, TestAllBandsHaveSameDelay) {
-  const int kTestSampleRate = AudioProcessing::kSampleRate32kHz;
-  const int kTestSplitRate = AudioProcessing::kSampleRate16kHz;
-  const size_t kTestNumBands =
-      rtc::CheckedDivExact(kTestSampleRate, kTestSplitRate);
-  const size_t kTestFragmentSize = rtc::CheckedDivExact(kTestSampleRate, 100);
-  const size_t kTestSplitFragmentSize =
-      rtc::CheckedDivExact(kTestSplitRate, 100);
-  enh_.reset(new IntelligibilityEnhancer(kTestSplitRate, kNumChannels,
-                                         kTestNumBands, kNumNoiseBins));
-  size_t initial_delay = enh_->render_mangler_->initial_delay();
-  std::vector<float> rand_gen_buf(kTestFragmentSize);
-  AudioBuffer original_buffer(kTestFragmentSize, kNumChannels,
-                              kTestFragmentSize, kNumChannels,
-                              kTestFragmentSize);
-  AudioBuffer audio_buffer(kTestFragmentSize, kNumChannels, kTestFragmentSize,
-                           kNumChannels, kTestFragmentSize);
-  for (size_t i = 0u; i < kTestNumBands; ++i) {
-    std::generate(rand_gen_buf.begin(), rand_gen_buf.end(), float_rand);
-    original_buffer.split_data_f()->SetDataForTesting(rand_gen_buf.data(),
-                                                      rand_gen_buf.size());
-    audio_buffer.split_data_f()->SetDataForTesting(rand_gen_buf.data(),
-                                                   rand_gen_buf.size());
-  }
-  enh_->ProcessRenderAudio(&audio_buffer);
-  for (size_t i = 0u; i < kTestNumBands; ++i) {
-    const float* original_ptr = original_buffer.split_bands_const_f(0)[i];
-    const float* audio_ptr = audio_buffer.split_bands_const_f(0)[i];
-    for (size_t j = initial_delay; j < kTestSplitFragmentSize; ++j) {
-      EXPECT_LT(std::fabs(original_ptr[j - initial_delay] - audio_ptr[j]),
-                kMaxTestError);
-    }
-  }
-}
-
-TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Mono8kHz) {
-  const float kOutputReference[] = {-0.001892f, -0.003296f, -0.001953f};
-
-  RunBitexactnessTest(AudioProcessing::kSampleRate8kHz, 1, kOutputReference);
-}
-
-TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Mono16kHz) {
-  const float kOutputReference[] = {-0.000977f, -0.003296f, -0.002441f};
-
-  RunBitexactnessTest(AudioProcessing::kSampleRate16kHz, 1, kOutputReference);
-}
-
-TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Mono32kHz) {
-  const float kOutputReference[] = {0.003021f, -0.011780f, -0.008209f};
-
-  RunBitexactnessTest(AudioProcessing::kSampleRate32kHz, 1, kOutputReference);
-}
-
-TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Mono48kHz) {
-  const float kOutputReference[] = {-0.027696f, -0.026253f, -0.018001f};
-
-  RunBitexactnessTest(AudioProcessing::kSampleRate48kHz, 1, kOutputReference);
-}
-
-TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Stereo8kHz) {
-  const float kOutputReference[] = {0.021454f,  0.035919f, 0.026428f,
-                                    -0.000641f, 0.000366f, 0.000641f};
-
-  RunBitexactnessTest(AudioProcessing::kSampleRate8kHz, 2, kOutputReference);
-}
-
-TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Stereo16kHz) {
-  const float kOutputReference[] = {0.021362f,  0.035736f,  0.023895f,
-                                    -0.001404f, -0.001465f, 0.000549f};
-
-  RunBitexactnessTest(AudioProcessing::kSampleRate16kHz, 2, kOutputReference);
-}
-
-TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Stereo32kHz) {
-  const float kOutputReference[] = {0.030641f,  0.027406f,  0.028321f,
-                                    -0.001343f, -0.004578f, 0.000977f};
-
-  RunBitexactnessTest(AudioProcessing::kSampleRate32kHz, 2, kOutputReference);
-}
-
-TEST(IntelligibilityEnhancerBitExactnessTest, DISABLED_Stereo48kHz) {
-  const float kOutputReference[] = {-0.009276f, -0.001601f, -0.008255f,
-                                    -0.012975f, -0.015940f, -0.017820f};
-
-  RunBitexactnessTest(AudioProcessing::kSampleRate48kHz, 2, kOutputReference);
-}
-
-}  // namespace webrtc
diff --git a/modules/audio_processing/intelligibility/intelligibility_utils.cc b/modules/audio_processing/intelligibility/intelligibility_utils.cc
deleted file mode 100644
index b606d95..0000000
--- a/modules/audio_processing/intelligibility/intelligibility_utils.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *  Copyright (c) 2014 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 "modules/audio_processing/intelligibility/intelligibility_utils.h"
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <algorithm>
-#include <limits>
-
-#include "rtc_base/numerics/safe_minmax.h"
-
-namespace webrtc {
-
-namespace intelligibility {
-
-namespace {
-
-const float kMinFactor = 0.01f;
-const float kMaxFactor = 100.f;
-
-// Return |current| changed towards |target|, with the relative change being at
-// most |limit|.
-float UpdateFactor(float target, float current, float limit) {
-  const float gain = target / (current + std::numeric_limits<float>::epsilon());
-  const float clamped_gain = rtc::SafeClamp(gain, 1 - limit, 1 + limit);
-  return rtc::SafeClamp(current * clamped_gain, kMinFactor, kMaxFactor);
-}
-
-}  // namespace
-
-template <typename T>
-PowerEstimator<T>::PowerEstimator(size_t num_freqs, float decay)
-    : power_(num_freqs, 0.f), decay_(decay) {}
-
-template <typename T>
-void PowerEstimator<T>::Step(const T* data) {
-  for (size_t i = 0; i < power_.size(); ++i) {
-    power_[i] = decay_ * power_[i] +
-                (1.f - decay_) * std::abs(data[i]) * std::abs(data[i]);
-  }
-}
-
-template class PowerEstimator<float>;
-template class PowerEstimator<std::complex<float>>;
-
-GainApplier::GainApplier(size_t freqs, float relative_change_limit)
-    : num_freqs_(freqs),
-      relative_change_limit_(relative_change_limit),
-      target_(freqs, 1.f),
-      current_(freqs, 1.f) {}
-
-GainApplier::~GainApplier() {}
-
-void GainApplier::Apply(const std::complex<float>* in_block,
-                        std::complex<float>* out_block) {
-  for (size_t i = 0; i < num_freqs_; ++i) {
-    current_[i] = UpdateFactor(target_[i], current_[i], relative_change_limit_);
-    out_block[i] = sqrtf(fabsf(current_[i])) * in_block[i];
-  }
-}
-
-DelayBuffer::DelayBuffer(size_t delay, size_t num_channels)
-    : buffer_(num_channels, std::vector<float>(delay, 0.f)), read_index_(0u) {}
-
-DelayBuffer::~DelayBuffer() {}
-
-void DelayBuffer::Delay(float* const* data, size_t length) {
-  size_t sample_index = read_index_;
-  for (size_t i = 0u; i < buffer_.size(); ++i) {
-    sample_index = read_index_;
-    for (size_t j = 0u; j < length; ++j) {
-      float swap = data[i][j];
-      data[i][j] = buffer_[i][sample_index];
-      buffer_[i][sample_index] = swap;
-      if (++sample_index == buffer_.size()) {
-        sample_index = 0u;
-      }
-    }
-  }
-  read_index_ = sample_index;
-}
-
-}  // namespace intelligibility
-
-}  // namespace webrtc
diff --git a/modules/audio_processing/intelligibility/intelligibility_utils.h b/modules/audio_processing/intelligibility/intelligibility_utils.h
deleted file mode 100644
index 4dc17d5..0000000
--- a/modules/audio_processing/intelligibility/intelligibility_utils.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- *  Copyright (c) 2014 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 MODULES_AUDIO_PROCESSING_INTELLIGIBILITY_INTELLIGIBILITY_UTILS_H_
-#define MODULES_AUDIO_PROCESSING_INTELLIGIBILITY_INTELLIGIBILITY_UTILS_H_
-
-#include <complex>
-#include <vector>
-
-namespace webrtc {
-
-namespace intelligibility {
-
-// Internal helper for computing the power of a stream of arrays.
-// The result is an array of power per position: the i-th power is the power of
-// the stream of data on the i-th positions in the input arrays.
-template <typename T>
-class PowerEstimator {
- public:
-  // Construct an instance for the given input array length (|freqs|), with the
-  // appropriate parameters. |decay| is the forgetting factor.
-  PowerEstimator(size_t freqs, float decay);
-
-  // Add a new data point to the series.
-  void Step(const T* data);
-
-  // The current power array.
-  const std::vector<float>& power() { return power_; };
-
- private:
-  // The current power array.
-  std::vector<float> power_;
-
-  const float decay_;
-};
-
-// Helper class for smoothing gain changes. On each application step, the
-// currently used gains are changed towards a set of settable target gains,
-// constrained by a limit on the relative changes.
-class GainApplier {
- public:
-  GainApplier(size_t freqs, float relative_change_limit);
-
-  ~GainApplier();
-
-  // Copy |in_block| to |out_block|, multiplied by the current set of gains,
-  // and step the current set of gains towards the target set.
-  void Apply(const std::complex<float>* in_block,
-             std::complex<float>* out_block);
-
-  // Return the current target gain set. Modify this array to set the targets.
-  float* target() { return target_.data(); }
-
- private:
-  const size_t num_freqs_;
-  const float relative_change_limit_;
-  std::vector<float> target_;
-  std::vector<float> current_;
-};
-
-// Helper class to delay a signal by an integer number of samples.
-class DelayBuffer {
- public:
-  DelayBuffer(size_t delay, size_t num_channels);
-
-  ~DelayBuffer();
-
-  void Delay(float* const* data, size_t length);
-
- private:
-  std::vector<std::vector<float>> buffer_;
-  size_t read_index_;
-};
-
-}  // namespace intelligibility
-
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_PROCESSING_INTELLIGIBILITY_INTELLIGIBILITY_UTILS_H_
diff --git a/modules/audio_processing/intelligibility/intelligibility_utils_unittest.cc b/modules/audio_processing/intelligibility/intelligibility_utils_unittest.cc
deleted file mode 100644
index fea394c..0000000
--- a/modules/audio_processing/intelligibility/intelligibility_utils_unittest.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *  Copyright (c) 2015 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 <cmath>
-#include <complex>
-#include <vector>
-
-#include "modules/audio_processing/intelligibility/intelligibility_utils.h"
-#include "rtc_base/arraysize.h"
-#include "test/gtest.h"
-
-namespace webrtc {
-
-namespace intelligibility {
-
-std::vector<std::vector<std::complex<float>>> GenerateTestData(size_t freqs,
-                                                               size_t samples) {
-  std::vector<std::vector<std::complex<float>>> data(samples);
-  for (size_t i = 0; i < samples; ++i) {
-    for (size_t j = 0; j < freqs; ++j) {
-      const float val = 0.99f / ((i + 1) * (j + 1));
-      data[i].push_back(std::complex<float>(val, val));
-    }
-  }
-  return data;
-}
-
-// Tests PowerEstimator, for all power step types.
-TEST(IntelligibilityUtilsTest, TestPowerEstimator) {
-  const size_t kFreqs = 10;
-  const size_t kSamples = 100;
-  const float kDecay = 0.5f;
-  const std::vector<std::vector<std::complex<float>>> test_data(
-      GenerateTestData(kFreqs, kSamples));
-  PowerEstimator<std::complex<float>> power_estimator(kFreqs, kDecay);
-  EXPECT_EQ(0, power_estimator.power()[0]);
-
-  // Makes sure Step is doing something.
-  power_estimator.Step(test_data[0].data());
-  for (size_t i = 1; i < kSamples; ++i) {
-    power_estimator.Step(test_data[i].data());
-    for (size_t j = 0; j < kFreqs; ++j) {
-      EXPECT_GE(power_estimator.power()[j], 0.f);
-      EXPECT_LE(power_estimator.power()[j], 1.f);
-    }
-  }
-}
-
-// Tests gain applier.
-TEST(IntelligibilityUtilsTest, TestGainApplier) {
-  const size_t kFreqs = 10;
-  const size_t kSamples = 100;
-  const float kChangeLimit = 0.1f;
-  GainApplier gain_applier(kFreqs, kChangeLimit);
-  const std::vector<std::vector<std::complex<float>>> in_data(
-      GenerateTestData(kFreqs, kSamples));
-  std::vector<std::vector<std::complex<float>>> out_data(
-      GenerateTestData(kFreqs, kSamples));
-  for (size_t i = 0; i < kSamples; ++i) {
-    gain_applier.Apply(in_data[i].data(), out_data[i].data());
-    for (size_t j = 0; j < kFreqs; ++j) {
-      EXPECT_GT(out_data[i][j].real(), 0.f);
-      EXPECT_LT(out_data[i][j].real(), 1.f);
-      EXPECT_GT(out_data[i][j].imag(), 0.f);
-      EXPECT_LT(out_data[i][j].imag(), 1.f);
-    }
-  }
-}
-
-}  // namespace intelligibility
-
-}  // namespace webrtc
diff --git a/modules/audio_processing/module.mk b/modules/audio_processing/module.mk
index d45b414..7d8b360 100644
--- a/modules/audio_processing/module.mk
+++ b/modules/audio_processing/module.mk
@@ -14,7 +14,9 @@
 	modules/audio_processing/audio_buffer.o \
 	modules/audio_processing/audio_processing_impl.o \
 	modules/audio_processing/echo_cancellation_impl.o \
+	modules/audio_processing/echo_cancellation_proxy.o \
 	modules/audio_processing/echo_control_mobile_impl.o \
+	modules/audio_processing/echo_control_mobile_proxy.o \
 	modules/audio_processing/echo_detector/circular_buffer.o \
 	modules/audio_processing/echo_detector/mean_variance_estimator.o \
 	modules/audio_processing/echo_detector/moving_max.o \
@@ -90,11 +92,11 @@
 	modules/audio_processing/aec3/aec3_common.o \
 	modules/audio_processing/aec3/aec3_fft.o \
 	modules/audio_processing/aec3/aec_state.o \
+	modules/audio_processing/aec3/block_delay_buffer.o \
 	modules/audio_processing/aec3/block_framer.o \
 	modules/audio_processing/aec3/block_processor.o \
 	modules/audio_processing/aec3/block_processor_metrics.o \
 	modules/audio_processing/aec3/cascaded_biquad_filter.o \
-	modules/audio_processing/aec3/coherence_gain.o \
 	modules/audio_processing/aec3/comfort_noise_generator.o \
 	modules/audio_processing/aec3/decimator.o \
 	modules/audio_processing/aec3/downsampled_render_buffer.o \
@@ -120,6 +122,8 @@
 	modules/audio_processing/aec3/render_delay_controller_metrics.o \
 	modules/audio_processing/aec3/render_signal_analyzer.o \
 	modules/audio_processing/aec3/residual_echo_estimator.o \
+	modules/audio_processing/aec3/reverb_decay_estimator.o \
+	modules/audio_processing/aec3/reverb_frequency_response.o \
 	modules/audio_processing/aec3/reverb_model.o \
 	modules/audio_processing/aec3/reverb_model_estimator.o \
 	modules/audio_processing/aec3/reverb_model_fallback.o \
diff --git a/modules/audio_processing/ns/noise_suppression.h b/modules/audio_processing/ns/noise_suppression.h
index fd6aa96..0775ffa 100644
--- a/modules/audio_processing/ns/noise_suppression.h
+++ b/modules/audio_processing/ns/noise_suppression.h
@@ -12,8 +12,7 @@
 #define MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSION_H_
 
 #include <stddef.h>
-
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 typedef struct NsHandleT NsHandle;
 
diff --git a/modules/audio_processing/ns/noise_suppression_x.h b/modules/audio_processing/ns/noise_suppression_x.h
index f25fb7a..972784e 100644
--- a/modules/audio_processing/ns/noise_suppression_x.h
+++ b/modules/audio_processing/ns/noise_suppression_x.h
@@ -12,8 +12,7 @@
 #define MODULES_AUDIO_PROCESSING_NS_NOISE_SUPPRESSION_X_H_
 
 #include <stddef.h>
-
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 typedef struct NsxHandleT NsxHandle;
 
diff --git a/modules/audio_processing/ns/ns_core.c b/modules/audio_processing/ns/ns_core.c
index c87713a..bc5dd6d 100644
--- a/modules/audio_processing/ns/ns_core.c
+++ b/modules/audio_processing/ns/ns_core.c
@@ -13,8 +13,8 @@
 #include <stdlib.h>
 
 #include "rtc_base/checks.h"
-#include "common_audio/fft4g.h"
 #include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "common_audio/third_party/fft4g/fft4g.h"
 #include "modules/audio_processing/ns/noise_suppression.h"
 #include "modules/audio_processing/ns/ns_core.h"
 #include "modules/audio_processing/ns/windows_private.h"
diff --git a/modules/audio_processing/ns/nsx_core.h b/modules/audio_processing/ns/nsx_core.h
index 479e90c..9e9d142 100644
--- a/modules/audio_processing/ns/nsx_core.h
+++ b/modules/audio_processing/ns/nsx_core.h
@@ -17,7 +17,6 @@
 
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 #include "modules/audio_processing/ns/nsx_defines.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 typedef struct NoiseSuppressionFixedC_ {
   uint32_t fs;
diff --git a/modules/audio_processing/rms_level.h b/modules/audio_processing/rms_level.h
index ae45a45..9aa549a 100644
--- a/modules/audio_processing/rms_level.h
+++ b/modules/audio_processing/rms_level.h
@@ -13,7 +13,6 @@
 
 #include "absl/types/optional.h"
 #include "api/array_view.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/transient/dyadic_decimator.h b/modules/audio_processing/transient/dyadic_decimator.h
index e5b1961..fcb56b7 100644
--- a/modules/audio_processing/transient/dyadic_decimator.h
+++ b/modules/audio_processing/transient/dyadic_decimator.h
@@ -13,8 +13,6 @@
 
 #include <cstdlib>
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 // Provides a set of static methods to perform dyadic decimations.
 
 namespace webrtc {
diff --git a/modules/audio_processing/transient/file_utils.cc b/modules/audio_processing/transient/file_utils.cc
index 40732b9..58f9932 100644
--- a/modules/audio_processing/transient/file_utils.cc
+++ b/modules/audio_processing/transient/file_utils.cc
@@ -13,7 +13,6 @@
 #include <memory>
 
 #include "rtc_base/system/file_wrapper.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/transient/file_utils.h b/modules/audio_processing/transient/file_utils.h
index 4b04fac..6184017 100644
--- a/modules/audio_processing/transient/file_utils.h
+++ b/modules/audio_processing/transient/file_utils.h
@@ -14,7 +14,6 @@
 #include <string.h>
 
 #include "rtc_base/system/file_wrapper.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/transient/file_utils_unittest.cc b/modules/audio_processing/transient/file_utils_unittest.cc
index 05f8341..89902ec 100644
--- a/modules/audio_processing/transient/file_utils_unittest.cc
+++ b/modules/audio_processing/transient/file_utils_unittest.cc
@@ -18,7 +18,6 @@
 #include "rtc_base/system/file_wrapper.h"
 #include "test/gtest.h"
 #include "test/testsupport/fileutils.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/transient/moving_moments.cc b/modules/audio_processing/transient/moving_moments.cc
index 4be4d6a..a199bb0 100644
--- a/modules/audio_processing/transient/moving_moments.cc
+++ b/modules/audio_processing/transient/moving_moments.cc
@@ -10,8 +10,7 @@
 
 #include "modules/audio_processing/transient/moving_moments.h"
 
-#include <math.h>
-#include <string.h>
+#include <cmath>
 
 #include "rtc_base/checks.h"
 
@@ -44,7 +43,7 @@
     sum_ += in[i] - old_value;
     sum_of_squares_ += in[i] * in[i] - old_value * old_value;
     first[i] = sum_ / length_;
-    second[i] = sum_of_squares_ / length_;
+    second[i] = std::max(0.f, sum_of_squares_ / length_);
   }
 }
 
diff --git a/modules/audio_processing/transient/transient_detector_unittest.cc b/modules/audio_processing/transient/transient_detector_unittest.cc
index 69a669f..d1eb7af 100644
--- a/modules/audio_processing/transient/transient_detector_unittest.cc
+++ b/modules/audio_processing/transient/transient_detector_unittest.cc
@@ -19,7 +19,6 @@
 #include "rtc_base/system/file_wrapper.h"
 #include "test/gtest.h"
 #include "test/testsupport/fileutils.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/transient/transient_suppression_test.cc b/modules/audio_processing/transient/transient_suppression_test.cc
index 00e1989..9e7ecd5 100644
--- a/modules/audio_processing/transient/transient_suppression_test.cc
+++ b/modules/audio_processing/transient/transient_suppression_test.cc
@@ -22,7 +22,6 @@
 #include "rtc_base/flags.h"
 #include "test/gtest.h"
 #include "test/testsupport/fileutils.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 DEFINE_string(in_file_name, "", "PCM file that contains the signal.");
 DEFINE_string(detection_file_name,
diff --git a/modules/audio_processing/transient/transient_suppressor.cc b/modules/audio_processing/transient/transient_suppressor.cc
index 28eb666..1a5ed56 100644
--- a/modules/audio_processing/transient/transient_suppressor.cc
+++ b/modules/audio_processing/transient/transient_suppressor.cc
@@ -17,15 +17,14 @@
 #include <deque>
 #include <set>
 
-#include "common_audio/fft4g.h"
 #include "common_audio/include/audio_util.h"
 #include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "common_audio/third_party/fft4g/fft4g.h"
 #include "modules/audio_processing/ns/windows_private.h"
 #include "modules/audio_processing/transient/common.h"
 #include "modules/audio_processing/transient/transient_detector.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/transient/transient_suppressor.h b/modules/audio_processing/transient/transient_suppressor.h
index 27b096c..9ae3fc6 100644
--- a/modules/audio_processing/transient/transient_suppressor.h
+++ b/modules/audio_processing/transient/transient_suppressor.h
@@ -16,7 +16,6 @@
 #include <set>
 
 #include "rtc_base/gtest_prod_util.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/transient/wpd_node.h b/modules/audio_processing/transient/wpd_node.h
index 117a633..6a52fb7 100644
--- a/modules/audio_processing/transient/wpd_node.h
+++ b/modules/audio_processing/transient/wpd_node.h
@@ -13,8 +13,6 @@
 
 #include <memory>
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 namespace webrtc {
 
 class FIRFilter;
diff --git a/modules/audio_processing/typing_detection.h b/modules/audio_processing/typing_detection.h
index 14dfe1d..70fd903 100644
--- a/modules/audio_processing/typing_detection.h
+++ b/modules/audio_processing/typing_detection.h
@@ -11,8 +11,6 @@
 #ifndef MODULES_AUDIO_PROCESSING_TYPING_DETECTION_H_
 #define MODULES_AUDIO_PROCESSING_TYPING_DETECTION_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 namespace webrtc {
 
 class TypingDetection {
diff --git a/modules/audio_processing/utility/BUILD.gn b/modules/audio_processing/utility/BUILD.gn
index cd23d01..6a4304d 100644
--- a/modules/audio_processing/utility/BUILD.gn
+++ b/modules/audio_processing/utility/BUILD.gn
@@ -28,7 +28,6 @@
     "delay_estimator_wrapper.h",
   ]
   deps = [
-    "../../..:typedefs",
     "../../../rtc_base:checks",
   ]
 }
@@ -40,7 +39,7 @@
     "ooura_fft_tables_common.h",
   ]
   deps = [
-    "../../..:typedefs",
+    "../../../rtc_base/system:arch",
     "../../../system_wrappers:cpu_features_api",
   ]
   cflags = []
@@ -64,9 +63,7 @@
     deps += [ "../../../common_audio" ]
 
     if (current_cpu != "arm64") {
-      # Enable compilation for the NEON instruction set. This is needed
-      # since //build/config/arm.gni only enables NEON for iOS, not Android.
-      # This provides the same functionality as webrtc/build/arm_neon.gypi.
+      # Enable compilation for the NEON instruction set.
       suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
       cflags += [ "-mfpu=neon" ]
     }
@@ -109,7 +106,6 @@
     ]
     deps = [
       ":legacy_delay_estimator",
-      "../../..:typedefs",
       "../../../rtc_base:rtc_base_approved",
       "../../../test:test_support",
       "//testing/gtest",
diff --git a/modules/audio_processing/utility/delay_estimator.h b/modules/audio_processing/utility/delay_estimator.h
index 11483ec..2f47e26 100644
--- a/modules/audio_processing/utility/delay_estimator.h
+++ b/modules/audio_processing/utility/delay_estimator.h
@@ -14,7 +14,7 @@
 #ifndef MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_H_
 #define MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 static const int32_t kMaxBitCountsQ9 = (32 << 9);  // 32 matching bits in Q9.
 
diff --git a/modules/audio_processing/utility/delay_estimator_internal.h b/modules/audio_processing/utility/delay_estimator_internal.h
index 46eea3e..e99fe21 100644
--- a/modules/audio_processing/utility/delay_estimator_internal.h
+++ b/modules/audio_processing/utility/delay_estimator_internal.h
@@ -14,7 +14,6 @@
 #define MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_INTERNAL_H_
 
 #include "modules/audio_processing/utility/delay_estimator.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 typedef union {
   float float_;
diff --git a/modules/audio_processing/utility/delay_estimator_unittest.cc b/modules/audio_processing/utility/delay_estimator_unittest.cc
index 8d65cb9..324bc37 100644
--- a/modules/audio_processing/utility/delay_estimator_unittest.cc
+++ b/modules/audio_processing/utility/delay_estimator_unittest.cc
@@ -12,7 +12,6 @@
 #include "modules/audio_processing/utility/delay_estimator_internal.h"
 #include "modules/audio_processing/utility/delay_estimator_wrapper.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace {
 
diff --git a/modules/audio_processing/utility/delay_estimator_wrapper.h b/modules/audio_processing/utility/delay_estimator_wrapper.h
index 6b6e51f..995470f 100644
--- a/modules/audio_processing/utility/delay_estimator_wrapper.h
+++ b/modules/audio_processing/utility/delay_estimator_wrapper.h
@@ -14,7 +14,7 @@
 #ifndef MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_WRAPPER_H_
 #define MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_WRAPPER_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 // Releases the memory allocated by WebRtc_CreateDelayEstimatorFarend(...)
 void WebRtc_FreeDelayEstimatorFarend(void* handle);
diff --git a/modules/audio_processing/utility/ooura_fft.cc b/modules/audio_processing/utility/ooura_fft.cc
index 2add4eb..c3333ce 100644
--- a/modules/audio_processing/utility/ooura_fft.cc
+++ b/modules/audio_processing/utility/ooura_fft.cc
@@ -26,8 +26,8 @@
 #include <math.h>
 
 #include "modules/audio_processing/utility/ooura_fft_tables_common.h"
+#include "rtc_base/system/arch.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/utility/ooura_fft.h b/modules/audio_processing/utility/ooura_fft.h
index 96d57dc..0cdd6aa 100644
--- a/modules/audio_processing/utility/ooura_fft.h
+++ b/modules/audio_processing/utility/ooura_fft.h
@@ -11,7 +11,7 @@
 #ifndef MODULES_AUDIO_PROCESSING_UTILITY_OOURA_FFT_H_
 #define MODULES_AUDIO_PROCESSING_UTILITY_OOURA_FFT_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include "rtc_base/system/arch.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/utility/ooura_fft_mips.cc b/modules/audio_processing/utility/ooura_fft_mips.cc
index c782ee7..9fe577d 100644
--- a/modules/audio_processing/utility/ooura_fft_mips.cc
+++ b/modules/audio_processing/utility/ooura_fft_mips.cc
@@ -11,7 +11,6 @@
 #include "modules/audio_processing/utility/ooura_fft.h"
 
 #include "modules/audio_processing/utility/ooura_fft_tables_common.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/utility/ooura_fft_sse2.cc b/modules/audio_processing/utility/ooura_fft_sse2.cc
index b44458e..9b5d0f3 100644
--- a/modules/audio_processing/utility/ooura_fft_sse2.cc
+++ b/modules/audio_processing/utility/ooura_fft_sse2.cc
@@ -14,6 +14,7 @@
 
 #include "modules/audio_processing/utility/ooura_fft_tables_common.h"
 #include "modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h"
+#include "rtc_base/system/arch.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h b/modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h
index 1c44ae7..b6e4a07 100644
--- a/modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h
+++ b/modules/audio_processing/utility/ooura_fft_tables_neon_sse2.h
@@ -12,6 +12,7 @@
 #define MODULES_AUDIO_PROCESSING_UTILITY_OOURA_FFT_TABLES_NEON_SSE2_H_
 
 #include "modules/audio_processing/utility/ooura_fft.h"
+#include "rtc_base/system/arch.h"
 
 #ifdef _MSC_VER /* visual c++ */
 #define ALIGN16_BEG __declspec(align(16))
diff --git a/modules/audio_processing/vad/BUILD.gn b/modules/audio_processing/vad/BUILD.gn
index e16b57f..6c64e94 100644
--- a/modules/audio_processing/vad/BUILD.gn
+++ b/modules/audio_processing/vad/BUILD.gn
@@ -35,11 +35,10 @@
     "voice_gmm_tables.h",
   ]
   deps = [
-    "../../..:typedefs",
     "../../../audio/utility:audio_frame_operations",
     "../../../common_audio",
     "../../../common_audio:common_audio_c",
-    "../../../common_audio:fft4g",
+    "../../../common_audio/third_party/fft4g:fft4g",
     "../../../rtc_base:checks",
     "../../audio_coding:isac_vad",
   ]
diff --git a/modules/audio_processing/vad/gmm.cc b/modules/audio_processing/vad/gmm.cc
index 266ca44..cd8a1a8 100644
--- a/modules/audio_processing/vad/gmm.cc
+++ b/modules/audio_processing/vad/gmm.cc
@@ -13,8 +13,6 @@
 #include <math.h>
 #include <stdlib.h>
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 namespace webrtc {
 
 static const int kMaxDimension = 10;
diff --git a/modules/audio_processing/vad/pitch_based_vad.h b/modules/audio_processing/vad/pitch_based_vad.h
index 584dcc7..4d32765 100644
--- a/modules/audio_processing/vad/pitch_based_vad.h
+++ b/modules/audio_processing/vad/pitch_based_vad.h
@@ -15,7 +15,6 @@
 
 #include "modules/audio_processing/vad/common.h"
 #include "modules/audio_processing/vad/gmm.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/vad/pole_zero_filter.h b/modules/audio_processing/vad/pole_zero_filter.h
index 283deec..11a0511 100644
--- a/modules/audio_processing/vad/pole_zero_filter.h
+++ b/modules/audio_processing/vad/pole_zero_filter.h
@@ -11,9 +11,8 @@
 #ifndef MODULES_AUDIO_PROCESSING_VAD_POLE_ZERO_FILTER_H_
 #define MODULES_AUDIO_PROCESSING_VAD_POLE_ZERO_FILTER_H_
 
-#include <cstddef>
-
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stddef.h>
+#include <stdint.h>
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/vad/standalone_vad.cc b/modules/audio_processing/vad/standalone_vad.cc
index 813d375..19a5282 100644
--- a/modules/audio_processing/vad/standalone_vad.cc
+++ b/modules/audio_processing/vad/standalone_vad.cc
@@ -14,7 +14,6 @@
 
 #include "audio/utility/audio_frame_operations.h"
 #include "rtc_base/checks.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/vad/standalone_vad.h b/modules/audio_processing/vad/standalone_vad.h
index 3f6eb7f..79650fb 100644
--- a/modules/audio_processing/vad/standalone_vad.h
+++ b/modules/audio_processing/vad/standalone_vad.h
@@ -13,7 +13,6 @@
 
 #include "common_audio/vad/include/webrtc_vad.h"
 #include "modules/audio_processing/vad/common.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/audio_processing/vad/vad_audio_proc.cc b/modules/audio_processing/vad/vad_audio_proc.cc
index e9007c6..53eb6de 100644
--- a/modules/audio_processing/vad/vad_audio_proc.cc
+++ b/modules/audio_processing/vad/vad_audio_proc.cc
@@ -14,7 +14,7 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "common_audio/fft4g.h"
+#include "common_audio/third_party/fft4g/fft4g.h"
 #include "modules/audio_processing/vad/pitch_internal.h"
 #include "modules/audio_processing/vad/pole_zero_filter.h"
 #include "modules/audio_processing/vad/vad_audio_proc_internal.h"
diff --git a/modules/audio_processing/vad/vad_audio_proc.h b/modules/audio_processing/vad/vad_audio_proc.h
index b1441a0..e34091b 100644
--- a/modules/audio_processing/vad/vad_audio_proc.h
+++ b/modules/audio_processing/vad/vad_audio_proc.h
@@ -14,7 +14,6 @@
 #include <memory>
 
 #include "modules/audio_processing/vad/common.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/include/module.h b/modules/include/module.h
index fc2a1b5..3b1e046 100644
--- a/modules/include/module.h
+++ b/modules/include/module.h
@@ -11,7 +11,7 @@
 #ifndef MODULES_INCLUDE_MODULE_H_
 #define MODULES_INCLUDE_MODULE_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 namespace webrtc {
 
diff --git a/modules/include/module_common_types.h b/modules/include/module_common_types.h
index 47fd3c2..8ee2369 100644
--- a/modules/include/module_common_types.h
+++ b/modules/include/module_common_types.h
@@ -29,13 +29,9 @@
 #include "rtc_base/deprecation.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/timeutils.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
-// TODO(nisse): Deprecated, use webrtc::VideoCodecType instead.
-using RtpVideoCodecTypes = VideoCodecType;
-
 struct WebRtcRTPHeader {
   RTPVideoHeader& video_header() { return video; }
   const RTPVideoHeader& video_header() const { return video; }
diff --git a/modules/include/module_common_types_public.h b/modules/include/module_common_types_public.h
index 2afd9af..345e45c 100644
--- a/modules/include/module_common_types_public.h
+++ b/modules/include/module_common_types_public.h
@@ -14,7 +14,6 @@
 #include <limits>
 
 #include "absl/types/optional.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -84,11 +83,15 @@
 using SequenceNumberUnwrapper = Unwrapper<uint16_t>;
 using TimestampUnwrapper = Unwrapper<uint32_t>;
 
+// NB: Doesn't fulfill strict weak ordering requirements.
+//     Mustn't be used as std::map Compare function.
 inline bool IsNewerSequenceNumber(uint16_t sequence_number,
                                   uint16_t prev_sequence_number) {
   return IsNewer(sequence_number, prev_sequence_number);
 }
 
+// NB: Doesn't fulfill strict weak ordering requirements.
+//     Mustn't be used as std::map Compare function.
 inline bool IsNewerTimestamp(uint32_t timestamp, uint32_t prev_timestamp) {
   return IsNewer(timestamp, prev_timestamp);
 }
diff --git a/modules/rtp_rtcp/BUILD.gn b/modules/rtp_rtcp/BUILD.gn
index da546cd..055d712 100644
--- a/modules/rtp_rtcp/BUILD.gn
+++ b/modules/rtp_rtcp/BUILD.gn
@@ -87,7 +87,6 @@
   deps = [
     "..:module_api",
     "../..:webrtc_common",
-    "../../:typedefs",
     "../../api:array_view",
     "../../api:libjingle_peerconnection_api",
     "../../api/audio_codecs:audio_codecs_api",
@@ -114,6 +113,8 @@
     "include/rtp_receiver.h",
     "include/rtp_rtcp.h",
     "include/ulpfec_receiver.h",
+    "source/contributing_sources.cc",
+    "source/contributing_sources.h",
     "source/dtmf_queue.cc",
     "source/dtmf_queue.h",
     "source/fec_private_tables_bursty.cc",
@@ -196,12 +197,13 @@
     ":rtp_rtcp_format",
     "..:module_api",
     "../..:webrtc_common",
-    "../../:typedefs",
     "../../api:array_view",
     "../../api:libjingle_peerconnection_api",
     "../../api:transport_api",
     "../../api/audio_codecs:audio_codecs_api",
     "../../api/video:video_bitrate_allocation",
+    "../../api/video:video_bitrate_allocator",
+    "../../api/video:video_frame",
     "../../api/video_codecs:video_codecs_api",
     "../../common_video",
     "../../logging:rtc_event_audio",
@@ -268,6 +270,7 @@
     "../../:webrtc_common",
     "../../api/video:video_frame",
     "../../modules/video_coding:codec_globals_headers",
+    "//third_party/abseil-cpp/absl/container:inlined_vector",
     "//third_party/abseil-cpp/absl/types:variant",
   ]
 }
@@ -350,6 +353,7 @@
 
     sources = [
       "source/byte_io_unittest.cc",
+      "source/contributing_sources_unittest.cc",
       "source/fec_private_tables_bursty_unittest.cc",
       "source/flexfec_header_reader_writer_unittest.cc",
       "source/flexfec_receiver_unittest.cc",
@@ -421,11 +425,11 @@
       ":rtp_rtcp_format",
       "..:module_api",
       "../..:webrtc_common",
-      "../../:typedefs",
       "../../api:array_view",
       "../../api:libjingle_peerconnection_api",
       "../../api:transport_api",
       "../../api/video:video_bitrate_allocation",
+      "../../api/video:video_bitrate_allocator",
       "../../api/video:video_frame",
       "../../api/video_codecs:video_codecs_api",
       "../../call:rtp_receiver",
diff --git a/modules/rtp_rtcp/include/receive_statistics.h b/modules/rtp_rtcp/include/receive_statistics.h
index a3b4798..fe72ada 100644
--- a/modules/rtp_rtcp/include/receive_statistics.h
+++ b/modules/rtp_rtcp/include/receive_statistics.h
@@ -18,7 +18,7 @@
 #include "modules/include/module_common_types.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
-#include "typedefs.h"  // NOLINT(build/include)
+#include "rtc_base/deprecation.h"
 
 namespace webrtc {
 
@@ -46,10 +46,6 @@
       StreamDataCounters* data_counters) const = 0;
 
   virtual uint32_t BitrateReceived() const = 0;
-
-  // Returns true if the packet with RTP header |header| is likely to be a
-  // retransmitted packet, false otherwise.
-  virtual bool IsRetransmitOfOldPacket(const RTPHeader& header) const = 0;
 };
 
 class ReceiveStatistics : public ReceiveStatisticsProvider {
@@ -60,8 +56,16 @@
 
   // Updates the receive statistics with this packet.
   virtual void IncomingPacket(const RTPHeader& rtp_header,
-                              size_t packet_length,
-                              bool retransmitted) = 0;
+                              size_t packet_length) = 0;
+
+  // TODO(nisse): Wrapper for backwards compatibility. Delete as soon as
+  // downstream callers are updated.
+  RTC_DEPRECATED
+  void IncomingPacket(const RTPHeader& rtp_header,
+                      size_t packet_length,
+                      bool retransmitted) {
+    IncomingPacket(rtp_header, packet_length);
+  }
 
   // Increment counter for number of FEC packets received.
   virtual void FecPacketReceived(const RTPHeader& header,
@@ -72,6 +76,9 @@
 
   // Sets the max reordering threshold in number of packets.
   virtual void SetMaxReorderingThreshold(int max_reordering_threshold) = 0;
+  // Detect retransmissions, enabling updates of the retransmitted counters. The
+  // default is false.
+  virtual void EnableRetransmitDetection(uint32_t ssrc, bool enable) = 0;
 
   // Called on new RTCP stats creation.
   virtual void RegisterRtcpStatisticsCallback(
diff --git a/modules/rtp_rtcp/include/rtp_header_parser.h b/modules/rtp_rtcp/include/rtp_header_parser.h
index 59012ce..2d84fc1 100644
--- a/modules/rtp_rtcp/include/rtp_header_parser.h
+++ b/modules/rtp_rtcp/include/rtp_header_parser.h
@@ -11,7 +11,6 @@
 #define MODULES_RTP_RTCP_INCLUDE_RTP_HEADER_PARSER_H_
 
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/include/rtp_payload_registry.h b/modules/rtp_rtcp/include/rtp_payload_registry.h
index be296da..229c71b 100644
--- a/modules/rtp_rtcp/include/rtp_payload_registry.h
+++ b/modules/rtp_rtcp/include/rtp_payload_registry.h
@@ -45,20 +45,6 @@
   absl::optional<RtpUtility::Payload> PayloadTypeToPayload(
       uint8_t payload_type) const;
 
-  void ResetLastReceivedPayloadTypes() {
-    rtc::CritScope cs(&crit_sect_);
-    last_received_payload_type_ = -1;
-  }
-
-  int8_t last_received_payload_type() const {
-    rtc::CritScope cs(&crit_sect_);
-    return last_received_payload_type_;
-  }
-  void set_last_received_payload_type(int8_t last_received_payload_type) {
-    rtc::CritScope cs(&crit_sect_);
-    last_received_payload_type_ = last_received_payload_type;
-  }
-
  private:
   // Prunes the payload type map of the specific payload type, if it exists.
   void DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
@@ -66,7 +52,6 @@
 
   rtc::CriticalSection crit_sect_;
   std::map<int, RtpUtility::Payload> payload_type_map_;
-  int8_t last_received_payload_type_;
 
 // As a first step in splitting this class up in separate cases for audio and
 // video, DCHECK that no instance is used for both audio and video.
diff --git a/modules/rtp_rtcp/include/rtp_receiver.h b/modules/rtp_rtcp/include/rtp_receiver.h
index d2d73b4..d93d656 100644
--- a/modules/rtp_rtcp/include/rtp_receiver.h
+++ b/modules/rtp_rtcp/include/rtp_receiver.h
@@ -15,28 +15,12 @@
 
 #include "api/rtpreceiverinterface.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
 class RTPPayloadRegistry;
 class VideoCodec;
 
-class TelephoneEventHandler {
- public:
-  virtual ~TelephoneEventHandler() {}
-
-  // The following three methods implement the TelephoneEventHandler interface.
-  // Forward DTMFs to decoder for playout.
-  virtual void SetTelephoneEventForwardToDecoder(bool forward_to_decoder) = 0;
-
-  // Is forwarding of outband telephone events turned on/off?
-  virtual bool TelephoneEventForwardToDecoder() const = 0;
-
-  // Is TelephoneEvent configured with payload type payload_type
-  virtual bool TelephoneEventPayloadType(const int8_t payload_type) const = 0;
-};
-
 class RtpReceiver {
  public:
   // Creates a video-enabled RTP receiver.
@@ -53,9 +37,6 @@
 
   virtual ~RtpReceiver() {}
 
-  // Returns a TelephoneEventHandler if available.
-  virtual TelephoneEventHandler* GetTelephoneEventHandler() = 0;
-
   // Registers a receive payload in the payload registry and notifies the media
   // receiver strategy.
   virtual int32_t RegisterReceivePayload(
@@ -98,9 +79,6 @@
   // Returns the remote SSRC of the currently received RTP stream.
   virtual uint32_t SSRC() const = 0;
 
-  // Returns the current remote CSRCs.
-  virtual int32_t CSRCs(uint32_t array_of_csrc[kRtpCsrcSize]) const = 0;
-
   virtual std::vector<RtpSource> GetSources() const = 0;
 };
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/include/rtp_rtcp.h b/modules/rtp_rtcp/include/rtp_rtcp.h
index 94237e0..f982a9b 100644
--- a/modules/rtp_rtcp/include/rtp_rtcp.h
+++ b/modules/rtp_rtcp/include/rtp_rtcp.h
@@ -33,7 +33,6 @@
 class ReceiveStatisticsProvider;
 class RemoteBitrateEstimator;
 class RtcEventLog;
-class RtpReceiver;
 class Transport;
 class VideoBitrateAllocationObserver;
 
diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.cc b/modules/rtp_rtcp/include/rtp_rtcp_defines.cc
index ad9bd45..f86b238 100644
--- a/modules/rtp_rtcp/include/rtp_rtcp_defines.cc
+++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.cc
@@ -16,7 +16,19 @@
 
 constexpr size_t StreamId::kMaxSize;
 
-bool StreamId::IsLegalName(rtc::ArrayView<const char> name) {
+// Check if passed character is a "token-char" from RFC 4566.
+static bool IsTokenChar(char ch) {
+  return ch == 0x21 || (ch >= 0x23 && ch <= 0x27) || ch == 0x2a || ch == 0x2b ||
+         ch == 0x2d || ch == 0x2e || (ch >= 0x30 && ch <= 0x39) ||
+         (ch >= 0x41 && ch <= 0x5a) || (ch >= 0x5e && ch <= 0x7e);
+}
+
+bool StreamId::IsLegalMidName(rtc::ArrayView<const char> name) {
+  return (name.size() <= kMaxSize && name.size() > 0 &&
+          std::all_of(name.data(), name.data() + name.size(), IsTokenChar));
+}
+
+bool StreamId::IsLegalRsidName(rtc::ArrayView<const char> name) {
   return (name.size() <= kMaxSize && name.size() > 0 &&
           std::all_of(name.data(), name.data() + name.size(), isalnum));
 }
diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/modules/rtp_rtcp/include/rtp_rtcp_defines.h
index cfd9030..34c7428 100644
--- a/modules/rtp_rtcp/include/rtp_rtcp_defines.h
+++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.h
@@ -21,11 +21,9 @@
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/include/module_common_types.h"
 #include "system_wrappers/include/clock.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 #define RTCP_CNAME_SIZE 256  // RFC 3550 page 44, including null termination
 #define IP_PACKET_SIZE 1500  // we assume ethernet
-#define MAX_NUMBER_OF_PARALLEL_TELEPHONE_EVENTS 10
 
 namespace webrtc {
 namespace rtcp {
@@ -91,8 +89,6 @@
   absl::variant<AudioPayload, VideoPayload> payload_;
 };
 
-enum RTPAliveType { kRtpDead = 0, kRtpNoRtp = 1, kRtpAlive = 2 };
-
 enum ProtectionType { kUnprotectedPacket, kProtectedPacket };
 
 enum StorageType { kDontRetransmit, kAllowRetransmission };
@@ -197,7 +193,7 @@
   uint32_t sender_ssrc;  // SSRC of sender of this report.
   uint32_t source_ssrc;  // SSRC of the RTP packet sender.
   uint8_t fraction_lost;
-  uint32_t packets_lost;  // 24 bits valid.
+  int32_t packets_lost;  // 24 bits valid.
   uint32_t extended_highest_sequence_number;
   uint32_t jitter;
   uint32_t last_sender_report_timestamp;
diff --git a/modules/rtp_rtcp/include/ulpfec_receiver.h b/modules/rtp_rtcp/include/ulpfec_receiver.h
index 6ea8496..fce6e88 100644
--- a/modules/rtp_rtcp/include/ulpfec_receiver.h
+++ b/modules/rtp_rtcp/include/ulpfec_receiver.h
@@ -12,7 +12,6 @@
 #define MODULES_RTP_RTCP_INCLUDE_ULPFEC_RECEIVER_H_
 
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/byte_io.h b/modules/rtp_rtcp/source/byte_io.h
index f9d973b..955bce7 100644
--- a/modules/rtp_rtcp/source/byte_io.h
+++ b/modules/rtp_rtcp/source/byte_io.h
@@ -34,10 +34,9 @@
 // These classes are implemented as recursive templetizations, inteded to make
 // it easy for the compiler to completely inline the reading/writing.
 
+#include <stdint.h>
 #include <limits>
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 namespace webrtc {
 
 // According to ISO C standard ISO/IEC 9899, section 6.2.6.2 (2), the three
diff --git a/modules/rtp_rtcp/source/contributing_sources.cc b/modules/rtp_rtcp/source/contributing_sources.cc
new file mode 100644
index 0000000..853706c
--- /dev/null
+++ b/modules/rtp_rtcp/source/contributing_sources.cc
@@ -0,0 +1,68 @@
+/*
+ *  Copyright (c) 2018 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 "modules/rtp_rtcp/source/contributing_sources.h"
+
+namespace webrtc {
+
+namespace {
+
+// Allow some stale records to accumulate before cleaning.
+constexpr int64_t kPruningIntervalMs = 15 * rtc::kNumMillisecsPerSec;
+
+}  // namespace
+
+constexpr int64_t ContributingSources::kHistoryMs;
+
+ContributingSources::ContributingSources() = default;
+ContributingSources::~ContributingSources() = default;
+
+void ContributingSources::Update(int64_t now_ms,
+                                 rtc::ArrayView<const uint32_t> csrcs) {
+  for (uint32_t csrc : csrcs) {
+    last_seen_ms_[csrc] = now_ms;
+  }
+  if (!next_pruning_ms_) {
+    next_pruning_ms_ = now_ms + kPruningIntervalMs;
+  } else if (now_ms > next_pruning_ms_) {
+    // To prevent unlimited growth, prune it every 15 seconds.
+    DeleteOldEntries(now_ms);
+  }
+}
+
+// Return contributing sources seen the last 10 s.
+// TODO(nisse): It would be more efficient to delete any stale entries while
+// iterating over the mapping, but then we'd have to make the method
+// non-const.
+std::vector<RtpSource> ContributingSources::GetSources(int64_t now_ms) const {
+  std::vector<RtpSource> sources;
+  for (auto& record : last_seen_ms_) {
+    if (record.second >= now_ms - kHistoryMs) {
+      sources.emplace_back(record.second, record.first, RtpSourceType::CSRC);
+    }
+  }
+
+  return sources;
+}
+
+// Delete stale entries.
+void ContributingSources::DeleteOldEntries(int64_t now_ms) {
+  for (auto it = last_seen_ms_.begin(); it != last_seen_ms_.end();) {
+    if (it->second >= now_ms - kHistoryMs) {
+      // Still relevant.
+      ++it;
+    } else {
+      it = last_seen_ms_.erase(it);
+    }
+  }
+  next_pruning_ms_ = now_ms + kPruningIntervalMs;
+}
+
+}  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/contributing_sources.h b/modules/rtp_rtcp/source/contributing_sources.h
new file mode 100644
index 0000000..1a4a572
--- /dev/null
+++ b/modules/rtp_rtcp/source/contributing_sources.h
@@ -0,0 +1,51 @@
+/*
+ *  Copyright (c) 2018 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 MODULES_RTP_RTCP_SOURCE_CONTRIBUTING_SOURCES_H_
+#define MODULES_RTP_RTCP_SOURCE_CONTRIBUTING_SOURCES_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/rtpreceiverinterface.h"
+
+namespace webrtc {
+
+class ContributingSources {
+ public:
+  // Set by the spec, see
+  // https://www.w3.org/TR/webrtc/#dom-rtcrtpreceiver-getcontributingsources
+  static constexpr int64_t kHistoryMs = 10 * rtc::kNumMillisecsPerSec;
+
+  ContributingSources();
+  ~ContributingSources();
+
+  // TODO(bugs.webrtc.org/3333): Needs to be extended with audio-level, to
+  // support RFC6465.
+  void Update(int64_t now_ms, rtc::ArrayView<const uint32_t> csrcs);
+
+  // Returns contributing sources seen the last 10 s.
+  std::vector<RtpSource> GetSources(int64_t now_ms) const;
+
+ private:
+  void DeleteOldEntries(int64_t now_ms);
+
+  // Indexed by csrc.
+  std::map<uint32_t, int64_t> last_seen_ms_;
+  absl::optional<int64_t> next_pruning_ms_;
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_RTP_RTCP_SOURCE_CONTRIBUTING_SOURCES_H_
diff --git a/modules/rtp_rtcp/source/contributing_sources_unittest.cc b/modules/rtp_rtcp/source/contributing_sources_unittest.cc
new file mode 100644
index 0000000..8b22d26
--- /dev/null
+++ b/modules/rtp_rtcp/source/contributing_sources_unittest.cc
@@ -0,0 +1,111 @@
+/*
+ *  Copyright (c) 2018 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 "modules/rtp_rtcp/source/contributing_sources.h"
+
+#include "rtc_base/timeutils.h"
+
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+using ::testing::UnorderedElementsAre;
+
+constexpr uint32_t kCsrc1 = 111;
+constexpr uint32_t kCsrc2 = 222;
+constexpr uint32_t kCsrc3 = 333;
+
+}  // namespace
+
+TEST(ContributingSourcesTest, RecordSources) {
+  ContributingSources csrcs;
+  constexpr uint32_t kCsrcs[] = {kCsrc1, kCsrc2};
+  constexpr int64_t kTime1 = 10;
+  csrcs.Update(kTime1, kCsrcs);
+  EXPECT_THAT(
+      csrcs.GetSources(kTime1),
+      UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC),
+                           RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC)));
+}
+
+TEST(ContributingSourcesTest, UpdateSources) {
+  ContributingSources csrcs;
+  // TODO(nisse): When migrating to absl::Span, the named constant arrays should
+  // be replaced by unnamed literals where they are passed to csrcs.Update(...).
+  constexpr uint32_t kCsrcs1[] = {kCsrc1, kCsrc2};
+  constexpr uint32_t kCsrcs2[] = {kCsrc2, kCsrc3};
+  constexpr int64_t kTime1 = 10;
+  constexpr int64_t kTime2 = kTime1 + 5 * rtc::kNumMillisecsPerSec;
+  csrcs.Update(kTime1, kCsrcs1);
+  EXPECT_THAT(
+      csrcs.GetSources(kTime1),
+      UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC),
+                           RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC)));
+  csrcs.Update(kTime2, kCsrcs2);
+  EXPECT_THAT(
+      csrcs.GetSources(kTime2),
+      UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC),
+                           RtpSource(kTime2, kCsrc2, RtpSourceType::CSRC),
+                           RtpSource(kTime2, kCsrc3, RtpSourceType::CSRC)));
+}
+
+TEST(ContributingSourcesTest, ReturnRecentOnly) {
+  ContributingSources csrcs;
+  constexpr uint32_t kCsrcs1[] = {kCsrc1, kCsrc2};
+  constexpr uint32_t kCsrcs2[] = {kCsrc2, kCsrc3};
+  constexpr int64_t kTime1 = 10;
+  constexpr int64_t kTime2 = kTime1 + 5 * rtc::kNumMillisecsPerSec;
+  constexpr int64_t kTime3 = kTime1 + 12 * rtc::kNumMillisecsPerSec;
+  csrcs.Update(kTime1, kCsrcs1);
+  EXPECT_THAT(
+      csrcs.GetSources(kTime1),
+      UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC),
+                           RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC)));
+  csrcs.Update(kTime2, kCsrcs2);
+  EXPECT_THAT(
+      csrcs.GetSources(kTime3),
+      UnorderedElementsAre(RtpSource(kTime2, kCsrc2, RtpSourceType::CSRC),
+                           RtpSource(kTime2, kCsrc3, RtpSourceType::CSRC)));
+}
+
+TEST(ContributingSourcesTest, PurgeOldSources) {
+  ContributingSources csrcs;
+  constexpr uint32_t kCsrcs1[] = {kCsrc1, kCsrc2};
+  constexpr uint32_t kCsrcs2[] = {kCsrc2, kCsrc3};
+  constexpr int64_t kTime1 = 10;
+  constexpr int64_t kTime2 = kTime1 + 10 * rtc::kNumMillisecsPerSec;
+  constexpr int64_t kTime3 = kTime1 + 20 * rtc::kNumMillisecsPerSec;
+  csrcs.Update(kTime1, kCsrcs1);
+  EXPECT_THAT(
+      csrcs.GetSources(kTime2),
+      UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC),
+                           RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC)));
+  csrcs.Update(kTime2, kCsrcs2);
+  EXPECT_THAT(
+      csrcs.GetSources(kTime2),
+      UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC),
+                           RtpSource(kTime2, kCsrc2, RtpSourceType::CSRC),
+                           RtpSource(kTime2, kCsrc3, RtpSourceType::CSRC)));
+  csrcs.Update(kTime3, kCsrcs2);
+  EXPECT_THAT(
+      csrcs.GetSources(kTime3),
+      UnorderedElementsAre(RtpSource(kTime3, kCsrc2, RtpSourceType::CSRC),
+                           RtpSource(kTime3, kCsrc3, RtpSourceType::CSRC)));
+  // Query at an earlier time; check that old sources really have been purged
+  // and don't reappear.
+  EXPECT_THAT(
+      csrcs.GetSources(kTime2),
+      UnorderedElementsAre(RtpSource(kTime3, kCsrc2, RtpSourceType::CSRC),
+                           RtpSource(kTime3, kCsrc3, RtpSourceType::CSRC)));
+}
+
+}  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/fec_private_tables_bursty.h b/modules/rtp_rtcp/source/fec_private_tables_bursty.h
index 4120cf9..5d67292 100644
--- a/modules/rtp_rtcp/source/fec_private_tables_bursty.h
+++ b/modules/rtp_rtcp/source/fec_private_tables_bursty.h
@@ -25,9 +25,7 @@
 // (i.e., more packets/symbols in the code, so larger (k,m), i.e.,  k > 4,
 // m > 3).
 
-#include <cstddef>
-
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 namespace webrtc {
 namespace fec_private_tables {
diff --git a/modules/rtp_rtcp/source/fec_private_tables_random.h b/modules/rtp_rtcp/source/fec_private_tables_random.h
index 96c3cef..cc7b929 100644
--- a/modules/rtp_rtcp/source/fec_private_tables_random.h
+++ b/modules/rtp_rtcp/source/fec_private_tables_random.h
@@ -15,9 +15,7 @@
 // this table are specifically designed to favor recovery to random loss.
 // These packet masks are defined to protect up to maximum of 48 media packets.
 
-#include <cstddef>
-
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 namespace webrtc {
 namespace fec_private_tables {
diff --git a/modules/rtp_rtcp/source/nack_rtx_unittest.cc b/modules/rtp_rtcp/source/nack_rtx_unittest.cc
index 53ff5d5..7ecec76 100644
--- a/modules/rtp_rtcp/source/nack_rtx_unittest.cc
+++ b/modules/rtp_rtcp/source/nack_rtx_unittest.cc
@@ -202,9 +202,10 @@
     uint32_t timestamp = 3000;
     uint16_t nack_list[kVideoNackListSize];
     for (int frame = 0; frame < kNumFrames; ++frame) {
+      RTPVideoHeader video_header;
       EXPECT_TRUE(rtp_rtcp_module_->SendOutgoingData(
           webrtc::kVideoFrameDelta, kPayloadType, timestamp, timestamp / 90,
-          payload_data, payload_data_length, nullptr, nullptr, nullptr));
+          payload_data, payload_data_length, nullptr, &video_header, nullptr));
       // Min required delay until retransmit = 5 + RTT ms (RTT = 0).
       fake_clock.AdvanceTimeMilliseconds(5);
       int length = BuildNackList(nack_list);
@@ -250,9 +251,10 @@
   // Send 30 frames which at the default size is roughly what we need to get
   // enough packets.
   for (int frame = 0; frame < kNumFrames; ++frame) {
+    RTPVideoHeader video_header;
     EXPECT_TRUE(rtp_rtcp_module_->SendOutgoingData(
         webrtc::kVideoFrameDelta, kPayloadType, timestamp, timestamp / 90,
-        payload_data, payload_data_length, nullptr, nullptr, nullptr));
+        payload_data, payload_data_length, nullptr, &video_header, nullptr));
     // Prepare next frame.
     timestamp += 3000;
     fake_clock.AdvanceTimeMilliseconds(33);
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc
index 362a7cf..80b8c9b 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc
@@ -31,6 +31,7 @@
 StreamStatisticianImpl::StreamStatisticianImpl(
     uint32_t ssrc,
     Clock* clock,
+    bool enable_retransmit_detection,
     RtcpStatisticsCallback* rtcp_callback,
     StreamDataCountersCallback* rtp_callback)
     : ssrc_(ssrc),
@@ -38,6 +39,7 @@
       incoming_bitrate_(kStatisticsProcessIntervalMs,
                         RateStatistics::kBpsScale),
       max_reordering_threshold_(kDefaultMaxReorderingThreshold),
+      enable_retransmit_detection_(enable_retransmit_detection),
       jitter_q4_(0),
       cumulative_loss_(0),
       last_receive_time_ms_(0),
@@ -55,9 +57,15 @@
 StreamStatisticianImpl::~StreamStatisticianImpl() = default;
 
 void StreamStatisticianImpl::IncomingPacket(const RTPHeader& header,
-                                            size_t packet_length,
-                                            bool retransmitted) {
-  auto counters = UpdateCounters(header, packet_length, retransmitted);
+                                            size_t packet_length) {
+  StreamDataCounters counters;
+  {
+    rtc::CritScope cs(&stream_lock_);
+
+    bool retransmitted =
+        enable_retransmit_detection_ && IsRetransmitOfOldPacket(header);
+    counters = UpdateCounters(header, packet_length, retransmitted);
+  }
   rtp_callback_->DataCountersUpdated(counters, ssrc_);
 }
 
@@ -65,7 +73,6 @@
     const RTPHeader& header,
     size_t packet_length,
     bool retransmitted) {
-  rtc::CritScope cs(&stream_lock_);
   bool in_order = InOrderPacketInternal(header.sequenceNumber);
   RTC_DCHECK_EQ(ssrc_, header.ssrc);
   incoming_bitrate_.Update(packet_length, clock_->TimeInMilliseconds());
@@ -152,6 +159,11 @@
   max_reordering_threshold_ = max_reordering_threshold;
 }
 
+void StreamStatisticianImpl::EnableRetransmitDetection(bool enable) {
+  rtc::CritScope cs(&stream_lock_);
+  enable_retransmit_detection_ = enable;
+}
+
 bool StreamStatisticianImpl::GetStatistics(RtcpStatistics* statistics,
                                            bool reset) {
   {
@@ -300,7 +312,6 @@
 
 bool StreamStatisticianImpl::IsRetransmitOfOldPacket(
     const RTPHeader& header) const {
-  rtc::CritScope cs(&stream_lock_);
   if (InOrderPacketInternal(header.sequenceNumber)) {
     return false;
   }
@@ -362,8 +373,7 @@
 }
 
 void ReceiveStatisticsImpl::IncomingPacket(const RTPHeader& header,
-                                           size_t packet_length,
-                                           bool retransmitted) {
+                                           size_t packet_length) {
   StreamStatisticianImpl* impl;
   {
     rtc::CritScope cs(&receive_statistics_lock_);
@@ -371,7 +381,9 @@
     if (it != statisticians_.end()) {
       impl = it->second;
     } else {
-      impl = new StreamStatisticianImpl(header.ssrc, clock_, this, this);
+      impl = new StreamStatisticianImpl(
+          header.ssrc, clock_, /* enable_retransmit_detection = */ false, this,
+          this);
       statisticians_[header.ssrc] = impl;
     }
   }
@@ -379,7 +391,7 @@
   // this whole ReceiveStatisticsImpl is destroyed. StreamStatisticianImpl has
   // it's own locking so don't hold receive_statistics_lock_ (potential
   // deadlock).
-  impl->IncomingPacket(header, packet_length, retransmitted);
+  impl->IncomingPacket(header, packet_length);
 }
 
 void ReceiveStatisticsImpl::FecPacketReceived(const RTPHeader& header,
@@ -413,6 +425,21 @@
   }
 }
 
+void ReceiveStatisticsImpl::EnableRetransmitDetection(uint32_t ssrc,
+                                                      bool enable) {
+  StreamStatisticianImpl* impl;
+  {
+    rtc::CritScope cs(&receive_statistics_lock_);
+    StreamStatisticianImpl*& impl_ref = statisticians_[ssrc];
+    if (impl_ref == nullptr) {  // new element
+      impl_ref = new StreamStatisticianImpl(ssrc, clock_, enable, this, this);
+      return;
+    }
+    impl = impl_ref;
+  }
+  impl->EnableRetransmitDetection(enable);
+}
+
 void ReceiveStatisticsImpl::RegisterRtcpStatisticsCallback(
     RtcpStatisticsCallback* callback) {
   rtc::CritScope cs(&receive_statistics_lock_);
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.h b/modules/rtp_rtcp/source/receive_statistics_impl.h
index 5559b7c..f94256a 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.h
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.h
@@ -27,6 +27,7 @@
  public:
   StreamStatisticianImpl(uint32_t ssrc,
                          Clock* clock,
+                         bool enable_retransmit_detection,
                          RtcpStatisticsCallback* rtcp_callback,
                          StreamDataCountersCallback* rtp_callback);
   ~StreamStatisticianImpl() override;
@@ -39,49 +40,54 @@
   void GetReceiveStreamDataCounters(
       StreamDataCounters* data_counters) const override;
   uint32_t BitrateReceived() const override;
-  bool IsRetransmitOfOldPacket(const RTPHeader& header) const override;
 
-  void IncomingPacket(const RTPHeader& rtp_header,
-                      size_t packet_length,
-                      bool retransmitted);
+  void IncomingPacket(const RTPHeader& rtp_header, size_t packet_length);
   void FecPacketReceived(const RTPHeader& header, size_t packet_length);
   void SetMaxReorderingThreshold(int max_reordering_threshold);
+  void EnableRetransmitDetection(bool enable);
 
  private:
-  bool InOrderPacketInternal(uint16_t sequence_number) const;
+  bool IsRetransmitOfOldPacket(const RTPHeader& header) const
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
+  bool InOrderPacketInternal(uint16_t sequence_number) const
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
   RtcpStatistics CalculateRtcpStatistics()
       RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
-  void UpdateJitter(const RTPHeader& header, NtpTime receive_time);
+  void UpdateJitter(const RTPHeader& header, NtpTime receive_time)
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
   StreamDataCounters UpdateCounters(const RTPHeader& rtp_header,
                                     size_t packet_length,
-                                    bool retransmitted);
+                                    bool retransmitted)
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(stream_lock_);
 
   const uint32_t ssrc_;
   Clock* const clock_;
   rtc::CriticalSection stream_lock_;
-  RateStatistics incoming_bitrate_;
-  int max_reordering_threshold_;  // In number of packets or sequence numbers.
+  RateStatistics incoming_bitrate_ RTC_GUARDED_BY(&stream_lock_);
+  // In number of packets or sequence numbers.
+  int max_reordering_threshold_ RTC_GUARDED_BY(&stream_lock_);
+  bool enable_retransmit_detection_ RTC_GUARDED_BY(&stream_lock_);
 
   // Stats on received RTP packets.
-  uint32_t jitter_q4_;
-  uint32_t cumulative_loss_;
+  uint32_t jitter_q4_ RTC_GUARDED_BY(&stream_lock_);
+  uint32_t cumulative_loss_ RTC_GUARDED_BY(&stream_lock_);
 
-  int64_t last_receive_time_ms_;
-  NtpTime last_receive_time_ntp_;
-  uint32_t last_received_timestamp_;
-  uint16_t received_seq_first_;
-  uint16_t received_seq_max_;
-  uint16_t received_seq_wraps_;
+  int64_t last_receive_time_ms_ RTC_GUARDED_BY(&stream_lock_);
+  NtpTime last_receive_time_ntp_ RTC_GUARDED_BY(&stream_lock_);
+  uint32_t last_received_timestamp_ RTC_GUARDED_BY(&stream_lock_);
+  uint16_t received_seq_first_ RTC_GUARDED_BY(&stream_lock_);
+  uint16_t received_seq_max_ RTC_GUARDED_BY(&stream_lock_);
+  uint16_t received_seq_wraps_ RTC_GUARDED_BY(&stream_lock_);
 
   // Current counter values.
-  size_t received_packet_overhead_;
-  StreamDataCounters receive_counters_;
+  size_t received_packet_overhead_ RTC_GUARDED_BY(&stream_lock_);
+  StreamDataCounters receive_counters_ RTC_GUARDED_BY(&stream_lock_);
 
   // Counter values when we sent the last report.
-  uint32_t last_report_inorder_packets_;
-  uint32_t last_report_old_packets_;
-  uint16_t last_report_seq_max_;
-  RtcpStatistics last_reported_statistics_;
+  uint32_t last_report_inorder_packets_ RTC_GUARDED_BY(&stream_lock_);
+  uint32_t last_report_old_packets_ RTC_GUARDED_BY(&stream_lock_);
+  uint16_t last_report_seq_max_ RTC_GUARDED_BY(&stream_lock_);
+  RtcpStatistics last_reported_statistics_ RTC_GUARDED_BY(&stream_lock_);
 
   // stream_lock_ shouldn't be held when calling callbacks.
   RtcpStatisticsCallback* const rtcp_callback_;
@@ -100,13 +106,12 @@
   std::vector<rtcp::ReportBlock> RtcpReportBlocks(size_t max_blocks) override;
 
   // Implement ReceiveStatistics.
-  void IncomingPacket(const RTPHeader& header,
-                      size_t packet_length,
-                      bool retransmitted) override;
+  void IncomingPacket(const RTPHeader& header, size_t packet_length) override;
   void FecPacketReceived(const RTPHeader& header,
                          size_t packet_length) override;
   StreamStatistician* GetStatistician(uint32_t ssrc) const override;
   void SetMaxReorderingThreshold(int max_reordering_threshold) override;
+  void EnableRetransmitDetection(uint32_t ssrc, bool enable) override;
 
   void RegisterRtcpStatisticsCallback(
       RtcpStatisticsCallback* callback) override;
diff --git a/modules/rtp_rtcp/source/receive_statistics_unittest.cc b/modules/rtp_rtcp/source/receive_statistics_unittest.cc
index 29fc88d..b721b03 100644
--- a/modules/rtp_rtcp/source/receive_statistics_unittest.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_unittest.cc
@@ -34,6 +34,7 @@
   memset(&header, 0, sizeof(header));
   header.ssrc = ssrc;
   header.sequenceNumber = 100;
+  header.payload_type_frequency = 90000;
   return header;
 }
 
@@ -53,14 +54,14 @@
 };
 
 TEST_F(ReceiveStatisticsTest, TwoIncomingSsrcs) {
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   ++header1_.sequenceNumber;
-  receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
+  receive_statistics_->IncomingPacket(header2_, kPacketSize2);
   ++header2_.sequenceNumber;
   clock_.AdvanceTimeMilliseconds(100);
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   ++header1_.sequenceNumber;
-  receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
+  receive_statistics_->IncomingPacket(header2_, kPacketSize2);
   ++header2_.sequenceNumber;
 
   StreamStatistician* statistician =
@@ -83,9 +84,9 @@
   EXPECT_EQ(2u, receive_statistics_->RtcpReportBlocks(3).size());
   // Add more incoming packets and verify that they are registered in both
   // access methods.
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   ++header1_.sequenceNumber;
-  receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
+  receive_statistics_->IncomingPacket(header2_, kPacketSize2);
   ++header2_.sequenceNumber;
 
   receive_statistics_->GetStatistician(kSsrc1)->GetDataCounters(
@@ -103,9 +104,9 @@
   RTPHeader header1 = CreateRtpHeader(kSsrc1);
   RTPHeader header2 = CreateRtpHeader(kSsrc2);
   RTPHeader header3 = CreateRtpHeader(kSsrc3);
-  receive_statistics_->IncomingPacket(header1, kPacketSize1, false);
-  receive_statistics_->IncomingPacket(header2, kPacketSize1, false);
-  receive_statistics_->IncomingPacket(header3, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1, kPacketSize1);
+  receive_statistics_->IncomingPacket(header2, kPacketSize1);
+  receive_statistics_->IncomingPacket(header3, kPacketSize1);
 
   EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
   EXPECT_THAT(receive_statistics_->RtcpReportBlocks(2), SizeIs(2));
@@ -118,10 +119,10 @@
   RTPHeader header2 = CreateRtpHeader(kSsrc2);
   RTPHeader header3 = CreateRtpHeader(kSsrc3);
   RTPHeader header4 = CreateRtpHeader(kSsrc4);
-  receive_statistics_->IncomingPacket(header1, kPacketSize1, false);
-  receive_statistics_->IncomingPacket(header2, kPacketSize1, false);
-  receive_statistics_->IncomingPacket(header3, kPacketSize1, false);
-  receive_statistics_->IncomingPacket(header4, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1, kPacketSize1);
+  receive_statistics_->IncomingPacket(header2, kPacketSize1);
+  receive_statistics_->IncomingPacket(header3, kPacketSize1);
+  receive_statistics_->IncomingPacket(header4, kPacketSize1);
 
   std::vector<uint32_t> observed_ssrcs;
   std::vector<rtcp::ReportBlock> report_blocks =
@@ -140,10 +141,10 @@
 }
 
 TEST_F(ReceiveStatisticsTest, ActiveStatisticians) {
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   ++header1_.sequenceNumber;
   clock_.AdvanceTimeMilliseconds(1000);
-  receive_statistics_->IncomingPacket(header2_, kPacketSize2, false);
+  receive_statistics_->IncomingPacket(header2_, kPacketSize2);
   ++header2_.sequenceNumber;
   // Nothing should time out since only 1000 ms has passed since the first
   // packet came in.
@@ -157,7 +158,7 @@
   // kSsrc2 should have timed out.
   EXPECT_EQ(0u, receive_statistics_->RtcpReportBlocks(3).size());
 
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   ++header1_.sequenceNumber;
   // kSsrc1 should be active again and the data counters should have survived.
   EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
@@ -171,8 +172,19 @@
   EXPECT_EQ(2u, packets_received);
 }
 
+TEST_F(ReceiveStatisticsTest,
+       DoesntCreateRtcpReportBlockUntilFirstReceivedPacketForSsrc) {
+  // Creates a statistician object for the ssrc.
+  receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
+  EXPECT_TRUE(receive_statistics_->GetStatistician(kSsrc1) != nullptr);
+  EXPECT_EQ(0u, receive_statistics_->RtcpReportBlocks(3).size());
+  // Receive first packet
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
+  EXPECT_EQ(1u, receive_statistics_->RtcpReportBlocks(3).size());
+}
+
 TEST_F(ReceiveStatisticsTest, GetReceiveStreamDataCounters) {
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   StreamStatistician* statistician =
       receive_statistics_->GetStatistician(kSsrc1);
   ASSERT_TRUE(statistician != NULL);
@@ -182,7 +194,7 @@
   EXPECT_GT(counters.first_packet_time_ms, -1);
   EXPECT_EQ(1u, counters.transmitted.packets);
 
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   statistician->GetReceiveStreamDataCounters(&counters);
   EXPECT_GT(counters.first_packet_time_ms, -1);
   EXPECT_EQ(2u, counters.transmitted.packets);
@@ -210,24 +222,25 @@
   } callback;
 
   receive_statistics_->RegisterRtcpStatisticsCallback(&callback);
+  receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
 
   // Add some arbitrary data, with loss and jitter.
   header1_.sequenceNumber = 1;
   clock_.AdvanceTimeMilliseconds(7);
   header1_.timestamp += 3;
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   header1_.sequenceNumber += 2;
   clock_.AdvanceTimeMilliseconds(9);
   header1_.timestamp += 9;
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   --header1_.sequenceNumber;
   clock_.AdvanceTimeMilliseconds(13);
   header1_.timestamp += 47;
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, true);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   header1_.sequenceNumber += 3;
   clock_.AdvanceTimeMilliseconds(11);
   header1_.timestamp += 17;
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   ++header1_.sequenceNumber;
 
   EXPECT_EQ(0u, callback.num_calls_);
@@ -247,7 +260,7 @@
   EXPECT_EQ(51, statistics.fraction_lost);
   EXPECT_EQ(1, statistics.packets_lost);
   EXPECT_EQ(5u, statistics.extended_highest_sequence_number);
-  EXPECT_EQ(4u, statistics.jitter);
+  EXPECT_EQ(177u, statistics.jitter);
 
   receive_statistics_->RegisterRtcpStatisticsCallback(NULL);
 
@@ -255,19 +268,19 @@
   header1_.sequenceNumber = 1;
   clock_.AdvanceTimeMilliseconds(7);
   header1_.timestamp += 3;
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   header1_.sequenceNumber += 2;
   clock_.AdvanceTimeMilliseconds(9);
   header1_.timestamp += 9;
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   --header1_.sequenceNumber;
   clock_.AdvanceTimeMilliseconds(13);
   header1_.timestamp += 47;
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, true);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   header1_.sequenceNumber += 3;
   clock_.AdvanceTimeMilliseconds(11);
   header1_.timestamp += 17;
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1, false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1);
   ++header1_.sequenceNumber;
 
   receive_statistics_->GetStatistician(kSsrc1)->GetStatistics(&statistics,
@@ -316,14 +329,14 @@
 TEST_F(ReceiveStatisticsTest, RtpCallbacks) {
   RtpTestCallback callback;
   receive_statistics_->RegisterRtpStatisticsCallback(&callback);
+  receive_statistics_->EnableRetransmitDetection(kSsrc1, true);
 
   const size_t kHeaderLength = 20;
   const size_t kPaddingLength = 9;
 
   // One packet of size kPacketSize1.
   header1_.headerLength = kHeaderLength;
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1 + kHeaderLength,
-                                      false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1 + kHeaderLength);
   StreamDataCounters expected;
   expected.transmitted.payload_bytes = kPacketSize1;
   expected.transmitted.header_bytes = kHeaderLength;
@@ -341,7 +354,7 @@
   header1_.paddingLength = 9;
   // Another packet of size kPacketSize1 with 9 bytes padding.
   receive_statistics_->IncomingPacket(
-      header1_, kPacketSize1 + kHeaderLength + kPaddingLength, false);
+      header1_, kPacketSize1 + kHeaderLength + kPaddingLength);
   expected.transmitted.payload_bytes = kPacketSize1 * 2;
   expected.transmitted.header_bytes = kHeaderLength * 2;
   expected.transmitted.padding_bytes = kPaddingLength;
@@ -351,7 +364,7 @@
   clock_.AdvanceTimeMilliseconds(5);
   // Retransmit last packet.
   receive_statistics_->IncomingPacket(
-      header1_, kPacketSize1 + kHeaderLength + kPaddingLength, true);
+      header1_, kPacketSize1 + kHeaderLength + kPaddingLength);
   expected.transmitted.payload_bytes = kPacketSize1 * 3;
   expected.transmitted.header_bytes = kHeaderLength * 3;
   expected.transmitted.padding_bytes = kPaddingLength * 2;
@@ -366,8 +379,7 @@
   ++header1_.sequenceNumber;
   clock_.AdvanceTimeMilliseconds(5);
   // One FEC packet.
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1 + kHeaderLength,
-                                      false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1 + kHeaderLength);
   receive_statistics_->FecPacketReceived(header1_,
                                          kPacketSize1 + kHeaderLength);
   expected.transmitted.payload_bytes = kPacketSize1 * 4;
@@ -383,8 +395,7 @@
   // New stats, but callback should not be called.
   ++header1_.sequenceNumber;
   clock_.AdvanceTimeMilliseconds(5);
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1 + kHeaderLength,
-                                      true);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1 + kHeaderLength);
   callback.Matches(5, kSsrc1, expected);
 }
 
@@ -400,8 +411,7 @@
                                          kPacketSize1 + kHeaderLength);
   EXPECT_EQ(0u, callback.num_calls_);
 
-  receive_statistics_->IncomingPacket(header1_, kPacketSize1 + kHeaderLength,
-                                      false);
+  receive_statistics_->IncomingPacket(header1_, kPacketSize1 + kHeaderLength);
   StreamDataCounters expected;
   expected.transmitted.payload_bytes = kPacketSize1;
   expected.transmitted.header_bytes = kHeaderLength;
diff --git a/modules/rtp_rtcp/source/rtcp_packet/report_block.cc b/modules/rtp_rtcp/source/rtcp_packet/report_block.cc
index 4f98963..d4579fc 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/report_block.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet/report_block.cc
@@ -54,7 +54,7 @@
 
   source_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[0]);
   fraction_lost_ = buffer[4];
-  cumulative_lost_ = ByteReader<uint32_t, 3>::ReadBigEndian(&buffer[5]);
+  cumulative_lost_ = ByteReader<int32_t, 3>::ReadBigEndian(&buffer[5]);
   extended_high_seq_num_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[8]);
   jitter_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[12]);
   last_sr_ = ByteReader<uint32_t>::ReadBigEndian(&buffer[16]);
diff --git a/modules/rtp_rtcp/source/rtcp_packet/report_block_unittest.cc b/modules/rtp_rtcp/source/rtcp_packet/report_block_unittest.cc
index a074a2f..5cc102f 100644
--- a/modules/rtp_rtcp/source/rtcp_packet/report_block_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_packet/report_block_unittest.cc
@@ -91,5 +91,20 @@
   EXPECT_EQ(0u, rb.cumulative_lost());
 }
 
+TEST(RtcpPacketReportBlockTest, ParseNegativeCumulativeLost) {
+  // CumulativeLost is a signed 24-bit integer.
+  const int32_t kNegativeCumulativeLost = -123;
+  ReportBlock rb;
+  EXPECT_TRUE(rb.SetCumulativeLost(kNegativeCumulativeLost));
+
+  uint8_t buffer[kBufferLength];
+  rb.Create(buffer);
+
+  ReportBlock parsed;
+  EXPECT_TRUE(parsed.Parse(buffer, kBufferLength));
+
+  EXPECT_EQ(kNegativeCumulativeLost, parsed.cumulative_lost_signed());
+}
+
 }  // namespace
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtcp_receiver.cc b/modules/rtp_rtcp/source/rtcp_receiver.cc
index 491bd45..4966754 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver.cc
+++ b/modules/rtp_rtcp/source/rtcp_receiver.cc
@@ -19,8 +19,8 @@
 #include <vector>
 
 #include "api/video/video_bitrate_allocation.h"
+#include "api/video/video_bitrate_allocator.h"
 #include "common_types.h"  // NOLINT(build/include)
-#include "common_video/include/video_bitrate_allocator.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/compound_packet.h"
diff --git a/modules/rtp_rtcp/source/rtcp_receiver.h b/modules/rtp_rtcp/source/rtcp_receiver.h
index c868837..a863cae 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver.h
+++ b/modules/rtp_rtcp/source/rtcp_receiver.h
@@ -23,7 +23,6 @@
 #include "rtc_base/criticalsection.h"
 #include "rtc_base/thread_annotations.h"
 #include "system_wrappers/include/ntp_time.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 class VideoBitrateAllocationObserver;
diff --git a/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
index 41d4725..6cd953c 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
@@ -12,8 +12,8 @@
 
 #include "api/array_view.h"
 #include "api/video/video_bitrate_allocation.h"
+#include "api/video/video_bitrate_allocator.h"
 #include "common_types.h"  // NOLINT(build/include)
-#include "common_video/include/video_bitrate_allocator.h"
 #include "modules/rtp_rtcp/mocks/mock_rtcp_bandwidth_observer.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
 #include "modules/rtp_rtcp/source/rtcp_packet.h"
@@ -441,7 +441,7 @@
 TEST_F(RtcpReceiverTest, InjectRrPacketsFromTwoRemoteSsrcs) {
   const uint32_t kSenderSsrc2 = 0x20304;
   const uint16_t kSequenceNumbers[] = {10, 12423};
-  const uint32_t kCumLost[] = {13, 555};
+  const int32_t kCumLost[] = {13, 555};
   const uint8_t kFracLost[] = {20, 11};
 
   rtcp::ReportBlock rb1;
diff --git a/modules/rtp_rtcp/source/rtcp_sender.h b/modules/rtp_rtcp/source/rtcp_sender.h
index e274915..133bf68 100644
--- a/modules/rtp_rtcp/source/rtcp_sender.h
+++ b/modules/rtp_rtcp/source/rtcp_sender.h
@@ -33,7 +33,6 @@
 #include "rtc_base/criticalsection.h"
 #include "rtc_base/random.h"
 #include "rtc_base/thread_annotations.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/rtcp_sender_unittest.cc b/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
index 974f19f..bccf96d 100644
--- a/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
@@ -99,7 +99,7 @@
     header.timestamp = 12345;
     header.headerLength = 12;
     size_t kPacketLength = 100;
-    receive_statistics_->IncomingPacket(header, kPacketLength, false);
+    receive_statistics_->IncomingPacket(header, kPacketLength);
   }
 
   test::RtcpPacketParser* parser() { return &test_transport_.parser_; }
diff --git a/modules/rtp_rtcp/source/rtp_format.cc b/modules/rtp_rtcp/source/rtp_format.cc
index 8bd27a7..72beb17 100644
--- a/modules/rtp_rtcp/source/rtp_format.cc
+++ b/modules/rtp_rtcp/source/rtp_format.cc
@@ -12,37 +12,53 @@
 
 #include <utility>
 
+#include "absl/memory/memory.h"
 #include "modules/rtp_rtcp/source/rtp_format_h264.h"
 #include "modules/rtp_rtcp/source/rtp_format_video_generic.h"
 #include "modules/rtp_rtcp/source/rtp_format_vp8.h"
 #include "modules/rtp_rtcp/source/rtp_format_vp9.h"
 
 namespace webrtc {
-RtpPacketizer* RtpPacketizer::Create(VideoCodecType type,
-                                     size_t max_payload_len,
-                                     size_t last_packet_reduction_len,
-                                     const RTPVideoHeader* rtp_video_header,
-                                     FrameType frame_type) {
+
+std::unique_ptr<RtpPacketizer> RtpPacketizer::Create(
+    VideoCodecType type,
+    rtc::ArrayView<const uint8_t> payload,
+    PayloadSizeLimits limits,
+    // Codec-specific details.
+    const RTPVideoHeader& rtp_video_header,
+    FrameType frame_type,
+    const RTPFragmentationHeader* fragmentation) {
   switch (type) {
-    case kVideoCodecH264:
-      RTC_CHECK(rtp_video_header);
-      return new RtpPacketizerH264(max_payload_len, last_packet_reduction_len,
-                                   rtp_video_header->h264().packetization_mode);
-    case kVideoCodecVP8:
-      RTC_CHECK(rtp_video_header);
-      return new RtpPacketizerVp8(rtp_video_header->vp8(), max_payload_len,
-                                  last_packet_reduction_len);
-    case kVideoCodecVP9:
-      RTC_CHECK(rtp_video_header);
-      return new RtpPacketizerVp9(rtp_video_header->vp9(), max_payload_len,
-                                  last_packet_reduction_len);
-    case kVideoCodecGeneric:
-      return new RtpPacketizerGeneric(frame_type, max_payload_len,
-                                      last_packet_reduction_len);
-    default:
-      RTC_NOTREACHED();
+    case kVideoCodecH264: {
+      const auto& h264 =
+          absl::get<RTPVideoHeaderH264>(rtp_video_header.video_type_header);
+      auto packetizer = absl::make_unique<RtpPacketizerH264>(
+          limits.max_payload_len, limits.last_packet_reduction_len,
+          h264.packetization_mode);
+      packetizer->SetPayloadData(payload.data(), payload.size(), fragmentation);
+      return std::move(packetizer);
+    }
+    case kVideoCodecVP8: {
+      const auto& vp8 =
+          absl::get<RTPVideoHeaderVP8>(rtp_video_header.video_type_header);
+      return absl::make_unique<RtpPacketizerVp8>(payload, limits, vp8);
+    }
+    case kVideoCodecVP9: {
+      const auto& vp9 =
+          absl::get<RTPVideoHeaderVP9>(rtp_video_header.video_type_header);
+      auto packetizer = absl::make_unique<RtpPacketizerVp9>(
+          vp9, limits.max_payload_len, limits.last_packet_reduction_len);
+      packetizer->SetPayloadData(payload.data(), payload.size(), nullptr);
+      return std::move(packetizer);
+    }
+    default: {
+      auto packetizer = absl::make_unique<RtpPacketizerGeneric>(
+          rtp_video_header, frame_type, limits.max_payload_len,
+          limits.last_packet_reduction_len);
+      packetizer->SetPayloadData(payload.data(), payload.size(), nullptr);
+      return std::move(packetizer);
+    }
   }
-  return nullptr;
 }
 
 RtpDepacketizer* RtpDepacketizer::Create(VideoCodecType type) {
@@ -53,11 +69,8 @@
       return new RtpDepacketizerVp8();
     case kVideoCodecVP9:
       return new RtpDepacketizerVp9();
-    case kVideoCodecGeneric:
-      return new RtpDepacketizerGeneric();
     default:
-      RTC_NOTREACHED();
+      return new RtpDepacketizerGeneric();
   }
-  return nullptr;
 }
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_format.h b/modules/rtp_rtcp/source/rtp_format.h
index 76d7f47..007ddbc 100644
--- a/modules/rtp_rtcp/source/rtp_format.h
+++ b/modules/rtp_rtcp/source/rtp_format.h
@@ -11,8 +11,10 @@
 #ifndef MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H_
 #define MODULES_RTP_RTCP_SOURCE_RTP_FORMAT_H_
 
+#include <memory>
 #include <string>
 
+#include "api/array_view.h"
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/include/module_common_types.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
@@ -23,26 +25,28 @@
 
 class RtpPacketizer {
  public:
-  static RtpPacketizer* Create(VideoCodecType type,
-                               size_t max_payload_len,
-                               size_t last_packet_reduction_len,
-                               const RTPVideoHeader* rtp_video_header,
-                               FrameType frame_type);
+  struct PayloadSizeLimits {
+    size_t max_payload_len = 1200;
+    size_t last_packet_reduction_len = 0;
+  };
+  static std::unique_ptr<RtpPacketizer> Create(
+      VideoCodecType type,
+      rtc::ArrayView<const uint8_t> payload,
+      PayloadSizeLimits limits,
+      // Codec-specific details.
+      const RTPVideoHeader& rtp_video_header,
+      FrameType frame_type,
+      const RTPFragmentationHeader* fragmentation);
 
-  virtual ~RtpPacketizer() {}
+  virtual ~RtpPacketizer() = default;
 
-  // Returns total number of packets which would be produced by the packetizer.
-  virtual size_t SetPayloadData(
-      const uint8_t* payload_data,
-      size_t payload_size,
-      const RTPFragmentationHeader* fragmentation) = 0;
+  // Returns number of remaining packets to produce by the packetizer.
+  virtual size_t NumPackets() const = 0;
 
   // Get the next payload with payload header.
   // Write payload and set marker bit of the |packet|.
   // Returns true on success, false otherwise.
   virtual bool NextPacket(RtpPacketToSend* packet) = 0;
-
-  virtual std::string ToString() = 0;
 };
 
 // TODO(sprang): Update the depacketizer to return a std::unqie_ptr with a copy
diff --git a/modules/rtp_rtcp/source/rtp_format_h264.cc b/modules/rtp_rtcp/source/rtp_format_h264.cc
index 0b8c15f..373cce9 100644
--- a/modules/rtp_rtcp/source/rtp_format_h264.cc
+++ b/modules/rtp_rtcp/source/rtp_format_h264.cc
@@ -182,6 +182,10 @@
   return num_packets_left_;
 }
 
+size_t RtpPacketizerH264::NumPackets() const {
+  return num_packets_left_;
+}
+
 bool RtpPacketizerH264::GeneratePackets() {
   for (size_t i = 0; i < input_fragments_.size();) {
     switch (packetization_mode_) {
@@ -408,10 +412,6 @@
   packets_.pop();
 }
 
-std::string RtpPacketizerH264::ToString() {
-  return "RtpPacketizerH264";
-}
-
 RtpDepacketizerH264::RtpDepacketizerH264() : offset_(0), length_(0) {}
 RtpDepacketizerH264::~RtpDepacketizerH264() {}
 
@@ -429,7 +429,8 @@
   modified_buffer_.reset();
 
   uint8_t nal_type = payload_data[0] & kTypeMask;
-  parsed_payload->video_header().h264().nalus_length = 0;
+  parsed_payload->video_header()
+      .video_type_header.emplace<RTPVideoHeaderH264>();
   if (nal_type == H264::NaluType::kFuA) {
     // Fragmented NAL units (FU-A).
     if (!ParseFuaNalu(parsed_payload, payload_data))
@@ -458,7 +459,8 @@
   parsed_payload->video_header().codec = kVideoCodecH264;
   parsed_payload->video_header().simulcastIdx = 0;
   parsed_payload->video_header().is_first_packet_in_frame = true;
-  RTPVideoHeaderH264* h264_header = &parsed_payload->video_header().h264();
+  auto& h264_header = absl::get<RTPVideoHeaderH264>(
+      parsed_payload->video_header().video_type_header);
 
   const uint8_t* nalu_start = payload_data + kNalHeaderSize;
   const size_t nalu_length = length_ - kNalHeaderSize;
@@ -476,13 +478,13 @@
       return false;
     }
 
-    h264_header->packetization_type = kH264StapA;
+    h264_header.packetization_type = kH264StapA;
     nal_type = payload_data[kStapAHeaderSize] & kTypeMask;
   } else {
-    h264_header->packetization_type = kH264SingleNalu;
+    h264_header.packetization_type = kH264SingleNalu;
     nalu_start_offsets.push_back(0);
   }
-  h264_header->nalu_type = nal_type;
+  h264_header.nalu_type = nal_type;
   parsed_payload->frame_type = kVideoFrameDelta;
 
   nalu_start_offsets.push_back(length_ + kLengthFieldSize);  // End offset.
@@ -528,7 +530,7 @@
             }
 
             // Rewrite length field to new SPS size.
-            if (h264_header->packetization_type == kH264StapA) {
+            if (h264_header.packetization_type == kH264StapA) {
               size_t length_field_offset =
                   start_offset - (H264::kNaluTypeSize + kLengthFieldSize);
               // Stap-A Length includes payload data and type header.
@@ -617,13 +619,13 @@
         RTC_LOG(LS_WARNING) << "Unexpected STAP-A or FU-A received.";
         return false;
     }
-    RTPVideoHeaderH264* h264 = &parsed_payload->video_header().h264();
-    if (h264->nalus_length == kMaxNalusPerPacket) {
+
+    if (h264_header.nalus_length == kMaxNalusPerPacket) {
       RTC_LOG(LS_WARNING)
           << "Received packet containing more than " << kMaxNalusPerPacket
           << " NAL units. Will not keep track sps and pps ids for all of them.";
     } else {
-      h264->nalus[h264->nalus_length++] = nalu;
+      h264_header.nalus[h264_header.nalus_length++] = nalu;
     }
   }
 
@@ -676,12 +678,13 @@
   parsed_payload->video_header().codec = kVideoCodecH264;
   parsed_payload->video_header().simulcastIdx = 0;
   parsed_payload->video_header().is_first_packet_in_frame = first_fragment;
-  RTPVideoHeaderH264* h264 = &parsed_payload->video_header().h264();
-  h264->packetization_type = kH264FuA;
-  h264->nalu_type = original_nal_type;
+  auto& h264_header = absl::get<RTPVideoHeaderH264>(
+      parsed_payload->video_header().video_type_header);
+  h264_header.packetization_type = kH264FuA;
+  h264_header.nalu_type = original_nal_type;
   if (first_fragment) {
-    h264->nalus[h264->nalus_length] = nalu;
-    h264->nalus_length = 1;
+    h264_header.nalus[h264_header.nalus_length] = nalu;
+    h264_header.nalus_length = 1;
   }
   return true;
 }
diff --git a/modules/rtp_rtcp/source/rtp_format_h264.h b/modules/rtp_rtcp/source/rtp_format_h264.h
index 99b080b..1f6702a 100644
--- a/modules/rtp_rtcp/source/rtp_format_h264.h
+++ b/modules/rtp_rtcp/source/rtp_format_h264.h
@@ -34,15 +34,15 @@
 
   size_t SetPayloadData(const uint8_t* payload_data,
                         size_t payload_size,
-                        const RTPFragmentationHeader* fragmentation) override;
+                        const RTPFragmentationHeader* fragmentation);
+
+  size_t NumPackets() const override;
 
   // Get the next payload with H264 payload header.
   // Write payload and set marker bit of the |packet|.
   // Returns true on success, false otherwise.
   bool NextPacket(RtpPacketToSend* rtp_packet) override;
 
-  std::string ToString() override;
-
  private:
   // Input fragments (NAL units), with an optionally owned temporary buffer,
   // used in case the fragment gets modified.
diff --git a/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc b/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc
index dc17b4f..0183a6a 100644
--- a/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_format_h264_unittest.cc
@@ -16,7 +16,7 @@
 #include "modules/include/module_common_types.h"
 #include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
-#include "modules/rtp_rtcp/source/rtp_format.h"
+#include "modules/rtp_rtcp/source/rtp_format_h264.h"
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
@@ -26,6 +26,12 @@
 
 using ::testing::ElementsAreArray;
 
+struct H264ParsedPayload : public RtpDepacketizer::ParsedPayload {
+  RTPVideoHeaderH264& h264() {
+    return absl::get<RTPVideoHeaderH264>(video.video_type_header);
+  }
+};
+
 constexpr RtpPacketToSend::ExtensionManager* kNoExtensions = nullptr;
 const size_t kMaxPayloadSize = 1200;
 const size_t kLengthFieldLength = 2;
@@ -62,13 +68,12 @@
       kNalHeaderSize + frameSize - payloadOffset;
 }
 
-RtpPacketizer* CreateH264Packetizer(H264PacketizationMode mode,
-                                    size_t max_payload_size,
-                                    size_t last_packet_reduction) {
-  RTPVideoHeader header;
-  header.h264().packetization_mode = mode;
-  return RtpPacketizer::Create(kVideoCodecH264, max_payload_size,
-                               last_packet_reduction, &header, kEmptyFrame);
+std::unique_ptr<RtpPacketizerH264> CreateH264Packetizer(
+    H264PacketizationMode mode,
+    size_t max_payload_size,
+    size_t last_packet_reduction) {
+  return absl::make_unique<RtpPacketizerH264>(max_payload_size,
+                                              last_packet_reduction, mode);
 }
 
 void VerifyFua(size_t fua_index,
@@ -111,7 +116,7 @@
   fragmentation.VerifyAndAllocateFragmentationHeader(1);
   fragmentation.fragmentationOffset[0] = 0;
   fragmentation.fragmentationLength[0] = frame_size;
-  std::unique_ptr<RtpPacketizer> packetizer(
+  std::unique_ptr<RtpPacketizerH264> packetizer(
       CreateH264Packetizer(H264PacketizationMode::NonInterleaved,
                            max_payload_size, last_packet_reduction));
   EXPECT_EQ(
@@ -184,7 +189,7 @@
   fragmentation.VerifyAndAllocateFragmentationHeader(1);
   fragmentation.fragmentationOffset[0] = 0;
   fragmentation.fragmentationLength[0] = sizeof(frame);
-  std::unique_ptr<RtpPacketizer> packetizer(
+  std::unique_ptr<RtpPacketizerH264> packetizer(
       CreateH264Packetizer(GetParam(), kMaxPayloadSize, 0));
   ASSERT_EQ(1u,
             packetizer->SetPayloadData(frame, sizeof(frame), &fragmentation));
@@ -211,7 +216,7 @@
   frame[fragmentation.fragmentationOffset[0]] = 0x01;
   frame[fragmentation.fragmentationOffset[1]] = 0x01;
 
-  std::unique_ptr<RtpPacketizer> packetizer(
+  std::unique_ptr<RtpPacketizerH264> packetizer(
       CreateH264Packetizer(GetParam(), kMaxPayloadSize, 0));
   ASSERT_EQ(2u, packetizer->SetPayloadData(frame, kFrameSize, &fragmentation));
 
@@ -244,7 +249,7 @@
     frame[i + kPayloadOffset] = i;
   RTPFragmentationHeader fragmentation;
   CreateThreeFragments(&fragmentation, kFrameSize, kPayloadOffset);
-  std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer(
+  std::unique_ptr<RtpPacketizerH264> packetizer(CreateH264Packetizer(
       H264PacketizationMode::NonInterleaved, kMaxPayloadSize, 0));
   ASSERT_EQ(1u, packetizer->SetPayloadData(frame, kFrameSize, &fragmentation));
 
@@ -279,7 +284,7 @@
   fragmentation.fragmentationOffset[2] = 4;
   fragmentation.fragmentationLength[2] =
       kNalHeaderSize + kFrameSize - kPayloadOffset;
-  std::unique_ptr<RtpPacketizer> packetizer(
+  std::unique_ptr<RtpPacketizerH264> packetizer(
       CreateH264Packetizer(H264PacketizationMode::NonInterleaved,
                            kMaxPayloadSize, kLastPacketReduction));
   ASSERT_EQ(2u, packetizer->SetPayloadData(frame, kFrameSize, &fragmentation));
@@ -316,7 +321,7 @@
     frame[i + kPayloadOffset] = i;
   RTPFragmentationHeader fragmentation;
   CreateThreeFragments(&fragmentation, kFrameSize, kPayloadOffset);
-  std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer(
+  std::unique_ptr<RtpPacketizerH264> packetizer(CreateH264Packetizer(
       H264PacketizationMode::SingleNalUnit, kMaxPayloadSize, 0));
   packetizer->SetPayloadData(frame, kFrameSize, &fragmentation);
 
@@ -345,7 +350,7 @@
   fragmentation.fragmentationOffset[2] = 4;
   fragmentation.fragmentationLength[2] =
       kNalHeaderSize + kFrameSize - kPayloadOffset;
-  std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer(
+  std::unique_ptr<RtpPacketizerH264> packetizer(CreateH264Packetizer(
       H264PacketizationMode::NonInterleaved, kMaxPayloadSize, 0));
   ASSERT_EQ(2u, packetizer->SetPayloadData(frame, kFrameSize, &fragmentation));
 
@@ -390,7 +395,7 @@
       frame[nalu_offset + j] = i + j;
     }
   }
-  std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer(
+  std::unique_ptr<RtpPacketizerH264> packetizer(CreateH264Packetizer(
       H264PacketizationMode::NonInterleaved, kMaxPayloadSize, 0));
   ASSERT_EQ(3u, packetizer->SetPayloadData(frame, kFrameSize, &fragmentation));
 
@@ -479,7 +484,7 @@
   // Set NAL headers.
   frame[fragmentation.fragmentationOffset[0]] = 0x01;
 
-  std::unique_ptr<RtpPacketizer> packetizer(CreateH264Packetizer(
+  std::unique_ptr<RtpPacketizerH264> packetizer(CreateH264Packetizer(
       H264PacketizationMode::SingleNalUnit, kMaxPayloadSize, 0));
   EXPECT_EQ(0u, packetizer->SetPayloadData(frame, kFrameSize, &fragmentation));
 }
@@ -517,16 +522,16 @@
  protected:
   rtc::Buffer in_buffer_;
   RTPFragmentationHeader fragmentation_header_;
-  std::unique_ptr<RtpPacketizer> packetizer_;
+  std::unique_ptr<RtpPacketizerH264> packetizer_;
 };
 
 TEST_F(RtpPacketizerH264TestSpsRewriting, FuASps) {
   const size_t kHeaderOverhead = kFuAHeaderSize + 1;
 
   // Set size to fragment SPS into two FU-A packets.
-  packetizer_.reset(
+  packetizer_ =
       CreateH264Packetizer(H264PacketizationMode::NonInterleaved,
-                           sizeof(kOriginalSps) - 2 + kHeaderOverhead, 0));
+                           sizeof(kOriginalSps) - 2 + kHeaderOverhead, 0);
 
   packetizer_->SetPayloadData(in_buffer_.data(), in_buffer_.size(),
                               &fragmentation_header_);
@@ -557,9 +562,8 @@
                                     sizeof(kIdrTwo) + (kLengthFieldLength * 3);
 
   // Set size to include SPS and the rest of the packets in a Stap-A package.
-  packetizer_.reset(CreateH264Packetizer(H264PacketizationMode::NonInterleaved,
-                                         kExpectedTotalSize + kHeaderOverhead,
-                                         0));
+  packetizer_ = CreateH264Packetizer(H264PacketizationMode::NonInterleaved,
+                                     kExpectedTotalSize + kHeaderOverhead, 0);
 
   packetizer_->SetPayloadData(in_buffer_.data(), in_buffer_.size(),
                               &fragmentation_header_);
@@ -579,7 +583,7 @@
   RtpDepacketizerH264Test()
       : depacketizer_(RtpDepacketizer::Create(kVideoCodecH264)) {}
 
-  void ExpectPacket(RtpDepacketizer::ParsedPayload* parsed_payload,
+  void ExpectPacket(H264ParsedPayload* parsed_payload,
                     const uint8_t* data,
                     size_t length) {
     ASSERT_TRUE(parsed_payload != NULL);
@@ -594,29 +598,29 @@
 
 TEST_F(RtpDepacketizerH264Test, TestSingleNalu) {
   uint8_t packet[2] = {0x05, 0xFF};  // F=0, NRI=0, Type=5 (IDR).
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
 
   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
   ExpectPacket(&payload, packet, sizeof(packet));
   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
   EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
   EXPECT_TRUE(payload.video_header().is_first_packet_in_frame);
-  EXPECT_EQ(kH264SingleNalu, payload.video_header().h264().packetization_type);
-  EXPECT_EQ(kIdr, payload.video_header().h264().nalu_type);
+  EXPECT_EQ(kH264SingleNalu, payload.h264().packetization_type);
+  EXPECT_EQ(kIdr, payload.h264().nalu_type);
 }
 
 TEST_F(RtpDepacketizerH264Test, TestSingleNaluSpsWithResolution) {
   uint8_t packet[] = {kSps, 0x7A, 0x00, 0x1F, 0xBC, 0xD9, 0x40, 0x50,
                       0x05, 0xBA, 0x10, 0x00, 0x00, 0x03, 0x00, 0xC0,
                       0x00, 0x00, 0x03, 0x2A, 0xE0, 0xF1, 0x83, 0x25};
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
 
   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
   ExpectPacket(&payload, packet, sizeof(packet));
   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
   EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
   EXPECT_TRUE(payload.video_header().is_first_packet_in_frame);
-  EXPECT_EQ(kH264SingleNalu, payload.video_header().h264().packetization_type);
+  EXPECT_EQ(kH264SingleNalu, payload.h264().packetization_type);
   EXPECT_EQ(1280u, payload.video_header().width);
   EXPECT_EQ(720u, payload.video_header().height);
 }
@@ -639,13 +643,13 @@
                         0x85, 0xB8, 0x0, 0x4, 0x0, 0x0, 0x13, 0x93, 0x12, 0x0};
   // clang-format on
 
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
   ExpectPacket(&payload, packet, sizeof(packet));
   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
   EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
   EXPECT_TRUE(payload.video_header().is_first_packet_in_frame);
-  const RTPVideoHeaderH264& h264 = payload.video_header().h264();
+  const RTPVideoHeaderH264& h264 = payload.h264();
   EXPECT_EQ(kH264StapA, h264.packetization_type);
   // NALU type for aggregated packets is the type of the first packet only.
   EXPECT_EQ(kSps, h264.nalu_type);
@@ -669,14 +673,14 @@
                       0x00, 0x03, kIdr, 0xFF, 0x00, 0x00, 0x04, kIdr, 0xFF,
                       0x00, 0x11};
 
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
 
   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
   ExpectPacket(&payload, packet, sizeof(packet));
   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
   EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
   EXPECT_TRUE(payload.video_header().is_first_packet_in_frame);
-  EXPECT_EQ(kH264StapA, payload.video_header().h264().packetization_type);
+  EXPECT_EQ(kH264StapA, payload.h264().packetization_type);
   EXPECT_EQ(1280u, payload.video_header().width);
   EXPECT_EQ(720u, payload.video_header().height);
 }
@@ -693,7 +697,7 @@
   uint8_t trailing_empty_packet[] = {kStapA, 0x00, 0x03, kIdr,
                                      0xFF,   0x00, 0x00, 0x00};
 
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
 
   EXPECT_FALSE(depacketizer_->Parse(&payload, lone_empty_packet,
                                     sizeof(lone_empty_packet)));
@@ -732,7 +736,7 @@
   out_buffer.AppendData(kHeader, 2);
   out_buffer.AppendData(kIdrTwo);
 
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
   EXPECT_TRUE(
       depacketizer_->Parse(&payload, in_buffer.data(), in_buffer.size()));
 
@@ -779,7 +783,7 @@
   out_buffer.AppendData(kHeader, 2);
   out_buffer.AppendData(kIdrTwo);
 
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
   EXPECT_TRUE(
       depacketizer_->Parse(&payload, in_buffer.data(), in_buffer.size()));
 
@@ -796,16 +800,16 @@
                                  // Length, nal header, payload.
                         0, 0x02, kSlice, 0xFF, 0, 0x03, kSlice, 0xFF, 0x00, 0,
                         0x04, kSlice, 0xFF, 0x00, 0x11};
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
 
   ASSERT_TRUE(depacketizer_->Parse(&payload, packet, sizeof(packet)));
   ExpectPacket(&payload, packet, sizeof(packet));
   EXPECT_EQ(kVideoFrameDelta, payload.frame_type);
   EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
   EXPECT_TRUE(payload.video_header().is_first_packet_in_frame);
-  EXPECT_EQ(kH264StapA, payload.video_header().h264().packetization_type);
+  EXPECT_EQ(kH264StapA, payload.h264().packetization_type);
   // NALU type for aggregated packets is the type of the first packet only.
-  EXPECT_EQ(kSlice, payload.video_header().h264().nalu_type);
+  EXPECT_EQ(kSlice, payload.h264().nalu_type);
 }
 
 TEST_F(RtpDepacketizerH264Test, TestFuA) {
@@ -833,7 +837,7 @@
   };
   const uint8_t kExpected3[] = {0x03};
 
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
 
   // We expect that the first packet is one byte shorter since the FU-A header
   // has been replaced by the original nal header.
@@ -842,7 +846,7 @@
   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
   EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
   EXPECT_TRUE(payload.video_header().is_first_packet_in_frame);
-  const RTPVideoHeaderH264& h264 = payload.video_header().h264();
+  const RTPVideoHeaderH264& h264 = payload.h264();
   EXPECT_EQ(kH264FuA, h264.packetization_type);
   EXPECT_EQ(kIdr, h264.nalu_type);
   ASSERT_EQ(1u, h264.nalus_length);
@@ -852,28 +856,28 @@
 
   // Following packets will be 2 bytes shorter since they will only be appended
   // onto the first packet.
-  payload = RtpDepacketizer::ParsedPayload();
+  payload = H264ParsedPayload();
   ASSERT_TRUE(depacketizer_->Parse(&payload, packet2, sizeof(packet2)));
   ExpectPacket(&payload, kExpected2, sizeof(kExpected2));
   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
   EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
   EXPECT_FALSE(payload.video_header().is_first_packet_in_frame);
   {
-    const RTPVideoHeaderH264& h264 = payload.video_header().h264();
+    const RTPVideoHeaderH264& h264 = payload.h264();
     EXPECT_EQ(kH264FuA, h264.packetization_type);
     EXPECT_EQ(kIdr, h264.nalu_type);
     // NALU info is only expected for the first FU-A packet.
     EXPECT_EQ(0u, h264.nalus_length);
   }
 
-  payload = RtpDepacketizer::ParsedPayload();
+  payload = H264ParsedPayload();
   ASSERT_TRUE(depacketizer_->Parse(&payload, packet3, sizeof(packet3)));
   ExpectPacket(&payload, kExpected3, sizeof(kExpected3));
   EXPECT_EQ(kVideoFrameKey, payload.frame_type);
   EXPECT_EQ(kVideoCodecH264, payload.video_header().codec);
   EXPECT_FALSE(payload.video_header().is_first_packet_in_frame);
   {
-    const RTPVideoHeaderH264& h264 = payload.video_header().h264();
+    const RTPVideoHeaderH264& h264 = payload.h264();
     EXPECT_EQ(kH264FuA, h264.packetization_type);
     EXPECT_EQ(kIdr, h264.nalu_type);
     // NALU info is only expected for the first FU-A packet.
@@ -884,37 +888,37 @@
 TEST_F(RtpDepacketizerH264Test, TestEmptyPayload) {
   // Using a wild pointer to crash on accesses from inside the depacketizer.
   uint8_t* garbage_ptr = reinterpret_cast<uint8_t*>(0x4711);
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
   EXPECT_FALSE(depacketizer_->Parse(&payload, garbage_ptr, 0));
 }
 
 TEST_F(RtpDepacketizerH264Test, TestTruncatedFuaNalu) {
   const uint8_t kPayload[] = {0x9c};
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
   EXPECT_FALSE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
 }
 
 TEST_F(RtpDepacketizerH264Test, TestTruncatedSingleStapANalu) {
   const uint8_t kPayload[] = {0xd8, 0x27};
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
   EXPECT_FALSE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
 }
 
 TEST_F(RtpDepacketizerH264Test, TestStapAPacketWithTruncatedNalUnits) {
   const uint8_t kPayload[] = {0x58, 0xCB, 0xED, 0xDF};
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
   EXPECT_FALSE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
 }
 
 TEST_F(RtpDepacketizerH264Test, TestTruncationJustAfterSingleStapANalu) {
   const uint8_t kPayload[] = {0x38, 0x27, 0x27};
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
   EXPECT_FALSE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
 }
 
 TEST_F(RtpDepacketizerH264Test, TestShortSpsPacket) {
   const uint8_t kPayload[] = {0x27, 0x80, 0x00};
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
   EXPECT_TRUE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
 }
 
@@ -923,9 +927,9 @@
       kSei,                   // F=0, NRI=0, Type=6.
       0x03, 0x03, 0x03, 0x03  // Payload.
   };
-  RtpDepacketizer::ParsedPayload payload;
+  H264ParsedPayload payload;
   ASSERT_TRUE(depacketizer_->Parse(&payload, kPayload, sizeof(kPayload)));
-  const RTPVideoHeaderH264& h264 = payload.video_header().h264();
+  const RTPVideoHeaderH264& h264 = payload.h264();
   EXPECT_EQ(kVideoFrameDelta, payload.frame_type);
   EXPECT_EQ(kH264SingleNalu, h264.packetization_type);
   EXPECT_EQ(kSei, h264.nalu_type);
diff --git a/modules/rtp_rtcp/source/rtp_format_video_generic.cc b/modules/rtp_rtcp/source/rtp_format_video_generic.cc
index a2a3ad1..1731237 100644
--- a/modules/rtp_rtcp/source/rtp_format_video_generic.cc
+++ b/modules/rtp_rtcp/source/rtp_format_video_generic.cc
@@ -18,13 +18,21 @@
 namespace webrtc {
 
 static const size_t kGenericHeaderLength = 1;
+static const size_t kExtendedHeaderLength = 2;
 
-RtpPacketizerGeneric::RtpPacketizerGeneric(FrameType frame_type,
-                                           size_t max_payload_len,
-                                           size_t last_packet_reduction_len)
-    : payload_data_(NULL),
+RtpPacketizerGeneric::RtpPacketizerGeneric(
+    const RTPVideoHeader& rtp_video_header,
+    FrameType frame_type,
+    size_t max_payload_len,
+    size_t last_packet_reduction_len)
+    : picture_id_(rtp_video_header.generic
+                      ? absl::optional<uint16_t>(
+                            rtp_video_header.generic->frame_id & 0x7FFF)
+                      : absl::nullopt),
+      payload_data_(nullptr),
       payload_size_(0),
-      max_payload_len_(max_payload_len - kGenericHeaderLength),
+      max_payload_len_(max_payload_len - kGenericHeaderLength -
+                       (picture_id_.has_value() ? kExtendedHeaderLength : 0)),
       last_packet_reduction_len_(last_packet_reduction_len),
       frame_type_(frame_type),
       num_packets_left_(0),
@@ -62,6 +70,14 @@
   if (frame_type_ == kVideoFrameKey) {
     generic_header_ |= RtpFormatVideoGeneric::kKeyFrameBit;
   }
+  if (picture_id_.has_value()) {
+    generic_header_ |= RtpFormatVideoGeneric::kExtendedHeaderBit;
+  }
+
+  return num_packets_left_;
+}
+
+size_t RtpPacketizerGeneric::NumPackets() const {
   return num_packets_left_;
 }
 
@@ -86,16 +102,24 @@
   }
   RTC_DCHECK_LE(next_packet_payload_len, max_payload_len_);
 
-  uint8_t* out_ptr =
-      packet->AllocatePayload(kGenericHeaderLength + next_packet_payload_len);
+  size_t total_length = next_packet_payload_len + kGenericHeaderLength +
+                        (picture_id_.has_value() ? kExtendedHeaderLength : 0);
+  uint8_t* out_ptr = packet->AllocatePayload(total_length);
+
   // Put generic header in packet.
   out_ptr[0] = generic_header_;
+  out_ptr += kGenericHeaderLength;
+
+  if (picture_id_.has_value()) {
+    WriteExtendedHeader(out_ptr);
+    out_ptr += kExtendedHeaderLength;
+  }
+
   // Remove first-packet bit, following packets are intermediate.
   generic_header_ &= ~RtpFormatVideoGeneric::kFirstPacketBit;
 
   // Put payload in packet.
-  memcpy(out_ptr + kGenericHeaderLength, payload_data_,
-         next_packet_payload_len);
+  memcpy(out_ptr, payload_data_, next_packet_payload_len);
   payload_data_ += next_packet_payload_len;
   payload_size_ -= next_packet_payload_len;
   --num_packets_left_;
@@ -107,8 +131,11 @@
   return true;
 }
 
-std::string RtpPacketizerGeneric::ToString() {
-  return "RtpPacketizerGeneric";
+void RtpPacketizerGeneric::WriteExtendedHeader(uint8_t* out_ptr) {
+  // Store bottom 15 bits of the the sequence number. Only 15 bits are used for
+  // compatibility with other packetizer implemenetations that also use 15 bits.
+  out_ptr[0] = (*picture_id_ >> 8) & 0x7F;
+  out_ptr[1] = *picture_id_ & 0xFF;
 }
 
 RtpDepacketizerGeneric::~RtpDepacketizerGeneric() = default;
@@ -118,7 +145,7 @@
                                    size_t payload_data_length) {
   assert(parsed_payload != NULL);
   if (payload_data_length == 0) {
-    RTC_LOG(LS_ERROR) << "Empty payload.";
+    RTC_LOG(LS_WARNING) << "Empty payload.";
     return false;
   }
 
@@ -135,6 +162,18 @@
   parsed_payload->video_header().width = 0;
   parsed_payload->video_header().height = 0;
 
+  if (generic_header & RtpFormatVideoGeneric::kExtendedHeaderBit) {
+    if (payload_data_length < kExtendedHeaderLength) {
+      RTC_LOG(LS_WARNING) << "Too short payload for generic header.";
+      return false;
+    }
+    parsed_payload->video_header().generic.emplace();
+    parsed_payload->video_header().generic->frame_id =
+        ((payload_data[0] & 0x7F) << 8) | payload_data[1];
+    payload_data += kExtendedHeaderLength;
+    payload_data_length -= kExtendedHeaderLength;
+  }
+
   parsed_payload->payload = payload_data;
   parsed_payload->payload_length = payload_data_length;
   return true;
diff --git a/modules/rtp_rtcp/source/rtp_format_video_generic.h b/modules/rtp_rtcp/source/rtp_format_video_generic.h
index 9a916bf..293b6e9 100644
--- a/modules/rtp_rtcp/source/rtp_format_video_generic.h
+++ b/modules/rtp_rtcp/source/rtp_format_video_generic.h
@@ -15,19 +15,22 @@
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/rtp_rtcp/source/rtp_format.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace RtpFormatVideoGeneric {
 static const uint8_t kKeyFrameBit = 0x01;
 static const uint8_t kFirstPacketBit = 0x02;
+// If this bit is set, there will be an extended header contained in this
+// packet. This was added later so old clients will not send this.
+static const uint8_t kExtendedHeaderBit = 0x04;
 }  // namespace RtpFormatVideoGeneric
 
 class RtpPacketizerGeneric : public RtpPacketizer {
  public:
   // Initialize with payload from encoder.
   // The payload_data must be exactly one encoded generic frame.
-  RtpPacketizerGeneric(FrameType frametype,
+  RtpPacketizerGeneric(const RTPVideoHeader& rtp_video_header,
+                       FrameType frametype,
                        size_t max_payload_len,
                        size_t last_packet_reduction_len);
 
@@ -36,16 +39,17 @@
   // Returns total number of packets to be generated.
   size_t SetPayloadData(const uint8_t* payload_data,
                         size_t payload_size,
-                        const RTPFragmentationHeader* fragmentation) override;
+                        const RTPFragmentationHeader* fragmentation);
+
+  size_t NumPackets() const override;
 
   // Get the next payload with generic payload header.
   // Write payload and set marker bit of the |packet|.
   // Returns true on success, false otherwise.
   bool NextPacket(RtpPacketToSend* packet) override;
 
-  std::string ToString() override;
-
  private:
+  const absl::optional<uint16_t> picture_id_;
   const uint8_t* payload_data_;
   size_t payload_size_;
   const size_t max_payload_len_;
@@ -58,6 +62,8 @@
   // Number of packets, which will be 1 byte more than the rest.
   size_t num_larger_packets_;
 
+  void WriteExtendedHeader(uint8_t* out_ptr);
+
   RTC_DISALLOW_COPY_AND_ASSIGN(RtpPacketizerGeneric);
 };
 
diff --git a/modules/rtp_rtcp/source/rtp_format_video_generic_unittest.cc b/modules/rtp_rtcp/source/rtp_format_video_generic_unittest.cc
index 983bd8f..e77dabf 100644
--- a/modules/rtp_rtcp/source/rtp_format_video_generic_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_format_video_generic_unittest.cc
@@ -63,8 +63,8 @@
   const size_t kMaxPayloadLen = 6;
   const size_t kLastPacketReductionLen = 2;
   const size_t kPayloadSize = 13;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -78,8 +78,8 @@
   const size_t kMaxPayloadLen = 6;
   const size_t kLastPacketReductionLen = 2;
   const size_t kPayloadSize = 13;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -93,8 +93,8 @@
   const size_t kMaxPayloadLen = 6;
   const size_t kLastPacketReductionLen = 2;
   const size_t kPayloadSize = 13;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -114,8 +114,8 @@
   // generic header lengh for each packet minus last packet reduction).
   // 4 packets is enough for kPayloadSize.
   const size_t kMinNumPackets = 4;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -128,8 +128,8 @@
   const size_t kMaxPayloadLen = 8;
   const size_t kLastPacketReductionLen = 5;
   const size_t kPayloadSize = 28;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -143,8 +143,8 @@
   const size_t kMaxPayloadLen = 8;
   const size_t kLastPacketReductionLen = 5;
   const size_t kPayloadSize = 28;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -158,8 +158,8 @@
   const size_t kMaxPayloadLen = 8;
   const size_t kLastPacketReductionLen = 5;
   const size_t kPayloadSize = 28;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -179,8 +179,8 @@
   // generic header lengh for each packet minus last packet reduction).
   // 5 packets is enough for kPayloadSize.
   const size_t kMinNumPackets = 5;
-  RtpPacketizerGeneric packetizer(kVideoFrameKey, kMaxPayloadLen,
-                                  kLastPacketReductionLen);
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
   size_t num_packets =
       packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
   std::vector<size_t> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
@@ -189,4 +189,85 @@
   EXPECT_EQ(num_packets, kMinNumPackets);
 }
 
+TEST(RtpPacketizerVideoGeneric, HasFrameIdWritesExtendedHeader) {
+  const size_t kMaxPayloadLen = 6;
+  const size_t kLastPacketReductionLen = 2;
+  const size_t kPayloadSize = 13;
+
+  RTPVideoHeader rtp_video_header;
+  rtp_video_header.generic.emplace().frame_id = 37;
+  RtpPacketizerGeneric packetizer(rtp_video_header, kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
+  packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
+
+  RtpPacketToSend packet(nullptr);
+  packetizer.NextPacket(&packet);
+
+  rtc::ArrayView<const uint8_t> payload = packet.payload();
+  EXPECT_TRUE(payload[0] & 0x04);  // Extended header bit is set.
+  // Frame id is 37.
+  EXPECT_EQ(0u, payload[1]);
+  EXPECT_EQ(37u, payload[2]);
+}
+
+TEST(RtpPacketizerVideoGeneric, FrameIdOver15bitsWrapsAround) {
+  const size_t kMaxPayloadLen = 6;
+  const size_t kLastPacketReductionLen = 2;
+  const size_t kPayloadSize = 13;
+
+  RTPVideoHeader rtp_video_header;
+  rtp_video_header.generic.emplace().frame_id = 0x8137;
+  RtpPacketizerGeneric packetizer(rtp_video_header, kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
+  packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
+
+  RtpPacketToSend packet(nullptr);
+  packetizer.NextPacket(&packet);
+
+  rtc::ArrayView<const uint8_t> payload = packet.payload();
+  EXPECT_TRUE(payload[0] & 0x04);  // Extended header bit is set.
+  // Frame id is 0x137.
+  EXPECT_EQ(0x01u, payload[1]);
+  EXPECT_EQ(0x37u, payload[2]);
+}
+
+TEST(RtpPacketizerVideoGeneric, NoFrameIdDoesNotWriteExtendedHeader) {
+  const size_t kMaxPayloadLen = 6;
+  const size_t kLastPacketReductionLen = 2;
+  const size_t kPayloadSize = 13;
+
+  RtpPacketizerGeneric packetizer(RTPVideoHeader(), kVideoFrameKey,
+                                  kMaxPayloadLen, kLastPacketReductionLen);
+  packetizer.SetPayloadData(kTestPayload, kPayloadSize, nullptr);
+
+  RtpPacketToSend packet(nullptr);
+  packetizer.NextPacket(&packet);
+
+  rtc::ArrayView<const uint8_t> payload = packet.payload();
+  EXPECT_FALSE(payload[0] & 0x04);
+}
+
+TEST(RtpDepacketizerVideoGeneric, NonExtendedHeaderNoFrameId) {
+  const size_t kPayloadLen = 1;
+  uint8_t payload[kPayloadLen] = {0x01};
+
+  RtpDepacketizerGeneric depacketizer;
+  RtpDepacketizer::ParsedPayload parsed_payload;
+  depacketizer.Parse(&parsed_payload, payload, kPayloadLen);
+
+  EXPECT_FALSE(parsed_payload.video_header().generic);
+}
+
+TEST(RtpDepacketizerVideoGeneric, ExtendedHeaderParsesFrameId) {
+  const size_t kPayloadLen = 3;
+  uint8_t payload[kPayloadLen] = {0x05, 0x13, 0x37};
+
+  RtpDepacketizerGeneric depacketizer;
+  RtpDepacketizer::ParsedPayload parsed_payload;
+  depacketizer.Parse(&parsed_payload, payload, kPayloadLen);
+
+  ASSERT_TRUE(parsed_payload.video_header().generic);
+  EXPECT_EQ(0x1337, parsed_payload.video_header().generic->frame_id);
+}
+
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_format_vp8.cc b/modules/rtp_rtcp/source/rtp_format_vp8.cc
index 48c7351..4a511fc 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp8.cc
+++ b/modules/rtp_rtcp/source/rtp_format_vp8.cc
@@ -22,6 +22,10 @@
 
 namespace webrtc {
 namespace {
+
+// Length of VP8 payload descriptors' fixed part.
+constexpr int kVp8FixedPayloadDescriptorSize = 1;
+
 int ParseVP8PictureID(RTPVideoHeaderVP8* vp8,
                       const uint8_t** data,
                       size_t* data_length,
@@ -158,29 +162,17 @@
 
 }  // namespace
 
-RtpPacketizerVp8::RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info,
-                                   size_t max_payload_len,
-                                   size_t last_packet_reduction_len)
-    : payload_data_(NULL),
-      payload_size_(0),
-      vp8_fixed_payload_descriptor_bytes_(1),
-      hdr_info_(hdr_info),
-      max_payload_len_(max_payload_len),
-      last_packet_reduction_len_(last_packet_reduction_len) {
+RtpPacketizerVp8::RtpPacketizerVp8(rtc::ArrayView<const uint8_t> payload,
+                                   PayloadSizeLimits limits,
+                                   const RTPVideoHeaderVP8& hdr_info)
+    : payload_data_(payload.data()), hdr_info_(hdr_info), limits_(limits) {
   RTC_DCHECK(ValidateHeader(hdr_info));
+  GeneratePackets(payload.size());
 }
 
-RtpPacketizerVp8::~RtpPacketizerVp8() {}
+RtpPacketizerVp8::~RtpPacketizerVp8() = default;
 
-size_t RtpPacketizerVp8::SetPayloadData(
-    const uint8_t* payload_data,
-    size_t payload_size,
-    const RTPFragmentationHeader* /* fragmentation */) {
-  payload_data_ = payload_data;
-  payload_size_ = payload_size;
-  if (GeneratePackets() < 0) {
-    return 0;
-  }
+size_t RtpPacketizerVp8::NumPackets() const {
   return packets_.size();
 }
 
@@ -192,10 +184,12 @@
   InfoStruct packet_info = packets_.front();
   packets_.pop();
 
-  uint8_t* buffer = packet->AllocatePayload(
-      packets_.empty() ? max_payload_len_ - last_packet_reduction_len_
-                       : max_payload_len_);
-  int bytes = WriteHeaderAndPayload(packet_info, buffer, max_payload_len_);
+  size_t packet_payload_len =
+      packets_.empty()
+          ? limits_.max_payload_len - limits_.last_packet_reduction_len
+          : limits_.max_payload_len;
+  uint8_t* buffer = packet->AllocatePayload(packet_payload_len);
+  int bytes = WriteHeaderAndPayload(packet_info, buffer, packet_payload_len);
   if (bytes < 0) {
     return false;
   }
@@ -204,33 +198,20 @@
   return true;
 }
 
-std::string RtpPacketizerVp8::ToString() {
-  return "RtpPacketizerVp8";
-}
-
-int RtpPacketizerVp8::GeneratePackets() {
-  if (max_payload_len_ < vp8_fixed_payload_descriptor_bytes_ +
-                             PayloadDescriptorExtraLength() + 1 +
-                             last_packet_reduction_len_) {
+void RtpPacketizerVp8::GeneratePackets(size_t payload_len) {
+  if (limits_.max_payload_len - limits_.last_packet_reduction_len <
+      kVp8FixedPayloadDescriptorSize + PayloadDescriptorExtraLength() + 1) {
     // The provided payload length is not long enough for the payload
     // descriptor and one payload byte in the last packet.
-    // Return an error.
-    return -1;
+    return;
   }
 
-  size_t per_packet_capacity =
-      max_payload_len_ -
-      (vp8_fixed_payload_descriptor_bytes_ + PayloadDescriptorExtraLength());
+  size_t capacity = limits_.max_payload_len - (kVp8FixedPayloadDescriptorSize +
+                                               PayloadDescriptorExtraLength());
 
-  GeneratePacketsSplitPayloadBalanced(payload_size_, per_packet_capacity);
-  return 0;
-}
-
-void RtpPacketizerVp8::GeneratePacketsSplitPayloadBalanced(size_t payload_len,
-                                                           size_t capacity) {
   // Last packet of the last partition is smaller. Pretend that it's the same
   // size, but we must write more payload to it.
-  size_t total_bytes = payload_len + last_packet_reduction_len_;
+  size_t total_bytes = payload_len + limits_.last_packet_reduction_len;
   // Integer divisions with rounding up.
   size_t num_packets_left = (total_bytes + capacity - 1) / capacity;
   size_t bytes_per_packet = total_bytes / num_packets_left;
@@ -251,7 +232,7 @@
       --current_packet_bytes;
     }
     QueuePacket(payload_len - remaining_data, current_packet_bytes,
-                remaining_data == payload_len);
+                /*first_packet=*/remaining_data == payload_len);
     remaining_data -= current_packet_bytes;
     --num_packets_left;
   }
@@ -299,19 +280,18 @@
   if (extension_length < 0)
     return -1;
 
-  memcpy(&buffer[vp8_fixed_payload_descriptor_bytes_ + extension_length],
+  memcpy(&buffer[kVp8FixedPayloadDescriptorSize + extension_length],
          &payload_data_[packet_info.payload_start_pos], packet_info.size);
 
   // Return total length of written data.
-  return packet_info.size + vp8_fixed_payload_descriptor_bytes_ +
-         extension_length;
+  return packet_info.size + kVp8FixedPayloadDescriptorSize + extension_length;
 }
 
 int RtpPacketizerVp8::WriteExtensionFields(uint8_t* buffer,
                                            size_t buffer_length) const {
   size_t extension_length = 0;
   if (XFieldPresent()) {
-    uint8_t* x_field = buffer + vp8_fixed_payload_descriptor_bytes_;
+    uint8_t* x_field = buffer + kVp8FixedPayloadDescriptorSize;
     *x_field = 0;
     extension_length = 1;  // One octet for the X field.
     if (PictureIdPresent()) {
@@ -343,10 +323,10 @@
                                            size_t* extension_length) const {
   *x_field |= kIBit;
   RTC_DCHECK_GE(buffer_length,
-                vp8_fixed_payload_descriptor_bytes_ + *extension_length);
+                kVp8FixedPayloadDescriptorSize + *extension_length);
   const int pic_id_length = WritePictureID(
-      buffer + vp8_fixed_payload_descriptor_bytes_ + *extension_length,
-      buffer_length - vp8_fixed_payload_descriptor_bytes_ - *extension_length);
+      buffer + kVp8FixedPayloadDescriptorSize + *extension_length,
+      buffer_length - kVp8FixedPayloadDescriptorSize - *extension_length);
   if (pic_id_length < 0)
     return -1;
   *extension_length += pic_id_length;
@@ -372,12 +352,11 @@
                                            uint8_t* buffer,
                                            size_t buffer_length,
                                            size_t* extension_length) const {
-  if (buffer_length <
-      vp8_fixed_payload_descriptor_bytes_ + *extension_length + 1) {
+  if (buffer_length < kVp8FixedPayloadDescriptorSize + *extension_length + 1) {
     return -1;
   }
   *x_field |= kLBit;
-  buffer[vp8_fixed_payload_descriptor_bytes_ + *extension_length] =
+  buffer[kVp8FixedPayloadDescriptorSize + *extension_length] =
       hdr_info_.tl0PicIdx;
   ++*extension_length;
   return 0;
@@ -387,12 +366,11 @@
                                               uint8_t* buffer,
                                               size_t buffer_length,
                                               size_t* extension_length) const {
-  if (buffer_length <
-      vp8_fixed_payload_descriptor_bytes_ + *extension_length + 1) {
+  if (buffer_length < kVp8FixedPayloadDescriptorSize + *extension_length + 1) {
     return -1;
   }
   uint8_t* data_field =
-      &buffer[vp8_fixed_payload_descriptor_bytes_ + *extension_length];
+      &buffer[kVp8FixedPayloadDescriptorSize + *extension_length];
   *data_field = 0;
   if (TIDFieldPresent()) {
     *x_field |= kTBit;
diff --git a/modules/rtp_rtcp/source/rtp_format_vp8.h b/modules/rtp_rtcp/source/rtp_format_vp8.h
index 3f0d7e5..dd66762 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp8.h
+++ b/modules/rtp_rtcp/source/rtp_format_vp8.h
@@ -32,7 +32,6 @@
 #include "modules/include/module_common_types.h"
 #include "modules/rtp_rtcp/source/rtp_format.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -41,23 +40,19 @@
  public:
   // Initialize with payload from encoder.
   // The payload_data must be exactly one encoded VP8 frame.
-  RtpPacketizerVp8(const RTPVideoHeaderVP8& hdr_info,
-                   size_t max_payload_len,
-                   size_t last_packet_reduction_len);
+  RtpPacketizerVp8(rtc::ArrayView<const uint8_t> payload,
+                   PayloadSizeLimits limits,
+                   const RTPVideoHeaderVP8& hdr_info);
 
   ~RtpPacketizerVp8() override;
 
-  size_t SetPayloadData(const uint8_t* payload_data,
-                        size_t payload_size,
-                        const RTPFragmentationHeader* fragmentation) override;
+  size_t NumPackets() const override;
 
   // Get the next payload with VP8 payload header.
   // Write payload and set marker bit of the |packet|.
   // Returns true on success, false otherwise.
   bool NextPacket(RtpPacketToSend* packet) override;
 
-  std::string ToString() override;
-
  private:
   typedef struct {
     size_t payload_start_pos;
@@ -78,11 +73,7 @@
   static const int kYBit = 0x20;
 
   // Calculate all packet sizes and load to packet info queue.
-  int GeneratePackets();
-
-  // Splits given part of payload to packets with a given capacity. The last
-  // packet should be reduced by last_packet_reduction_len_.
-  void GeneratePacketsSplitPayloadBalanced(size_t payload_len, size_t capacity);
+  void GeneratePackets(size_t payload_len);
 
   // Insert packet into packet queue.
   void QueuePacket(size_t start_pos, size_t packet_size, bool first_packet);
@@ -142,12 +133,8 @@
   bool PictureIdPresent() const { return (PictureIdLength() > 0); }
 
   const uint8_t* payload_data_;
-  size_t payload_size_;
-  const size_t vp8_fixed_payload_descriptor_bytes_;  // Length of VP8 payload
-                                                     // descriptors' fixed part.
   const RTPVideoHeaderVP8 hdr_info_;
-  const size_t max_payload_len_;
-  const size_t last_packet_reduction_len_;
+  const PayloadSizeLimits limits_;
   InfoQueue packets_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(RtpPacketizerVp8);
diff --git a/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.cc b/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.cc
index 8dc7ba0..abc0c89 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.cc
+++ b/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.cc
@@ -22,7 +22,6 @@
     : packet_(kNoExtensions),
       payload_data_(NULL),
       data_ptr_(NULL),
-      fragmentation_(NULL),
       hdr_info_(hdr),
       payload_start_(0),
       payload_size_(0),
@@ -30,7 +29,6 @@
       inited_(false) {}
 
 RtpFormatVp8TestHelper::~RtpFormatVp8TestHelper() {
-  delete fragmentation_;
   delete[] payload_data_;
 }
 
@@ -38,8 +36,6 @@
                                   size_t num_partitions) {
   if (inited_)
     return false;
-  fragmentation_ = new RTPFragmentationHeader;
-  fragmentation_->VerifyAndAllocateFragmentationHeader(num_partitions);
   payload_size_ = 0;
   // Calculate sum payload size.
   for (size_t p = 0; p < num_partitions; ++p) {
@@ -49,8 +45,6 @@
   size_t j = 0;
   // Loop through the partitions again.
   for (size_t p = 0; p < num_partitions; ++p) {
-    fragmentation_->fragmentationLength[p] = partition_sizes[p];
-    fragmentation_->fragmentationOffset[p] = j;
     for (size_t i = 0; i < partition_sizes[p]; ++i) {
       assert(j < payload_size_);
       payload_data_[j++] = p;  // Set the payload value to the partition index.
@@ -124,6 +118,7 @@
   payload_start_ = 1;
   rtc::ArrayView<const uint8_t> buffer = packet_.payload();
   EXPECT_BIT_EQ(buffer[0], 6, 0);  // Check reserved bit.
+  EXPECT_PART_ID_EQ(buffer[0], 0);  // In equal size mode, PartID is always 0.
 
   if (hdr_info_->pictureId != kNoPictureId ||
       hdr_info_->temporalIdx != kNoTemporalIdx ||
diff --git a/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h b/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h
index 1ed63ab..7d5a090 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h
+++ b/modules/rtp_rtcp/source/rtp_format_vp8_test_helper.h
@@ -22,7 +22,6 @@
 #include "modules/rtp_rtcp/source/rtp_format_vp8.h"
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -39,9 +38,10 @@
                              const bool* expected_frag_start,
                              size_t expected_num_packets);
 
-  uint8_t* payload_data() const { return payload_data_; }
+  rtc::ArrayView<const uint8_t> payload() const {
+    return rtc::ArrayView<const uint8_t>(payload_data_, payload_size_);
+  }
   size_t payload_size() const { return payload_size_; }
-  RTPFragmentationHeader* fragmentation() const { return fragmentation_; }
   size_t buffer_size() const {
     static constexpr size_t kVp8PayloadDescriptorMaxSize = 6;
     return payload_size_ + kVp8PayloadDescriptorMaxSize;
@@ -60,7 +60,6 @@
   RtpPacketToSend packet_;
   uint8_t* payload_data_;
   uint8_t* data_ptr_;
-  RTPFragmentationHeader* fragmentation_;
   const RTPVideoHeaderVP8* hdr_info_;
   int payload_start_;
   size_t payload_size_;
diff --git a/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc b/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc
index adcc5a2..b1096d8 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_format_vp8_unittest.cc
@@ -15,7 +15,6 @@
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 #define CHECK_ARRAY_SIZE(expected_size, array)                     \
   static_assert(expected_size == sizeof(array) / sizeof(array[0]), \
@@ -107,10 +106,10 @@
   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
 
   hdr_info_.pictureId = 200;          // > 0x7F should produce 2-byte PictureID
-  const size_t kMaxPayloadSize = 12;  // Small enough to produce 4 packets.
-  RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, 0);
-  size_t num_packets = packetizer.SetPayloadData(
-      helper_->payload_data(), helper_->payload_size(), nullptr);
+  RtpPacketizer::PayloadSizeLimits limits;
+  limits.max_payload_len = 12;  // Small enough to produce 4 packets.
+  RtpPacketizerVp8 packetizer(helper_->payload(), limits, hdr_info_);
+  size_t num_packets = packetizer.NumPackets();
 
   // Expecting three full packets, and one with the remainder.
   const size_t kExpectedSizes[] = {11, 11, 12, 12};
@@ -133,11 +132,11 @@
   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
 
   hdr_info_.pictureId = 200;
-  const size_t kMaxPayloadSize = 15;  // Small enough to produce 5 packets.
-  const size_t kLastPacketReduction = 5;
-  RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, kLastPacketReduction);
-  size_t num_packets = packetizer.SetPayloadData(
-      helper_->payload_data(), helper_->payload_size(), nullptr);
+  RtpPacketizer::PayloadSizeLimits limits;
+  limits.max_payload_len = 15;  // Small enough to produce 5 packets.
+  limits.last_packet_reduction_len = 5;
+  RtpPacketizerVp8 packetizer(helper_->payload(), limits, hdr_info_);
+  size_t num_packets = packetizer.NumPackets();
 
   // Calculated by hand. VP8 payload descriptors are 4 byte each. 5 packets is
   // minimum possible to fit 43 payload bytes into packets with capacity of
@@ -165,10 +164,10 @@
   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
 
   hdr_info_.nonReference = true;
-  const size_t kMaxPayloadSize = 25;  // Small enough to produce two packets.
-  RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, 0);
-  size_t num_packets = packetizer.SetPayloadData(
-      helper_->payload_data(), helper_->payload_size(), nullptr);
+  RtpPacketizer::PayloadSizeLimits limits;
+  limits.max_payload_len = 25;  // Small enough to produce two packets.
+  RtpPacketizerVp8 packetizer(helper_->payload(), limits, hdr_info_);
+  size_t num_packets = packetizer.NumPackets();
 
   // EqualSize mode => First packet full; other not.
   const size_t kExpectedSizes[] = {16, 16};
@@ -194,12 +193,11 @@
   hdr_info_.tl0PicIdx = 117;
   hdr_info_.temporalIdx = 2;
   hdr_info_.layerSync = true;
-  // kMaxPayloadSize is only limited by allocated buffer size.
-  const size_t kMaxPayloadSize = helper_->buffer_size();
-  RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, 0);
-  size_t num_packets = packetizer.SetPayloadData(helper_->payload_data(),
-                                                 helper_->payload_size(),
-                                                 helper_->fragmentation());
+  RtpPacketizer::PayloadSizeLimits limits;
+  // max_payload_len is only limited by allocated buffer size.
+  limits.max_payload_len = helper_->buffer_size();
+  RtpPacketizerVp8 packetizer(helper_->payload(), limits, hdr_info_);
+  size_t num_packets = packetizer.NumPackets();
 
   // Expect one single packet of payload_size() + 4 bytes header.
   const size_t kExpectedSizes[1] = {helper_->payload_size() + 4};
@@ -221,12 +219,11 @@
   ASSERT_TRUE(Init(kSizeVector, kNumPartitions));
 
   hdr_info_.keyIdx = 17;
-  // kMaxPayloadSize is only limited by allocated buffer size.
-  const size_t kMaxPayloadSize = helper_->buffer_size();
-  RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, 0);
-  size_t num_packets = packetizer.SetPayloadData(helper_->payload_data(),
-                                                 helper_->payload_size(),
-                                                 helper_->fragmentation());
+  RtpPacketizer::PayloadSizeLimits limits;
+  // max payload len is only limited by allocated buffer size.
+  limits.max_payload_len = helper_->buffer_size();
+  RtpPacketizerVp8 packetizer(helper_->payload(), limits, hdr_info_);
+  size_t num_packets = packetizer.NumPackets();
 
   // Expect one single packet of payload_size() + 3 bytes header.
   const size_t kExpectedSizes[1] = {helper_->payload_size() + 3};
@@ -249,12 +246,11 @@
 
   hdr_info_.temporalIdx = 1;
   hdr_info_.keyIdx = 5;
-  // kMaxPayloadSize is only limited by allocated buffer size.
-  const size_t kMaxPayloadSize = helper_->buffer_size();
-  RtpPacketizerVp8 packetizer(hdr_info_, kMaxPayloadSize, 0);
-  size_t num_packets = packetizer.SetPayloadData(helper_->payload_data(),
-                                                 helper_->payload_size(),
-                                                 helper_->fragmentation());
+  RtpPacketizer::PayloadSizeLimits limits;
+  // max_payload_len is only limited by allocated buffer size.
+  limits.max_payload_len = helper_->buffer_size();
+  RtpPacketizerVp8 packetizer(helper_->payload(), limits, hdr_info_);
+  size_t num_packets = packetizer.NumPackets();
 
   // Expect one single packet of payload_size() + 3 bytes header.
   const size_t kExpectedSizes[1] = {helper_->payload_size() + 3};
@@ -436,8 +432,10 @@
   input_header.layerSync = false;
   input_header.tl0PicIdx = kNoTl0PicIdx;  // Disable.
   input_header.keyIdx = 31;
-  RtpPacketizerVp8 packetizer(input_header, 20, 0);
-  EXPECT_EQ(packetizer.SetPayloadData(data, 10, NULL), 1u);
+  RtpPacketizer::PayloadSizeLimits limits;
+  limits.max_payload_len = 20;
+  RtpPacketizerVp8 packetizer(data, limits, input_header);
+  EXPECT_EQ(packetizer.NumPackets(), 1u);
   ASSERT_TRUE(packetizer.NextPacket(&packet));
   EXPECT_TRUE(packet.Marker());
 
diff --git a/modules/rtp_rtcp/source/rtp_format_vp9.cc b/modules/rtp_rtcp/source/rtp_format_vp9.cc
index 8fd1be8..f800ff8 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp9.cc
+++ b/modules/rtp_rtcp/source/rtp_format_vp9.cc
@@ -471,10 +471,6 @@
 
 RtpPacketizerVp9::~RtpPacketizerVp9() {}
 
-std::string RtpPacketizerVp9::ToString() {
-  return "RtpPacketizerVp9";
-}
-
 size_t RtpPacketizerVp9::SetPayloadData(
     const uint8_t* payload,
     size_t payload_size,
@@ -485,6 +481,10 @@
   return packets_.size();
 }
 
+size_t RtpPacketizerVp9::NumPackets() const {
+  return packets_.size();
+}
+
 // Splits payload in minimal number of roughly equal in size packets.
 void RtpPacketizerVp9::GeneratePackets() {
   if (max_payload_length_ < PayloadDescriptorLength(hdr_) + 1) {
@@ -719,41 +719,42 @@
 
   parsed_payload->frame_type = p_bit ? kVideoFrameDelta : kVideoFrameKey;
 
-  RTPVideoHeaderVP9* vp9 = &parsed_payload->video_header().vp9();
-  vp9->InitRTPVideoHeaderVP9();
-  vp9->inter_pic_predicted = p_bit ? true : false;
-  vp9->flexible_mode = f_bit ? true : false;
-  vp9->beginning_of_frame = b_bit ? true : false;
-  vp9->end_of_frame = e_bit ? true : false;
-  vp9->ss_data_available = v_bit ? true : false;
-  vp9->non_ref_for_inter_layer_pred = z_bit ? true : false;
+  auto& vp9_header = parsed_payload->video_header()
+                         .video_type_header.emplace<RTPVideoHeaderVP9>();
+  vp9_header.InitRTPVideoHeaderVP9();
+  vp9_header.inter_pic_predicted = p_bit ? true : false;
+  vp9_header.flexible_mode = f_bit ? true : false;
+  vp9_header.beginning_of_frame = b_bit ? true : false;
+  vp9_header.end_of_frame = e_bit ? true : false;
+  vp9_header.ss_data_available = v_bit ? true : false;
+  vp9_header.non_ref_for_inter_layer_pred = z_bit ? true : false;
 
   // Parse fields that are present.
-  if (i_bit && !ParsePictureId(&parser, vp9)) {
+  if (i_bit && !ParsePictureId(&parser, &vp9_header)) {
     RTC_LOG(LS_ERROR) << "Failed parsing VP9 picture id.";
     return false;
   }
-  if (l_bit && !ParseLayerInfo(&parser, vp9)) {
+  if (l_bit && !ParseLayerInfo(&parser, &vp9_header)) {
     RTC_LOG(LS_ERROR) << "Failed parsing VP9 layer info.";
     return false;
   }
-  if (p_bit && f_bit && !ParseRefIndices(&parser, vp9)) {
+  if (p_bit && f_bit && !ParseRefIndices(&parser, &vp9_header)) {
     RTC_LOG(LS_ERROR) << "Failed parsing VP9 ref indices.";
     return false;
   }
   if (v_bit) {
-    if (!ParseSsData(&parser, vp9)) {
+    if (!ParseSsData(&parser, &vp9_header)) {
       RTC_LOG(LS_ERROR) << "Failed parsing VP9 SS data.";
       return false;
     }
-    if (vp9->spatial_layer_resolution_present) {
+    if (vp9_header.spatial_layer_resolution_present) {
       // TODO(asapersson): Add support for spatial layers.
-      parsed_payload->video_header().width = vp9->width[0];
-      parsed_payload->video_header().height = vp9->height[0];
+      parsed_payload->video_header().width = vp9_header.width[0];
+      parsed_payload->video_header().height = vp9_header.height[0];
     }
   }
   parsed_payload->video_header().is_first_packet_in_frame =
-      b_bit && (!l_bit || !vp9->inter_layer_predicted);
+      b_bit && (!l_bit || !vp9_header.inter_layer_predicted);
 
   uint64_t rem_bits = parser.RemainingBitCount();
   assert(rem_bits % 8 == 0);
diff --git a/modules/rtp_rtcp/source/rtp_format_vp9.h b/modules/rtp_rtcp/source/rtp_format_vp9.h
index 9017864..61f04d4 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp9.h
+++ b/modules/rtp_rtcp/source/rtp_format_vp9.h
@@ -27,7 +27,6 @@
 #include "modules/include/module_common_types.h"
 #include "modules/rtp_rtcp/source/rtp_format.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -39,12 +38,12 @@
 
   ~RtpPacketizerVp9() override;
 
-  std::string ToString() override;
-
   // The payload data must be one encoded VP9 layer frame.
   size_t SetPayloadData(const uint8_t* payload,
                         size_t payload_size,
-                        const RTPFragmentationHeader* fragmentation) override;
+                        const RTPFragmentationHeader* fragmentation);
+
+  size_t NumPackets() const override;
 
   // Gets the next payload with VP9 payload header.
   // Write payload and set marker bit of the |packet|.
diff --git a/modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc b/modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc
index b9480ef..66c6091 100644
--- a/modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_format_vp9_unittest.cc
@@ -15,7 +15,6 @@
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace {
@@ -83,7 +82,9 @@
   RtpDepacketizer::ParsedPayload parsed;
   ASSERT_TRUE(depacketizer->Parse(&parsed, packet, expected_length));
   EXPECT_EQ(kVideoCodecVP9, parsed.video_header().codec);
-  VerifyHeader(expected, parsed.video_header().vp9());
+  auto& vp9_header =
+      absl::get<RTPVideoHeaderVP9>(parsed.video_header().video_type_header);
+  VerifyHeader(expected, vp9_header);
   const size_t kExpectedPayloadLength = expected_length - expected_hdr_length;
   VerifyPayload(parsed, packet + expected_hdr_length, kExpectedPayloadLength);
 }
diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc
index 080cac7..b5b8ce5 100644
--- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc
+++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc
@@ -14,7 +14,9 @@
 
 namespace webrtc {
 
-constexpr size_t RtpGenericFrameDescriptor::kMaxNumFrameDependencies;
+constexpr int RtpGenericFrameDescriptor::kMaxNumFrameDependencies;
+constexpr int RtpGenericFrameDescriptor::kMaxTemporalLayers;
+constexpr int RtpGenericFrameDescriptor::kMaxSpatialLayers;
 
 RtpGenericFrameDescriptor::RtpGenericFrameDescriptor() = default;
 
@@ -25,7 +27,7 @@
 
 void RtpGenericFrameDescriptor::SetTemporalLayer(int temporal_layer) {
   RTC_DCHECK_GE(temporal_layer, 0);
-  RTC_DCHECK_LE(temporal_layer, 7);
+  RTC_DCHECK_LT(temporal_layer, kMaxTemporalLayers);
   temporal_layer_ = temporal_layer;
 }
 
diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h
index 51a9ac0..e4b775e 100644
--- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h
+++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h
@@ -20,6 +20,10 @@
 // Data to put on the wire for FrameDescriptor rtp header extension.
 class RtpGenericFrameDescriptor {
  public:
+  static constexpr int kMaxNumFrameDependencies = 8;
+  static constexpr int kMaxTemporalLayers = 8;
+  static constexpr int kMaxSpatialLayers = 8;
+
   RtpGenericFrameDescriptor();
 
   bool FirstPacketInSubFrame() const { return beginning_of_subframe_; }
@@ -51,8 +55,6 @@
   bool AddFrameDependencyDiff(uint16_t fdiff);
 
  private:
-  static constexpr size_t kMaxNumFrameDependencies = 8;
-
   bool beginning_of_subframe_ = false;
   bool end_of_subframe_ = false;
   bool beginning_of_frame_ = false;
diff --git a/modules/rtp_rtcp/source/rtp_header_extension_map_unittest.cc b/modules/rtp_rtcp/source/rtp_header_extension_map_unittest.cc
index 5eb8f1a..ad9f79c 100644
--- a/modules/rtp_rtcp/source/rtp_header_extension_map_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_header_extension_map_unittest.cc
@@ -14,7 +14,6 @@
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/rtp_packet.cc b/modules/rtp_rtcp/source/rtp_packet.cc
index 878942b..4387fe7 100644
--- a/modules/rtp_rtcp/source/rtp_packet.cc
+++ b/modules/rtp_rtcp/source/rtp_packet.cc
@@ -107,32 +107,6 @@
   return true;
 }
 
-bool RtpPacket::Marker() const {
-  RTC_DCHECK_EQ(marker_, (data()[1] & 0x80) != 0);
-  return marker_;
-}
-
-uint8_t RtpPacket::PayloadType() const {
-  RTC_DCHECK_EQ(payload_type_, data()[1] & 0x7f);
-  return payload_type_;
-}
-
-uint16_t RtpPacket::SequenceNumber() const {
-  RTC_DCHECK_EQ(sequence_number_,
-                ByteReader<uint16_t>::ReadBigEndian(data() + 2));
-  return sequence_number_;
-}
-
-uint32_t RtpPacket::Timestamp() const {
-  RTC_DCHECK_EQ(timestamp_, ByteReader<uint32_t>::ReadBigEndian(data() + 4));
-  return timestamp_;
-}
-
-uint32_t RtpPacket::Ssrc() const {
-  RTC_DCHECK_EQ(ssrc_, ByteReader<uint32_t>::ReadBigEndian(data() + 8));
-  return ssrc_;
-}
-
 std::vector<uint32_t> RtpPacket::Csrcs() const {
   size_t num_csrc = data()[0] & 0x0F;
   RTC_DCHECK_GE(capacity(), kFixedHeaderSize + num_csrc * 4);
@@ -144,48 +118,6 @@
   return csrcs;
 }
 
-size_t RtpPacket::headers_size() const {
-  return payload_offset_;
-}
-
-size_t RtpPacket::payload_size() const {
-  return payload_size_;
-}
-
-size_t RtpPacket::padding_size() const {
-  return padding_size_;
-}
-
-rtc::ArrayView<const uint8_t> RtpPacket::payload() const {
-  return rtc::MakeArrayView(data() + payload_offset_, payload_size_);
-}
-
-rtc::CopyOnWriteBuffer RtpPacket::Buffer() const {
-  return buffer_;
-}
-
-size_t RtpPacket::capacity() const {
-  return buffer_.capacity();
-}
-
-size_t RtpPacket::size() const {
-  size_t ret = payload_offset_ + payload_size_ + padding_size_;
-  RTC_DCHECK_EQ(buffer_.size(), ret);
-  return ret;
-}
-
-const uint8_t* RtpPacket::data() const {
-  return buffer_.cdata();
-}
-
-size_t RtpPacket::FreeCapacity() const {
-  return capacity() - size();
-}
-
-size_t RtpPacket::MaxPayloadSize() const {
-  return capacity() - payload_offset_;
-}
-
 void RtpPacket::CopyHeaderFrom(const RtpPacket& packet) {
   RTC_DCHECK_GE(capacity(), packet.headers_size());
 
@@ -235,7 +167,7 @@
   ByteWriter<uint32_t>::WriteBigEndian(WriteAt(8), ssrc);
 }
 
-void RtpPacket::SetCsrcs(const std::vector<uint32_t>& csrcs) {
+void RtpPacket::SetCsrcs(rtc::ArrayView<const uint32_t> csrcs) {
   RTC_DCHECK_EQ(extensions_size_, 0);
   RTC_DCHECK_EQ(payload_size_, 0);
   RTC_DCHECK_EQ(padding_size_, 0);
@@ -251,37 +183,7 @@
   buffer_.SetSize(payload_offset_);
 }
 
-bool RtpPacket::HasRawExtension(int id) const {
-  if (id == ExtensionManager::kInvalidId)
-    return false;
-  RTC_DCHECK_GE(id, kMinExtensionId);
-  RTC_DCHECK_LE(id, kMaxExtensionId);
-  return extension_entries_[id - 1].offset != 0;
-}
-
-rtc::ArrayView<const uint8_t> RtpPacket::GetRawExtension(int id) const {
-  if (id == ExtensionManager::kInvalidId)
-    return nullptr;
-  RTC_DCHECK_GE(id, kMinExtensionId);
-  RTC_DCHECK_LE(id, kMaxExtensionId);
-  const ExtensionInfo& extension = extension_entries_[id - 1];
-  if (extension.offset == 0)
-    return nullptr;
-  return rtc::MakeArrayView(data() + extension.offset, extension.length);
-}
-
-bool RtpPacket::SetRawExtension(int id, rtc::ArrayView<const uint8_t> data) {
-  auto buffer = AllocateRawExtension(id, data.size());
-  if (buffer.empty())
-    return false;
-  RTC_DCHECK_EQ(buffer.size(), data.size());
-  memcpy(buffer.data(), data.data(), data.size());
-  return true;
-}
-
 rtc::ArrayView<uint8_t> RtpPacket::AllocateRawExtension(int id, size_t length) {
-  if (id == ExtensionManager::kInvalidId)
-    return nullptr;
   RTC_DCHECK_GE(id, kMinExtensionId);
   RTC_DCHECK_LE(id, kMaxExtensionId);
   RTC_DCHECK_GE(length, 1);
@@ -547,12 +449,4 @@
   return nullptr;
 }
 
-uint8_t* RtpPacket::WriteAt(size_t offset) {
-  return buffer_.data() + offset;
-}
-
-void RtpPacket::WriteAt(size_t offset, uint8_t byte) {
-  buffer_.data()[offset] = byte;
-}
-
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_packet.h b/modules/rtp_rtcp/source/rtp_packet.h
index 2f0ef75..21adf62 100644
--- a/modules/rtp_rtcp/source/rtp_packet.h
+++ b/modules/rtp_rtcp/source/rtp_packet.h
@@ -51,27 +51,31 @@
   void IdentifyExtensions(const ExtensionManager& extensions);
 
   // Header.
-  bool Marker() const;
-  uint8_t PayloadType() const;
-  uint16_t SequenceNumber() const;
-  uint32_t Timestamp() const;
-  uint32_t Ssrc() const;
+  bool Marker() const { return marker_; }
+  uint8_t PayloadType() const { return payload_type_; }
+  uint16_t SequenceNumber() const { return sequence_number_; }
+  uint32_t Timestamp() const { return timestamp_; }
+  uint32_t Ssrc() const { return ssrc_; }
   std::vector<uint32_t> Csrcs() const;
 
-  size_t headers_size() const;
+  size_t headers_size() const { return payload_offset_; }
 
   // Payload.
-  size_t payload_size() const;
-  size_t padding_size() const;
-  rtc::ArrayView<const uint8_t> payload() const;
+  size_t payload_size() const { return payload_size_; }
+  size_t padding_size() const { return padding_size_; }
+  rtc::ArrayView<const uint8_t> payload() const {
+    return rtc::MakeArrayView(data() + payload_offset_, payload_size_);
+  }
 
   // Buffer.
-  rtc::CopyOnWriteBuffer Buffer() const;
-  size_t capacity() const;
-  size_t size() const;
-  const uint8_t* data() const;
-  size_t FreeCapacity() const;
-  size_t MaxPayloadSize() const;
+  rtc::CopyOnWriteBuffer Buffer() const { return buffer_; }
+  size_t capacity() const { return buffer_.capacity(); }
+  size_t size() const {
+    return payload_offset_ + payload_size_ + padding_size_;
+  }
+  const uint8_t* data() const { return buffer_.cdata(); }
+  size_t FreeCapacity() const { return capacity() - size(); }
+  size_t MaxPayloadSize() const { return capacity() - headers_size(); }
 
   // Reset fields and buffer.
   void Clear();
@@ -87,7 +91,7 @@
   // Writes csrc list. Assumes:
   // a) There is enough room left in buffer.
   // b) Extension headers, payload or padding data has not already been added.
-  void SetCsrcs(const std::vector<uint32_t>& csrcs);
+  void SetCsrcs(rtc::ArrayView<const uint32_t> csrcs);
 
   // Header extensions.
   template <typename Extension>
@@ -102,21 +106,6 @@
   template <typename Extension>
   bool ReserveExtension();
 
-  // Following 4 helpers identify rtp header extension by |id| negotiated with
-  // remote peer and written in an rtp packet.
-  bool HasRawExtension(int id) const;
-
-  // Returns place where extension with |id| is stored.
-  // Returns empty arrayview if extension is not present.
-  rtc::ArrayView<const uint8_t> GetRawExtension(int id) const;
-
-  // Allocates and store header extension. Returns true on success.
-  bool SetRawExtension(int id, rtc::ArrayView<const uint8_t> data);
-
-  // Allocates and returns place to store rtp header extension.
-  // Returns empty arrayview on failure.
-  rtc::ArrayView<uint8_t> AllocateRawExtension(int id, size_t length);
-
   // Reserve size_bytes for payload. Returns nullptr on failure.
   uint8_t* SetPayloadSize(size_t size_bytes);
   // Same as SetPayloadSize but doesn't guarantee to keep current payload.
@@ -138,12 +127,16 @@
   // Returns view of the raw extension or empty view on failure.
   rtc::ArrayView<const uint8_t> FindExtension(ExtensionType type) const;
 
+  // Allocates and returns place to store rtp header extension.
+  // Returns empty arrayview on failure.
+  rtc::ArrayView<uint8_t> AllocateRawExtension(int id, size_t length);
+
   // Find or allocate an extension |type|. Returns view of size |length|
   // to write raw extension to or an empty view on failure.
   rtc::ArrayView<uint8_t> AllocateExtension(ExtensionType type, size_t length);
 
-  uint8_t* WriteAt(size_t offset);
-  void WriteAt(size_t offset, uint8_t byte);
+  uint8_t* WriteAt(size_t offset) { return buffer_.data() + offset; }
+  void WriteAt(size_t offset, uint8_t byte) { buffer_.data()[offset] = byte; }
 
   // Header.
   bool marker_;
diff --git a/modules/rtp_rtcp/source/rtp_packet_history.h b/modules/rtp_rtcp/source/rtp_packet_history.h
index 03527ff..433da0e 100644
--- a/modules/rtp_rtcp/source/rtp_packet_history.h
+++ b/modules/rtp_rtcp/source/rtp_packet_history.h
@@ -19,7 +19,6 @@
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/criticalsection.h"
 #include "rtc_base/thread_annotations.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc b/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc
index 026c187..ab5aeb0 100644
--- a/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc
@@ -17,7 +17,6 @@
 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
 #include "system_wrappers/include/clock.h"
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 namespace {
diff --git a/modules/rtp_rtcp/source/rtp_packet_unittest.cc b/modules/rtp_rtcp/source/rtp_packet_unittest.cc
index 60d23d8..e19f191 100644
--- a/modules/rtp_rtcp/source/rtp_packet_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_packet_unittest.cc
@@ -196,50 +196,27 @@
   EXPECT_FALSE(packet.SetExtension<RtpMid>(kLongMid));
 }
 
-TEST(RtpPacketTest, CreateWithExtensionsWithoutManager) {
-  RtpPacketToSend packet(nullptr);
-  packet.SetPayloadType(kPayloadType);
-  packet.SetSequenceNumber(kSeqNum);
-  packet.SetTimestamp(kTimestamp);
-  packet.SetSsrc(kSsrc);
-
-  auto raw = packet.AllocateRawExtension(kTransmissionOffsetExtensionId,
-                                         TransmissionOffset::kValueSizeBytes);
-  EXPECT_EQ(raw.size(), TransmissionOffset::kValueSizeBytes);
-  TransmissionOffset::Write(raw, kTimeOffset);
-
-  raw = packet.AllocateRawExtension(kAudioLevelExtensionId,
-                                    AudioLevel::kValueSizeBytes);
-  EXPECT_EQ(raw.size(), AudioLevel::kValueSizeBytes);
-  AudioLevel::Write(raw, kVoiceActive, kAudioLevel);
-
-  EXPECT_THAT(kPacketWithTOAndAL,
-              ElementsAreArray(packet.data(), packet.size()));
-}
-
 TEST(RtpPacketTest, CreateWithMaxSizeHeaderExtension) {
-  const size_t kMaxExtensionSize = 16;
-  const int kId = 1;
-  const uint8_t kValue[16] = "123456789abcdef";
+  const std::string kValue = "123456789abcdef";
+  RtpPacket::ExtensionManager extensions;
+  extensions.Register<RtpMid>(1);
+  extensions.Register<RtpStreamId>(2);
 
-  // Write packet with a custom extension.
-  RtpPacketToSend packet(nullptr);
-  packet.SetRawExtension(kId, kValue);
-  // Using different size for same id is not allowed.
-  EXPECT_TRUE(packet.AllocateRawExtension(kId, kMaxExtensionSize - 1).empty());
+  RtpPacket packet(&extensions);
+  EXPECT_TRUE(packet.SetExtension<RtpMid>(kValue));
 
   packet.SetPayloadSize(42);
   // Rewriting allocated extension is allowed.
-  EXPECT_EQ(packet.AllocateRawExtension(kId, kMaxExtensionSize).size(),
-            kMaxExtensionSize);
+  EXPECT_TRUE(packet.SetExtension<RtpMid>(kValue));
   // Adding another extension after payload is set is not allowed.
-  EXPECT_TRUE(packet.AllocateRawExtension(kId + 1, kMaxExtensionSize).empty());
+  EXPECT_FALSE(packet.SetExtension<RtpStreamId>(kValue));
 
-  // Read packet with the custom extension.
-  RtpPacketReceived parsed;
+  // Read packet with the extension.
+  RtpPacketReceived parsed(&extensions);
   EXPECT_TRUE(parsed.Parse(packet.Buffer()));
-  auto read_raw = parsed.GetRawExtension(kId);
-  EXPECT_THAT(read_raw, ElementsAreArray(kValue, kMaxExtensionSize));
+  std::string read;
+  EXPECT_TRUE(parsed.GetExtension<RtpMid>(&read));
+  EXPECT_EQ(read, kValue);
 }
 
 TEST(RtpPacketTest, SetReservedExtensionsAfterPayload) {
@@ -426,23 +403,6 @@
   EXPECT_EQ(0u, packet.padding_size());
 }
 
-TEST(RtpPacketTest, ParseWithoutExtensionManager) {
-  RtpPacketReceived packet;
-  EXPECT_TRUE(packet.Parse(kPacketWithTO, sizeof(kPacketWithTO)));
-
-  EXPECT_FALSE(packet.HasRawExtension(kAudioLevelExtensionId));
-  EXPECT_TRUE(packet.GetRawExtension(kAudioLevelExtensionId).empty());
-
-  EXPECT_TRUE(packet.HasRawExtension(kTransmissionOffsetExtensionId));
-
-  int32_t time_offset = 0;
-  auto raw_extension = packet.GetRawExtension(kTransmissionOffsetExtensionId);
-  EXPECT_EQ(raw_extension.size(), TransmissionOffset::kValueSizeBytes);
-  EXPECT_TRUE(TransmissionOffset::Parse(raw_extension, &time_offset));
-
-  EXPECT_EQ(time_offset, kTimeOffset);
-}
-
 TEST(RtpPacketTest, ParseDynamicSizeExtension) {
   // clang-format off
   const uint8_t kPacket1[] = {
@@ -493,23 +453,6 @@
   EXPECT_EQ(mid, kMid);
 }
 
-TEST(RtpPacketTest, RawExtensionFunctionsAcceptZeroIdAndReturnFalse) {
-  RtpPacketReceived::ExtensionManager extensions;
-  RtpPacketReceived packet(&extensions);
-  // Use ExtensionManager to set kInvalidId to 0 to demonstrate natural way for
-  // using zero value as a parameter to Packet::*RawExtension functions.
-  const int kInvalidId = extensions.GetId(TransmissionOffset::kId);
-  ASSERT_EQ(kInvalidId, 0);
-
-  ASSERT_TRUE(packet.Parse(kPacket, sizeof(kPacket)));
-
-  EXPECT_FALSE(packet.HasRawExtension(kInvalidId));
-  EXPECT_THAT(packet.GetRawExtension(kInvalidId), IsEmpty());
-  const uint8_t kExtension[] = {'e', 'x', 't'};
-  EXPECT_FALSE(packet.SetRawExtension(kInvalidId, kExtension));
-  EXPECT_THAT(packet.AllocateRawExtension(kInvalidId, 3), IsEmpty());
-}
-
 TEST(RtpPacketTest, CreateAndParseTimingFrameExtension) {
   // Create a packet with video frame timing extension populated.
   RtpPacketToSend::ExtensionManager send_extensions;
diff --git a/modules/rtp_rtcp/source/rtp_payload_registry.cc b/modules/rtp_rtcp/source/rtp_payload_registry.cc
index f69940a..4bbb03a 100644
--- a/modules/rtp_rtcp/source/rtp_payload_registry.cc
+++ b/modules/rtp_rtcp/source/rtp_payload_registry.cc
@@ -47,20 +47,9 @@
           PayloadUnion(AudioPayload{audio_format, 0})};
 }
 
-RtpVideoCodecTypes ConvertToRtpVideoCodecType(VideoCodecType type) {
-  switch (type) {
-    case kVideoCodecVP8:
-    case kVideoCodecVP9:
-    case kVideoCodecH264:
-      return type;
-    default:
-      return kVideoCodecGeneric;
-  }
-}
-
 RtpUtility::Payload CreatePayloadType(const VideoCodec& video_codec) {
   VideoPayload p;
-  p.videoCodecType = ConvertToRtpVideoCodecType(video_codec.codecType);
+  p.videoCodecType = video_codec.codecType;
   if (video_codec.codecType == kVideoCodecH264)
     p.h264_profile = video_codec.H264().profile;
   return {CodecTypeToPayloadString(video_codec.codecType), PayloadUnion(p)};
@@ -91,7 +80,7 @@
 
 }  // namespace
 
-RTPPayloadRegistry::RTPPayloadRegistry() : last_received_payload_type_(-1) {}
+RTPPayloadRegistry::RTPPayloadRegistry() = default;
 
 RTPPayloadRegistry::~RTPPayloadRegistry() = default;
 
@@ -112,10 +101,6 @@
     payload_type_map_.emplace(rtp_payload_type,
                               CreatePayloadType(audio_format));
   }
-
-  // Clear the value of last received payload type since it might mean
-  // something else now.
-  last_received_payload_type_ = -1;
 }
 
 int32_t RTPPayloadRegistry::RegisterReceivePayload(
@@ -153,9 +138,7 @@
   RTC_DCHECK(insert_status.second);  // Insertion succeeded.
   *created_new_payload = true;
 
-  // Successful set of payload type, clear the value of last received payload
-  // type since it might mean something else.
-  last_received_payload_type_ = -1;
+  // Successful set of payload type.
   return 0;
 }
 
@@ -186,9 +169,7 @@
       video_codec.plType, CreatePayloadType(video_codec));
   RTC_DCHECK(insert_status.second);  // Insertion succeeded.
 
-  // Successful set of payload type, clear the value of last received payload
-  // type since it might mean something else.
-  last_received_payload_type_ = -1;
+  // Successful set of payload type.
   return 0;
 }
 
diff --git a/modules/rtp_rtcp/source/rtp_payload_registry_unittest.cc b/modules/rtp_rtcp/source/rtp_payload_registry_unittest.cc
index e7362c7..9ae6aef 100644
--- a/modules/rtp_rtcp/source/rtp_payload_registry_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_payload_registry_unittest.cc
@@ -149,21 +149,6 @@
       << "Not compatible; both payloads should be kept.";
 }
 
-TEST(RtpPayloadRegistryTest,
-     LastReceivedCodecTypesAreResetWhenRegisteringNewPayloadTypes) {
-  RTPPayloadRegistry rtp_payload_registry;
-  rtp_payload_registry.set_last_received_payload_type(17);
-  EXPECT_EQ(17, rtp_payload_registry.last_received_payload_type());
-
-  bool ignored;
-  constexpr int payload_type = 34;
-  const SdpAudioFormat audio_format("name", 44000, 1);
-  EXPECT_EQ(0, rtp_payload_registry.RegisterReceivePayload(
-                   payload_type, audio_format, &ignored));
-
-  EXPECT_EQ(-1, rtp_payload_registry.last_received_payload_type());
-}
-
 class ParameterizedRtpPayloadRegistryTest
     : public ::testing::TestWithParam<int> {};
 
diff --git a/modules/rtp_rtcp/source/rtp_receiver_audio.cc b/modules/rtp_rtcp/source/rtp_receiver_audio.cc
index ac57138..030c79f 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_audio.cc
+++ b/modules/rtp_rtcp/source/rtp_receiver_audio.cc
@@ -25,47 +25,10 @@
 }
 
 RTPReceiverAudio::RTPReceiverAudio(RtpData* data_callback)
-    : RTPReceiverStrategy(data_callback),
-      TelephoneEventHandler(),
-      telephone_event_forward_to_decoder_(false),
-      telephone_event_payload_type_(-1),
-      cng_nb_payload_type_(-1),
-      cng_wb_payload_type_(-1),
-      cng_swb_payload_type_(-1),
-      cng_fb_payload_type_(-1) {}
+    : RTPReceiverStrategy(data_callback) {}
 
 RTPReceiverAudio::~RTPReceiverAudio() = default;
 
-// Outband TelephoneEvent(DTMF) detection
-void RTPReceiverAudio::SetTelephoneEventForwardToDecoder(
-    bool forward_to_decoder) {
-  rtc::CritScope lock(&crit_sect_);
-  telephone_event_forward_to_decoder_ = forward_to_decoder;
-}
-
-// Is forwarding of outband telephone events turned on/off?
-bool RTPReceiverAudio::TelephoneEventForwardToDecoder() const {
-  rtc::CritScope lock(&crit_sect_);
-  return telephone_event_forward_to_decoder_;
-}
-
-bool RTPReceiverAudio::TelephoneEventPayloadType(int8_t payload_type) const {
-  rtc::CritScope lock(&crit_sect_);
-  return telephone_event_payload_type_ == payload_type;
-}
-
-TelephoneEventHandler* RTPReceiverAudio::GetTelephoneEventHandler() {
-  return this;
-}
-
-bool RTPReceiverAudio::CNGPayloadType(int8_t payload_type) {
-  rtc::CritScope lock(&crit_sect_);
-  return payload_type == cng_nb_payload_type_ ||
-         payload_type == cng_wb_payload_type_ ||
-         payload_type == cng_swb_payload_type_ ||
-         payload_type == cng_fb_payload_type_;
-}
-
 // -   Sample based or frame based codecs based on RFC 3551
 // -
 // -   NOTE! There is one error in the RFC, stating G.722 uses 8 bits/samples.
@@ -98,32 +61,6 @@
 // -   MPA       frame         N/A              var.      var.
 // -
 // -   G7221     frame         N/A
-int32_t RTPReceiverAudio::OnNewPayloadTypeCreated(
-    int payload_type,
-    const SdpAudioFormat& audio_format) {
-  rtc::CritScope lock(&crit_sect_);
-
-  if (RtpUtility::StringCompare(audio_format.name.c_str(), "telephone-event",
-                                15)) {
-    telephone_event_payload_type_ = payload_type;
-  }
-  if (RtpUtility::StringCompare(audio_format.name.c_str(), "cn", 2)) {
-    // We support comfort noise at four different frequencies.
-    if (audio_format.clockrate_hz == 8000) {
-      cng_nb_payload_type_ = payload_type;
-    } else if (audio_format.clockrate_hz == 16000) {
-      cng_wb_payload_type_ = payload_type;
-    } else if (audio_format.clockrate_hz == 32000) {
-      cng_swb_payload_type_ = payload_type;
-    } else if (audio_format.clockrate_hz == 48000) {
-      cng_fb_payload_type_ = payload_type;
-    } else {
-      assert(false);
-      return -1;
-    }
-  }
-  return 0;
-}
 
 int32_t RTPReceiverAudio::ParseRtpPacket(WebRtcRTPHeader* rtp_header,
                                          const PayloadUnion& specific_payload,
@@ -138,24 +75,6 @@
                                  specific_payload.audio_payload());
 }
 
-RTPAliveType RTPReceiverAudio::ProcessDeadOrAlive(
-    uint16_t last_payload_length) const {
-  // Our CNG is 9 bytes; if it's a likely CNG the receiver needs to check
-  // kRtpNoRtp against NetEq speech_type kOutputPLCtoCNG.
-  if (last_payload_length < 10) {  // our CNG is 9 bytes
-    return kRtpNoRtp;
-  } else {
-    return kRtpDead;
-  }
-}
-
-void RTPReceiverAudio::CheckPayloadChanged(int8_t payload_type,
-                                           PayloadUnion* /* specific_payload */,
-                                           bool* should_discard_changes) {
-  *should_discard_changes =
-      TelephoneEventPayloadType(payload_type) || CNGPayloadType(payload_type);
-}
-
 // We are not allowed to have any critsects when calling data_callback.
 int32_t RTPReceiverAudio::ParseAudioCodecSpecific(
     WebRtcRTPHeader* rtp_header,
@@ -170,71 +89,6 @@
     return data_callback_->OnReceivedPayloadData(nullptr, 0, rtp_header);
   }
 
-  bool telephone_event_packet =
-      TelephoneEventPayloadType(rtp_header->header.payloadType);
-  if (telephone_event_packet) {
-    rtc::CritScope lock(&crit_sect_);
-
-    // RFC 4733 2.3
-    // 0                   1                   2                   3
-    // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
-    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-    // |     event     |E|R| volume    |          duration             |
-    // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-    //
-    if (payload_data_length % 4 != 0) {
-      return -1;
-    }
-    size_t number_of_events = payload_data_length / 4;
-
-    // sanity
-    if (number_of_events >= MAX_NUMBER_OF_PARALLEL_TELEPHONE_EVENTS) {
-      number_of_events = MAX_NUMBER_OF_PARALLEL_TELEPHONE_EVENTS;
-    }
-    for (size_t n = 0; n < number_of_events; ++n) {
-      RTC_DCHECK_GE(payload_data_length, (4 * n) + 2);
-      bool end = (payload_data[(4 * n) + 1] & 0x80) ? true : false;
-
-      std::set<uint8_t>::iterator event =
-          telephone_event_reported_.find(payload_data[4 * n]);
-
-      if (event != telephone_event_reported_.end()) {
-        // we have already seen this event
-        if (end) {
-          telephone_event_reported_.erase(payload_data[4 * n]);
-        }
-      } else {
-        if (end) {
-          // don't add if it's a end of a tone
-        } else {
-          telephone_event_reported_.insert(payload_data[4 * n]);
-        }
-      }
-    }
-
-    // RFC 4733 2.5.1.3 & 2.5.2.3 Long-Duration Events
-    // should not be a problem since we don't care about the duration
-
-    // RFC 4733 See 2.5.1.5. & 2.5.2.4.  Multiple Events in a Packet
-  }
-
-  {
-    rtc::CritScope lock(&crit_sect_);
-
-    // check if it's a DTMF event, hence something we can playout
-    if (telephone_event_packet) {
-      if (!telephone_event_forward_to_decoder_) {
-        // don't forward event to decoder
-        return 0;
-      }
-      std::set<uint8_t>::iterator first = telephone_event_reported_.begin();
-      if (first != telephone_event_reported_.end() && *first > 15) {
-        // don't forward non DTMF events
-        return 0;
-      }
-    }
-  }
-
   return data_callback_->OnReceivedPayloadData(payload_data,
                                                payload_data_length, rtp_header);
 }
diff --git a/modules/rtp_rtcp/source/rtp_receiver_audio.h b/modules/rtp_rtcp/source/rtp_receiver_audio.h
index d88acfd..5d97a1f 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_audio.h
+++ b/modules/rtp_rtcp/source/rtp_receiver_audio.h
@@ -18,64 +18,27 @@
 #include "modules/rtp_rtcp/source/rtp_receiver_strategy.h"
 #include "modules/rtp_rtcp/source/rtp_utility.h"
 #include "rtc_base/onetimeevent.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
 // Handles audio RTP packets. This class is thread-safe.
-class RTPReceiverAudio : public RTPReceiverStrategy,
-                         public TelephoneEventHandler {
+class RTPReceiverAudio : public RTPReceiverStrategy {
  public:
   explicit RTPReceiverAudio(RtpData* data_callback);
   ~RTPReceiverAudio() override;
 
-  // The following three methods implement the TelephoneEventHandler interface.
-  // Forward DTMFs to decoder for playout.
-  void SetTelephoneEventForwardToDecoder(bool forward_to_decoder) override;
-
-  // Is forwarding of outband telephone events turned on/off?
-  bool TelephoneEventForwardToDecoder() const override;
-
-  // Is TelephoneEvent configured with |payload_type|.
-  bool TelephoneEventPayloadType(const int8_t payload_type) const override;
-
-  TelephoneEventHandler* GetTelephoneEventHandler() override;
-
-  // Returns true if CNG is configured with |payload_type|.
-  bool CNGPayloadType(const int8_t payload_type);
-
   int32_t ParseRtpPacket(WebRtcRTPHeader* rtp_header,
                          const PayloadUnion& specific_payload,
                          const uint8_t* packet,
                          size_t payload_length,
                          int64_t timestamp_ms) override;
 
-  RTPAliveType ProcessDeadOrAlive(uint16_t last_payload_length) const override;
-
-  int32_t OnNewPayloadTypeCreated(int payload_type,
-                                  const SdpAudioFormat& audio_format) override;
-
-  // We need to look out for special payload types here and sometimes reset
-  // statistics. In addition we sometimes need to tweak the frequency.
-  void CheckPayloadChanged(int8_t payload_type,
-                           PayloadUnion* specific_payload,
-                           bool* should_discard_changes) override;
-
  private:
   int32_t ParseAudioCodecSpecific(WebRtcRTPHeader* rtp_header,
                                   const uint8_t* payload_data,
                                   size_t payload_length,
                                   const AudioPayload& audio_specific);
 
-  bool telephone_event_forward_to_decoder_;
-  int8_t telephone_event_payload_type_;
-  std::set<uint8_t> telephone_event_reported_;
-
-  int8_t cng_nb_payload_type_;
-  int8_t cng_wb_payload_type_;
-  int8_t cng_swb_payload_type_;
-  int8_t cng_fb_payload_type_;
-
   ThreadUnsafeOneTimeEvent first_packet_received_;
 };
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_receiver_impl.cc b/modules/rtp_rtcp/source/rtp_receiver_impl.cc
index ac18688..ea63e5e 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_impl.cc
+++ b/modules/rtp_rtcp/source/rtp_receiver_impl.cc
@@ -85,12 +85,8 @@
       rtp_payload_registry_(rtp_payload_registry),
       rtp_media_receiver_(rtp_media_receiver),
       ssrc_(0),
-      num_csrcs_(0),
-      current_remote_csrc_(),
       last_received_timestamp_(0),
-      last_received_frame_time_ms_(-1) {
-  memset(current_remote_csrc_, 0, sizeof(current_remote_csrc_));
-}
+      last_received_frame_time_ms_(-1) {}
 
 RtpReceiverImpl::~RtpReceiverImpl() {}
 
@@ -105,14 +101,6 @@
   bool created_new_payload = false;
   int32_t result = rtp_payload_registry_->RegisterReceivePayload(
       payload_type, audio_format, &created_new_payload);
-  if (created_new_payload) {
-    if (rtp_media_receiver_->OnNewPayloadTypeCreated(payload_type,
-                                                     audio_format) != 0) {
-      RTC_LOG(LS_ERROR) << "Failed to register payload: " << audio_format.name
-                        << "/" << payload_type;
-      return -1;
-    }
-  }
   return result;
 }
 
@@ -131,18 +119,6 @@
   return ssrc_;
 }
 
-// Get remote CSRC.
-int32_t RtpReceiverImpl::CSRCs(uint32_t array_of_csrcs[kRtpCsrcSize]) const {
-  rtc::CritScope lock(&critical_section_rtp_receiver_);
-
-  assert(num_csrcs_ <= kRtpCsrcSize);
-
-  if (num_csrcs_ > 0) {
-    memcpy(array_of_csrcs, current_remote_csrc_, sizeof(uint32_t) * num_csrcs_);
-  }
-  return num_csrcs_;
-}
-
 bool RtpReceiverImpl::IncomingRtpPacket(const RTPHeader& rtp_header,
                                         const uint8_t* payload,
                                         size_t payload_length,
@@ -150,18 +126,21 @@
   // Trigger our callbacks.
   CheckSSRCChanged(rtp_header);
 
-  if (CheckPayloadChanged(rtp_header, &payload_specific) == -1) {
-    if (payload_length == 0) {
-      // OK, keep-alive packet.
-      return true;
-    }
-    RTC_LOG(LS_WARNING) << "Receiving invalid payload type.";
-    return false;
+  if (payload_length == 0) {
+    // OK, keep-alive packet.
+    return true;
+  }
+  int64_t now_ms = clock_->TimeInMilliseconds();
+
+  {
+    rtc::CritScope lock(&critical_section_rtp_receiver_);
+
+    csrcs_.Update(
+        now_ms, rtc::MakeArrayView(rtp_header.arrOfCSRCs, rtp_header.numCSRCs));
   }
 
   WebRtcRTPHeader webrtc_rtp_header{};
   webrtc_rtp_header.header = rtp_header;
-  CheckCSRC(webrtc_rtp_header);
 
   auto audio_level =
       rtp_header.extension.hasAudioLevel
@@ -170,8 +149,7 @@
   UpdateSources(audio_level);
 
   int32_t ret_val = rtp_media_receiver_->ParseRtpPacket(
-      &webrtc_rtp_header, payload_specific, payload, payload_length,
-      clock_->TimeInMilliseconds());
+      &webrtc_rtp_header, payload_specific, payload, payload_length, now_ms);
 
   if (ret_val < 0) {
     return false;
@@ -195,24 +173,15 @@
   return true;
 }
 
-TelephoneEventHandler* RtpReceiverImpl::GetTelephoneEventHandler() {
-  return rtp_media_receiver_->GetTelephoneEventHandler();
-}
-
 std::vector<RtpSource> RtpReceiverImpl::GetSources() const {
   rtc::CritScope lock(&critical_section_rtp_receiver_);
 
   int64_t now_ms = clock_->TimeInMilliseconds();
-  std::vector<RtpSource> sources;
-
   RTC_DCHECK(std::is_sorted(ssrc_sources_.begin(), ssrc_sources_.end(),
                             [](const RtpSource& lhs, const RtpSource& rhs) {
                               return lhs.timestamp_ms() < rhs.timestamp_ms();
                             }));
-  RTC_DCHECK(std::is_sorted(csrc_sources_.begin(), csrc_sources_.end(),
-                            [](const RtpSource& lhs, const RtpSource& rhs) {
-                              return lhs.timestamp_ms() < rhs.timestamp_ms();
-                            }));
+  std::vector<RtpSource> sources = csrcs_.GetSources(now_ms);
 
   std::set<uint32_t> selected_ssrcs;
   for (auto rit = ssrc_sources_.rbegin(); rit != ssrc_sources_.rend(); ++rit) {
@@ -223,13 +192,6 @@
       sources.push_back(*rit);
     }
   }
-
-  for (auto rit = csrc_sources_.rbegin(); rit != csrc_sources_.rend(); ++rit) {
-    if ((now_ms - rit->timestamp_ms()) > kGetSourcesTimeoutMs) {
-      break;
-    }
-    sources.push_back(*rit);
-  }
   return sources;
 }
 
@@ -252,85 +214,11 @@
   ssrc_ = rtp_header.ssrc;
 }
 
-// Implementation note: must not hold critsect when called.
-// TODO(phoglund): Move as much as possible of this code path into the media
-// specific receivers. Basically this method goes through a lot of trouble to
-// compute something which is only used by the media specific parts later. If
-// this code path moves we can get rid of some of the rtp_receiver ->
-// media_specific interface (such as CheckPayloadChange, possibly get/set
-// last known payload).
-int32_t RtpReceiverImpl::CheckPayloadChanged(const RTPHeader& rtp_header,
-                                             PayloadUnion* specific_payload) {
-  int8_t payload_type = rtp_header.payloadType;
-
-  {
-    rtc::CritScope lock(&critical_section_rtp_receiver_);
-
-    int8_t last_received_payload_type =
-        rtp_payload_registry_->last_received_payload_type();
-    // TODO(holmer): Remove this code when RED parsing has been broken out from
-    // RtpReceiverAudio.
-    if (payload_type != last_received_payload_type) {
-      bool should_discard_changes = false;
-
-      rtp_media_receiver_->CheckPayloadChanged(payload_type, specific_payload,
-                                               &should_discard_changes);
-
-      if (should_discard_changes) {
-        return 0;
-      }
-
-      const auto payload =
-          rtp_payload_registry_->PayloadTypeToPayload(payload_type);
-      if (!payload) {
-        // Not a registered payload type.
-        return -1;
-      }
-      rtp_payload_registry_->set_last_received_payload_type(payload_type);
-    }
-  }  // End critsect.
-
-  return 0;
-}
-
-// Implementation note: must not hold critsect when called.
-void RtpReceiverImpl::CheckCSRC(const WebRtcRTPHeader& rtp_header) {
-  const uint8_t num_csrcs = rtp_header.header.numCSRCs;
-  if (num_csrcs > kRtpCsrcSize) {
-    // Ignore.
-    return;
-  }
-  {
-    rtc::CritScope lock(&critical_section_rtp_receiver_);
-
-    // Copy new.
-    memcpy(current_remote_csrc_, rtp_header.header.arrOfCSRCs,
-           num_csrcs * sizeof(uint32_t));
-
-    num_csrcs_ = num_csrcs;
-  }  // End critsect.
-}
-
 void RtpReceiverImpl::UpdateSources(
     const absl::optional<uint8_t>& ssrc_audio_level) {
   rtc::CritScope lock(&critical_section_rtp_receiver_);
   int64_t now_ms = clock_->TimeInMilliseconds();
 
-  for (size_t i = 0; i < num_csrcs_; ++i) {
-    auto map_it = iterator_by_csrc_.find(current_remote_csrc_[i]);
-    if (map_it == iterator_by_csrc_.end()) {
-      // If it is a new CSRC, append a new object to the end of the list.
-      csrc_sources_.emplace_back(now_ms, current_remote_csrc_[i],
-                                 RtpSourceType::CSRC);
-    } else {
-      // If it is an existing CSRC, move the object to the end of the list.
-      map_it->second->update_timestamp_ms(now_ms);
-      csrc_sources_.splice(csrc_sources_.end(), csrc_sources_, map_it->second);
-    }
-    // Update the unordered_map.
-    iterator_by_csrc_[current_remote_csrc_[i]] = std::prev(csrc_sources_.end());
-  }
-
   // If this is the first packet or the SSRC is changed, insert a new
   // contributing source that uses the SSRC.
   if (ssrc_sources_.empty() || ssrc_sources_.rbegin()->source_id() != ssrc_) {
@@ -345,15 +233,6 @@
 }
 
 void RtpReceiverImpl::RemoveOutdatedSources(int64_t now_ms) {
-  std::list<RtpSource>::iterator it;
-  for (it = csrc_sources_.begin(); it != csrc_sources_.end(); ++it) {
-    if ((now_ms - it->timestamp_ms()) <= kGetSourcesTimeoutMs) {
-      break;
-    }
-    iterator_by_csrc_.erase(it->source_id());
-  }
-  csrc_sources_.erase(csrc_sources_.begin(), it);
-
   std::vector<RtpSource>::iterator vec_it;
   for (vec_it = ssrc_sources_.begin(); vec_it != ssrc_sources_.end();
        ++vec_it) {
diff --git a/modules/rtp_rtcp/source/rtp_receiver_impl.h b/modules/rtp_rtcp/source/rtp_receiver_impl.h
index ec218d3..66265f5 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_impl.h
+++ b/modules/rtp_rtcp/source/rtp_receiver_impl.h
@@ -11,7 +11,6 @@
 #ifndef MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_IMPL_H_
 #define MODULES_RTP_RTCP_SOURCE_RTP_RECEIVER_IMPL_H_
 
-#include <list>
 #include <memory>
 #include <unordered_map>
 #include <vector>
@@ -19,9 +18,9 @@
 #include "absl/types/optional.h"
 #include "modules/rtp_rtcp/include/rtp_receiver.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/contributing_sources.h"
 #include "modules/rtp_rtcp/source/rtp_receiver_strategy.h"
 #include "rtc_base/criticalsection.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -52,25 +51,10 @@
 
   uint32_t SSRC() const override;
 
-  int32_t CSRCs(uint32_t array_of_csrc[kRtpCsrcSize]) const override;
-
-  TelephoneEventHandler* GetTelephoneEventHandler() override;
-
   std::vector<RtpSource> GetSources() const override;
 
-  const std::vector<RtpSource>& ssrc_sources_for_testing() const {
-    return ssrc_sources_;
-  }
-
-  const std::list<RtpSource>& csrc_sources_for_testing() const {
-    return csrc_sources_;
-  }
-
  private:
   void CheckSSRCChanged(const RTPHeader& rtp_header);
-  void CheckCSRC(const WebRtcRTPHeader& rtp_header);
-  int32_t CheckPayloadChanged(const RTPHeader& rtp_header,
-                              PayloadUnion* payload);
 
   void UpdateSources(const absl::optional<uint8_t>& ssrc_audio_level);
   void RemoveOutdatedSources(int64_t now_ms);
@@ -84,9 +68,8 @@
 
   // SSRCs.
   uint32_t ssrc_ RTC_GUARDED_BY(critical_section_rtp_receiver_);
-  uint8_t num_csrcs_ RTC_GUARDED_BY(critical_section_rtp_receiver_);
-  uint32_t current_remote_csrc_[kRtpCsrcSize] RTC_GUARDED_BY(
-      critical_section_rtp_receiver_);
+
+  ContributingSources csrcs_ RTC_GUARDED_BY(critical_section_rtp_receiver_);
 
   // Sequence number and timestamps for the latest in-order packet.
   absl::optional<uint16_t> last_received_sequence_number_
@@ -96,10 +79,7 @@
   int64_t last_received_frame_time_ms_
       RTC_GUARDED_BY(critical_section_rtp_receiver_);
 
-  std::unordered_map<uint32_t, std::list<RtpSource>::iterator>
-      iterator_by_csrc_;
   // The RtpSource objects are sorted chronologically.
-  std::list<RtpSource> csrc_sources_;
   std::vector<RtpSource> ssrc_sources_;
 };
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_receiver_strategy.cc b/modules/rtp_rtcp/source/rtp_receiver_strategy.cc
index bcce3e3..647ecea 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_strategy.cc
+++ b/modules/rtp_rtcp/source/rtp_receiver_strategy.cc
@@ -19,11 +19,4 @@
 
 RTPReceiverStrategy::~RTPReceiverStrategy() = default;
 
-void RTPReceiverStrategy::CheckPayloadChanged(int8_t payload_type,
-                                              PayloadUnion* specific_payload,
-                                              bool* should_discard_changes) {
-  // Default: Keep changes.
-  *should_discard_changes = false;
-}
-
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_receiver_strategy.h b/modules/rtp_rtcp/source/rtp_receiver_strategy.h
index 8b13f18..987af7c 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_strategy.h
+++ b/modules/rtp_rtcp/source/rtp_receiver_strategy.h
@@ -15,14 +15,11 @@
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/rtp_utility.h"
 #include "rtc_base/criticalsection.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
 struct CodecInst;
 
-class TelephoneEventHandler;
-
 // This strategy deals with media-specific RTP packet processing.
 // This class is not thread-safe and must be protected by its caller.
 class RTPReceiverStrategy {
@@ -43,24 +40,6 @@
                                  size_t payload_length,
                                  int64_t timestamp_ms) = 0;
 
-  virtual TelephoneEventHandler* GetTelephoneEventHandler() = 0;
-
-  // Computes the current dead-or-alive state.
-  virtual RTPAliveType ProcessDeadOrAlive(
-      uint16_t last_payload_length) const = 0;
-
-  // Notifies the strategy that we have created a new non-RED audio payload type
-  // in the payload registry.
-  virtual int32_t OnNewPayloadTypeCreated(
-      int payload_type,
-      const SdpAudioFormat& audio_format) = 0;
-
-  // Checks if the payload type has changed, and returns whether we should
-  // reset statistics and/or discard this packet.
-  virtual void CheckPayloadChanged(int8_t payload_type,
-                                   PayloadUnion* specific_payload,
-                                   bool* should_discard_changes);
-
  protected:
   // The data callback is where we should send received payload data.
   // See ParseRtpPacket. This class does not claim ownership of the callback.
diff --git a/modules/rtp_rtcp/source/rtp_receiver_unittest.cc b/modules/rtp_rtcp/source/rtp_receiver_unittest.cc
index e8dccf4..1400288 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_receiver_unittest.cc
@@ -16,7 +16,6 @@
 #include "modules/rtp_rtcp/include/rtp_receiver.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
-#include "modules/rtp_rtcp/source/rtp_receiver_impl.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 
@@ -235,20 +234,11 @@
   header.arrOfCSRCs[0] = kCsrc1;
   EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
       header, kTestPayload, sizeof(kTestPayload), payload_specific));
-  auto* rtp_receiver_impl = static_cast<RtpReceiverImpl*>(rtp_receiver_.get());
-  auto ssrc_sources = rtp_receiver_impl->ssrc_sources_for_testing();
-  ASSERT_EQ(1u, ssrc_sources.size());
-  EXPECT_EQ(kSsrc1, ssrc_sources.begin()->source_id());
-  EXPECT_EQ(RtpSourceType::SSRC, ssrc_sources.begin()->source_type());
-  EXPECT_EQ(fake_clock_.TimeInMilliseconds(),
-            ssrc_sources.begin()->timestamp_ms());
-
-  auto csrc_sources = rtp_receiver_impl->csrc_sources_for_testing();
-  ASSERT_EQ(1u, csrc_sources.size());
-  EXPECT_EQ(kCsrc1, csrc_sources.begin()->source_id());
-  EXPECT_EQ(RtpSourceType::CSRC, csrc_sources.begin()->source_type());
-  EXPECT_EQ(fake_clock_.TimeInMilliseconds(),
-            csrc_sources.begin()->timestamp_ms());
+  now_ms = fake_clock_.TimeInMilliseconds();
+  sources = rtp_receiver_->GetSources();
+  EXPECT_THAT(sources, UnorderedElementsAre(
+                           RtpSource(now_ms, kSsrc1, RtpSourceType::SSRC),
+                           RtpSource(now_ms, kCsrc1, RtpSourceType::CSRC)));
 }
 
 // The audio level from the RTPHeader extension should be stored in the
diff --git a/modules/rtp_rtcp/source/rtp_receiver_video.cc b/modules/rtp_rtcp/source/rtp_receiver_video.cc
index 5e6bf3e..1101bec 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_video.cc
+++ b/modules/rtp_rtcp/source/rtp_receiver_video.cc
@@ -36,13 +36,6 @@
 
 RTPReceiverVideo::~RTPReceiverVideo() {}
 
-int32_t RTPReceiverVideo::OnNewPayloadTypeCreated(
-    int payload_type,
-    const SdpAudioFormat& audio_format) {
-  RTC_NOTREACHED();
-  return 0;
-}
-
 int32_t RTPReceiverVideo::ParseRtpPacket(WebRtcRTPHeader* rtp_header,
                                          const PayloadUnion& specific_payload,
                                          const uint8_t* payload,
@@ -108,13 +101,4 @@
              : -1;
 }
 
-TelephoneEventHandler* RTPReceiverVideo::GetTelephoneEventHandler() {
-  return nullptr;
-}
-
-RTPAliveType RTPReceiverVideo::ProcessDeadOrAlive(
-    uint16_t last_payload_length) const {
-  return kRtpDead;
-}
-
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_receiver_video.h b/modules/rtp_rtcp/source/rtp_receiver_video.h
index d9404d1..46b97f5 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_video.h
+++ b/modules/rtp_rtcp/source/rtp_receiver_video.h
@@ -15,7 +15,6 @@
 #include "modules/rtp_rtcp/source/rtp_receiver_strategy.h"
 #include "modules/rtp_rtcp/source/rtp_utility.h"
 #include "rtc_base/onetimeevent.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -31,13 +30,6 @@
                          size_t packet_length,
                          int64_t timestamp) override;
 
-  TelephoneEventHandler* GetTelephoneEventHandler() override;
-
-  RTPAliveType ProcessDeadOrAlive(uint16_t last_payload_length) const override;
-
-  int32_t OnNewPayloadTypeCreated(int payload_type,
-                                  const SdpAudioFormat& audio_format) override;
-
   void SetPacketOverHead(uint16_t packet_over_head);
 
  private:
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_config.h b/modules/rtp_rtcp/source/rtp_rtcp_config.h
index a24bcdf..6863c4c 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_config.h
+++ b/modules/rtp_rtcp/source/rtp_rtcp_config.h
@@ -13,31 +13,11 @@
 
 // Configuration file for RTP utilities (RTPSender, RTPReceiver ...)
 namespace webrtc {
-enum { NACK_BYTECOUNT_SIZE = 60 };  // size of our NACK history
-// A sanity for the NACK list parsing at the send-side.
-enum { kSendSideNackListSizeSanity = 20000 };
 enum { kDefaultMaxReorderingThreshold = 50 };  // In sequence numbers.
 enum { kRtcpMaxNackFields = 253 };
 
 enum { RTCP_SEND_BEFORE_KEY_FRAME_MS = 100 };
 enum { RTCP_MAX_REPORT_BLOCKS = 31 };  // RFC 3550 page 37
-enum {
-  kRtcpAppCode_DATA_SIZE = 32 * 4
-};  // multiple of 4, this is not a limitation of the size
-enum { RTCP_NUMBER_OF_SR = 60 };
-
-enum { MAX_NUMBER_OF_TEMPORAL_ID = 8 };              // RFC
-enum { MAX_NUMBER_OF_DEPENDENCY_QUALITY_ID = 128 };  // RFC
-enum { MAX_NUMBER_OF_REMB_FEEDBACK_SSRCS = 255 };
-
-enum { BW_HISTORY_SIZE = 35 };
-
-#define MIN_AUDIO_BW_MANAGEMENT_BITRATE 6
-#define MIN_VIDEO_BW_MANAGEMENT_BITRATE 30
-
-enum { RTP_MAX_BURST_SLEEP_TIME = 500 };
-enum { RTP_AUDIO_LEVEL_UNIQUE_ID = 0xbede };
-enum { RTP_MAX_PACKETS_PER_FRAME = 512 };  // must be multiple of 32
 }  // namespace webrtc
 
 #endif  // MODULES_RTP_RTCP_SOURCE_RTP_RTCP_CONFIG_H_
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
index 5071eee..2de6175 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
@@ -327,7 +327,7 @@
   header.sequenceNumber = 123;
   header.ssrc = kSenderSsrc;
   header.headerLength = 12;
-  receiver_.receive_statistics_->IncomingPacket(header, 100, false);
+  receiver_.receive_statistics_->IncomingPacket(header, 100);
 
   // Send Frame before sending an SR.
   SendFrame(&sender_, kBaseLayerTid);
diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc
index e0347f0..ba04b5c 100644
--- a/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/modules/rtp_rtcp/source/rtp_sender.cc
@@ -160,7 +160,9 @@
       overhead_observer_(overhead_observer),
       populate_network2_timestamp_(populate_network2_timestamp),
       send_side_bwe_with_overhead_(
-          webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")) {
+          webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
+      unlimited_retransmission_experiment_(
+          field_trial::IsEnabled("WebRTC-UnlimitedScreenshareRetransmission")) {
   // This random initialization is not intended to be cryptographic strong.
   timestamp_offset_ = random_.Rand<uint32_t>();
   // Random start, 16 bits. Can't be 0.
@@ -412,6 +414,11 @@
       *transport_frame_id_out = rtp_timestamp;
     if (!sending_media_)
       return true;
+
+    // Cache video content type.
+    if (!audio_configured_ && rtp_header) {
+      video_content_type_ = rtp_header->content_type;
+    }
   }
   VideoCodecType video_type = kVideoCodecGeneric;
   if (CheckPayloadType(payload_type, &video_type) != 0) {
@@ -643,10 +650,21 @@
 
   const int32_t packet_size = static_cast<int32_t>(stored_packet->payload_size);
 
+  // Skip retransmission rate check if sending screenshare and the experiment
+  // is on.
+  bool skip_retransmission_rate_limit;
+  {
+    rtc::CritScope lock(&send_critsect_);
+    skip_retransmission_rate_limit =
+        unlimited_retransmission_experiment_ && video_content_type_ &&
+        videocontenttypehelpers::IsScreenshare(*video_content_type_);
+  }
+
   RTC_DCHECK(retransmission_rate_limiter_);
   // Check if we're overusing retransmission bitrate.
   // TODO(sprang): Add histograms for nack success or failure reasons.
-  if (!retransmission_rate_limiter_->TryUseRate(packet_size)) {
+  if (!skip_retransmission_rate_limit &&
+      !retransmission_rate_limiter_->TryUseRate(packet_size)) {
     return -1;
   }
 
diff --git a/modules/rtp_rtcp/source/rtp_sender.h b/modules/rtp_rtcp/source/rtp_sender.h
index 5ff4a0f..7f66d24 100644
--- a/modules/rtp_rtcp/source/rtp_sender.h
+++ b/modules/rtp_rtcp/source/rtp_sender.h
@@ -20,6 +20,7 @@
 #include "absl/types/optional.h"
 #include "api/array_view.h"
 #include "api/call/transport.h"
+#include "api/video/video_content_type.h"
 #include "common_types.h"  // NOLINT(build/include)
 #include "modules/rtp_rtcp/include/flexfec_sender.h"
 #include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
@@ -338,6 +339,11 @@
 
   const bool send_side_bwe_with_overhead_;
 
+  const bool unlimited_retransmission_experiment_;
+
+  absl::optional<VideoContentType> video_content_type_
+      RTC_GUARDED_BY(send_critsect_);
+
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RTPSender);
 };
 
diff --git a/modules/rtp_rtcp/source/rtp_sender_audio.h b/modules/rtp_rtcp/source/rtp_sender_audio.h
index 16648cd..63dfc2b 100644
--- a/modules/rtp_rtcp/source/rtp_sender_audio.h
+++ b/modules/rtp_rtcp/source/rtp_sender_audio.h
@@ -19,7 +19,6 @@
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/criticalsection.h"
 #include "rtc_base/onetimeevent.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
index 1d0ddaf..d143c87 100644
--- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
@@ -34,7 +34,6 @@
 #include "test/gmock.h"
 #include "test/gtest.h"
 #include "test/mock_transport.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -245,9 +244,10 @@
     EXPECT_EQ(0, rtp_sender_->RegisterPayload(payload_name, kPayloadType, 90000,
                                               0, 1500));
 
+    RTPVideoHeader video_header;
     EXPECT_TRUE(rtp_sender_->SendOutgoingData(
         kVideoFrameKey, kPayloadType, kTimestamp, kCaptureTimeMs, kPayloadData,
-        sizeof(kPayloadData), nullptr, nullptr, nullptr,
+        sizeof(kPayloadData), nullptr, &video_header, nullptr,
         kDefaultExpectedRetransmissionTimeMs));
   }
 };
@@ -969,9 +969,10 @@
   uint8_t payload[] = {47, 11, 32, 93, 89};
 
   // Send keyframe
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   auto sent_payload = transport_.last_sent_packet().payload();
   uint8_t generic_header = sent_payload[0];
@@ -986,7 +987,7 @@
 
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   sent_payload = transport_.last_sent_packet().payload();
   generic_header = sent_payload[0];
@@ -1102,7 +1103,6 @@
   EXPECT_EQ(0, rtp_sender_->RegisterPayload(payload_name, kPayloadType, 90000,
                                             0, 1500));
   RTPVideoHeader video_header;
-  memset(&video_header, 0, sizeof(RTPVideoHeader));
   video_header.video_timing.flags = VideoSendTiming::kTriggeredByTimer;
   EXPECT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameKey, kPayloadType, kTimestamp, kCaptureTimeMs, kPayloadData,
@@ -1301,9 +1301,10 @@
   EXPECT_CALL(mock_paced_sender_, InsertPacket(_, _, _, _, _, _))
       .Times(::testing::AtLeast(2));
 
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   EXPECT_EQ(1U, callback.num_calls_);
   EXPECT_EQ(ssrc, callback.ssrc_);
@@ -1312,7 +1313,7 @@
 
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   EXPECT_EQ(2U, callback.num_calls_);
   EXPECT_EQ(ssrc, callback.ssrc_);
@@ -1375,10 +1376,11 @@
   rtp_sender_->ProcessBitrate();
 
   // Send a few frames.
+  RTPVideoHeader video_header;
   for (uint32_t i = 0; i < kNumPackets; ++i) {
     ASSERT_TRUE(rtp_sender_->SendOutgoingData(
         kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload),
-        nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+        nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
     fake_clock_.AdvanceTimeMilliseconds(kPacketInterval);
   }
 
@@ -1459,9 +1461,10 @@
   rtp_sender_->RegisterRtpStatisticsCallback(&callback);
 
   // Send a frame.
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameKey, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
   StreamDataCounters expected;
   expected.transmitted.payload_bytes = 6;
   expected.transmitted.header_bytes = 12;
@@ -1503,7 +1506,7 @@
   rtp_sender_->SetFecParameters(fec_params, fec_params);
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameDelta, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
   expected.transmitted.payload_bytes = 40;
   expected.transmitted.header_bytes = 60;
   expected.transmitted.packets = 5;
@@ -1520,9 +1523,10 @@
                                             0, 1500));
   uint8_t payload[] = {47, 11, 32, 93, 89};
 
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kAudioFrameCN, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   auto sent_payload = transport_.last_sent_packet().payload();
   EXPECT_THAT(sent_payload, ElementsAreArray(payload));
@@ -1539,9 +1543,10 @@
                                             0, 1500));
   uint8_t payload[] = {47, 11, 32, 93, 89};
 
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kAudioFrameCN, payload_type, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   auto sent_payload = transport_.last_sent_packet().payload();
   EXPECT_THAT(sent_payload, ElementsAreArray(payload));
@@ -1578,22 +1583,23 @@
   // During start, it takes the starting timestamp as last sent timestamp.
   // The duration is calculated as the difference of current and last sent
   // timestamp. So for first call it will skip since the duration is zero.
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kEmptyFrame, kPayloadType, capture_time_ms, 0, nullptr, 0, nullptr,
-      nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
   // DTMF Sample Length is (Frequency/1000) * Duration.
   // So in this case, it is (8000/1000) * 500 = 4000.
   // Sending it as two packets.
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kEmptyFrame, kPayloadType, capture_time_ms + 2000, 0, nullptr, 0, nullptr,
-      nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   // Marker Bit should be set to 1 for first packet.
   EXPECT_TRUE(transport_.last_sent_packet().Marker());
 
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kEmptyFrame, kPayloadType, capture_time_ms + 4000, 0, nullptr, 0, nullptr,
-      nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
   // Marker Bit should be set to 0 for rest of the packets.
   EXPECT_FALSE(transport_.last_sent_packet().Marker());
 }
@@ -1610,9 +1616,10 @@
                                             0, 1500));
   uint8_t payload[] = {47, 11, 32, 93, 89};
 
+  RTPVideoHeader video_header;
   ASSERT_TRUE(rtp_sender_->SendOutgoingData(
       kVideoFrameKey, kPayloadType, 1234, 4321, payload, sizeof(payload),
-      nullptr, nullptr, nullptr, kDefaultExpectedRetransmissionTimeMs));
+      nullptr, &video_header, nullptr, kDefaultExpectedRetransmissionTimeMs));
 
   // Will send 2 full-size padding packets.
   rtp_sender_->TimeToSendPadding(1, PacedPacketInfo());
@@ -1810,8 +1817,9 @@
 
 TEST_P(RtpSenderVideoTest, RetransmissionTypesH264) {
   RTPVideoHeader header;
+  header.video_type_header.emplace<RTPVideoHeaderH264>().packetization_mode =
+      H264PacketizationMode::NonInterleaved;
   header.codec = kVideoCodecH264;
-  header.h264().packetization_mode = H264PacketizationMode::NonInterleaved;
 
   EXPECT_EQ(kDontRetransmit,
             rtp_sender_video_->GetStorageType(
@@ -1892,8 +1900,9 @@
   RTPVideoHeader header;
   header.codec = kVideoCodecVP9;
 
+  auto& vp9_header = header.video_type_header.emplace<RTPVideoHeaderVP9>();
   for (int tid = 1; tid <= kMaxTemporalStreams; ++tid) {
-    header.vp9().temporal_idx = tid;
+    vp9_header.temporal_idx = tid;
 
     EXPECT_EQ(kDontRetransmit, rtp_sender_video_->GetStorageType(
                                    header, kRetransmitOff,
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc
index a7f3df0..bf8150d 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -280,6 +280,7 @@
                                int64_t expected_retransmission_time_ms) {
   if (payload_size == 0)
     return false;
+  RTC_CHECK(video_header);
 
   // Create header that will be reused in all packets.
   std::unique_ptr<RtpPacketToSend> rtp_header = rtp_sender_->AllocatePacket();
@@ -303,24 +304,22 @@
     // packet in each group of packets which make up another type of frame
     // (e.g. a P-Frame) only if the current value is different from the previous
     // value sent.
-    if (video_header) {
-      // Set rotation when key frame or when changed (to follow standard).
-      // Or when different from 0 (to follow current receiver implementation).
-      VideoRotation current_rotation = video_header->rotation;
-      if (frame_type == kVideoFrameKey || current_rotation != last_rotation_ ||
-          current_rotation != kVideoRotation_0)
-        last_packet->SetExtension<VideoOrientation>(current_rotation);
-      last_rotation_ = current_rotation;
-      // Report content type only for key frames.
-      if (frame_type == kVideoFrameKey &&
-          video_header->content_type != VideoContentType::UNSPECIFIED) {
-        last_packet->SetExtension<VideoContentTypeExtension>(
-            video_header->content_type);
-      }
-      if (video_header->video_timing.flags != VideoSendTiming::kInvalid) {
-        last_packet->SetExtension<VideoTimingExtension>(
-            video_header->video_timing);
-      }
+    // Set rotation when key frame or when changed (to follow standard).
+    // Or when different from 0 (to follow current receiver implementation).
+    VideoRotation current_rotation = video_header->rotation;
+    if (frame_type == kVideoFrameKey || current_rotation != last_rotation_ ||
+        current_rotation != kVideoRotation_0)
+      last_packet->SetExtension<VideoOrientation>(current_rotation);
+    last_rotation_ = current_rotation;
+    // Report content type only for key frames.
+    if (frame_type == kVideoFrameKey &&
+        video_header->content_type != VideoContentType::UNSPECIFIED) {
+      last_packet->SetExtension<VideoContentTypeExtension>(
+          video_header->content_type);
+    }
+    if (video_header->video_timing.flags != VideoSendTiming::kInvalid) {
+      last_packet->SetExtension<VideoTimingExtension>(
+          video_header->video_timing);
     }
 
     // FEC settings.
@@ -347,16 +346,17 @@
   size_t last_packet_reduction_len =
       last_packet->headers_size() - rtp_header->headers_size();
 
-  std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create(
-      video_type, max_data_payload_length, last_packet_reduction_len,
-      video_header, frame_type));
+  RtpPacketizer::PayloadSizeLimits limits;
+  limits.max_payload_len = max_data_payload_length;
+  limits.last_packet_reduction_len = last_packet_reduction_len;
+  std::unique_ptr<RtpPacketizer> packetizer = RtpPacketizer::Create(
+      video_type, rtc::MakeArrayView(payload_data, payload_size), limits,
+      *video_header, frame_type, fragmentation);
 
-  const uint8_t temporal_id =
-      video_header ? GetTemporalId(*video_header) : kNoTemporalIdx;
+  const uint8_t temporal_id = GetTemporalId(*video_header);
   StorageType storage = GetStorageType(temporal_id, retransmission_settings,
                                        expected_retransmission_time_ms);
-  size_t num_packets =
-      packetizer->SetPayloadData(payload_data, payload_size, fragmentation);
+  size_t num_packets = packetizer->NumPackets();
 
   if (num_packets == 0)
     return false;
@@ -471,7 +471,8 @@
     case kVideoCodecVP8:
       return header.vp8().temporalIdx;
     case kVideoCodecVP9:
-      return header.vp9().temporal_idx;
+      return absl::get<RTPVideoHeaderVP9>(header.video_type_header)
+          .temporal_idx;
     default:
       return kNoTemporalIdx;
   }
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.h b/modules/rtp_rtcp/source/rtp_sender_video.h
index 08724c7..ce7be16 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.h
+++ b/modules/rtp_rtcp/source/rtp_sender_video.h
@@ -27,7 +27,6 @@
 #include "rtc_base/rate_statistics.h"
 #include "rtc_base/sequenced_task_checker.h"
 #include "rtc_base/thread_annotations.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 class RtpPacketizer;
diff --git a/modules/rtp_rtcp/source/rtp_utility.h b/modules/rtp_rtcp/source/rtp_utility.h
index 51732df..762f964 100644
--- a/modules/rtp_rtcp/source/rtp_utility.h
+++ b/modules/rtp_rtcp/source/rtp_utility.h
@@ -19,7 +19,6 @@
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "modules/rtp_rtcp/source/rtp_rtcp_config.h"
 #include "rtc_base/deprecation.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/rtp_video_header.cc b/modules/rtp_rtcp/source/rtp_video_header.cc
index 020a52e..a3ee8ba 100644
--- a/modules/rtp_rtcp/source/rtp_video_header.cc
+++ b/modules/rtp_rtcp/source/rtp_video_header.cc
@@ -12,16 +12,13 @@
 
 namespace webrtc {
 
-RTPVideoHeader::RTPVideoHeader()
-    : width(),
-      height(),
-      rotation(),
-      playout_delay(),
-      content_type(),
-      video_timing(),
-      is_first_packet_in_frame(),
-      simulcastIdx(),
-      codec() {}
+RTPVideoHeader::RTPVideoHeader() : playout_delay(), video_timing() {}
 RTPVideoHeader::RTPVideoHeader(const RTPVideoHeader& other) = default;
+RTPVideoHeader::~RTPVideoHeader() = default;
+
+RTPVideoHeader::GenericDescriptorInfo::GenericDescriptorInfo() = default;
+RTPVideoHeader::GenericDescriptorInfo::GenericDescriptorInfo(
+    const GenericDescriptorInfo& other) = default;
+RTPVideoHeader::GenericDescriptorInfo::~GenericDescriptorInfo() = default;
 
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_video_header.h b/modules/rtp_rtcp/source/rtp_video_header.h
index 49e2d29..520f4d4 100644
--- a/modules/rtp_rtcp/source/rtp_video_header.h
+++ b/modules/rtp_rtcp/source/rtp_video_header.h
@@ -10,6 +10,7 @@
 #ifndef MODULES_RTP_RTCP_SOURCE_RTP_VIDEO_HEADER_H_
 #define MODULES_RTP_RTCP_SOURCE_RTP_VIDEO_HEADER_H_
 
+#include "absl/container/inlined_vector.h"
 #include "absl/types/variant.h"
 #include "api/video/video_content_type.h"
 #include "api/video/video_rotation.h"
@@ -24,9 +25,23 @@
     absl::variant<RTPVideoHeaderVP8, RTPVideoHeaderVP9, RTPVideoHeaderH264>;
 
 struct RTPVideoHeader {
+  struct GenericDescriptorInfo {
+    GenericDescriptorInfo();
+    GenericDescriptorInfo(const GenericDescriptorInfo& other);
+    ~GenericDescriptorInfo();
+
+    int64_t frame_id = 0;
+    int spatial_index = 0;
+    int temporal_index = 0;
+    absl::InlinedVector<int64_t, 5> dependencies;
+    absl::InlinedVector<int, 5> higher_spatial_layers;
+  };
+
   RTPVideoHeader();
   RTPVideoHeader(const RTPVideoHeader& other);
 
+  ~RTPVideoHeader();
+
   // TODO(philipel): Remove when downstream projects have been updated.
   RTPVideoHeaderVP8& vp8() {
     if (!absl::holds_alternative<RTPVideoHeaderVP8>(video_type_header))
@@ -41,44 +56,19 @@
 
     return absl::get<RTPVideoHeaderVP8>(video_type_header);
   }
-  // TODO(philipel): Remove when downstream projects have been updated.
-  RTPVideoHeaderVP9& vp9() {
-    if (!absl::holds_alternative<RTPVideoHeaderVP9>(video_type_header))
-      video_type_header.emplace<RTPVideoHeaderVP9>();
 
-    return absl::get<RTPVideoHeaderVP9>(video_type_header);
-  }
-  // TODO(philipel): Remove when downstream projects have been updated.
-  const RTPVideoHeaderVP9& vp9() const {
-    if (!absl::holds_alternative<RTPVideoHeaderVP9>(video_type_header))
-      video_type_header.emplace<RTPVideoHeaderVP9>();
+  absl::optional<GenericDescriptorInfo> generic;
 
-    return absl::get<RTPVideoHeaderVP9>(video_type_header);
-  }
-  // TODO(philipel): Remove when downstream projects have been updated.
-  RTPVideoHeaderH264& h264() {
-    if (!absl::holds_alternative<RTPVideoHeaderH264>(video_type_header))
-      video_type_header.emplace<RTPVideoHeaderH264>();
+  uint16_t width = 0;
+  uint16_t height = 0;
+  VideoRotation rotation = VideoRotation::kVideoRotation_0;
+  VideoContentType content_type = VideoContentType::UNSPECIFIED;
+  bool is_first_packet_in_frame = false;
+  uint8_t simulcastIdx = 0;
+  VideoCodecType codec = VideoCodecType::kVideoCodecGeneric;
 
-    return absl::get<RTPVideoHeaderH264>(video_type_header);
-  }
-  // TODO(philipel): Remove when downstream projects have been updated.
-  const RTPVideoHeaderH264& h264() const {
-    if (!absl::holds_alternative<RTPVideoHeaderH264>(video_type_header))
-      video_type_header.emplace<RTPVideoHeaderH264>();
-
-    return absl::get<RTPVideoHeaderH264>(video_type_header);
-  }
-
-  uint16_t width;
-  uint16_t height;
-  VideoRotation rotation;
   PlayoutDelay playout_delay;
-  VideoContentType content_type;
   VideoSendTiming video_timing;
-  bool is_first_packet_in_frame;
-  uint8_t simulcastIdx;
-  VideoCodecType codec;
   // TODO(philipel): remove mutable when downstream projects have been updated.
   mutable RTPVideoTypeHeader video_type_header;
 };
diff --git a/modules/rtp_rtcp/source/tmmbr_help.h b/modules/rtp_rtcp/source/tmmbr_help.h
index 46ce845..91aeaf4 100644
--- a/modules/rtp_rtcp/source/tmmbr_help.h
+++ b/modules/rtp_rtcp/source/tmmbr_help.h
@@ -13,7 +13,6 @@
 
 #include <vector>
 #include "modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/rtp_rtcp/source/ulpfec_receiver_impl.h b/modules/rtp_rtcp/source/ulpfec_receiver_impl.h
index 7dbc7dd..96367dc 100644
--- a/modules/rtp_rtcp/source/ulpfec_receiver_impl.h
+++ b/modules/rtp_rtcp/source/ulpfec_receiver_impl.h
@@ -18,7 +18,6 @@
 #include "modules/rtp_rtcp/include/ulpfec_receiver.h"
 #include "modules/rtp_rtcp/source/forward_error_correction.h"
 #include "rtc_base/criticalsection.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/modules/third_party/fft/BUILD.gn b/modules/third_party/fft/BUILD.gn
new file mode 100644
index 0000000..ad51341
--- /dev/null
+++ b/modules/third_party/fft/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright (c) 2018 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.
+
+import("../../../webrtc.gni")
+
+rtc_source_set("fft") {
+  sources = [
+    "fft.c",
+    "fft.h",
+  ]
+}
diff --git a/modules/third_party/fft/LICENSE b/modules/third_party/fft/LICENSE
new file mode 100644
index 0000000..c0a7805
--- /dev/null
+++ b/modules/third_party/fft/LICENSE
@@ -0,0 +1,25 @@
+/*
+ * Copyright(c)1995,97 Mark Olesen <olesen@me.QueensU.CA>
+ *    Queen's Univ at Kingston (Canada)
+ *
+ * Permission to use, copy, modify, and distribute this software for
+ * any purpose without fee is hereby granted, provided that this
+ * entire notice is included in all copies of any software which is
+ * or includes a copy or modification of this software and in all
+ * copies of the supporting documentation for such software.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR QUEEN'S
+ * UNIVERSITY AT KINGSTON MAKES ANY REPRESENTATION OR WARRANTY OF ANY
+ * KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
+ * FITNESS FOR ANY PARTICULAR PURPOSE.
+ *
+ * All of which is to say that you can do what you like with this
+ * source code provided you don't try to sell it as your own and you
+ * include an unaltered copy of this message (including the
+ * copyright).
+ *
+ * It is also implicitly understood that bug fixes and improvements
+ * should make their way back to the general Internet community so
+ * that everyone benefits.
+ */
diff --git a/modules/third_party/fft/README.chromium b/modules/third_party/fft/README.chromium
new file mode 100644
index 0000000..94d20d4
--- /dev/null
+++ b/modules/third_party/fft/README.chromium
@@ -0,0 +1,12 @@
+Name: fft
+Short Name: fft
+URL:
+Version: 0
+Date: 2018-07-26
+License: Custom license
+License File: LICENSE
+Security Critical: yes
+
+Description:
+Multivariate complex Fourier transform, computed in place
+using mixed-radix Fast Fourier Transform algorithm.
diff --git a/modules/audio_coding/codecs/isac/main/source/fft.c b/modules/third_party/fft/fft.c
similarity index 99%
rename from modules/audio_coding/codecs/isac/main/source/fft.c
rename to modules/third_party/fft/fft.c
index a3cbd5e..7260462 100644
--- a/modules/audio_coding/codecs/isac/main/source/fft.c
+++ b/modules/third_party/fft/fft.c
@@ -127,7 +127,7 @@
 #include <stdlib.h>
 #include <math.h>
 
-#include "modules/audio_coding/codecs/isac/main/source/fft.h"
+#include "modules/third_party/fft/fft.h"
 
 /* double precision routine */
 static int
@@ -211,7 +211,7 @@
     {
       max_factors = (int)nSpan;
     }
-    if ((int)nSpan > max_perm) 
+    if ((int)nSpan > max_perm)
     {
       max_perm = (int)nSpan;
     }
@@ -415,7 +415,7 @@
   }
 
   /* test that mfactors is in range */
-  if (mfactor > NFACTOR)
+  if (mfactor > FFT_NFACTOR)
   {
     return -1;
   }
diff --git a/modules/audio_coding/codecs/isac/main/source/fft.h b/modules/third_party/fft/fft.h
similarity index 73%
rename from modules/audio_coding/codecs/isac/main/source/fft.h
rename to modules/third_party/fft/fft.h
index 34e5f94..f8f8b6f 100644
--- a/modules/audio_coding/codecs/isac/main/source/fft.h
+++ b/modules/third_party/fft/fft.h
@@ -2,7 +2,7 @@
  *  Copyright (c) 2011 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
+ *  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.
@@ -27,10 +27,23 @@
  * See the comments in the code for correct usage!
  */
 
-#ifndef MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FFT_H_
-#define MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FFT_H_
+#ifndef MODULES_THIRD_PARTY_FFT_FFT_H_
+#define MODULES_THIRD_PARTY_FFT_FFT_H_
 
-#include "modules/audio_coding/codecs/isac/main/source/structs.h"
+#define FFT_MAXFFTSIZE 2048
+#define FFT_NFACTOR 11
+
+typedef struct {
+  unsigned int SpaceAlloced;
+  unsigned int MaxPermAlloced;
+  double Tmp0[FFT_MAXFFTSIZE];
+  double Tmp1[FFT_MAXFFTSIZE];
+  double Tmp2[FFT_MAXFFTSIZE];
+  double Tmp3[FFT_MAXFFTSIZE];
+  int Perm[FFT_MAXFFTSIZE];
+  int factor[FFT_NFACTOR];
+
+} FFTstr;
 
 /* double precision routine */
 
@@ -42,4 +55,4 @@
                      double scaling,
                      FFTstr* fftstate);
 
-#endif /* MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_SOURCE_FFT_H_ */
+#endif /* MODULES_THIRD_PARTY_FFT_FFT_H_ */
diff --git a/modules/third_party/fft/module.mk b/modules/third_party/fft/module.mk
new file mode 100644
index 0000000..37c23f4
--- /dev/null
+++ b/modules/third_party/fft/module.mk
@@ -0,0 +1,5 @@
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+include common.mk
diff --git a/modules/third_party/g711/BUILD.gn b/modules/third_party/g711/BUILD.gn
new file mode 100644
index 0000000..ca1ccf3
--- /dev/null
+++ b/modules/third_party/g711/BUILD.gn
@@ -0,0 +1,17 @@
+# Copyright (c) 2018 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.
+
+import("../../../webrtc.gni")
+
+rtc_source_set("g711_3p") {
+  poisonous = [ "audio_codecs" ]
+  sources = [
+    "g711.c",
+    "g711.h",
+  ]
+}
diff --git a/modules/third_party/g711/LICENSE b/modules/third_party/g711/LICENSE
new file mode 100644
index 0000000..3cdf910
--- /dev/null
+++ b/modules/third_party/g711/LICENSE
@@ -0,0 +1,14 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g711.h - In line A-law and u-law conversion routines
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2001 Steve Underwood
+ *
+ *  Despite my general liking of the GPL, I place this code in the
+ *  public domain for the benefit of all mankind - even the slimy
+ *  ones who might try to proprietize my work and use it to my
+ *  detriment.
+ */
diff --git a/modules/third_party/g711/README.chromium b/modules/third_party/g711/README.chromium
new file mode 100644
index 0000000..1baa263
--- /dev/null
+++ b/modules/third_party/g711/README.chromium
@@ -0,0 +1,11 @@
+Name: In line A-law and u-law conversion routines
+Short Name: g711
+URL:
+Version: 0
+Date: 2018-06-25
+License: Custom license
+License File: LICENSE
+Security Critical: yes
+
+Description:
+In line A-law and u-law conversion routines
diff --git a/modules/audio_coding/codecs/g711/g711.c b/modules/third_party/g711/g711.c
similarity index 98%
rename from modules/audio_coding/codecs/g711/g711.c
rename to modules/third_party/g711/g711.c
index 46a21f4..b7ae6bb 100644
--- a/modules/audio_coding/codecs/g711/g711.c
+++ b/modules/third_party/g711/g711.c
@@ -20,7 +20,7 @@
  * -Added option to run encoder bitexact with ITU-T reference implementation
  */
 
-#include "modules/audio_coding/codecs/g711/g711.h"
+#include "modules/third_party/g711/g711.h"
 
 /* Copied from the CCITT G.711 specification */
 static const uint8_t ulaw_to_alaw_table[256] = {
diff --git a/modules/audio_coding/codecs/g711/g711.h b/modules/third_party/g711/g711.h
similarity index 98%
rename from modules/audio_coding/codecs/g711/g711.h
rename to modules/third_party/g711/g711.h
index ac43377..4eef42c 100644
--- a/modules/audio_coding/codecs/g711/g711.h
+++ b/modules/third_party/g711/g711.h
@@ -43,8 +43,8 @@
 specification by other means.
 */
 
-#if !defined(_G711_H_)
-#define _G711_H_
+#ifndef MODULES_THIRD_PARTY_G711_G711_H_
+#define MODULES_THIRD_PARTY_G711_G711_H_
 
 #ifdef __cplusplus
 extern "C" {
@@ -347,4 +347,4 @@
 }
 #endif
 
-#endif
+#endif /* MODULES_THIRD_PARTY_G711_G711_H_ */
diff --git a/modules/third_party/g722/BUILD.gn b/modules/third_party/g722/BUILD.gn
new file mode 100644
index 0000000..a1bfe89
--- /dev/null
+++ b/modules/third_party/g722/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright (c) 2018 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.
+
+import("../../../webrtc.gni")
+
+rtc_source_set("g722_3p") {
+  poisonous = [ "audio_codecs" ]
+  sources = [
+    "g722_decode.c",
+    "g722_enc_dec.h",
+    "g722_encode.c",
+  ]
+}
diff --git a/modules/third_party/g722/LICENSE b/modules/third_party/g722/LICENSE
new file mode 100644
index 0000000..ea6308f
--- /dev/null
+++ b/modules/third_party/g722/LICENSE
@@ -0,0 +1,20 @@
+/*
+ * SpanDSP - a series of DSP components for telephony
+ *
+ * g722_decode.c - The ITU G.722 codec, decode part.
+ *
+ * Written by Steve Underwood <steveu@coppice.org>
+ *
+ * Copyright (C) 2005 Steve Underwood
+ *
+ *  Despite my general liking of the GPL, I place my own contributions
+ *  to this code in the public domain for the benefit of all mankind -
+ *  even the slimy ones who might try to proprietize my work and use it
+ *  to my detriment.
+ *
+ * Based in part on a single channel G.722 codec which is:
+ *
+ * Copyright (c) CMU 1993
+ * Computer Science, Speech Group
+ * Chengxiang Lu and Alex Hauptmann
+ */
diff --git a/modules/third_party/g722/README.chromium b/modules/third_party/g722/README.chromium
new file mode 100644
index 0000000..c427ed8
--- /dev/null
+++ b/modules/third_party/g722/README.chromium
@@ -0,0 +1,11 @@
+Name: The ITU G.722 codec, encode and decode part.
+Short Name: g722
+URL:
+Version: 0
+Date: 2018-06-25
+License: Custom license
+License File: LICENSE
+Security Critical: yes
+
+Description:
+The ITU G.722 codec, encode and decode part.
diff --git a/modules/audio_coding/codecs/g722/g722_decode.c b/modules/third_party/g722/g722_decode.c
similarity index 99%
rename from modules/audio_coding/codecs/g722/g722_decode.c
rename to modules/third_party/g722/g722_decode.c
index d638f50..012aeb5 100644
--- a/modules/audio_coding/codecs/g722/g722_decode.c
+++ b/modules/third_party/g722/g722_decode.c
@@ -34,7 +34,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "modules/audio_coding/codecs/g722/g722_enc_dec.h"
+#include "modules/third_party/g722/g722_enc_dec.h"
 
 #if !defined(FALSE)
 #define FALSE 0
diff --git a/modules/audio_coding/codecs/g722/g722_enc_dec.h b/modules/third_party/g722/g722_enc_dec.h
similarity index 96%
rename from modules/audio_coding/codecs/g722/g722_enc_dec.h
rename to modules/third_party/g722/g722_enc_dec.h
index cc3aa98..898fa27 100644
--- a/modules/audio_coding/codecs/g722/g722_enc_dec.h
+++ b/modules/third_party/g722/g722_enc_dec.h
@@ -27,8 +27,8 @@
 
 /*! \file */
 
-#if !defined(_G722_ENC_DEC_H_)
-#define _G722_ENC_DEC_H_
+#ifndef MODULES_THIRD_PARTY_G722_G722_H_
+#define MODULES_THIRD_PARTY_G722_G722_H_
 
 #include <stdint.h>
 
@@ -150,4 +150,4 @@
 }
 #endif
 
-#endif
+#endif /* MODULES_THIRD_PARTY_G722_G722_H_ */
diff --git a/modules/audio_coding/codecs/g722/g722_encode.c b/modules/third_party/g722/g722_encode.c
similarity index 99%
rename from modules/audio_coding/codecs/g722/g722_encode.c
rename to modules/third_party/g722/g722_encode.c
index cd19252..10a5bcf 100644
--- a/modules/audio_coding/codecs/g722/g722_encode.c
+++ b/modules/third_party/g722/g722_encode.c
@@ -34,7 +34,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "modules/audio_coding/codecs/g722/g722_enc_dec.h"
+#include "modules/third_party/g722/g722_enc_dec.h"
 
 #if !defined(FALSE)
 #define FALSE 0
diff --git a/modules/third_party/module.mk b/modules/third_party/module.mk
new file mode 100644
index 0000000..37c23f4
--- /dev/null
+++ b/modules/third_party/module.mk
@@ -0,0 +1,5 @@
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+include common.mk
diff --git a/modules/third_party/portaudio/BUILD.gn b/modules/third_party/portaudio/BUILD.gn
new file mode 100644
index 0000000..1f701db
--- /dev/null
+++ b/modules/third_party/portaudio/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright (c) 2018 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.
+
+import("../../../webrtc.gni")
+
+rtc_source_set("mac_portaudio") {
+  visibility = [ "../../audio_device:*" ]
+  sources = [
+    "pa_memorybarrier.h",
+    "pa_ringbuffer.c",
+    "pa_ringbuffer.h",
+  ]
+}
diff --git a/modules/third_party/portaudio/LICENSE b/modules/third_party/portaudio/LICENSE
new file mode 100644
index 0000000..6ccaca2
--- /dev/null
+++ b/modules/third_party/portaudio/LICENSE
@@ -0,0 +1,91 @@
+/*
+ * $Id: pa_memorybarrier.h 1240 2007-07-17 13:05:07Z bjornroche $
+ * Portable Audio I/O Library
+ * Memory barrier utilities
+ *
+ * Author: Bjorn Roche, XO Audio, LLC
+ *
+ * This program uses the PortAudio Portable Audio Library.
+ * For more information see: http://www.portaudio.com
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+/*
+ * $Id: pa_ringbuffer.c 1421 2009-11-18 16:09:05Z bjornroche $
+ * Portable Audio I/O Library
+ * Ring Buffer utility.
+ *
+ * Author: Phil Burk, http://www.softsynth.com
+ * modified for SMP safety on Mac OS X by Bjorn Roche
+ * modified for SMP safety on Linux by Leland Lucius
+ * also, allowed for const where possible
+ * modified for multiple-byte-sized data elements by Sven Fischer
+ *
+ * Note that this is safe only for a single-thread reader and a
+ * single-thread writer.
+ *
+ * This program uses the PortAudio Portable Audio Library.
+ * For more information see: http://www.portaudio.com
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
diff --git a/modules/third_party/portaudio/README.chromium b/modules/third_party/portaudio/README.chromium
new file mode 100644
index 0000000..7a15b2e
--- /dev/null
+++ b/modules/third_party/portaudio/README.chromium
@@ -0,0 +1,12 @@
+Name: Portaudio library for mac
+Short Name: portaudio
+URL: https://app.assembla.com/spaces/portaudio/git/source/master/src/common
+Version: 0
+Date: 2018-02-01
+License: Custom license
+License File: LICENSE
+Security Critical: yes
+
+Description:
+Part of portaudio library to operate with memory barriers and ring buffer.
+
diff --git a/modules/third_party/portaudio/pa_memorybarrier.h b/modules/third_party/portaudio/pa_memorybarrier.h
new file mode 100644
index 0000000..c1040d1
--- /dev/null
+++ b/modules/third_party/portaudio/pa_memorybarrier.h
@@ -0,0 +1,132 @@
+/*
+ * $Id: pa_memorybarrier.h 1240 2007-07-17 13:05:07Z bjornroche $
+ * Portable Audio I/O Library
+ * Memory barrier utilities
+ *
+ * Author: Bjorn Roche, XO Audio, LLC
+ *
+ * This program uses the PortAudio Portable Audio Library.
+ * For more information see: http://www.portaudio.com
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+/**
+ @file pa_memorybarrier.h
+ @ingroup common_src
+*/
+
+/****************
+ * Some memory barrier primitives based on the system.
+ * right now only OS X, FreeBSD, and Linux are supported. In addition to
+ *providing memory barriers, these functions should ensure that data cached in
+ *registers is written out to cache where it can be snooped by other CPUs. (ie,
+ *the volatile keyword should not be required)
+ *
+ * the primitives that must be defined are:
+ *
+ * PaUtil_FullMemoryBarrier()
+ * PaUtil_ReadMemoryBarrier()
+ * PaUtil_WriteMemoryBarrier()
+ *
+ ****************/
+
+#ifndef MODULES_THIRD_PARTY_PORTAUDIO_PA_MEMORYBARRIER_H_
+#define MODULES_THIRD_PARTY_PORTAUDIO_PA_MEMORYBARRIER_H_
+
+#if defined(__APPLE__)
+#include <libkern/OSAtomic.h>
+/* Here are the memory barrier functions. Mac OS X only provides
+   full memory barriers, so the three types of barriers are the same,
+   however, these barriers are superior to compiler-based ones. */
+#define PaUtil_FullMemoryBarrier() OSMemoryBarrier()
+#define PaUtil_ReadMemoryBarrier() OSMemoryBarrier()
+#define PaUtil_WriteMemoryBarrier() OSMemoryBarrier()
+#elif defined(__GNUC__)
+/* GCC >= 4.1 has built-in intrinsics. We'll use those */
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
+#define PaUtil_FullMemoryBarrier() __sync_synchronize()
+#define PaUtil_ReadMemoryBarrier() __sync_synchronize()
+#define PaUtil_WriteMemoryBarrier() __sync_synchronize()
+/* as a fallback, GCC understands volatile asm and "memory" to mean it
+ * should not reorder memory read/writes */
+/* Note that it is not clear that any compiler actually defines __PPC__,
+ * it can probably removed safely. */
+#elif defined(__ppc__) || defined(__powerpc__) || defined(__PPC__)
+#define PaUtil_FullMemoryBarrier() asm volatile("sync" ::: "memory")
+#define PaUtil_ReadMemoryBarrier() asm volatile("sync" ::: "memory")
+#define PaUtil_WriteMemoryBarrier() asm volatile("sync" ::: "memory")
+#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || \
+    defined(__i686__) || defined(__x86_64__)
+#define PaUtil_FullMemoryBarrier() asm volatile("mfence" ::: "memory")
+#define PaUtil_ReadMemoryBarrier() asm volatile("lfence" ::: "memory")
+#define PaUtil_WriteMemoryBarrier() asm volatile("sfence" ::: "memory")
+#else
+#ifdef ALLOW_SMP_DANGERS
+#warning Memory barriers not defined on this system or system unknown
+#warning For SMP safety, you should fix this.
+#define PaUtil_FullMemoryBarrier()
+#define PaUtil_ReadMemoryBarrier()
+#define PaUtil_WriteMemoryBarrier()
+#else
+#         error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
+#endif
+#endif
+#elif (_MSC_VER >= 1400) && !defined(_WIN32_WCE)
+#include <intrin.h>
+#pragma intrinsic(_ReadWriteBarrier)
+#pragma intrinsic(_ReadBarrier)
+#pragma intrinsic(_WriteBarrier)
+#define PaUtil_FullMemoryBarrier() _ReadWriteBarrier()
+#define PaUtil_ReadMemoryBarrier() _ReadBarrier()
+#define PaUtil_WriteMemoryBarrier() _WriteBarrier()
+#elif defined(_WIN32_WCE)
+#define PaUtil_FullMemoryBarrier()
+#define PaUtil_ReadMemoryBarrier()
+#define PaUtil_WriteMemoryBarrier()
+#elif defined(_MSC_VER) || defined(__BORLANDC__)
+#define PaUtil_FullMemoryBarrier() _asm { lock add    [esp], 0}
+#define PaUtil_ReadMemoryBarrier() _asm { lock add    [esp], 0}
+#define PaUtil_WriteMemoryBarrier() _asm { lock add    [esp], 0}
+#else
+#ifdef ALLOW_SMP_DANGERS
+#warning Memory barriers not defined on this system or system unknown
+#warning For SMP safety, you should fix this.
+#define PaUtil_FullMemoryBarrier()
+#define PaUtil_ReadMemoryBarrier()
+#define PaUtil_WriteMemoryBarrier()
+#else
+#      error Memory barriers are not defined on this system. You can still compile by defining ALLOW_SMP_DANGERS, but SMP safety will not be guaranteed.
+#endif
+#endif
+
+#endif /* MODULES_THIRD_PARTY_PORTAUDIO_PA_MEMORYBARRIER_H_ */
diff --git a/modules/third_party/portaudio/pa_ringbuffer.c b/modules/third_party/portaudio/pa_ringbuffer.c
new file mode 100644
index 0000000..fc1053c
--- /dev/null
+++ b/modules/third_party/portaudio/pa_ringbuffer.c
@@ -0,0 +1,237 @@
+/*
+ * $Id: pa_ringbuffer.c 1421 2009-11-18 16:09:05Z bjornroche $
+ * Portable Audio I/O Library
+ * Ring Buffer utility.
+ *
+ * Author: Phil Burk, http://www.softsynth.com
+ * modified for SMP safety on Mac OS X by Bjorn Roche
+ * modified for SMP safety on Linux by Leland Lucius
+ * also, allowed for const where possible
+ * modified for multiple-byte-sized data elements by Sven Fischer 
+ *
+ * Note that this is safe only for a single-thread reader and a
+ * single-thread writer.
+ *
+ * This program uses the PortAudio Portable Audio Library.
+ * For more information see: http://www.portaudio.com
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however, 
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also 
+ * requested that these non-binding requests be included along with the 
+ * license above.
+ */
+
+/**
+ @file
+ @ingroup common_src
+*/
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "modules/third_party/portaudio/pa_memorybarrier.h"
+#include "modules/third_party/portaudio/pa_ringbuffer.h"
+
+/***************************************************************************
+ * Initialize FIFO.
+ * elementCount must be power of 2, returns -1 if not.
+ */
+PaRingBufferSize PaUtil_InitializeRingBuffer(PaUtilRingBuffer* rbuf,
+                                             PaRingBufferSize elementSizeBytes,
+                                             PaRingBufferSize elementCount,
+                                             void* dataPtr) {
+    if( ((elementCount-1) & elementCount) != 0) return -1; /* Not Power of two. */
+    rbuf->bufferSize = elementCount;
+    rbuf->buffer = (char *)dataPtr;
+    PaUtil_FlushRingBuffer( rbuf );
+    rbuf->bigMask = (elementCount*2)-1;
+    rbuf->smallMask = (elementCount)-1;
+    rbuf->elementSizeBytes = elementSizeBytes;
+    return 0;
+}
+
+/***************************************************************************
+** Return number of elements available for reading. */
+PaRingBufferSize PaUtil_GetRingBufferReadAvailable( PaUtilRingBuffer *rbuf )
+{
+    PaUtil_ReadMemoryBarrier();
+    return ( (rbuf->writeIndex - rbuf->readIndex) & rbuf->bigMask );
+}
+/***************************************************************************
+** Return number of elements available for writing. */
+PaRingBufferSize PaUtil_GetRingBufferWriteAvailable( PaUtilRingBuffer *rbuf )
+{
+    /* Since we are calling PaUtil_GetRingBufferReadAvailable, we don't need an aditional MB */
+    return ( rbuf->bufferSize - PaUtil_GetRingBufferReadAvailable(rbuf));
+}
+
+/***************************************************************************
+** Clear buffer. Should only be called when buffer is NOT being read. */
+void PaUtil_FlushRingBuffer( PaUtilRingBuffer *rbuf )
+{
+    rbuf->writeIndex = rbuf->readIndex = 0;
+}
+
+/***************************************************************************
+** Get address of region(s) to which we can write data.
+** If the region is contiguous, size2 will be zero.
+** If non-contiguous, size2 will be the size of second region.
+** Returns room available to be written or elementCount, whichever is smaller.
+*/
+PaRingBufferSize PaUtil_GetRingBufferWriteRegions(PaUtilRingBuffer* rbuf,
+                                                  PaRingBufferSize elementCount,
+                                                  void** dataPtr1,
+                                                  PaRingBufferSize* sizePtr1,
+                                                  void** dataPtr2,
+                                                  PaRingBufferSize* sizePtr2) {
+    PaRingBufferSize   index;
+    PaRingBufferSize   available = PaUtil_GetRingBufferWriteAvailable( rbuf );
+    if( elementCount > available ) elementCount = available;
+    /* Check to see if write is not contiguous. */
+    index = rbuf->writeIndex & rbuf->smallMask;
+    if( (index + elementCount) > rbuf->bufferSize )
+    {
+        /* Write data in two blocks that wrap the buffer. */
+        PaRingBufferSize   firstHalf = rbuf->bufferSize - index;
+        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
+        *sizePtr1 = firstHalf;
+        *dataPtr2 = &rbuf->buffer[0];
+        *sizePtr2 = elementCount - firstHalf;
+    }
+    else
+    {
+        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
+        *sizePtr1 = elementCount;
+        *dataPtr2 = NULL;
+        *sizePtr2 = 0;
+    }
+    return elementCount;
+}
+
+
+/***************************************************************************
+*/
+PaRingBufferSize PaUtil_AdvanceRingBufferWriteIndex(
+    PaUtilRingBuffer* rbuf,
+    PaRingBufferSize elementCount) {
+    /* we need to ensure that previous writes are seen before we update the write index */
+    PaUtil_WriteMemoryBarrier();
+    return rbuf->writeIndex = (rbuf->writeIndex + elementCount) & rbuf->bigMask;
+}
+
+/***************************************************************************
+** Get address of region(s) from which we can read data.
+** If the region is contiguous, size2 will be zero.
+** If non-contiguous, size2 will be the size of second region.
+** Returns room available to be written or elementCount, whichever is smaller.
+*/
+PaRingBufferSize PaUtil_GetRingBufferReadRegions(PaUtilRingBuffer* rbuf,
+                                                 PaRingBufferSize elementCount,
+                                                 void** dataPtr1,
+                                                 PaRingBufferSize* sizePtr1,
+                                                 void** dataPtr2,
+                                                 PaRingBufferSize* sizePtr2) {
+    PaRingBufferSize   index;
+    PaRingBufferSize   available = PaUtil_GetRingBufferReadAvailable( rbuf );
+    if( elementCount > available ) elementCount = available;
+    /* Check to see if read is not contiguous. */
+    index = rbuf->readIndex & rbuf->smallMask;
+    if( (index + elementCount) > rbuf->bufferSize )
+    {
+        /* Write data in two blocks that wrap the buffer. */
+        PaRingBufferSize firstHalf = rbuf->bufferSize - index;
+        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
+        *sizePtr1 = firstHalf;
+        *dataPtr2 = &rbuf->buffer[0];
+        *sizePtr2 = elementCount - firstHalf;
+    }
+    else
+    {
+        *dataPtr1 = &rbuf->buffer[index*rbuf->elementSizeBytes];
+        *sizePtr1 = elementCount;
+        *dataPtr2 = NULL;
+        *sizePtr2 = 0;
+    }
+    return elementCount;
+}
+/***************************************************************************
+*/
+PaRingBufferSize PaUtil_AdvanceRingBufferReadIndex(
+    PaUtilRingBuffer* rbuf,
+    PaRingBufferSize elementCount) {
+    /* we need to ensure that previous writes are always seen before updating the index. */
+    PaUtil_WriteMemoryBarrier();
+    return rbuf->readIndex = (rbuf->readIndex + elementCount) & rbuf->bigMask;
+}
+
+/***************************************************************************
+** Return elements written. */
+PaRingBufferSize PaUtil_WriteRingBuffer(PaUtilRingBuffer* rbuf,
+                                        const void* data,
+                                        PaRingBufferSize elementCount) {
+    PaRingBufferSize size1, size2, numWritten;
+    void *data1, *data2;
+    numWritten = PaUtil_GetRingBufferWriteRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 );
+    if( size2 > 0 )
+    {
+
+        memcpy( data1, data, size1*rbuf->elementSizeBytes );
+        data = ((char *)data) + size1*rbuf->elementSizeBytes;
+        memcpy( data2, data, size2*rbuf->elementSizeBytes );
+    }
+    else
+    {
+        memcpy( data1, data, size1*rbuf->elementSizeBytes );
+    }
+    PaUtil_AdvanceRingBufferWriteIndex( rbuf, numWritten );
+    return numWritten;
+}
+
+/***************************************************************************
+** Return elements read. */
+PaRingBufferSize PaUtil_ReadRingBuffer(PaUtilRingBuffer* rbuf,
+                                       void* data,
+                                       PaRingBufferSize elementCount) {
+    PaRingBufferSize size1, size2, numRead;
+    void *data1, *data2;
+    numRead = PaUtil_GetRingBufferReadRegions( rbuf, elementCount, &data1, &size1, &data2, &size2 );
+    if( size2 > 0 )
+    {
+        memcpy( data, data1, size1*rbuf->elementSizeBytes );
+        data = ((char *)data) + size1*rbuf->elementSizeBytes;
+        memcpy( data, data2, size2*rbuf->elementSizeBytes );
+    }
+    else
+    {
+        memcpy( data, data1, size1*rbuf->elementSizeBytes );
+    }
+    PaUtil_AdvanceRingBufferReadIndex( rbuf, numRead );
+    return numRead;
+}
diff --git a/modules/third_party/portaudio/pa_ringbuffer.h b/modules/third_party/portaudio/pa_ringbuffer.h
new file mode 100644
index 0000000..3ad8216
--- /dev/null
+++ b/modules/third_party/portaudio/pa_ringbuffer.h
@@ -0,0 +1,251 @@
+#ifndef MODULES_THIRD_PARTY_PORTAUDIO_PA_RINGBUFFER_H_
+#define MODULES_THIRD_PARTY_PORTAUDIO_PA_RINGBUFFER_H_
+/*
+ * $Id: pa_ringbuffer.h 1421 2009-11-18 16:09:05Z bjornroche $
+ * Portable Audio I/O Library
+ * Ring Buffer utility.
+ *
+ * Author: Phil Burk, http://www.softsynth.com
+ * modified for SMP safety on OS X by Bjorn Roche.
+ * also allowed for const where possible.
+ * modified for multiple-byte-sized data elements by Sven Fischer
+ *
+ * Note that this is safe only for a single-thread reader
+ * and a single-thread writer.
+ *
+ * This program is distributed with the PortAudio Portable Audio Library.
+ * For more information see: http://www.portaudio.com
+ * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * The text above constitutes the entire PortAudio license; however,
+ * the PortAudio community also makes the following non-binding requests:
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
+ * license above.
+ */
+
+/** @file
+ @ingroup common_src
+ @brief Single-reader single-writer lock-free ring buffer
+
+ PaUtilRingBuffer is a ring buffer used to transport samples between
+ different execution contexts (threads, OS callbacks, interrupt handlers)
+ without requiring the use of any locks. This only works when there is
+ a single reader and a single writer (ie. one thread or callback writes
+ to the ring buffer, another thread or callback reads from it).
+
+ The PaUtilRingBuffer structure manages a ring buffer containing N
+ elements, where N must be a power of two. An element may be any size
+ (specified in bytes).
+
+ The memory area used to store the buffer elements must be allocated by
+ the client prior to calling PaUtil_InitializeRingBuffer() and must outlive
+ the use of the ring buffer.
+*/
+
+#if defined(__APPLE__)
+#include <sys/types.h>
+typedef int32_t PaRingBufferSize;
+#elif defined(__GNUC__)
+typedef long PaRingBufferSize;
+#elif (_MSC_VER >= 1400)
+typedef long PaRingBufferSize;
+#elif defined(_MSC_VER) || defined(__BORLANDC__)
+typedef long PaRingBufferSize;
+#else
+typedef long PaRingBufferSize;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct PaUtilRingBuffer {
+  PaRingBufferSize
+      bufferSize;                    /**< Number of elements in FIFO. Power of 2. Set by
+                                        PaUtil_InitRingBuffer. */
+  PaRingBufferSize writeIndex;       /**< Index of next writable element. Set by
+                                        PaUtil_AdvanceRingBufferWriteIndex. */
+  PaRingBufferSize readIndex;        /**< Index of next readable element. Set by
+                                        PaUtil_AdvanceRingBufferReadIndex. */
+  PaRingBufferSize bigMask;          /**< Used for wrapping indices with extra bit to
+                                        distinguish full/empty. */
+  PaRingBufferSize smallMask;        /**< Used for fitting indices to buffer. */
+  PaRingBufferSize elementSizeBytes; /**< Number of bytes per element. */
+  char* buffer; /**< Pointer to the buffer containing the actual data. */
+} PaUtilRingBuffer;
+
+/** Initialize Ring Buffer.
+
+ @param rbuf The ring buffer.
+
+ @param elementSizeBytes The size of a single data element in bytes.
+
+ @param elementCount The number of elements in the buffer (must be power of 2).
+
+ @param dataPtr A pointer to a previously allocated area where the data
+ will be maintained.  It must be elementCount*elementSizeBytes long.
+
+ @return -1 if elementCount is not a power of 2, otherwise 0.
+*/
+PaRingBufferSize PaUtil_InitializeRingBuffer(PaUtilRingBuffer* rbuf,
+                                             PaRingBufferSize elementSizeBytes,
+                                             PaRingBufferSize elementCount,
+                                             void* dataPtr);
+
+/** Clear buffer. Should only be called when buffer is NOT being read.
+
+ @param rbuf The ring buffer.
+*/
+void PaUtil_FlushRingBuffer(PaUtilRingBuffer* rbuf);
+
+/** Retrieve the number of elements available in the ring buffer for writing.
+
+ @param rbuf The ring buffer.
+
+ @return The number of elements available for writing.
+*/
+PaRingBufferSize PaUtil_GetRingBufferWriteAvailable(PaUtilRingBuffer* rbuf);
+
+/** Retrieve the number of elements available in the ring buffer for reading.
+
+ @param rbuf The ring buffer.
+
+ @return The number of elements available for reading.
+*/
+PaRingBufferSize PaUtil_GetRingBufferReadAvailable(PaUtilRingBuffer* rbuf);
+
+/** Write data to the ring buffer.
+
+ @param rbuf The ring buffer.
+
+ @param data The address of new data to write to the buffer.
+
+ @param elementCount The number of elements to be written.
+
+ @return The number of elements written.
+*/
+PaRingBufferSize PaUtil_WriteRingBuffer(PaUtilRingBuffer* rbuf,
+                                        const void* data,
+                                        PaRingBufferSize elementCount);
+
+/** Read data from the ring buffer.
+
+ @param rbuf The ring buffer.
+
+ @param data The address where the data should be stored.
+
+ @param elementCount The number of elements to be read.
+
+ @return The number of elements read.
+*/
+PaRingBufferSize PaUtil_ReadRingBuffer(PaUtilRingBuffer* rbuf,
+                                       void* data,
+                                       PaRingBufferSize elementCount);
+
+/** Get address of region(s) to which we can write data.
+
+ @param rbuf The ring buffer.
+
+ @param elementCount The number of elements desired.
+
+ @param dataPtr1 The address where the first (or only) region pointer will be
+ stored.
+
+ @param sizePtr1 The address where the first (or only) region length will be
+ stored.
+
+ @param dataPtr2 The address where the second region pointer will be stored if
+ the first region is too small to satisfy elementCount.
+
+ @param sizePtr2 The address where the second region length will be stored if
+ the first region is too small to satisfy elementCount.
+
+ @return The room available to be written or elementCount, whichever is smaller.
+*/
+PaRingBufferSize PaUtil_GetRingBufferWriteRegions(PaUtilRingBuffer* rbuf,
+                                                  PaRingBufferSize elementCount,
+                                                  void** dataPtr1,
+                                                  PaRingBufferSize* sizePtr1,
+                                                  void** dataPtr2,
+                                                  PaRingBufferSize* sizePtr2);
+
+/** Advance the write index to the next location to be written.
+
+ @param rbuf The ring buffer.
+
+ @param elementCount The number of elements to advance.
+
+ @return The new position.
+*/
+PaRingBufferSize PaUtil_AdvanceRingBufferWriteIndex(
+    PaUtilRingBuffer* rbuf,
+    PaRingBufferSize elementCount);
+
+/** Get address of region(s) from which we can write data.
+
+ @param rbuf The ring buffer.
+
+ @param elementCount The number of elements desired.
+
+ @param dataPtr1 The address where the first (or only) region pointer will be
+ stored.
+
+ @param sizePtr1 The address where the first (or only) region length will be
+ stored.
+
+ @param dataPtr2 The address where the second region pointer will be stored if
+ the first region is too small to satisfy elementCount.
+
+ @param sizePtr2 The address where the second region length will be stored if
+ the first region is too small to satisfy elementCount.
+
+ @return The number of elements available for reading.
+*/
+PaRingBufferSize PaUtil_GetRingBufferReadRegions(PaUtilRingBuffer* rbuf,
+                                                 PaRingBufferSize elementCount,
+                                                 void** dataPtr1,
+                                                 PaRingBufferSize* sizePtr1,
+                                                 void** dataPtr2,
+                                                 PaRingBufferSize* sizePtr2);
+
+/** Advance the read index to the next location to be read.
+
+ @param rbuf The ring buffer.
+
+ @param elementCount The number of elements to advance.
+
+ @return The new position.
+*/
+PaRingBufferSize PaUtil_AdvanceRingBufferReadIndex(
+    PaUtilRingBuffer* rbuf,
+    PaRingBufferSize elementCount);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* MODULES_THIRD_PARTY_PORTAUDIO_PA_RINGBUFFER_H_ */
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
index 982d5c4..2ef79fa 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -15,18 +15,6 @@
   import("//build/config/android/rules.gni")
 }
 
-group("base") {
-  public_deps = [
-    ":rtc_base",
-    ":rtc_base_approved",
-    ":rtc_task_queue",
-    ":weak_ptr",
-  ]
-  if (is_android) {
-    public_deps += [ ":base_java" ]
-  }
-}
-
 config("rtc_base_chromium_config") {
   defines = [ "NO_MAIN_THREAD_WRAPPING" ]
 }
@@ -66,7 +54,8 @@
     "protobuf_utils.h",
   ]
   if (rtc_enable_protobuf) {
-    public_deps = [
+    public_configs = [ "//third_party/protobuf:protobuf_config" ]
+    deps = [
       "//third_party/protobuf:protobuf_lite",
     ]
   }
@@ -102,6 +91,8 @@
 }
 
 rtc_source_set("macromagic") {
+  # TODO(bugs.webrtc.org/9606): This should not be public.
+  visibility = [ "*" ]
   sources = [
     "arraysize.h",
     "constructormagic.h",
@@ -109,6 +100,9 @@
     "stringize_macros.h",
     "thread_annotations.h",
   ]
+  deps = [
+    "system:arch",
+  ]
 }
 
 rtc_source_set("platform_thread_types") {
@@ -119,16 +113,14 @@
 }
 
 rtc_source_set("ptr_util") {
+  visibility = [ "*" ]
   sources = [
-    "ptr_util.h",
     "scoped_ref_ptr.h",
   ]
-  deps = [
-    "//third_party/abseil-cpp/absl/memory",
-  ]
 }
 
 rtc_source_set("refcount") {
+  visibility = [ "*" ]
   sources = [
     "refcount.h",
     "refcountedobject.h",
@@ -150,7 +142,7 @@
     ":checks",
     ":macromagic",
     ":platform_thread_types",
-    "..:typedefs",
+    "system:unused",
   ]
 }
 
@@ -174,7 +166,6 @@
     ":rtc_event",
     ":thread_checker",
     ":timeutils",
-    "..:typedefs",
   ]
 }
 
@@ -200,6 +191,7 @@
 }
 
 rtc_source_set("logging") {
+  visibility = [ "*" ]
   deps = [
     ":criticalsection",
     ":macromagic",
@@ -239,7 +231,6 @@
     ":criticalsection",
     ":macromagic",
     ":platform_thread_types",
-    "..:typedefs",
   ]
 }
 
@@ -250,13 +241,14 @@
 }
 
 rtc_source_set("checks") {
+  # TODO(bugs.webrtc.org/9607): This should not be public.
+  visibility = [ "*" ]
   sources = [
     "checks.cc",
     "checks.h",
   ]
   deps = [
     ":safe_compare",
-    "..:typedefs",
     "system:inline",
   ]
 }
@@ -309,6 +301,7 @@
 }
 
 rtc_source_set("timeutils") {
+  visibility = [ "*" ]
   sources = [
     "timeutils.cc",
     "timeutils.h",
@@ -321,6 +314,8 @@
 
 rtc_source_set("stringutils") {
   sources = [
+    "string_to_number.cc",
+    "string_to_number.h",
     "stringencode.cc",
     "stringencode.h",
     "strings/string_builder.cc",
@@ -330,8 +325,10 @@
   ]
   deps = [
     ":checks",
+    ":macromagic",
     ":safe_minmax",
     "../api:array_view",
+    "//third_party/abseil-cpp/absl/types:optional",
   ]
 }
 
@@ -371,7 +368,6 @@
   data_deps = []
   deps = [
     ":atomicops",
-    ":base64",
     ":checks",
     ":criticalsection",
     ":logging",
@@ -388,8 +384,9 @@
     ":thread_checker",
     ":timeutils",
     ":type_traits",
-    "../:typedefs",
     "system:arch",
+    "system:unused",
+    "third_party/base64",
   ]
 
   sources = [
@@ -416,6 +413,7 @@
     "ignore_wundef.h",
     "location.cc",
     "location.h",
+    "message_buffer_reader.h",
     "numerics/histogram_percentile_counter.cc",
     "numerics/histogram_percentile_counter.h",
     "numerics/mod_ops.h",
@@ -435,8 +433,6 @@
     "rate_statistics.h",
     "ratetracker.cc",
     "ratetracker.h",
-    "string_to_number.cc",
-    "string_to_number.h",
     "swap_queue.h",
     "template_util.h",
     "timestampaligner.cc",
@@ -449,6 +445,7 @@
   deps += [
     "..:webrtc_common",
     "../api:array_view",
+    "//third_party/abseil-cpp/absl/memory:memory",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
 
@@ -492,14 +489,6 @@
   }
 }
 
-rtc_source_set("base64") {
-  visibility = [ "*" ]
-  sources = [
-    "base64.cc",
-    "base64.h",
-  ]
-}
-
 rtc_source_set("rtc_task_queue") {
   visibility = [ "*" ]
   deps = []
@@ -555,6 +544,7 @@
       ":rtc_task_queue_api",
       ":safe_conversions",
       ":timeutils",
+      "system:unused",
     ]
     if (rtc_build_libevent) {
       deps += [ "//base/third_party/libevent" ]
@@ -723,11 +713,12 @@
   libs = []
   defines = []
   deps = [
-    ":base64",
     ":checks",
     ":stringutils",
     "..:webrtc_common",
     "../api:array_view",
+    "third_party/base64",
+    "third_party/sigslot",
     "//third_party/abseil-cpp/absl/memory",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
@@ -815,8 +806,6 @@
     "rtccertificategenerator.h",
     "signalthread.cc",
     "signalthread.h",
-    "sigslot.cc",
-    "sigslot.h",
     "sigslotrepeater.h",
     "socket.cc",
     "socket.h",
@@ -885,10 +874,6 @@
     configs += [ ":external_ssl_library" ]
   }
 
-  if (rtc_builtin_ssl_root_certificates) {
-    defines += [ "WEBRTC_BUILT_IN_SSL_ROOT_CERTIFICATES" ]
-  }
-
   if (is_android) {
     sources += [
       "ifaddrs-android.cc",
@@ -976,10 +961,6 @@
   ]
 }
 
-config("rtc_base_tests_utils_exported_config") {
-  defines = [ "GTEST_RELATIVE_PATH" ]
-}
-
 rtc_source_set("rtc_base_tests_utils") {
   testonly = true
   sources = [
@@ -1023,7 +1004,6 @@
     "virtualsocketserver.cc",
     "virtualsocketserver.h",
   ]
-  public_configs = [ ":rtc_base_tests_utils_exported_config" ]
   deps = [
     ":checks",
     ":rtc_base",
@@ -1032,6 +1012,7 @@
     "../test:field_trial",
     "../test:test_support",
     "system:fallthrough",
+    "third_party/sigslot",
     "//third_party/abseil-cpp/absl/memory",
   ]
   public_deps = [
@@ -1055,12 +1036,23 @@
 }
 
 if (rtc_include_tests) {
+  rtc_source_set("sigslot_unittest") {
+    testonly = true
+    sources = [
+      "sigslot_unittest.cc",
+    ]
+    deps = [
+      ":rtc_base",
+      ":rtc_base_tests_utils",
+      "third_party/sigslot",
+    ]
+  }
+
   rtc_source_set("rtc_base_tests_main") {
     testonly = true
     sources = [
       "unittest_main.cc",
     ]
-    public_configs = [ ":rtc_base_tests_utils_exported_config" ]
     deps = [
       ":rtc_base",
       ":rtc_base_approved",
@@ -1160,7 +1152,6 @@
       sources += [ "win/windows_version_unittest.cc" ]
     }
     deps = [
-      ":base64",
       ":checks",
       ":rate_limiter",
       ":rtc_base",
@@ -1177,6 +1168,7 @@
       "../test:fileutils",
       "../test:test_support",
       "memory:unittests",
+      "third_party/base64",
       "//third_party/abseil-cpp/absl/memory",
     ]
   }
@@ -1268,12 +1260,10 @@
       "network_unittest.cc",
       "optionsfile_unittest.cc",
       "proxy_unittest.cc",
-      "ptr_util_unittest.cc",
       "rollingaccumulator_unittest.cc",
       "rtccertificate_unittest.cc",
       "rtccertificategenerator_unittest.cc",
       "signalthread_unittest.cc",
-      "sigslot_unittest.cc",
       "sigslottester_unittest.cc",
       "stream_unittest.cc",
       "testclient_unittest.cc",
@@ -1303,6 +1293,7 @@
       "../api:array_view",
       "../test:fileutils",
       "../test:test_support",
+      "third_party/sigslot",
       "//third_party/abseil-cpp/absl/memory",
       "//third_party/abseil-cpp/absl/types:optional",
     ]
@@ -1317,9 +1308,6 @@
     } else {
       configs += [ ":external_ssl_library" ]
     }
-    if (rtc_builtin_ssl_root_certificates) {
-      defines += [ "WEBRTC_BUILT_IN_SSL_ROOT_CERTIFICATES" ]
-    }
   }
 }
 
diff --git a/rtc_base/OWNERS b/rtc_base/OWNERS
index 6355075..69ce253 100644
--- a/rtc_base/OWNERS
+++ b/rtc_base/OWNERS
@@ -4,7 +4,9 @@
 mflodman@webrtc.org
 perkj@webrtc.org
 pthatcher@webrtc.org
+qingsi@webrtc.org
 sergeyu@chromium.org
+steveanton@webrtc.org
 tommi@webrtc.org
 
 # These are for the common case of adding or renaming files. If you're doing
diff --git a/rtc_base/asyncinvoker-inl.h b/rtc_base/asyncinvoker-inl.h
index 3ae2430..0dadc0f 100644
--- a/rtc_base/asyncinvoker-inl.h
+++ b/rtc_base/asyncinvoker-inl.h
@@ -17,7 +17,7 @@
 #include "rtc_base/messagehandler.h"
 #include "rtc_base/refcountedobject.h"
 #include "rtc_base/scoped_ref_ptr.h"
-#include "rtc_base/sigslot.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread.h"
 #include "rtc_base/thread_annotations.h"
 
diff --git a/rtc_base/asyncinvoker.h b/rtc_base/asyncinvoker.h
index 74e8689..474ec7c 100644
--- a/rtc_base/asyncinvoker.h
+++ b/rtc_base/asyncinvoker.h
@@ -21,7 +21,7 @@
 #include "rtc_base/event.h"
 #include "rtc_base/refcountedobject.h"
 #include "rtc_base/scoped_ref_ptr.h"
-#include "rtc_base/sigslot.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread.h"
 
 namespace rtc {
diff --git a/rtc_base/asyncpacketsocket.h b/rtc_base/asyncpacketsocket.h
index 820fe94..bb0b3bc 100644
--- a/rtc_base/asyncpacketsocket.h
+++ b/rtc_base/asyncpacketsocket.h
@@ -13,8 +13,8 @@
 
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/dscp.h"
-#include "rtc_base/sigslot.h"
 #include "rtc_base/socket.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/timeutils.h"
 
 namespace rtc {
diff --git a/rtc_base/asyncresolverinterface.h b/rtc_base/asyncresolverinterface.h
index 96b5ec1..5b2303f 100644
--- a/rtc_base/asyncresolverinterface.h
+++ b/rtc_base/asyncresolverinterface.h
@@ -11,8 +11,8 @@
 #ifndef RTC_BASE_ASYNCRESOLVERINTERFACE_H_
 #define RTC_BASE_ASYNCRESOLVERINTERFACE_H_
 
-#include "rtc_base/sigslot.h"
 #include "rtc_base/socketaddress.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
 
diff --git a/rtc_base/asyncsocket.h b/rtc_base/asyncsocket.h
index bf9c282..0abdc27 100644
--- a/rtc_base/asyncsocket.h
+++ b/rtc_base/asyncsocket.h
@@ -11,8 +11,8 @@
 #ifndef RTC_BASE_ASYNCSOCKET_H_
 #define RTC_BASE_ASYNCSOCKET_H_
 
-#include "rtc_base/sigslot.h"
 #include "rtc_base/socket.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
 
diff --git a/rtc_base/base64_unittest.cc b/rtc_base/base64_unittest.cc
index f73b396..4b857f1 100644
--- a/rtc_base/base64_unittest.cc
+++ b/rtc_base/base64_unittest.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/base64.h"
+#include "rtc_base/third_party/base64/base64.h"
 #include "rtc_base/gunit.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/stringutils.h"
diff --git a/rtc_base/buffer.h b/rtc_base/buffer.h
index 64974d3..22f8937 100644
--- a/rtc_base/buffer.h
+++ b/rtc_base/buffer.h
@@ -87,7 +87,7 @@
   BufferT(size_t size, size_t capacity)
       : size_(size),
         capacity_(std::max(size, capacity)),
-        data_(new T[capacity_]) {
+        data_(capacity_ > 0 ? new T[capacity_] : nullptr) {
     RTC_DCHECK(IsConsistent());
   }
 
diff --git a/rtc_base/bytebuffer.h b/rtc_base/bytebuffer.h
index 9036bcd..9e08f02 100644
--- a/rtc_base/bytebuffer.h
+++ b/rtc_base/bytebuffer.h
@@ -185,7 +185,7 @@
   // after this call.
   bool Consume(size_t size);
 
- private:
+ protected:
   void Construct(const char* bytes, size_t size);
 
   const char* bytes_;
@@ -193,6 +193,7 @@
   size_t start_;
   size_t end_;
 
+ private:
   RTC_DISALLOW_COPY_AND_ASSIGN(ByteBufferReader);
 };
 
diff --git a/rtc_base/copyonwritebuffer.cc b/rtc_base/copyonwritebuffer.cc
index 8874ea9..6c48d52 100644
--- a/rtc_base/copyonwritebuffer.cc
+++ b/rtc_base/copyonwritebuffer.cc
@@ -22,6 +22,9 @@
 CopyOnWriteBuffer::CopyOnWriteBuffer(CopyOnWriteBuffer&& buf)
     : buffer_(std::move(buf.buffer_)) {}
 
+CopyOnWriteBuffer::CopyOnWriteBuffer(const std::string& s)
+    : CopyOnWriteBuffer(s.data(), s.length()) {}
+
 CopyOnWriteBuffer::CopyOnWriteBuffer(size_t size)
     : buffer_(size > 0 ? new RefCountedObject<Buffer>(size) : nullptr) {
   RTC_DCHECK(IsConsistent());
diff --git a/rtc_base/copyonwritebuffer.h b/rtc_base/copyonwritebuffer.h
index 467baad..0514e2f 100644
--- a/rtc_base/copyonwritebuffer.h
+++ b/rtc_base/copyonwritebuffer.h
@@ -31,6 +31,9 @@
   // Move contents from an existing buffer.
   CopyOnWriteBuffer(CopyOnWriteBuffer&& buf);
 
+  // Construct a buffer from a string, convenient for unittests.
+  CopyOnWriteBuffer(const std::string& s);
+
   // Construct a buffer with the specified number of uninitialized bytes.
   explicit CopyOnWriteBuffer(size_t size);
   CopyOnWriteBuffer(size_t size, size_t capacity);
diff --git a/rtc_base/criticalsection.cc b/rtc_base/criticalsection.cc
index c786a40..d8a5b48 100644
--- a/rtc_base/criticalsection.cc
+++ b/rtc_base/criticalsection.cc
@@ -13,6 +13,7 @@
 #include "rtc_base/atomicops.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/platform_thread_types.h"
+#include "rtc_base/system/unused.h"
 
 // TODO(tommi): Split this file up to per-platform implementation files.
 
diff --git a/rtc_base/criticalsection.h b/rtc_base/criticalsection.h
index ce6fca1..f25e7d0 100644
--- a/rtc_base/criticalsection.h
+++ b/rtc_base/criticalsection.h
@@ -15,7 +15,6 @@
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/platform_thread_types.h"
 #include "rtc_base/thread_annotations.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 #if defined(WEBRTC_WIN)
 // clang-format off
diff --git a/rtc_base/experiments/BUILD.gn b/rtc_base/experiments/BUILD.gn
index a95e258..c0e1049 100644
--- a/rtc_base/experiments/BUILD.gn
+++ b/rtc_base/experiments/BUILD.gn
@@ -63,6 +63,17 @@
   ]
 }
 
+rtc_static_library("rtt_mult_experiment") {
+  sources = [
+    "rtt_mult_experiment.cc",
+    "rtt_mult_experiment.h",
+  ]
+  deps = [
+    "../:rtc_base_approved",
+    "../../system_wrappers:field_trial_api",
+  ]
+}
+
 if (rtc_include_tests) {
   rtc_source_set("experiments_unittests") {
     testonly = true
@@ -72,11 +83,13 @@
       "field_trial_parser_unittest.cc",
       "field_trial_units_unittest.cc",
       "quality_scaling_experiment_unittest.cc",
+      "rtt_mult_experiment_unittest.cc",
     ]
     deps = [
       ":congestion_controller_experiment",
       ":field_trial_parser",
       ":quality_scaling_experiment",
+      ":rtt_mult_experiment",
       "../:rtc_base_tests_main",
       "../:rtc_base_tests_utils",
       "../../system_wrappers:field_trial_api",
diff --git a/rtc_base/experiments/rtt_mult_experiment.cc b/rtc_base/experiments/rtt_mult_experiment.cc
new file mode 100644
index 0000000..f8f7f2a
--- /dev/null
+++ b/rtc_base/experiments/rtt_mult_experiment.cc
@@ -0,0 +1,49 @@
+/*
+ *  Copyright 2018 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 "rtc_base/experiments/rtt_mult_experiment.h"
+
+#include <algorithm>
+#include <string>
+
+#include "rtc_base/logging.h"
+#include "system_wrappers/include/field_trial.h"
+
+namespace webrtc {
+
+namespace {
+const char kRttMultExperiment[] = "WebRTC-RttMult";
+const float max_rtt_mult_setting = 1.0;
+const float min_rtt_mult_setting = 0.0;
+}  // namespace
+
+bool RttMultExperiment::RttMultEnabled() {
+  return field_trial::IsEnabled(kRttMultExperiment);
+}
+
+float RttMultExperiment::GetRttMultValue() {
+  const std::string group =
+      webrtc::field_trial::FindFullName(kRttMultExperiment);
+  if (group.empty()) {
+    RTC_LOG(LS_WARNING) << "Could not find rtt_mult_experiment.";
+    return 0.0;
+  }
+
+  float rtt_mult_setting;
+  if (sscanf(group.c_str(), "Enabled-%f", &rtt_mult_setting) != 1) {
+    RTC_LOG(LS_WARNING) << "Invalid number of parameters provided.";
+    return 0.0;
+  }
+  // Bounds check rtt_mult_setting value.
+  rtt_mult_setting = std::min(rtt_mult_setting, max_rtt_mult_setting);
+  rtt_mult_setting = std::max(rtt_mult_setting, min_rtt_mult_setting);
+  return rtt_mult_setting;
+}
+
+}  // namespace webrtc
diff --git a/rtc_base/experiments/rtt_mult_experiment.h b/rtc_base/experiments/rtt_mult_experiment.h
new file mode 100644
index 0000000..d431af6
--- /dev/null
+++ b/rtc_base/experiments/rtt_mult_experiment.h
@@ -0,0 +1,26 @@
+/*
+ *  Copyright 2018 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 RTC_BASE_EXPERIMENTS_RTT_MULT_EXPERIMENT_H_
+#define RTC_BASE_EXPERIMENTS_RTT_MULT_EXPERIMENT_H_
+
+namespace webrtc {
+
+class RttMultExperiment {
+ public:
+  // Returns true if the experiment is enabled.
+  static bool RttMultEnabled();
+
+  // Returns rtt_mult value from field trial.
+  static float GetRttMultValue();
+};
+
+}  // namespace webrtc
+
+#endif  // RTC_BASE_EXPERIMENTS_RTT_MULT_EXPERIMENT_H_
diff --git a/rtc_base/experiments/rtt_mult_experiment_unittest.cc b/rtc_base/experiments/rtt_mult_experiment_unittest.cc
new file mode 100644
index 0000000..0cd86d1
--- /dev/null
+++ b/rtc_base/experiments/rtt_mult_experiment_unittest.cc
@@ -0,0 +1,51 @@
+/*
+ *  Copyright 2018 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 "rtc_base/experiments/rtt_mult_experiment.h"
+#include "rtc_base/gunit.h"
+#include "test/field_trial.h"
+
+namespace webrtc {
+
+TEST(RttMultExperimentTest, RttMultDisabledByDefault) {
+  EXPECT_FALSE(RttMultExperiment::RttMultEnabled());
+}
+
+TEST(RttMultExperimentTest, RttMultEnabledByFieldTrial) {
+  webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Enabled-0.25/");
+  EXPECT_TRUE(RttMultExperiment::RttMultEnabled());
+}
+
+TEST(RttMultExperimentTest, RttMultTestValue) {
+  webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Enabled-0.25/");
+  EXPECT_EQ(0.25, RttMultExperiment::GetRttMultValue());
+}
+
+TEST(RttMultExperimentTest, RttMultTestMalformedEnabled) {
+  webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Enable-0.25/");
+  EXPECT_FALSE(RttMultExperiment::RttMultEnabled());
+}
+
+TEST(RttMultExperimentTest, RttMultTestValueOutOfBoundsPositive) {
+  webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Enabled-1.5/");
+  EXPECT_EQ(1.0, RttMultExperiment::GetRttMultValue());
+}
+
+TEST(RttMultExperimentTest, RttMultTestValueOutOfBoundsNegative) {
+  webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Enabled--0.5/");
+  EXPECT_EQ(0.0, RttMultExperiment::GetRttMultValue());
+}
+
+TEST(RttMultExperimentTest, RttMultTestMalformedValue) {
+  webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Enabled-0.2a5/");
+  EXPECT_NE(0.25, RttMultExperiment::GetRttMultValue());
+}
+
+}  // namespace webrtc
diff --git a/rtc_base/format_macros.h b/rtc_base/format_macros.h
index 48127e1..7252f2e 100644
--- a/rtc_base/format_macros.h
+++ b/rtc_base/format_macros.h
@@ -37,6 +37,8 @@
 
 #include <inttypes.h>
 
+#include "rtc_base/system/arch.h"
+
 #if !defined(PRIuS)
 #define PRIuS "zu"
 #endif
diff --git a/rtc_base/gunit.h b/rtc_base/gunit.h
index 145b466..910fbf3 100644
--- a/rtc_base/gunit.h
+++ b/rtc_base/gunit.h
@@ -14,11 +14,7 @@
 #include "rtc_base/fakeclock.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/thread.h"
-#if defined(GTEST_RELATIVE_PATH)
 #include "test/gtest.h"
-#else
-#include "testing/base/public/gunit.h"
-#endif
 
 // Wait until "ex" is true, or "timeout" expires.
 #define WAIT(ex, timeout)                                       \
diff --git a/rtc_base/gunit_prod.h b/rtc_base/gunit_prod.h
index bf4f9a1..dae2084 100644
--- a/rtc_base/gunit_prod.h
+++ b/rtc_base/gunit_prod.h
@@ -15,10 +15,8 @@
 // Android doesn't use gtest at all, so anything that relies on gtest should
 // check this define first.
 #define NO_GTEST
-#elif defined(GTEST_RELATIVE_PATH)
-#include "gtest/gtest_prod.h"
 #else
-#include "testing/base/gunit_prod.h"
+#include "gtest/gtest_prod.h"
 #endif
 
 #endif  // RTC_BASE_GUNIT_PROD_H_
diff --git a/rtc_base/helpers.cc b/rtc_base/helpers.cc
index 0260665..b9372b9 100644
--- a/rtc_base/helpers.cc
+++ b/rtc_base/helpers.cc
@@ -15,9 +15,9 @@
 
 #include <openssl/rand.h>
 
-#include "rtc_base/base64.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
+#include "rtc_base/third_party/base64/base64.h"
 #include "rtc_base/timeutils.h"
 
 // Protect against max macro inclusion.
diff --git a/rtc_base/httpbase.cc b/rtc_base/httpbase.cc
index 3e2f376..8f2869d 100644
--- a/rtc_base/httpbase.cc
+++ b/rtc_base/httpbase.cc
@@ -224,149 +224,11 @@
 }
 
 //////////////////////////////////////////////////////////////////////
-// HttpBase::DocumentStream
-//////////////////////////////////////////////////////////////////////
-
-class BlockingMemoryStream : public ExternalMemoryStream {
- public:
-  BlockingMemoryStream(char* buffer, size_t size)
-      : ExternalMemoryStream(buffer, size) {}
-
-  StreamResult DoReserve(size_t size, int* error) override {
-    return (buffer_length_ >= size) ? SR_SUCCESS : SR_BLOCK;
-  }
-};
-
-class HttpBase::DocumentStream : public StreamInterface {
- public:
-  DocumentStream(HttpBase* base) : base_(base), error_(HE_DEFAULT) {}
-
-  StreamState GetState() const override {
-    if (nullptr == base_)
-      return SS_CLOSED;
-    if (HM_RECV == base_->mode_)
-      return SS_OPEN;
-    return SS_OPENING;
-  }
-
-  StreamResult Read(void* buffer,
-                    size_t buffer_len,
-                    size_t* read,
-                    int* error) override {
-    if (!base_) {
-      if (error)
-        *error = error_;
-      return (HE_NONE == error_) ? SR_EOS : SR_ERROR;
-    }
-
-    if (HM_RECV != base_->mode_) {
-      return SR_BLOCK;
-    }
-
-    // DoReceiveLoop writes http document data to the StreamInterface* document
-    // member of HttpData.  In this case, we want this data to be written
-    // directly to our buffer.  To accomplish this, we wrap our buffer with a
-    // StreamInterface, and replace the existing document with our wrapper.
-    // When the method returns, we restore the old document.  Ideally, we would
-    // pass our StreamInterface* to DoReceiveLoop, but due to the callbacks
-    // of HttpParser, we would still need to store the pointer temporarily.
-    std::unique_ptr<StreamInterface> stream(
-        new BlockingMemoryStream(reinterpret_cast<char*>(buffer), buffer_len));
-
-    // Replace the existing document with our wrapped buffer.
-    base_->data_->document.swap(stream);
-
-    // Pump the I/O loop.  DoReceiveLoop is guaranteed not to attempt to
-    // complete the I/O process, which means that our wrapper is not in danger
-    // of being deleted.  To ensure this, DoReceiveLoop returns true when it
-    // wants complete to be called.  We make sure to uninstall our wrapper
-    // before calling complete().
-    HttpError http_error;
-    bool complete = base_->DoReceiveLoop(&http_error);
-
-    // Reinstall the original output document.
-    base_->data_->document.swap(stream);
-
-    // If we reach the end of the receive stream, we disconnect our stream
-    // adapter from the HttpBase, and further calls to read will either return
-    // EOS or ERROR, appropriately.  Finally, we call complete().
-    StreamResult result = SR_BLOCK;
-    if (complete) {
-      HttpBase* base = Disconnect(http_error);
-      if (error)
-        *error = error_;
-      result = (HE_NONE == error_) ? SR_EOS : SR_ERROR;
-      base->complete(http_error);
-    }
-
-    // Even if we are complete, if some data was read we must return SUCCESS.
-    // Future Reads will return EOS or ERROR based on the error_ variable.
-    size_t position;
-    stream->GetPosition(&position);
-    if (position > 0) {
-      if (read)
-        *read = position;
-      result = SR_SUCCESS;
-    }
-    return result;
-  }
-
-  StreamResult Write(const void* data,
-                     size_t data_len,
-                     size_t* written,
-                     int* error) override {
-    if (error)
-      *error = -1;
-    return SR_ERROR;
-  }
-
-  void Close() override {
-    if (base_) {
-      HttpBase* base = Disconnect(HE_NONE);
-      if (HM_RECV == base->mode_ && base->http_stream_) {
-        // Read I/O could have been stalled on the user of this DocumentStream,
-        // so restart the I/O process now that we've removed ourselves.
-        base->http_stream_->PostEvent(SE_READ, 0);
-      }
-    }
-  }
-
-  bool GetAvailable(size_t* size) const override {
-    if (!base_ || HM_RECV != base_->mode_)
-      return false;
-    size_t data_size = base_->GetDataRemaining();
-    if (SIZE_UNKNOWN == data_size)
-      return false;
-    if (size)
-      *size = data_size;
-    return true;
-  }
-
-  HttpBase* Disconnect(HttpError error) {
-    RTC_DCHECK(nullptr != base_);
-    RTC_DCHECK(nullptr != base_->doc_stream_);
-    HttpBase* base = base_;
-    base_->doc_stream_ = nullptr;
-    base_ = nullptr;
-    error_ = error;
-    return base;
-  }
-
- private:
-  HttpBase* base_;
-  HttpError error_;
-};
-
-//////////////////////////////////////////////////////////////////////
 // HttpBase
 //////////////////////////////////////////////////////////////////////
 
 HttpBase::HttpBase()
-    : mode_(HM_NONE),
-      data_(nullptr),
-      notify_(nullptr),
-      http_stream_(nullptr),
-      doc_stream_(nullptr) {}
+    : mode_(HM_NONE), data_(nullptr), notify_(nullptr), http_stream_(nullptr) {}
 
 HttpBase::~HttpBase() {
   RTC_DCHECK(HM_NONE == mode_);
@@ -451,11 +313,7 @@
   ignore_data_ = chunk_data_ = false;
 
   reset();
-  if (doc_stream_) {
-    doc_stream_->SignalEvent(doc_stream_, SE_OPEN | SE_READ, 0);
-  } else {
-    read_and_process_data();
-  }
+  read_and_process_data();
 }
 
 void HttpBase::abort(HttpError err) {
@@ -467,13 +325,6 @@
   }
 }
 
-StreamInterface* HttpBase::GetDocumentStream() {
-  if (doc_stream_)
-    return nullptr;
-  doc_stream_ = new DocumentStream(this);
-  return doc_stream_;
-}
-
 HttpError HttpBase::HandleStreamClose(int error) {
   if (http_stream_ != nullptr) {
     http_stream_->Close();
@@ -730,13 +581,6 @@
     data_->document->SignalEvent.disconnect(this);
   }
   data_ = nullptr;
-  if ((HM_RECV == mode) && doc_stream_) {
-    RTC_DCHECK(HE_NONE !=
-               err);  // We should have Disconnected doc_stream_ already.
-    DocumentStream* ds = doc_stream_;
-    ds->Disconnect(err);
-    ds->SignalEvent(ds, SE_CLOSE, err);
-  }
   if (notify_) {
     notify_->onHttpComplete(mode, err);
   }
@@ -761,11 +605,7 @@
   }
 
   if ((events & SE_READ) && (mode_ == HM_RECV)) {
-    if (doc_stream_) {
-      doc_stream_->SignalEvent(doc_stream_, SE_READ, 0);
-    } else {
-      read_and_process_data();
-    }
+    read_and_process_data();
     return;
   }
 
@@ -825,7 +665,6 @@
 HttpParser::ProcessResult HttpBase::ProcessHeaderComplete(bool chunked,
                                                           size_t& data_size,
                                                           HttpError* error) {
-  StreamInterface* old_docstream = doc_stream_;
   if (notify_) {
     *error = notify_->onHttpHeaderComplete(chunked, data_size);
     // The request must not be aborted as a result of this callback.
@@ -837,10 +676,6 @@
   if (HE_NONE != *error) {
     return PR_COMPLETE;
   }
-  if (old_docstream != doc_stream_) {
-    // Break out of Process loop, since our I/O model just changed.
-    return PR_BLOCK;
-  }
   return PR_CONTINUE;
 }
 
diff --git a/rtc_base/httpbase.h b/rtc_base/httpbase.h
index 25a11ab..b0e2425 100644
--- a/rtc_base/httpbase.h
+++ b/rtc_base/httpbase.h
@@ -119,11 +119,6 @@
   void set_ignore_data(bool ignore) { ignore_data_ = ignore; }
   bool ignore_data() const { return ignore_data_; }
 
-  // Obtaining this stream puts HttpBase into stream mode until the stream
-  // is closed.  HttpBase can only expose one open stream interface at a time.
-  // Further calls will return null.
-  StreamInterface* GetDocumentStream();
-
  protected:
   // Do cleanup when the http stream closes (error may be 0 for a clean
   // shutdown), and return the error code to signal.
@@ -180,7 +175,6 @@
   HttpData* data_;
   IHttpNotify* notify_;
   StreamInterface* http_stream_;
-  DocumentStream* doc_stream_;
   char buffer_[kBufferSize];
   size_t len_;
 
diff --git a/rtc_base/httpbase_unittest.cc b/rtc_base/httpbase_unittest.cc
index 260fb9b..35321da 100644
--- a/rtc_base/httpbase_unittest.cc
+++ b/rtc_base/httpbase_unittest.cc
@@ -34,16 +34,6 @@
     "Proxy-Authorization: 42\r\n"
     "\r\n";
 
-const char* const kHttpResponsePrefix =
-    "HTTP/1.1 200\r\n"
-    "Connection: Keep-Alive\r\n"
-    "Content-Type: text/plain\r\n"
-    "Proxy-Authorization: 42\r\n"
-    "Transfer-Encoding: chunked\r\n"
-    "\r\n"
-    "8\r\n"
-    "Goodbye!\r\n";
-
 class HttpBaseTest : public testing::Test, public IHttpNotify {
  public:
   enum EventType { E_HEADER_COMPLETE, E_COMPLETE, E_CLOSED };
@@ -54,7 +44,7 @@
     HttpMode mode;
     HttpError err;
   };
-  HttpBaseTest() : mem(nullptr), obtain_stream(false), http_stream(nullptr) {}
+  HttpBaseTest() : mem(nullptr), http_stream(nullptr) {}
 
   void TearDown() override {
     delete http_stream;
@@ -66,9 +56,6 @@
     RTC_LOG_F(LS_VERBOSE) << "chunked: " << chunked << " size: " << data_size;
     Event e = {E_HEADER_COMPLETE, chunked, data_size, HM_NONE, HE_NONE};
     events.push_back(e);
-    if (obtain_stream) {
-      ObtainDocumentStream();
-    }
     return HE_NONE;
   }
   void onHttpComplete(HttpMode mode, HttpError err) override {
@@ -88,7 +75,6 @@
   void VerifyDocumentContents(const char* expected_data,
                               size_t expected_length = SIZE_UNKNOWN);
 
-  void ObtainDocumentStream();
   void VerifyDocumentStreamIsOpening();
   void VerifyDocumentStreamOpenEvent();
   void ReadDocumentStreamData(const char* expected_data);
@@ -108,8 +94,7 @@
   webrtc::testing::StreamSource src;
   std::vector<Event> events;
 
-  // Document stream, and stream events
-  bool obtain_stream;
+  // Stream events
   StreamInterface* http_stream;
   webrtc::testing::StreamSink sink;
 };
@@ -184,15 +169,6 @@
   RTC_LOG_F(LS_VERBOSE) << "Exit";
 }
 
-void HttpBaseTest::ObtainDocumentStream() {
-  RTC_LOG_F(LS_VERBOSE) << "Enter";
-  EXPECT_FALSE(http_stream);
-  http_stream = base.GetDocumentStream();
-  ASSERT_TRUE(nullptr != http_stream);
-  sink.Monitor(http_stream);
-  RTC_LOG_F(LS_VERBOSE) << "Exit";
-}
-
 void HttpBaseTest::VerifyDocumentStreamIsOpening() {
   RTC_LOG_F(LS_VERBOSE) << "Enter";
   ASSERT_TRUE(nullptr != http_stream);
@@ -379,145 +355,4 @@
   VerifyDocumentContents("Goodbye!");
 }
 
-TEST_F(HttpBaseTest, SupportsReceiveViaStreamPull) {
-  // Switch to pull mode
-  ObtainDocumentStream();
-  VerifyDocumentStreamIsOpening();
-
-  // Queue response document
-  SetupSource(kHttpResponse);
-  VerifyDocumentStreamIsOpening();
-
-  // Begin receive
-  base.recv(&data);
-
-  // Pull document data
-  VerifyDocumentStreamOpenEvent();
-  ReadDocumentStreamData("Goodbye!");
-  VerifyDocumentStreamIsEOS();
-
-  // Document completed successfully
-  VerifyHeaderComplete(2, false);
-  VerifyTransferComplete(HM_RECV, HE_NONE);
-  VerifyDocumentContents("");
-}
-
-TEST_F(HttpBaseTest, DISABLED_AllowsCloseStreamBeforeDocumentIsComplete) {
-  // TODO: Remove extra logging once test failure is understood
-  LoggingSeverity old_sev = rtc::LogMessage::GetLogToDebug();
-  rtc::LogMessage::LogToDebug(LS_VERBOSE);
-
-  // Switch to pull mode
-  ObtainDocumentStream();
-  VerifyDocumentStreamIsOpening();
-
-  // Queue response document
-  SetupSource(kHttpResponse);
-  VerifyDocumentStreamIsOpening();
-
-  // Begin receive
-  base.recv(&data);
-
-  // Pull some of the data
-  VerifyDocumentStreamOpenEvent();
-  ReadDocumentStreamData("Goodb");
-
-  // We've seen the header by now
-  VerifyHeaderComplete(1, false);
-
-  // Close the pull stream, this will transition back to push I/O.
-  http_stream->Close();
-  Thread::Current()->ProcessMessages(0);
-
-  // Remainder of document completed successfully
-  VerifyTransferComplete(HM_RECV, HE_NONE);
-  VerifyDocumentContents("ye!");
-
-  rtc::LogMessage::LogToDebug(old_sev);
-}
-
-TEST_F(HttpBaseTest, AllowsGetDocumentStreamInResponseToHttpHeader) {
-  // Queue response document
-  SetupSource(kHttpResponse);
-
-  // Switch to pull mode in response to header arrival
-  obtain_stream = true;
-
-  // Begin receive
-  base.recv(&data);
-
-  // We've already seen the header, but not data has arrived
-  VerifyHeaderComplete(1, false);
-  VerifyDocumentContents("");
-
-  // Pull the document data
-  ReadDocumentStreamData("Goodbye!");
-  VerifyDocumentStreamIsEOS();
-
-  // Document completed successfully
-  VerifyTransferComplete(HM_RECV, HE_NONE);
-  VerifyDocumentContents("");
-}
-
-TEST_F(HttpBaseTest, AllowsGetDocumentStreamWithEmptyDocumentBody) {
-  // Queue empty response document
-  SetupSource(kHttpEmptyResponse);
-
-  // Switch to pull mode in response to header arrival
-  obtain_stream = true;
-
-  // Begin receive
-  base.recv(&data);
-
-  // We've already seen the header, but not data has arrived
-  VerifyHeaderComplete(1, true);
-  VerifyDocumentContents("");
-
-  // The document is still open, until we attempt to read
-  ASSERT_TRUE(nullptr != http_stream);
-  EXPECT_EQ(SS_OPEN, http_stream->GetState());
-
-  // Attempt to read data, and discover EOS
-  VerifyDocumentStreamIsEOS();
-
-  // Document completed successfully
-  VerifyTransferComplete(HM_RECV, HE_NONE);
-  VerifyDocumentContents("");
-}
-
-TEST_F(HttpBaseTest, SignalsDocumentStreamCloseOnUnexpectedClose) {
-  // Switch to pull mode
-  ObtainDocumentStream();
-  VerifyDocumentStreamIsOpening();
-
-  // Queue response document
-  SetupSource(kHttpResponsePrefix);
-  VerifyDocumentStreamIsOpening();
-
-  // Begin receive
-  base.recv(&data);
-
-  // Pull document data
-  VerifyDocumentStreamOpenEvent();
-  ReadDocumentStreamData("Goodbye!");
-
-  // Simulate unexpected close
-  src.SetState(SS_CLOSED);
-
-  // Observe error event on document stream
-  EXPECT_EQ(webrtc::testing::SSE_ERROR, sink.Events(http_stream));
-
-  // Future reads give an error
-  int error = 0;
-  char buffer[5] = {0};
-  EXPECT_EQ(SR_ERROR,
-            http_stream->Read(buffer, sizeof(buffer), nullptr, &error));
-  EXPECT_EQ(HE_DISCONNECTED, error);
-
-  // Document completed with error
-  VerifyHeaderComplete(2, false);
-  VerifyTransferComplete(HM_RECV, HE_DISCONNECTED);
-  VerifyDocumentContents("");
-}
-
 }  // namespace rtc
diff --git a/rtc_base/httpcommon.cc b/rtc_base/httpcommon.cc
index 5ac1e42..4ecb393 100644
--- a/rtc_base/httpcommon.cc
+++ b/rtc_base/httpcommon.cc
@@ -21,13 +21,13 @@
 #include <algorithm>
 
 #include "rtc_base/arraysize.h"
-#include "rtc_base/base64.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/cryptstring.h"
 #include "rtc_base/httpcommon-inl.h"
 #include "rtc_base/httpcommon.h"
 #include "rtc_base/messagedigest.h"
 #include "rtc_base/socketaddress.h"
+#include "rtc_base/third_party/base64/base64.h"
 #include "rtc_base/zero_memory.h"
 
 namespace rtc {
@@ -169,10 +169,6 @@
 static const char* kHttpVersions[HVER_LAST + 1] = {"1.0", "1.1", "Unknown"};
 ENUM(HttpVersion, kHttpVersions);
 
-static const char* kHttpVerbs[HV_LAST + 1] = {"GET",    "POST",    "PUT",
-                                              "DELETE", "CONNECT", "HEAD"};
-ENUM(HttpVerb, kHttpVerbs);
-
 static const char* kHttpHeaders[HH_LAST + 1] = {
     "Age",
     "Cache-Control",
@@ -213,14 +209,6 @@
   return Enum<HttpVersion>::Parse(version, str);
 }
 
-const char* ToString(HttpVerb verb) {
-  return Enum<HttpVerb>::Name(verb);
-}
-
-bool FromString(HttpVerb& verb, const std::string& str) {
-  return Enum<HttpVerb>::Parse(verb, str);
-}
-
 const char* ToString(HttpHeader header) {
   return Enum<HttpHeader>::Name(header);
 }
@@ -229,25 +217,6 @@
   return Enum<HttpHeader>::Parse(header, str);
 }
 
-bool HttpCodeHasBody(uint32_t code) {
-  return !HttpCodeIsInformational(code) && (code != HC_NO_CONTENT) &&
-         (code != HC_NOT_MODIFIED);
-}
-
-bool HttpCodeIsCacheable(uint32_t code) {
-  switch (code) {
-    case HC_OK:
-    case HC_NON_AUTHORITATIVE:
-    case HC_PARTIAL_CONTENT:
-    case HC_MULTIPLE_CHOICES:
-    case HC_MOVED_PERMANENTLY:
-    case HC_GONE:
-      return true;
-    default:
-      return false;
-  }
-}
-
 bool HttpHeaderIsEndToEnd(HttpHeader header) {
   switch (header) {
     case HH_CONNECTION:
@@ -494,10 +463,6 @@
   }
 }
 
-void HttpData::copy(const HttpData& src) {
-  headers_ = src.headers_;
-}
-
 void HttpData::changeHeader(const std::string& name,
                             const std::string& value,
                             HeaderCombine combine) {
@@ -572,21 +537,14 @@
 //
 
 void HttpRequestData::clear(bool release_document) {
-  verb = HV_GET;
   path.clear();
   HttpData::clear(release_document);
 }
 
-void HttpRequestData::copy(const HttpRequestData& src) {
-  verb = src.verb;
-  path = src.path;
-  HttpData::copy(src);
-}
-
 size_t HttpRequestData::formatLeader(char* buffer, size_t size) const {
   RTC_DCHECK(path.find(' ') == std::string::npos);
-  return sprintfn(buffer, size, "%s %.*s HTTP/%s", ToString(verb), path.size(),
-                  path.data(), ToString(version));
+  return sprintfn(buffer, size, "GET %.*s HTTP/%s", path.size(), path.data(),
+                  ToString(version));
 }
 
 HttpError HttpRequestData::parseLeader(const char* line, size_t len) {
@@ -608,8 +566,7 @@
   } else {
     return HE_PROTOCOL;
   }
-  std::string sverb(line, vend);
-  if (!FromString(verb, sverb.c_str())) {
+  if (vend != 3 || memcmp(line, "GET", 3)) {
     return HE_PROTOCOL;  // !?! HC_METHOD_NOT_SUPPORTED?
   }
   path.assign(line + dstart, line + dend);
@@ -617,8 +574,6 @@
 }
 
 bool HttpRequestData::getAbsoluteUri(std::string* uri) const {
-  if (HV_CONNECT == verb)
-    return false;
   Url<char> url(path);
   if (url.valid()) {
     uri->assign(path);
@@ -635,8 +590,6 @@
 
 bool HttpRequestData::getRelativeUri(std::string* host,
                                      std::string* path) const {
-  if (HV_CONNECT == verb)
-    return false;
   Url<char> url(this->path);
   if (url.valid()) {
     host->assign(url.address());
@@ -659,34 +612,12 @@
   HttpData::clear(release_document);
 }
 
-void HttpResponseData::copy(const HttpResponseData& src) {
-  scode = src.scode;
-  message = src.message;
-  HttpData::copy(src);
-}
-
 void HttpResponseData::set_success(uint32_t scode) {
   this->scode = scode;
   message.clear();
   setHeader(HH_CONTENT_LENGTH, "0", false);
 }
 
-void HttpResponseData::set_success(const std::string& content_type,
-                                   StreamInterface* document,
-                                   uint32_t scode) {
-  this->scode = scode;
-  message.erase(message.begin(), message.end());
-  setContent(content_type, document);
-}
-
-void HttpResponseData::set_redirect(const std::string& location,
-                                    uint32_t scode) {
-  this->scode = scode;
-  message.clear();
-  setHeader(HH_LOCATION, location);
-  setHeader(HH_CONTENT_LENGTH, "0", false);
-}
-
 void HttpResponseData::set_error(uint32_t scode) {
   this->scode = scode;
   message.clear();
diff --git a/rtc_base/httpcommon.h b/rtc_base/httpcommon.h
index 1b8768d..11c01ca 100644
--- a/rtc_base/httpcommon.h
+++ b/rtc_base/httpcommon.h
@@ -31,41 +31,11 @@
 
 enum HttpCode {
   HC_OK = 200,
-  HC_NON_AUTHORITATIVE = 203,
-  HC_NO_CONTENT = 204,
-  HC_PARTIAL_CONTENT = 206,
-
-  HC_MULTIPLE_CHOICES = 300,
-  HC_MOVED_PERMANENTLY = 301,
-  HC_FOUND = 302,
-  HC_SEE_OTHER = 303,
-  HC_NOT_MODIFIED = 304,
-  HC_MOVED_TEMPORARILY = 307,
-
-  HC_BAD_REQUEST = 400,
-  HC_UNAUTHORIZED = 401,
-  HC_FORBIDDEN = 403,
-  HC_NOT_FOUND = 404,
-  HC_PROXY_AUTHENTICATION_REQUIRED = 407,
-  HC_GONE = 410,
-
   HC_INTERNAL_SERVER_ERROR = 500,
-  HC_NOT_IMPLEMENTED = 501,
-  HC_SERVICE_UNAVAILABLE = 503,
 };
 
 enum HttpVersion { HVER_1_0, HVER_1_1, HVER_UNKNOWN, HVER_LAST = HVER_UNKNOWN };
 
-enum HttpVerb {
-  HV_GET,
-  HV_POST,
-  HV_PUT,
-  HV_DELETE,
-  HV_CONNECT,
-  HV_HEAD,
-  HV_LAST = HV_HEAD
-};
-
 enum HttpError {
   HE_NONE,
   HE_PROTOCOL,             // Received non-valid HTTP data
@@ -121,37 +91,12 @@
 // Utility Functions
 //////////////////////////////////////////////////////////////////////
 
-inline HttpError mkerr(HttpError err, HttpError def_err = HE_DEFAULT) {
-  return (err != HE_NONE) ? err : def_err;
-}
-
 const char* ToString(HttpVersion version);
 bool FromString(HttpVersion& version, const std::string& str);
 
-const char* ToString(HttpVerb verb);
-bool FromString(HttpVerb& verb, const std::string& str);
-
 const char* ToString(HttpHeader header);
 bool FromString(HttpHeader& header, const std::string& str);
 
-inline bool HttpCodeIsInformational(uint32_t code) {
-  return ((code / 100) == 1);
-}
-inline bool HttpCodeIsSuccessful(uint32_t code) {
-  return ((code / 100) == 2);
-}
-inline bool HttpCodeIsRedirection(uint32_t code) {
-  return ((code / 100) == 3);
-}
-inline bool HttpCodeIsClientError(uint32_t code) {
-  return ((code / 100) == 4);
-}
-inline bool HttpCodeIsServerError(uint32_t code) {
-  return ((code / 100) == 5);
-}
-
-bool HttpCodeHasBody(uint32_t code);
-bool HttpCodeIsCacheable(uint32_t code);
 bool HttpHeaderIsEndToEnd(HttpHeader header);
 bool HttpHeaderIsCollapsible(HttpHeader header);
 
@@ -382,20 +327,17 @@
  protected:
   virtual ~HttpData();
   void clear(bool release_document);
-  void copy(const HttpData& src);
 
  private:
   HeaderMap headers_;
 };
 
 struct HttpRequestData : public HttpData {
-  HttpVerb verb;
   std::string path;
 
-  HttpRequestData() : verb(HV_GET) {}
+  HttpRequestData() {}
 
   void clear(bool release_document);
-  void copy(const HttpRequestData& src);
 
   size_t formatLeader(char* buffer, size_t size) const override;
   HttpError parseLeader(const char* line, size_t len) override;
@@ -410,15 +352,9 @@
 
   HttpResponseData() : scode(HC_INTERNAL_SERVER_ERROR) {}
   void clear(bool release_document);
-  void copy(const HttpResponseData& src);
 
   // Convenience methods
   void set_success(uint32_t scode = HC_OK);
-  void set_success(const std::string& content_type,
-                   StreamInterface* document,
-                   uint32_t scode = HC_OK);
-  void set_redirect(const std::string& location,
-                    uint32_t scode = HC_MOVED_TEMPORARILY);
   void set_error(uint32_t scode);
 
   size_t formatLeader(char* buffer, size_t size) const override;
diff --git a/rtc_base/memory/BUILD.gn b/rtc_base/memory/BUILD.gn
index e24b8ce..05fd7ab 100644
--- a/rtc_base/memory/BUILD.gn
+++ b/rtc_base/memory/BUILD.gn
@@ -27,9 +27,7 @@
     "aligned_malloc.cc",
     "aligned_malloc.h",
   ]
-  deps = [
-    "../..:typedefs",
-  ]
+  deps = []
 }
 
 rtc_source_set("unittests") {
@@ -41,7 +39,6 @@
   deps = [
     ":aligned_array",
     ":aligned_malloc",
-    "../..:typedefs",
     "../../test:test_support",
   ]
 }
diff --git a/rtc_base/memory/aligned_malloc.cc b/rtc_base/memory/aligned_malloc.cc
index 4e1e85c..2943a64 100644
--- a/rtc_base/memory/aligned_malloc.cc
+++ b/rtc_base/memory/aligned_malloc.cc
@@ -19,8 +19,6 @@
 #include <stdint.h>
 #endif
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 // Reference on memory alignment:
 // http://stackoverflow.com/questions/227897/solve-the-memory-alignment-in-c-interview-question-that-stumped-me
 namespace webrtc {
diff --git a/rtc_base/memory/aligned_malloc_unittest.cc b/rtc_base/memory/aligned_malloc_unittest.cc
index 742a772..572af5a 100644
--- a/rtc_base/memory/aligned_malloc_unittest.cc
+++ b/rtc_base/memory/aligned_malloc_unittest.cc
@@ -19,7 +19,6 @@
 #endif
 
 #include "test/gtest.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/rtc_base/message_buffer_reader.h b/rtc_base/message_buffer_reader.h
new file mode 100644
index 0000000..baba89e
--- /dev/null
+++ b/rtc_base/message_buffer_reader.h
@@ -0,0 +1,37 @@
+/*
+ *  Copyright 2018 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 RTC_BASE_MESSAGE_BUFFER_READER_H_
+#define RTC_BASE_MESSAGE_BUFFER_READER_H_
+
+#include "rtc_base/bytebuffer.h"
+
+namespace webrtc {
+
+// A simple subclass of the ByteBufferReader that exposes the starting address
+// of the message and its length, so that we can recall previously parsed data.
+class MessageBufferReader : public rtc::ByteBufferReader {
+ public:
+  MessageBufferReader(const char* bytes, size_t len)
+      : rtc::ByteBufferReader(bytes, len) {}
+  ~MessageBufferReader() = default;
+
+  // Starting address of the message.
+  const char* MessageData() const { return bytes_; }
+  // Total length of the message. Note that this is different from Length(),
+  // which is the length of the remaining message from the current offset.
+  size_t MessageLength() const { return size_; }
+  // Current offset in the message.
+  size_t CurrentOffset() const { return start_; }
+};
+
+}  // namespace webrtc
+
+#endif  // RTC_BASE_MESSAGE_BUFFER_READER_H_
diff --git a/rtc_base/messagequeue.h b/rtc_base/messagequeue.h
index c156d15..fe64c9c 100644
--- a/rtc_base/messagequeue.h
+++ b/rtc_base/messagequeue.h
@@ -25,8 +25,8 @@
 #include "rtc_base/location.h"
 #include "rtc_base/messagehandler.h"
 #include "rtc_base/scoped_ref_ptr.h"
-#include "rtc_base/sigslot.h"
 #include "rtc_base/socketserver.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread_annotations.h"
 #include "rtc_base/timeutils.h"
 
diff --git a/rtc_base/module.mk b/rtc_base/module.mk
index 0f8f8ca..2a1b9f3 100644
--- a/rtc_base/module.mk
+++ b/rtc_base/module.mk
@@ -5,7 +5,7 @@
 include common.mk
 
 rtc_base_approved_generic_CXX_OBJECTS = \
-	rtc_base/base64.o \
+	rtc_base/third_party/base64/base64.o \
 	rtc_base/bitbuffer.o \
 	rtc_base/bitrateallocationstrategy.o \
 	rtc_base/bufferqueue.o \
diff --git a/rtc_base/nethelpers.h b/rtc_base/nethelpers.h
index de14a06..f9d188f 100644
--- a/rtc_base/nethelpers.h
+++ b/rtc_base/nethelpers.h
@@ -22,8 +22,8 @@
 
 #include "rtc_base/asyncresolverinterface.h"
 #include "rtc_base/signalthread.h"
-#include "rtc_base/sigslot.h"
 #include "rtc_base/socketaddress.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
 
diff --git a/rtc_base/network.cc b/rtc_base/network.cc
index 0f42d6f..34da828 100644
--- a/rtc_base/network.cc
+++ b/rtc_base/network.cc
@@ -95,6 +95,7 @@
 std::string AdapterTypeToString(AdapterType type) {
   switch (type) {
     case ADAPTER_TYPE_ANY:
+      return "Wildcard";
     case ADAPTER_TYPE_UNKNOWN:
       return "Unknown";
     case ADAPTER_TYPE_ETHERNET:
diff --git a/rtc_base/network.h b/rtc_base/network.h
index 03a0978..ad932d0 100644
--- a/rtc_base/network.h
+++ b/rtc_base/network.h
@@ -22,7 +22,7 @@
 #include "rtc_base/ipaddress.h"
 #include "rtc_base/messagehandler.h"
 #include "rtc_base/networkmonitor.h"
-#include "rtc_base/sigslot.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 #if defined(WEBRTC_POSIX)
 struct ifaddrs;
diff --git a/rtc_base/networkmonitor.h b/rtc_base/networkmonitor.h
index a174473..a84a30a 100644
--- a/rtc_base/networkmonitor.h
+++ b/rtc_base/networkmonitor.h
@@ -13,7 +13,7 @@
 
 #include "rtc_base/logging.h"
 #include "rtc_base/network_constants.h"
-#include "rtc_base/sigslot.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread.h"
 
 namespace rtc {
diff --git a/rtc_base/networkroute.h b/rtc_base/networkroute.h
index 5800ef8..31c0831 100644
--- a/rtc_base/networkroute.h
+++ b/rtc_base/networkroute.h
@@ -20,30 +20,13 @@
 namespace rtc {
 
 struct NetworkRoute {
-  bool connected;
-  uint16_t local_network_id;
-  uint16_t remote_network_id;
-  int last_sent_packet_id;  // Last packet id sent on the PREVIOUS route.
-  int packet_overhead;      // The overhead in bytes from IP layer and above.
-
-  NetworkRoute()
-      : connected(false),
-        local_network_id(0),
-        remote_network_id(0),
-        last_sent_packet_id(-1),
-        packet_overhead(0) {}
-
-  // The route is connected if the local and remote network ids are provided.
-  // TODO(zhihuang): Remove this and let the caller set the fields explicitly.
-  NetworkRoute(bool connected,
-               uint16_t local_net_id,
-               uint16_t remote_net_id,
-               int last_packet_id)
-      : connected(connected),
-        local_network_id(local_net_id),
-        remote_network_id(remote_net_id),
-        last_sent_packet_id(last_packet_id),
-        packet_overhead(0) {}
+  bool connected = false;
+  uint16_t local_network_id = 0;
+  uint16_t remote_network_id = 0;
+  // Last packet id sent on the PREVIOUS route.
+  int last_sent_packet_id = -1;
+  // The overhead in bytes from IP layer and above.
+  int packet_overhead = 0;
 
   // |last_sent_packet_id| and |packet_overhead| do not affect the NetworkRoute
   // comparison.
diff --git a/rtc_base/onetimeevent.h b/rtc_base/onetimeevent.h
index 8c55e26..f649f15 100644
--- a/rtc_base/onetimeevent.h
+++ b/rtc_base/onetimeevent.h
@@ -12,7 +12,6 @@
 #define RTC_BASE_ONETIMEEVENT_H_
 
 #include "rtc_base/criticalsection.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 // Provides a simple way to perform an operation (such as logging) one
diff --git a/rtc_base/openssladapter.cc b/rtc_base/openssladapter.cc
index 05de6d0..50284a6 100644
--- a/rtc_base/openssladapter.cc
+++ b/rtc_base/openssladapter.cc
@@ -907,14 +907,14 @@
     return nullptr;
   }
 
-#ifdef WEBRTC_BUILT_IN_SSL_ROOT_CERTIFICATES
+#ifndef WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
   if (!openssl::LoadBuiltinSSLRootCertificates(ctx)) {
     RTC_LOG(LS_ERROR) << "SSL_CTX creation failed: Failed to load any trusted "
                          "ssl root certificates.";
     SSL_CTX_free(ctx);
     return nullptr;
   }
-#endif  // WEBRTC_BUILT_IN_SSL_ROOT_CERTIFICATES
+#endif  // WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 
 #if !defined(NDEBUG)
   SSL_CTX_set_info_callback(ctx, SSLInfoCallback);
diff --git a/rtc_base/opensslcertificate.cc b/rtc_base/opensslcertificate.cc
index 15fc303..ed67a89 100644
--- a/rtc_base/opensslcertificate.cc
+++ b/rtc_base/opensslcertificate.cc
@@ -36,9 +36,9 @@
 #include "rtc_base/openssldigest.h"
 #include "rtc_base/opensslidentity.h"
 #include "rtc_base/opensslutility.h"
-#ifdef WEBRTC_BUILT_IN_SSL_ROOT_CERTIFICATES
+#ifndef WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 #include "rtc_base/sslroots.h"
-#endif
+#endif  // WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 
 namespace rtc {
 
diff --git a/rtc_base/opensslutility.cc b/rtc_base/opensslutility.cc
index 2b4ffb6..46f4547 100644
--- a/rtc_base/opensslutility.cc
+++ b/rtc_base/opensslutility.cc
@@ -23,6 +23,7 @@
 
 #include <openssl/bio.h>
 #include <openssl/crypto.h>
+#include <openssl/err.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
@@ -32,9 +33,9 @@
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/openssl.h"
 #include "rtc_base/opensslcertificate.h"
-#ifdef WEBRTC_BUILT_IN_SSL_ROOT_CERTIFICATES
+#ifndef WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 #include "rtc_base/sslroots.h"
-#endif  // WEBRTC_BUILT_IN_SSL_ROOT_CERTIFICATES
+#endif  // WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 
 namespace rtc {
 namespace openssl {
@@ -109,7 +110,7 @@
   }
 }
 
-#ifdef WEBRTC_BUILT_IN_SSL_ROOT_CERTIFICATES
+#ifndef WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 bool LoadBuiltinSSLRootCertificates(SSL_CTX* ctx) {
   int count_of_added_certs = 0;
   for (size_t i = 0; i < arraysize(kSSLCertCertificateList); i++) {
@@ -129,7 +130,7 @@
   }
   return count_of_added_certs > 0;
 }
-#endif  // WEBRTC_BUILT_IN_SSL_ROOT_CERTIFICATES
+#endif  // WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 
 }  // namespace openssl
 }  // namespace rtc
diff --git a/rtc_base/opensslutility.h b/rtc_base/opensslutility.h
index f579f50..7cb38b5 100644
--- a/rtc_base/opensslutility.h
+++ b/rtc_base/opensslutility.h
@@ -28,12 +28,12 @@
 // prefix can be provided for context.
 void LogSSLErrors(const std::string& prefix);
 
-#ifdef WEBRTC_BUILT_IN_SSL_ROOT_CERTIFICATES
+#ifndef WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 // Attempt to add the certificates from the loader into the SSL_CTX. False is
 // returned only if there are no certificates returned from the loader or none
 // of them can be added to the TrustStore for the provided context.
 bool LoadBuiltinSSLRootCertificates(SSL_CTX* ssl_ctx);
-#endif  // WEBRTC_BUILT_IN_SSL_ROOT_CERTIFICATES
+#endif  // WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 
 }  // namespace openssl
 }  // namespace rtc
diff --git a/rtc_base/optionsfile.cc b/rtc_base/optionsfile.cc
index 8d2d2e0..535859b 100644
--- a/rtc_base/optionsfile.cc
+++ b/rtc_base/optionsfile.cc
@@ -165,7 +165,8 @@
   if (!IsLegalName(option)) {
     return false;
   }
-  return ToString(value, &options_[option]);
+  options_[option] = ToString(value);
+  return true;
 }
 
 bool OptionsFile::RemoveValue(const std::string& option) {
diff --git a/rtc_base/ptr_util.h b/rtc_base/ptr_util.h
deleted file mode 100644
index 56d8da3..0000000
--- a/rtc_base/ptr_util.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *  Copyright 2017 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.
- */
-
-// This file contains rtc::MakeUnique and rtc::WrapUnique, which are backwards
-// compatibility aliases for absl::make_unique and absl::WrapUnique,
-// respectively. This file will go away soon; use the Abseil types directly in
-// new code.
-
-#ifndef RTC_BASE_PTR_UTIL_H_
-#define RTC_BASE_PTR_UTIL_H_
-
-#include "absl/memory/memory.h"
-
-namespace rtc {
-
-template <typename T, typename... Args>
-auto MakeUnique(Args&&... args)
-    -> decltype(absl::make_unique<T, Args...>(std::forward<Args>(args)...)) {
-  return absl::make_unique<T, Args...>(std::forward<Args>(args)...);
-}
-
-template <typename T>
-auto MakeUnique(size_t n) -> decltype(absl::make_unique<T>(n)) {
-  return absl::make_unique<T>(n);
-}
-
-using absl::WrapUnique;
-
-}  // namespace rtc
-
-#endif  // RTC_BASE_PTR_UTIL_H_
diff --git a/rtc_base/ptr_util_unittest.cc b/rtc_base/ptr_util_unittest.cc
deleted file mode 100644
index 6497fda..0000000
--- a/rtc_base/ptr_util_unittest.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  Copyright 2017 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 "rtc_base/ptr_util.h"
-
-#include <stddef.h>
-#include <string>
-
-#include "rtc_base/gunit.h"
-
-namespace rtc {
-
-namespace {
-
-class DeleteCounter {
- public:
-  DeleteCounter() { ++count_; }
-  ~DeleteCounter() { --count_; }
-
-  static size_t count() { return count_; }
-
- private:
-  static size_t count_;
-};
-
-size_t DeleteCounter::count_ = 0;
-
-}  // namespace
-
-TEST(PtrUtilTest, WrapUnique) {
-  EXPECT_EQ(0u, DeleteCounter::count());
-  DeleteCounter* counter = new DeleteCounter;
-  EXPECT_EQ(1u, DeleteCounter::count());
-  std::unique_ptr<DeleteCounter> owned_counter = WrapUnique(counter);
-  EXPECT_EQ(1u, DeleteCounter::count());
-  owned_counter.reset();
-  EXPECT_EQ(0u, DeleteCounter::count());
-}
-
-TEST(PtrUtilTest, MakeUniqueScalar) {
-  auto s = MakeUnique<std::string>();
-  EXPECT_EQ("", *s);
-
-  auto s2 = MakeUnique<std::string>("test");
-  EXPECT_EQ("test", *s2);
-}
-
-TEST(PtrUtilTest, MakeUniqueScalarWithMoveOnlyType) {
-  using MoveOnly = std::unique_ptr<std::string>;
-  auto p = MakeUnique<MoveOnly>(MakeUnique<std::string>("test"));
-  EXPECT_EQ("test", **p);
-}
-
-TEST(PtrUtilTest, MakeUniqueArray) {
-  EXPECT_EQ(0u, DeleteCounter::count());
-  auto a = MakeUnique<DeleteCounter[]>(5);
-  EXPECT_EQ(5u, DeleteCounter::count());
-  a.reset();
-  EXPECT_EQ(0u, DeleteCounter::count());
-}
-
-}  // namespace rtc
diff --git a/rtc_base/random.h b/rtc_base/random.h
index 7c103cc..2faa985 100644
--- a/rtc_base/random.h
+++ b/rtc_base/random.h
@@ -15,7 +15,6 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/constructormagic.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/rtc_base/rate_statistics.cc b/rtc_base/rate_statistics.cc
index 9b1ff8f..bb506aa 100644
--- a/rtc_base/rate_statistics.cc
+++ b/rtc_base/rate_statistics.cc
@@ -12,6 +12,7 @@
 
 #include <algorithm>
 
+#include "absl/memory/memory.h"
 #include "rtc_base/checks.h"
 
 namespace webrtc {
@@ -26,6 +27,21 @@
       max_window_size_ms_(window_size_ms),
       current_window_size_ms_(max_window_size_ms_) {}
 
+RateStatistics::RateStatistics(const RateStatistics& other)
+    : accumulated_count_(other.accumulated_count_),
+      num_samples_(other.num_samples_),
+      oldest_time_(other.oldest_time_),
+      oldest_index_(other.oldest_index_),
+      scale_(other.scale_),
+      max_window_size_ms_(other.max_window_size_ms_),
+      current_window_size_ms_(other.current_window_size_ms_) {
+  buckets_ = absl::make_unique<Bucket[]>(other.max_window_size_ms_);
+  std::copy(other.buckets_.get(),
+            other.buckets_.get() + other.max_window_size_ms_, buckets_.get());
+}
+
+RateStatistics::RateStatistics(RateStatistics&& other) = default;
+
 RateStatistics::~RateStatistics() {}
 
 void RateStatistics::Reset() {
diff --git a/rtc_base/rate_statistics.h b/rtc_base/rate_statistics.h
index fe5ae82..68035c9 100644
--- a/rtc_base/rate_statistics.h
+++ b/rtc_base/rate_statistics.h
@@ -14,7 +14,6 @@
 #include <memory>
 
 #include "absl/types/optional.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
@@ -28,6 +27,11 @@
   // scale = coefficient to convert counts/ms to desired unit
   //         ex: kBpsScale (8000) for bits/s if count represents bytes.
   RateStatistics(int64_t max_window_size_ms, float scale);
+
+  RateStatistics(const RateStatistics& other);
+
+  RateStatistics(RateStatistics&& other);
+
   ~RateStatistics();
 
   // Reset instance to original state.
diff --git a/rtc_base/signalthread.h b/rtc_base/signalthread.h
index 9d140c0..be54d9c 100644
--- a/rtc_base/signalthread.h
+++ b/rtc_base/signalthread.h
@@ -16,7 +16,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/nullsocketserver.h"
-#include "rtc_base/sigslot.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread.h"
 
 namespace rtc {
diff --git a/rtc_base/sigslot_unittest.cc b/rtc_base/sigslot_unittest.cc
index 114a59f..2f3de40 100644
--- a/rtc_base/sigslot_unittest.cc
+++ b/rtc_base/sigslot_unittest.cc
@@ -8,7 +8,7 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "rtc_base/sigslot.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/gunit.h"
 #include "rtc_base/sigslotrepeater.h"
 
diff --git a/rtc_base/sigslotrepeater.h b/rtc_base/sigslotrepeater.h
index ca44854..724e624 100644
--- a/rtc_base/sigslotrepeater.h
+++ b/rtc_base/sigslotrepeater.h
@@ -21,7 +21,7 @@
 // TODO(deadbeef): Actually use this, after we decide on some style points on
 // using signals, so it doesn't get deleted again.
 
-#include "rtc_base/sigslot.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace sigslot {
 
diff --git a/rtc_base/sigslottester.h b/rtc_base/sigslottester.h
index 646ba22..73f4365 100644
--- a/rtc_base/sigslottester.h
+++ b/rtc_base/sigslottester.h
@@ -39,7 +39,7 @@
 //   /* See unit-tests for more examples */
 
 #include "rtc_base/constructormagic.h"
-#include "rtc_base/sigslot.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
 
diff --git a/rtc_base/sigslottester.h.pump b/rtc_base/sigslottester.h.pump
index 1029a0f..0c7c693 100755
--- a/rtc_base/sigslottester.h.pump
+++ b/rtc_base/sigslottester.h.pump
@@ -36,7 +36,7 @@
 //   /* See unit-tests for more examples */
 
 #include "rtc_base/constructormagic.h"
-#include "rtc_base/sigslot.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
 
diff --git a/rtc_base/sigslottester_unittest.cc b/rtc_base/sigslottester_unittest.cc
index c8e87e5..8fde268 100644
--- a/rtc_base/sigslottester_unittest.cc
+++ b/rtc_base/sigslottester_unittest.cc
@@ -13,7 +13,7 @@
 #include <string>
 
 #include "rtc_base/gunit.h"
-#include "rtc_base/sigslot.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
 
diff --git a/rtc_base/sslcertificate.cc b/rtc_base/sslcertificate.cc
index d99da60..9a38fc0 100644
--- a/rtc_base/sslcertificate.cc
+++ b/rtc_base/sslcertificate.cc
@@ -15,11 +15,11 @@
 #include <utility>
 
 #include "absl/memory/memory.h"
-#include "rtc_base/base64.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/opensslcertificate.h"
 #include "rtc_base/sslfingerprint.h"
+#include "rtc_base/third_party/base64/base64.h"
 
 namespace rtc {
 
diff --git a/rtc_base/sslidentity.cc b/rtc_base/sslidentity.cc
index 94944f9..f286884 100644
--- a/rtc_base/sslidentity.cc
+++ b/rtc_base/sslidentity.cc
@@ -16,11 +16,11 @@
 #include <utility>
 
 #include "absl/memory/memory.h"
-#include "rtc_base/base64.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/opensslidentity.h"
 #include "rtc_base/sslfingerprint.h"
+#include "rtc_base/third_party/base64/base64.h"
 
 namespace rtc {
 
diff --git a/rtc_base/stream.cc b/rtc_base/stream.cc
index b9691c5..3f4d3dc 100644
--- a/rtc_base/stream.cc
+++ b/rtc_base/stream.cc
@@ -553,22 +553,6 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-
-ExternalMemoryStream::ExternalMemoryStream() {}
-
-ExternalMemoryStream::ExternalMemoryStream(void* data, size_t length) {
-  SetData(data, length);
-}
-
-ExternalMemoryStream::~ExternalMemoryStream() {}
-
-void ExternalMemoryStream::SetData(void* data, size_t length) {
-  data_length_ = buffer_length_ = length;
-  buffer_ = static_cast<char*>(data);
-  seek_position_ = 0;
-}
-
-///////////////////////////////////////////////////////////////////////////////
 // FifoBuffer
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/rtc_base/stream.h b/rtc_base/stream.h
index ee0f149..ac8193b 100644
--- a/rtc_base/stream.h
+++ b/rtc_base/stream.h
@@ -21,7 +21,7 @@
 #include "rtc_base/logging.h"
 #include "rtc_base/messagehandler.h"
 #include "rtc_base/messagequeue.h"
-#include "rtc_base/sigslot.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace rtc {
 
@@ -421,18 +421,6 @@
   StreamResult DoReserve(size_t size, int* error) override;
 };
 
-// ExternalMemoryStream adapts an external memory buffer, so writes which would
-// extend past the end of the buffer will return end-of-stream.
-
-class ExternalMemoryStream : public MemoryStreamBase {
- public:
-  ExternalMemoryStream();
-  ExternalMemoryStream(void* data, size_t length);
-  ~ExternalMemoryStream() override;
-
-  void SetData(void* data, size_t length);
-};
-
 // FifoBuffer allows for efficient, thread-safe buffering of data between
 // writer and reader. As the data can wrap around the end of the buffer,
 // MemoryStreamBase can't help us here.
diff --git a/rtc_base/string_to_number.cc b/rtc_base/string_to_number.cc
index 06ac9e9..9201242 100644
--- a/rtc_base/string_to_number.cc
+++ b/rtc_base/string_to_number.cc
@@ -48,5 +48,41 @@
   return absl::nullopt;
 }
 
+template <typename T>
+T StrToT(const char* str, char** str_end);
+
+template <>
+inline float StrToT(const char* str, char** str_end) {
+  return std::strtof(str, str_end);
+}
+
+template <>
+inline double StrToT(const char* str, char** str_end) {
+  return std::strtod(str, str_end);
+}
+
+template <>
+inline long double StrToT(const char* str, char** str_end) {
+  return std::strtold(str, str_end);
+}
+
+template <typename T>
+absl::optional<T> ParseFloatingPoint(const char* str) {
+  RTC_DCHECK(str);
+  if (*str == '\0')
+    return absl::nullopt;
+  char* end = nullptr;
+  errno = 0;
+  const T value = StrToT<T>(str, &end);
+  if (end && *end == '\0' && errno == 0) {
+    return value;
+  }
+  return absl::nullopt;
+}
+
+template absl::optional<float> ParseFloatingPoint(const char* str);
+template absl::optional<double> ParseFloatingPoint(const char* str);
+template absl::optional<long double> ParseFloatingPoint(const char* str);
+
 }  // namespace string_to_number_internal
 }  // namespace rtc
diff --git a/rtc_base/string_to_number.h b/rtc_base/string_to_number.h
index 9b4fa67..7ea9f25 100644
--- a/rtc_base/string_to_number.h
+++ b/rtc_base/string_to_number.h
@@ -48,6 +48,9 @@
 
 absl::optional<signed_type> ParseSigned(const char* str, int base);
 absl::optional<unsigned_type> ParseUnsigned(const char* str, int base);
+
+template <typename T>
+absl::optional<T> ParseFloatingPoint(const char* str);
 }  // namespace string_to_number_internal
 
 template <typename T>
@@ -88,6 +91,17 @@
   return absl::nullopt;
 }
 
+template <typename T>
+typename std::enable_if<std::is_floating_point<T>::value,
+                        absl::optional<T>>::type
+StringToNumber(const char* str, int base = 10) {
+  static_assert(
+      std::numeric_limits<T>::max() <= std::numeric_limits<long double>::max(),
+      "StringToNumber only supports floating-point numbers as large "
+      "as long double");
+  return string_to_number_internal::ParseFloatingPoint<T>(str);
+}
+
 // The std::string overloads only exists if there is a matching const char*
 // version.
 template <typename T>
diff --git a/rtc_base/stringencode.cc b/rtc_base/stringencode.cc
index 8e7c6d7..b410477 100644
--- a/rtc_base/stringencode.cc
+++ b/rtc_base/stringencode.cc
@@ -13,6 +13,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "rtc_base/arraysize.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/stringutils.h"
 
@@ -410,4 +411,90 @@
   return fields->size();
 }
 
+std::string ToString(const bool b) {
+  return b ? "true" : "false";
+}
+
+std::string ToString(const char* const s) {
+  return std::string(s);
+}
+std::string ToString(const std::string s) {
+  return s;
+}
+
+std::string ToString(const short s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%hd", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const unsigned short s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%hu", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const int s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%d", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const unsigned int s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%u", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const long int s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%ld", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const unsigned long int s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%lu", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const long long int s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%lld", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+std::string ToString(const unsigned long long int s) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%llu", s);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+
+std::string ToString(const double d) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%g", d);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+
+std::string ToString(const void* const p) {
+  char buf[32];
+  const int len = std::snprintf(&buf[0], arraysize(buf), "%p", p);
+  RTC_DCHECK_LE(len, arraysize(buf));
+  return std::string(&buf[0], len);
+}
+
+bool FromString(const std::string& s, bool* b) {
+  if (s == "false") {
+    *b = false;
+    return true;
+  }
+  if (s == "true") {
+    *b = true;
+    return true;
+  }
+  return false;
+}
+
 }  // namespace rtc
diff --git a/rtc_base/stringencode.h b/rtc_base/stringencode.h
index 7042c4a..830ea77 100644
--- a/rtc_base/stringencode.h
+++ b/rtc_base/stringencode.h
@@ -16,6 +16,7 @@
 #include <vector>
 
 #include "rtc_base/checks.h"
+#include "rtc_base/string_to_number.h"
 
 namespace rtc {
 
@@ -147,32 +148,40 @@
                     std::string* rest);
 
 // Convert arbitrary values to/from a string.
+// TODO(jonasolsson): Remove these when absl::StrCat becomes available.
+std::string ToString(bool b);
 
-template <class T>
-static bool ToString(const T& t, std::string* s) {
-  RTC_DCHECK(s);
-  std::ostringstream oss;
-  oss << std::boolalpha << t;
-  *s = oss.str();
-  return !oss.fail();
-}
+std::string ToString(const char* s);
+std::string ToString(std::string t);
 
-template <class T>
+std::string ToString(short s);
+std::string ToString(unsigned short s);
+std::string ToString(int s);
+std::string ToString(unsigned int s);
+std::string ToString(long int s);
+std::string ToString(unsigned long int s);
+std::string ToString(long long int s);
+std::string ToString(unsigned long long int s);
+
+std::string ToString(double t);
+
+std::string ToString(const void* p);
+
+template <typename T,
+          typename std::enable_if<std::is_arithmetic<T>::value &&
+                                      !std::is_same<T, bool>::value,
+                                  int>::type = 0>
 static bool FromString(const std::string& s, T* t) {
   RTC_DCHECK(t);
-  std::istringstream iss(s);
-  iss >> std::boolalpha >> *t;
-  return !iss.fail();
+  absl::optional<T> result = StringToNumber<T>(s);
+
+  if (result)
+    *t = *result;
+
+  return result.has_value();
 }
 
-// Inline versions of the string conversion routines.
-
-template <typename T>
-static inline std::string ToString(const T& val) {
-  std::string str;
-  ToString(val, &str);
-  return str;
-}
+bool FromString(const std::string& s, bool* b);
 
 template <typename T>
 static inline T FromString(const std::string& str) {
@@ -181,13 +190,6 @@
   return val;
 }
 
-template <typename T>
-static inline T FromString(const T& defaultValue, const std::string& str) {
-  T val(defaultValue);
-  FromString(str, &val);
-  return val;
-}
-
 //////////////////////////////////////////////////////////////////////
 
 }  // namespace rtc
diff --git a/rtc_base/stringencode_unittest.cc b/rtc_base/stringencode_unittest.cc
index ffb90b2..9bdc592 100644
--- a/rtc_base/stringencode_unittest.cc
+++ b/rtc_base/stringencode_unittest.cc
@@ -13,6 +13,8 @@
 #include "rtc_base/gunit.h"
 #include "rtc_base/stringutils.h"
 
+#include <sstream>  // no-presubmit-check TODO(webrtc:8982)
+
 namespace rtc {
 
 class HexEncodeTest : public testing::Test {
@@ -351,53 +353,79 @@
   ASSERT_STREQ("", fields.at(0).c_str());
 }
 
-TEST(BoolTest, DecodeValid) {
-  bool value;
-  EXPECT_TRUE(FromString("true", &value));
-  EXPECT_TRUE(value);
-  EXPECT_TRUE(FromString("true,", &value));
-  EXPECT_TRUE(value);
-  EXPECT_TRUE(FromString("true , true", &value));
-  EXPECT_TRUE(value);
-  EXPECT_TRUE(FromString("true ,\n false", &value));
-  EXPECT_TRUE(value);
-  EXPECT_TRUE(FromString("  true  \n", &value));
-  EXPECT_TRUE(value);
+TEST(ToString, SanityCheck) {
+  EXPECT_EQ(ToString(true), "true");
+  EXPECT_EQ(ToString(false), "false");
 
-  EXPECT_TRUE(FromString("false", &value));
-  EXPECT_FALSE(value);
-  EXPECT_TRUE(FromString("  false ", &value));
-  EXPECT_FALSE(value);
-  EXPECT_TRUE(FromString("  false, ", &value));
-  EXPECT_FALSE(value);
+  const char* c = "message";
+  EXPECT_EQ(ToString(c), c);
+  EXPECT_EQ(ToString(std::string(c)), c);
 
-  EXPECT_TRUE(FromString<bool>("true\n"));
-  EXPECT_FALSE(FromString<bool>("false\n"));
+  EXPECT_EQ(ToString(short{-123}), "-123");
+  EXPECT_EQ(ToString((unsigned short)123), "123");
+  EXPECT_EQ(ToString(int{-123}), "-123");
+  EXPECT_EQ(ToString((unsigned int)123), "123");
+  EXPECT_EQ(ToString((long int)-123), "-123");
+  EXPECT_EQ(ToString((unsigned long int)123), "123");
+  EXPECT_EQ(ToString((long long int)-123), "-123");
+  EXPECT_EQ(ToString((unsigned long long int)123), "123");
+
+  int i = 10;
+  int* p = &i;
+  std::ostringstream s;  // no-presubmit-check TODO(webrtc:8982)
+  s << p;
+  EXPECT_EQ(s.str(), ToString(p));
+
+  EXPECT_EQ(ToString(0.5), "0.5");
 }
 
-TEST(BoolTest, DecodeInvalid) {
-  bool value;
-  EXPECT_FALSE(FromString("True", &value));
-  EXPECT_FALSE(FromString("TRUE", &value));
-  EXPECT_FALSE(FromString("False", &value));
-  EXPECT_FALSE(FromString("FALSE", &value));
-  EXPECT_FALSE(FromString("0", &value));
-  EXPECT_FALSE(FromString("1", &value));
-  EXPECT_FALSE(FromString("0,", &value));
-  EXPECT_FALSE(FromString("1,", &value));
-  EXPECT_FALSE(FromString("1,0", &value));
-  EXPECT_FALSE(FromString("1.", &value));
-  EXPECT_FALSE(FromString("1.0", &value));
-  EXPECT_FALSE(FromString("", &value));
-  EXPECT_FALSE(FromString<bool>("false\nfalse"));
+template <typename T>
+void ParsesTo(std::string s, T t) {
+  T value;
+  EXPECT_TRUE(FromString(s, &value));
+  EXPECT_EQ(value, t);
 }
 
-TEST(BoolTest, RoundTrip) {
-  bool value;
-  EXPECT_TRUE(FromString(ToString(true), &value));
-  EXPECT_TRUE(value);
-  EXPECT_TRUE(FromString(ToString(false), &value));
-  EXPECT_FALSE(value);
+TEST(FromString, DecodeValid) {
+  ParsesTo("true", true);
+  ParsesTo("false", false);
+
+  ParsesTo("105", 105);
+  ParsesTo("0.25", 0.25);
+}
+
+template <typename T>
+void FailsToParse(std::string s) {
+  T value;
+  EXPECT_FALSE(FromString(s, &value)) << "[" << s << "]";
+}
+
+TEST(FromString, DecodeInvalid) {
+  FailsToParse<bool>("True");
+  FailsToParse<bool>("0");
+  FailsToParse<bool>("yes");
+
+  FailsToParse<int>("0.5");
+  FailsToParse<int>("XIV");
+  FailsToParse<double>("");
+  FailsToParse<double>("  ");
+  FailsToParse<int>("1 2");
+}
+
+template <typename T>
+void RoundTrip(T t) {
+  std::string s = ToString(t);
+  T value;
+  EXPECT_TRUE(FromString(s, &value));
+  EXPECT_EQ(value, t);
+}
+
+TEST(FromString, RoundTrip) {
+  RoundTrip<int>(123);
+  RoundTrip(false);
+  RoundTrip(true);
+  RoundTrip(0.5);
+  RoundTrip(-15l);
 }
 
 }  // namespace rtc
diff --git a/rtc_base/swap_queue.h b/rtc_base/swap_queue.h
index f794ad9..172f2f5 100644
--- a/rtc_base/swap_queue.h
+++ b/rtc_base/swap_queue.h
@@ -18,6 +18,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/criticalsection.h"
+#include "rtc_base/system/unused.h"
 
 namespace webrtc {
 
diff --git a/rtc_base/synchronization/BUILD.gn b/rtc_base/synchronization/BUILD.gn
index 9d9ea6f..447be38 100644
--- a/rtc_base/synchronization/BUILD.gn
+++ b/rtc_base/synchronization/BUILD.gn
@@ -21,7 +21,6 @@
   ]
   deps = [
     "..:macromagic",
-    "../..:typedefs",
   ]
   if (is_win) {
     sources += [
diff --git a/rtc_base/synchronization/rw_lock_posix.h b/rtc_base/synchronization/rw_lock_posix.h
index 9a92bcd..a103fe7 100644
--- a/rtc_base/synchronization/rw_lock_posix.h
+++ b/rtc_base/synchronization/rw_lock_posix.h
@@ -14,7 +14,6 @@
 #include <pthread.h>
 
 #include "rtc_base/synchronization/rw_lock_wrapper.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/rtc_base/system/BUILD.gn b/rtc_base/system/BUILD.gn
index 9d3fa2c..64df84f 100644
--- a/rtc_base/system/BUILD.gn
+++ b/rtc_base/system/BUILD.gn
@@ -38,7 +38,6 @@
   deps = [
     "..:checks",
     "..:criticalsection",
-    "../..:typedefs",
     "../..:webrtc_common",
   ]
 }
diff --git a/rtc_base/system/file_wrapper.h b/rtc_base/system/file_wrapper.h
index 4672cc4..5411b04 100644
--- a/rtc_base/system/file_wrapper.h
+++ b/rtc_base/system/file_wrapper.h
@@ -16,7 +16,6 @@
 
 #include "common_types.h"  // NOLINT(build/include)
 #include "rtc_base/criticalsection.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 // Implementation that can read (exclusive) or write from/to a file.
 
diff --git a/rtc_base/task_queue_libevent.cc b/rtc_base/task_queue_libevent.cc
index 4db4827..8dc9b15 100644
--- a/rtc_base/task_queue_libevent.cc
+++ b/rtc_base/task_queue_libevent.cc
@@ -24,6 +24,7 @@
 #include "rtc_base/platform_thread.h"
 #include "rtc_base/refcount.h"
 #include "rtc_base/refcountedobject.h"
+#include "rtc_base/system/unused.h"
 #include "rtc_base/task_queue.h"
 #include "rtc_base/task_queue_posix.h"
 #include "rtc_base/timeutils.h"
diff --git a/rtc_base/third_party/base64/BUILD.gn b/rtc_base/third_party/base64/BUILD.gn
new file mode 100644
index 0000000..dca47e0
--- /dev/null
+++ b/rtc_base/third_party/base64/BUILD.gn
@@ -0,0 +1,17 @@
+# Copyright (c) 2018 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.
+
+import("../../../webrtc.gni")
+
+rtc_source_set("base64") {
+  visibility = [ "*" ]
+  sources = [
+    "base64.cc",
+    "base64.h",
+  ]
+}
diff --git a/rtc_base/third_party/base64/LICENSE b/rtc_base/third_party/base64/LICENSE
new file mode 100644
index 0000000..4ad21d1
--- /dev/null
+++ b/rtc_base/third_party/base64/LICENSE
@@ -0,0 +1,14 @@
+//*********************************************************************
+//* Base64 - a simple base64 encoder and decoder.
+//*
+//*     Copyright (c) 1999, Bob Withers - bwit@pobox.com
+//*
+//* This code may be freely used for any purpose, either personal
+//* or commercial, provided the authors copyright notice remains
+//* intact.
+//*
+//* Enhancements by Stanley Yamane:
+//*     o reverse lookup table for the decode function
+//*     o reserve string buffer space in advance
+//*
+//*********************************************************************
diff --git a/rtc_base/third_party/base64/README.chromium b/rtc_base/third_party/base64/README.chromium
new file mode 100644
index 0000000..92ba0d3
--- /dev/null
+++ b/rtc_base/third_party/base64/README.chromium
@@ -0,0 +1,11 @@
+Name: A simple base64 encoder and decoder
+Short Name: base64
+URL:
+Version: 0
+Date: 2018-06-20
+License: Custom license
+License File: LICENSE
+Security Critical: yes
+
+Description:
+A simple base64 encoder and decoder
diff --git a/rtc_base/base64.cc b/rtc_base/third_party/base64/base64.cc
similarity index 99%
rename from rtc_base/base64.cc
rename to rtc_base/third_party/base64/base64.cc
index 6add993..53ff6b9 100644
--- a/rtc_base/base64.cc
+++ b/rtc_base/third_party/base64/base64.cc
@@ -14,10 +14,10 @@
 //*
 //*********************************************************************
 
-#include "rtc_base/base64.h"
+#include "rtc_base/third_party/base64/base64.h"
 
-#include <string.h>
 #include <assert.h>
+#include <string.h>
 
 using std::vector;
 
diff --git a/rtc_base/base64.h b/rtc_base/third_party/base64/base64.h
similarity index 96%
rename from rtc_base/base64.h
rename to rtc_base/third_party/base64/base64.h
index bfe2fe6..bbc93c8 100644
--- a/rtc_base/base64.h
+++ b/rtc_base/third_party/base64/base64.h
@@ -9,8 +9,8 @@
 //* intact.
 //*********************************************************************
 
-#ifndef RTC_BASE_BASE64_H_
-#define RTC_BASE_BASE64_H_
+#ifndef RTC_BASE_THIRD_PARTY_BASE64_BASE64_H_
+#define RTC_BASE_THIRD_PARTY_BASE64_BASE64_H_
 
 #include <string>
 #include <vector>
@@ -120,4 +120,4 @@
 
 }  // namespace rtc
 
-#endif  // RTC_BASE_BASE64_H_
+#endif  /* RTC_BASE_THIRD_PARTY_BASE64_BASE64_H_ */
diff --git a/rtc_base/third_party/base64/module.mk b/rtc_base/third_party/base64/module.mk
new file mode 100644
index 0000000..37c23f4
--- /dev/null
+++ b/rtc_base/third_party/base64/module.mk
@@ -0,0 +1,5 @@
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+include common.mk
diff --git a/rtc_base/third_party/module.mk b/rtc_base/third_party/module.mk
new file mode 100644
index 0000000..37c23f4
--- /dev/null
+++ b/rtc_base/third_party/module.mk
@@ -0,0 +1,5 @@
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+include common.mk
diff --git a/rtc_base/third_party/sigslot/BUILD.gn b/rtc_base/third_party/sigslot/BUILD.gn
new file mode 100644
index 0000000..aea748e
--- /dev/null
+++ b/rtc_base/third_party/sigslot/BUILD.gn
@@ -0,0 +1,17 @@
+# Copyright (c) 2018 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.
+
+import("../../../webrtc.gni")
+
+rtc_source_set("sigslot") {
+  visibility = [ "*" ]
+  sources = [
+    "sigslot.cc",
+    "sigslot.h",
+  ]
+}
diff --git a/rtc_base/third_party/sigslot/LICENSE b/rtc_base/third_party/sigslot/LICENSE
new file mode 100644
index 0000000..d1c66c7
--- /dev/null
+++ b/rtc_base/third_party/sigslot/LICENSE
@@ -0,0 +1,7 @@
+// sigslot.h: Signal/Slot classes
+//
+// Written by Sarah Thompson (sarah@telergy.com) 2002.
+//
+// License: Public domain. You are free to use this code however you like, with
+// the proviso that the author takes on no responsibility or liability for any
+// use.
diff --git a/rtc_base/third_party/sigslot/README.chromium b/rtc_base/third_party/sigslot/README.chromium
new file mode 100644
index 0000000..e0575cf
--- /dev/null
+++ b/rtc_base/third_party/sigslot/README.chromium
@@ -0,0 +1,20 @@
+Name: C++ Signal/Slot Library
+Short Name: sigslot
+URL: http://sigslot.sourceforge.net/
+Version: 0
+Date: 2018-07-09
+License: Custom license
+License File: LICENSE
+Security Critical: yes
+
+Description:
+C++ Signal/Slot Library
+
+This file has been modified such that has_slots and signalx do not have to be
+using the same threading requirements. E.g. it is possible to connect a
+has_slots<single_threaded> and signal0<multi_threaded_local> or
+has_slots<multi_threaded_local> and signal0<single_threaded>.
+If has_slots is single threaded the user must ensure that it is not trying
+to connect or disconnect to signalx concurrently or data race may occur.
+If signalx is single threaded the user must ensure that disconnect, connect
+or signal is not happening concurrently or data race may occur.
diff --git a/rtc_base/sigslot.cc b/rtc_base/third_party/sigslot/sigslot.cc
similarity index 90%
rename from rtc_base/sigslot.cc
rename to rtc_base/third_party/sigslot/sigslot.cc
index 9d792cb..d852a2b 100644
--- a/rtc_base/sigslot.cc
+++ b/rtc_base/third_party/sigslot/sigslot.cc
@@ -6,7 +6,7 @@
 // the proviso that the author takes on no responsibility or liability for any
 // use.
 
-#include "rtc_base/sigslot.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 
 namespace sigslot {
 
diff --git a/rtc_base/sigslot.h b/rtc_base/third_party/sigslot/sigslot.h
similarity index 98%
rename from rtc_base/sigslot.h
rename to rtc_base/third_party/sigslot/sigslot.h
index 15abdca..c77e4e6 100644
--- a/rtc_base/sigslot.h
+++ b/rtc_base/third_party/sigslot/sigslot.h
@@ -93,8 +93,8 @@
 // If signalx is single threaded the user must ensure that disconnect, connect
 // or signal is not happening concurrently or data race may occur.
 
-#ifndef RTC_BASE_SIGSLOT_H_
-#define RTC_BASE_SIGSLOT_H_
+#ifndef RTC_BASE_THIRD_PARTY_SIGSLOT_SIGSLOT_H_
+#define RTC_BASE_THIRD_PARTY_SIGSLOT_SIGSLOT_H_
 
 #include <stdlib.h>
 #include <cstring>
@@ -110,7 +110,7 @@
 #define _SIGSLOT_SINGLE_THREADED
 #elif defined(WEBRTC_WIN)
 #define _SIGSLOT_HAS_WIN32_THREADS
-#include "rtc_base/win32.h"
+#include "windows.h"
 #elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS)
 #define _SIGSLOT_HAS_POSIX_THREADS
 #include <pthread.h>
@@ -641,4 +641,4 @@
 
 }  // namespace sigslot
 
-#endif  // RTC_BASE_SIGSLOT_H_
+#endif  /* RTC_BASE_THIRD_PARTY_SIGSLOT_SIGSLOT_H_ */
diff --git a/rtc_base/thread_unittest.cc b/rtc_base/thread_unittest.cc
index 74f62eb..d5c53f8 100644
--- a/rtc_base/thread_unittest.cc
+++ b/rtc_base/thread_unittest.cc
@@ -16,8 +16,8 @@
 #include "rtc_base/gunit.h"
 #include "rtc_base/nullsocketserver.h"
 #include "rtc_base/physicalsocketserver.h"
-#include "rtc_base/sigslot.h"
 #include "rtc_base/socketaddress.h"
+#include "rtc_base/third_party/sigslot/sigslot.h"
 #include "rtc_base/thread.h"
 
 #if defined(WEBRTC_WIN)
diff --git a/rtc_base/time/BUILD.gn b/rtc_base/time/BUILD.gn
index f8f6244..7b298ce 100644
--- a/rtc_base/time/BUILD.gn
+++ b/rtc_base/time/BUILD.gn
@@ -18,7 +18,6 @@
     "timestamp_extrapolator.h",
   ]
   deps = [
-    "../..:typedefs",
     "../synchronization:rw_lock_wrapper",
   ]
 }
diff --git a/rtc_base/time/timestamp_extrapolator.h b/rtc_base/time/timestamp_extrapolator.h
index 6638184..63af57b 100644
--- a/rtc_base/time/timestamp_extrapolator.h
+++ b/rtc_base/time/timestamp_extrapolator.h
@@ -11,8 +11,9 @@
 #ifndef RTC_BASE_TIME_TIMESTAMP_EXTRAPOLATOR_H_
 #define RTC_BASE_TIME_TIMESTAMP_EXTRAPOLATOR_H_
 
+#include <stdint.h>
+
 #include "rtc_base/synchronization/rw_lock_wrapper.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/rtc_base/timeutils.cc b/rtc_base/timeutils.cc
index f65bd15..de8fc32 100644
--- a/rtc_base/timeutils.cc
+++ b/rtc_base/timeutils.cc
@@ -201,6 +201,9 @@
 }
 
 int64_t TimeUTCMicros() {
+  if (g_clock) {
+    return g_clock->TimeNanos() / kNumNanosecsPerMicrosec;
+  }
 #if defined(WEBRTC_POSIX)
   struct timeval time;
   gettimeofday(&time, nullptr);
@@ -217,4 +220,8 @@
 #endif
 }
 
+int64_t TimeUTCMillis() {
+  return TimeUTCMicros() / kNumMicrosecsPerMillisec;
+}
+
 }  // namespace rtc
diff --git a/rtc_base/timeutils.h b/rtc_base/timeutils.h
index 48b5c8d..20b1dac 100644
--- a/rtc_base/timeutils.h
+++ b/rtc_base/timeutils.h
@@ -126,6 +126,10 @@
 // measuring time intervals and timeouts.
 int64_t TimeUTCMicros();
 
+// Return the number of milliseconds since January 1, 1970, UTC.
+// See above.
+int64_t TimeUTCMillis();
+
 // Interval of time from the range [min, max] inclusive.
 class IntervalRange {
  public:
diff --git a/script/sync-apm.sh b/script/sync-apm.sh
index ab645f9..47eccdd 100755
--- a/script/sync-apm.sh
+++ b/script/sync-apm.sh
@@ -24,6 +24,7 @@
 rsync "${OPTIONS[@]}" ${FROM}/modules/audio_processing ${TO}/modules
 rsync "${OPTIONS[@]}" ${FROM}/modules/include ${TO}/modules
 rsync "${OPTIONS[@]}" ${FROM}/modules/rtp_rtcp ${TO}/modules
+rsync "${OPTIONS[@]}" ${FROM}/modules/third_party ${TO}/modules
 
 # Add video codecs headers for common includes to work.
 mkdir -p ${TO}/modules/video_coding/codecs
diff --git a/system_wrappers/BUILD.gn b/system_wrappers/BUILD.gn
index 4c09164..106c63b 100644
--- a/system_wrappers/BUILD.gn
+++ b/system_wrappers/BUILD.gn
@@ -39,10 +39,10 @@
     ":metrics_api",
     ":runtime_enabled_features_api",
     "..:webrtc_common",
-    "../:typedefs",
     "../modules:module_api_public",
     "../rtc_base:checks",
     "../rtc_base/synchronization:rw_lock_wrapper",
+    "../rtc_base/system:arch",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
 
@@ -103,7 +103,6 @@
   ]
   deps = [
     "..:webrtc_common",
-    "../:typedefs",
   ]
 }
 
@@ -194,6 +193,7 @@
     ]
     deps = [
       ":cpu_features_api",
+      "../rtc_base/system:arch",
     ]
   }
 }
@@ -218,7 +218,6 @@
       ":metrics_default",
       ":system_wrappers",
       "..:webrtc_common",
-      "../:typedefs",
       "../rtc_base:rtc_base_approved",
       "../test:test_main",
       "//testing/gtest",
diff --git a/system_wrappers/include/clock.h b/system_wrappers/include/clock.h
index 0164288..4b6eab8 100644
--- a/system_wrappers/include/clock.h
+++ b/system_wrappers/include/clock.h
@@ -15,7 +15,6 @@
 
 #include "rtc_base/synchronization/rw_lock_wrapper.h"
 #include "system_wrappers/include/ntp_time.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 
diff --git a/system_wrappers/include/cpu_features_wrapper.h b/system_wrappers/include/cpu_features_wrapper.h
index 07ee912..739161a 100644
--- a/system_wrappers/include/cpu_features_wrapper.h
+++ b/system_wrappers/include/cpu_features_wrapper.h
@@ -11,12 +11,12 @@
 #ifndef SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_
 #define SYSTEM_WRAPPERS_INCLUDE_CPU_FEATURES_WRAPPER_H_
 
+#include <stdint.h>
+
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
 #endif
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 // List of features in x86.
 typedef enum { kSSE2, kSSE3 } CPUFeature;
 
diff --git a/system_wrappers/include/cpu_info.h b/system_wrappers/include/cpu_info.h
index dbd5d60..ab546c7 100644
--- a/system_wrappers/include/cpu_info.h
+++ b/system_wrappers/include/cpu_info.h
@@ -11,7 +11,7 @@
 #ifndef SYSTEM_WRAPPERS_INCLUDE_CPU_INFO_H_
 #define SYSTEM_WRAPPERS_INCLUDE_CPU_INFO_H_
 
-#include "typedefs.h"  // NOLINT(build/include)
+#include <stdint.h>
 
 namespace webrtc {
 
diff --git a/system_wrappers/include/rtp_to_ntp_estimator.h b/system_wrappers/include/rtp_to_ntp_estimator.h
index 62a79a5..d7009d8 100644
--- a/system_wrappers/include/rtp_to_ntp_estimator.h
+++ b/system_wrappers/include/rtp_to_ntp_estimator.h
@@ -17,7 +17,6 @@
 #include "modules/include/module_common_types_public.h"
 #include "rtc_base/numerics/moving_median_filter.h"
 #include "system_wrappers/include/ntp_time.h"
-#include "typedefs.h"  // NOLINT(build/include)
 
 namespace webrtc {
 // Class for converting an RTP timestamp to the NTP domain in milliseconds.
diff --git a/system_wrappers/source/cpu_features.cc b/system_wrappers/source/cpu_features.cc
index 7417f53..d433a77 100644
--- a/system_wrappers/source/cpu_features.cc
+++ b/system_wrappers/source/cpu_features.cc
@@ -10,13 +10,13 @@
 
 // Parts of this file derived from Chromium's base/cpu.cc.
 
+#include "rtc_base/system/arch.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 
 #if defined(WEBRTC_ARCH_X86_FAMILY) && defined(_MSC_VER)
 #include <intrin.h>
 #endif
 
-#include "typedefs.h"  // NOLINT(build/include)
 
 // No CPU feature is available => straight C path.
 int GetCPUInfoNoASM(CPUFeature feature) {
diff --git a/system_wrappers/source/cpu_features_linux.c b/system_wrappers/source/cpu_features_linux.c
index 9c56450..004de5a 100644
--- a/system_wrappers/source/cpu_features_linux.c
+++ b/system_wrappers/source/cpu_features_linux.c
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include <link.h>
 #endif
+#include "rtc_base/system/arch.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 
 #if defined(WEBRTC_ARCH_ARM_FAMILY)
diff --git a/system_wrappers/source/event_timer_win.h b/system_wrappers/source/event_timer_win.h
index 0b4dff6..c99f8c6 100644
--- a/system_wrappers/source/event_timer_win.h
+++ b/system_wrappers/source/event_timer_win.h
@@ -11,12 +11,12 @@
 #ifndef SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_
 #define SYSTEM_WRAPPERS_SOURCE_EVENT_WIN_H_
 
+#include <stdint.h>
+
 #include <windows.h>
 
 #include "system_wrappers/include/event_wrapper.h"
 
-#include "typedefs.h"  // NOLINT(build/include)
-
 namespace webrtc {
 
 class EventTimerWin : public EventTimerWrapper {
diff --git a/webrtc_apm.cc b/webrtc_apm.cc
index 4985ac1..beba356 100644
--- a/webrtc_apm.cc
+++ b/webrtc_apm.cc
@@ -17,17 +17,27 @@
 		const struct aec_config *config,
 		webrtc::EchoCanceller3Config *aec3_config)
 {
-	aec3_config->delay = {
-		config->delay.default_delay,
-		config->delay.down_sampling_factor,
-		config->delay.num_filters,
-		config->delay.api_call_jitter_blocks,
+	aec3_config->delay.default_delay =
+		config->delay.default_delay;
+	aec3_config->delay.down_sampling_factor =
+		config->delay.down_sampling_factor;
+	aec3_config->delay.num_filters =
+		config->delay.num_filters;
+	aec3_config->delay.api_call_jitter_blocks =
+		config->delay.api_call_jitter_blocks;
+	aec3_config->delay.min_echo_path_delay_blocks =
 		config->delay.min_echo_path_delay_blocks,
-		config->delay.delay_headroom_blocks,
-		config->delay.hysteresis_limit_1_blocks,
+	aec3_config->delay.delay_headroom_blocks =
+		config->delay.delay_headroom_blocks;
+	aec3_config->delay.hysteresis_limit_1_blocks =
+		config->delay.hysteresis_limit_1_blocks;
+	aec3_config->delay.hysteresis_limit_2_blocks =
 		config->delay.hysteresis_limit_2_blocks,
-		config->delay.skew_hysteresis_blocks
-	};
+	aec3_config->delay.skew_hysteresis_blocks =
+		config->delay.skew_hysteresis_blocks;
+	aec3_config->delay.fixed_capture_delay_samples =
+		config->delay.fixed_capture_delay_samples;
+
 	aec3_config->filter.main = {
 		config->filter.main.length_blocks,
 		config->filter.main.leakage_converged,
@@ -54,20 +64,30 @@
 	};
 	aec3_config->filter.config_change_duration_blocks =
 		config->filter.config_change_duration_blocks;
+	aec3_config->filter.initial_state_seconds =
+		config->filter.initial_state_seconds;
+	aec3_config->filter.conservative_initial_phase =
+		static_cast<bool>(config->filter.conservative_initial_phase);
+	aec3_config->filter.enable_shadow_filter_output_usage =
+		static_cast<bool>(
+			config->filter.enable_shadow_filter_output_usage);
 	aec3_config->erle = {
 		config->erle.min,
 		config->erle.max_l,
 		config->erle.max_h,
+		static_cast<bool>(config->erle.onset_detection)
 	};
 	aec3_config->ep_strength = {
 		config->ep_strength.lf,
 		config->ep_strength.mf,
 		config->ep_strength.hf,
 		config->ep_strength.default_len,
+		static_cast<bool>(config->ep_strength.reverb_based_on_render),
 		static_cast<bool>(config->ep_strength.echo_can_saturate),
 		static_cast<bool>(config->ep_strength.bounded_erl)
 	};
 
+	aec3_config->gain_mask.m0 = config->gain_mask.m0;
 	aec3_config->gain_mask.m1 = config->gain_mask.m1;
 	aec3_config->gain_mask.m2 = config->gain_mask.m2;
 	aec3_config->gain_mask.m3 = config->gain_mask.m3;
@@ -100,49 +120,8 @@
 	aec3_config->render_levels = {
 		config->render_levels.active_render_limit,
 		config->render_levels.poor_excitation_render_limit,
+		config->render_levels.poor_excitation_render_limit_ds8,
 	};
-	aec3_config->gain_updates.low_noise = {
-		config->gain_updates.low_noise.max_inc,
-		config->gain_updates.low_noise.max_dec,
-		config->gain_updates.low_noise.rate_inc,
-		config->gain_updates.low_noise.rate_dec,
-		config->gain_updates.low_noise.min_inc,
-		config->gain_updates.low_noise.min_dec,
-	};
-	aec3_config->gain_updates.initial = {
-		config->gain_updates.initial.max_inc,
-		config->gain_updates.initial.max_dec,
-		config->gain_updates.initial.rate_inc,
-		config->gain_updates.initial.rate_dec,
-		config->gain_updates.initial.min_inc,
-		config->gain_updates.initial.min_dec,
-	};
-	aec3_config->gain_updates.normal = {
-		config->gain_updates.normal.max_inc,
-		config->gain_updates.normal.max_dec,
-		config->gain_updates.normal.rate_inc,
-		config->gain_updates.normal.rate_dec,
-		config->gain_updates.normal.min_inc,
-		config->gain_updates.normal.min_dec,
-	};
-	aec3_config->gain_updates.saturation = {
-		config->gain_updates.saturation.max_inc,
-		config->gain_updates.saturation.max_dec,
-		config->gain_updates.saturation.rate_inc,
-		config->gain_updates.saturation.rate_dec,
-		config->gain_updates.saturation.min_inc,
-		config->gain_updates.saturation.min_dec,
-	};
-	aec3_config->gain_updates.nonlinear = {
-		config->gain_updates.nonlinear.max_inc,
-		config->gain_updates.nonlinear.max_dec,
-		config->gain_updates.nonlinear.rate_inc,
-		config->gain_updates.nonlinear.rate_dec,
-		config->gain_updates.nonlinear.min_inc,
-		config->gain_updates.nonlinear.min_dec,
-	};
-	aec3_config->gain_updates.floor_first_increase =
-		config->gain_updates.floor_first_increase;
 
 	aec3_config->echo_removal_control = {
 		{
@@ -169,11 +148,69 @@
 			config->echo_model.render_pre_window_size;
 	echo_model.render_post_window_size =
 			config->echo_model.render_post_window_size;
+	echo_model.render_pre_window_size_init =
+			config->echo_model.render_pre_window_size_init;
+	echo_model.render_post_window_size_init =
+			config->echo_model.render_post_window_size_init;
 	echo_model.nonlinear_hold = config->echo_model.nonlinear_hold;
 	echo_model.nonlinear_release = config->echo_model.nonlinear_release;
 
 	aec3_config->echo_model = echo_model;
 
+	aec3_config->suppressor.normal_tuning.mask_lf.enr_transparent =
+		config->suppressor.normal_tuning.mask_lf.enr_transparent;
+	aec3_config->suppressor.normal_tuning.mask_lf.enr_suppress =
+		config->suppressor.normal_tuning.mask_lf.enr_suppress;
+	aec3_config->suppressor.normal_tuning.mask_lf.emr_transparent =
+		config->suppressor.normal_tuning.mask_lf.emr_transparent;
+	aec3_config->suppressor.normal_tuning.mask_hf.enr_transparent =
+		config->suppressor.normal_tuning.mask_hf.enr_transparent;
+	aec3_config->suppressor.normal_tuning.mask_hf.enr_suppress =
+		config->suppressor.normal_tuning.mask_hf.enr_suppress;
+	aec3_config->suppressor.normal_tuning.mask_hf.emr_transparent =
+		config->suppressor.normal_tuning.mask_hf.emr_transparent;
+	aec3_config->suppressor.normal_tuning.max_inc_factor =
+		config->suppressor.normal_tuning.max_inc_factor;
+	aec3_config->suppressor.normal_tuning.max_dec_factor_lf =
+		config->suppressor.normal_tuning.max_dec_factor_lf;
+
+	aec3_config->suppressor.nearend_tuning.mask_lf.enr_transparent =
+		config->suppressor.nearend_tuning.mask_lf.enr_transparent;
+	aec3_config->suppressor.nearend_tuning.mask_lf.enr_suppress =
+		config->suppressor.nearend_tuning.mask_lf.enr_suppress;
+	aec3_config->suppressor.nearend_tuning.mask_lf.emr_transparent =
+		config->suppressor.nearend_tuning.mask_lf.emr_transparent;
+	aec3_config->suppressor.nearend_tuning.mask_hf.enr_transparent =
+		config->suppressor.nearend_tuning.mask_hf.enr_transparent;
+	aec3_config->suppressor.nearend_tuning.mask_hf.enr_suppress =
+		config->suppressor.nearend_tuning.mask_hf.enr_suppress,
+	aec3_config->suppressor.nearend_tuning.mask_hf.emr_transparent =
+		config->suppressor.nearend_tuning.mask_hf.emr_transparent;
+	aec3_config->suppressor.nearend_tuning.max_inc_factor =
+		config->suppressor.nearend_tuning.max_inc_factor;
+	aec3_config->suppressor.nearend_tuning.max_dec_factor_lf =
+		config->suppressor.nearend_tuning.max_dec_factor_lf;
+
+	aec3_config->suppressor.dominant_nearend_detection.enr_threshold =
+		config->suppressor.dominant_nearend_detection.enr_threshold;
+	aec3_config->suppressor.dominant_nearend_detection.snr_threshold =
+		config->suppressor.dominant_nearend_detection.snr_threshold;
+	aec3_config->suppressor.dominant_nearend_detection.hold_duration =
+		config->suppressor.dominant_nearend_detection.hold_duration;
+	aec3_config->suppressor.dominant_nearend_detection.trigger_threshold =
+		config->suppressor.dominant_nearend_detection.trigger_threshold;
+
+	aec3_config->suppressor.high_bands_suppression.enr_threshold =
+		config->suppressor.high_bands_suppression.enr_threshold;
+	aec3_config->suppressor.high_bands_suppression.max_gain_during_echo =
+		config->suppressor.high_bands_suppression.max_gain_during_echo;
+
+	aec3_config->suppressor.floor_first_increase =
+		config->suppressor.floor_first_increase;
+	aec3_config->suppressor.enforce_transparent =
+		config->suppressor.enforce_transparent;
+	aec3_config->suppressor.enforce_empty_higher_bands =
+		config->suppressor.enforce_empty_higher_bands;
 
 	return 0;
 }
diff --git a/webrtc_apm.h b/webrtc_apm.h
index 31761fa..d32060b 100644
--- a/webrtc_apm.h
+++ b/webrtc_apm.h
@@ -27,6 +27,7 @@
 	size_t hysteresis_limit_1_blocks;
 	size_t hysteresis_limit_2_blocks;
 	size_t skew_hysteresis_blocks;
+	size_t fixed_capture_delay_samples;
 };
 
 struct MainConfiguration {
@@ -49,12 +50,16 @@
 	struct MainConfiguration main_initial;
 	struct ShadowConfiguration shadow_initial;
 	int config_change_duration_blocks;
+	float initial_state_seconds;
+	int conservative_initial_phase;
+	int enable_shadow_filter_output_usage;
 };
 
 struct erle {
 	float min;
 	float max_l;
 	float max_h;
+	int onset_detection;
 };
 
 struct ep_strength {
@@ -101,26 +106,6 @@
 	float poor_excitation_render_limit_ds8;
 };
 
-struct GainChanges {
-	float max_inc;
-	float max_dec;
-	float rate_inc;
-	float rate_dec;
-	float min_inc;
-	float min_dec;
-};
-
-struct gain_updates {
-	struct GainChanges low_noise;
-	struct GainChanges initial;
-	struct GainChanges normal;
-	struct GainChanges saturation;
-	struct GainChanges nonlinear;
-	float max_inc_factor;
-	float max_dec_factor_lf;
-	float floor_first_increase;
-};
-
 struct GainRampup {
 	float initial_gain;
 	float first_non_zero_gain;
@@ -148,16 +133,41 @@
 	float nonlinear_release;
 };
 
+struct masking_thresholds {
+	float enr_transparent;
+	float enr_suppress;
+	float emr_transparent;
+};
+
+struct tuning {
+	struct masking_thresholds mask_lf;
+	struct masking_thresholds mask_hf;
+	float max_inc_factor;
+	float max_dec_factor_lf;
+};
+
+struct dominant_nearend_detection {
+	float enr_threshold;
+	float snr_threshold;
+	int hold_duration;
+	int trigger_threshold;
+};
+
+struct high_bands_suppression {
+	float enr_threshold;
+	float max_gain_during_echo;
+};
+
 struct suppressor {
-	size_t bands_with_reliable_coherence;
 	size_t nearend_average_blocks;
-	float mask_lf_enr_transparent;
-	float mask_lf_enr_suppress;
-	float mask_lf_emr_transparent;
-	float mask_hf_enr_transparent;
-	float mask_hf_enr_suppress;
-	float mask_hf_emr_transparent;
- };
+	struct tuning normal_tuning;
+	struct tuning nearend_tuning;
+	struct dominant_nearend_detection dominant_nearend_detection;
+	struct high_bands_suppression high_bands_suppression;
+	float floor_first_increase;
+	int enforce_transparent;
+	int enforce_empty_higher_bands;
+};
 
 struct aec_config {
 	struct delay delay;
@@ -167,7 +177,6 @@
 	struct mask gain_mask;
 	struct echo_audibility echo_audibility;
 	struct render_levels render_levels;
-	struct gain_updates gain_updates;
 	struct echo_removal_control echo_removal_control;
 	struct echo_model echo_model;
 	struct suppressor suppressor;